Retrospective Analysis of the Infamous Telugu Crash on OS X / iOS from a Digital Forensics and Incident Response (DFIR) POV


Share on facebook
Share on twitter
Share on linkedin
Telugu crash - ZecOps

(CVE-2018-4124) TL;DR

  • Cool bug. Surprising results.
  • Theoretical exploitation is possible
  • Controlling the memory layout remotely is not trivial
  • Real-world exploitation is unlikely !

A few months ago, a blog post detailing a consistent crash surprised the iOS / OS X community. We wanted to determine if this ‘one-character crash bug’ (CVE-2018-4124) is exploitable and can be used by malicious actors to essentially hack every iOS device, remotely. ZecOps Research Team managed to achieve varied results as described below.

In his blog, Manish Goregaokar wrote that: “The original sequence is U+0C1C U+0C4D U+0C1E U+200C U+0C3E, which is a sequence of Telugu characters: the consonant ja (జ), a virama ( ్ ), the consonant nya (ఞ), a zero-width non-joiner, and the vowel aa ( ా)”.

This blog contains multiple crashing sequence and the logic behind it.

We took a deeper dive from an exploitation perspective, to try to determine if this bug could be exploited by directing the execution flow to predefined code that is controlled by potential attackers.

Researchers: If you get excited about bugs, vulnerabilities, exploits reproduction, and Digital Forensics and Incident Response (DFIR) like we do, don’t forget to register to ZecOps Reverse Bounty program HERE.

Bug Reproduction

In order to debug the crash, we need a non-Apple Application without System Integrity Protection(SIP), so we created a simple cocoa project.

After reproducing the crash, and running it hundreds of times, most of the crashes were heap corruption:

heap corruption forensic analysis

After testing our application hundreds of times, we found two stack corruptions!

Stack Corruptions?

Following hundreds of tests, we found two stack corruptions which were originated by Chrome which has a complex heap.

In both cases, the Telugu bug (CVE-2018-4124) overwrote a value in the heap which later led to stack corruption. Reproducing the stack corruption requires us to take full control of the heap.

telugu bug heap corruption

Even if we did take full control of the heap, it is still far from code execution since we have limited control of the stack corruption.

Source of the error

In this particular case, memory corruption is hard to reproduce. The source of the error is usually far from its manifestation. In order to solve it, we would ideally want the process to crash right after the error occurred.

The guard malloc could help us to place the allocated buffer at the end of the last page, and keeping the next page unallocated, thus accessing the address beyond the allocated memory will cause bad access error and therefore crash immediately.

The process with libgmalloc crashes on “CoreText`OpenTypeReorderingOutput::finalizeOutput() + 241” which was accessing an invalid address.

We then later find out that it allocated a size 4 vector which means the vector variable had valid indexes in the range[0-3], but accessed index 4 in later iterations, causing an heap overflow.

Allocating a size 4 vector
Accessing at index 4

We initially expected that this crash would be a non-exploitable bug, but were surprised to find out that this bug could be controlled under certain conditions.

Next step: Controlling the heap!

The bug allows for a heap overflow in the userspace heap by 4 bytes with a fixed value(0x40) on MacOS 10.13.1. Due to the design of the zone allocator, we are not able to overflow into heap metadata. So, we need to try to overwrite the contents of another heap chunk. In addition, the heap overflow does not control the contents that are written. Therefore, we must find a way to create a more powerful exploit primitive by overwriting the contents of another heap chunk with this fixed value(0x40).

The zone allocator categorizes memory allocation requests based on size into tiny, small, large, and huge requests. In order to place a heap chunk right after the overflown chunk, we must allocate a chunk with the same region type.

The overflown chunk belongs to a tiny region


The overflown chunk is a “tiny” buffer of 16 bytes which belongs to the tiny region, the tiny region allocation size range from 1 byte to 992 bytes. We have managed to place a chunk of size 60 bytes right after the overflown chunk by leveraging well known “Heap Fengshui” technique. The following screenshot shows the value of the chunk we placed was changed from 0xaaaaaaaa to 0x40.

We’ve hardcoded the “Heap Fengshui” part for the purpose of this Proof of Concept:

int main(int argc, const char *argv[]) 

  int size = 500000;
  struct demo *ptr[size];

  if (argc < 2) return -1;

  //allocate a large amount of tiny chunk
  for (int i = 0; i < size; ++i)
      ptr[i] = malloc(sizeof(struct demo));
      ptr[i]->len = 8;

  //create holes on the heap
  for (int i = 0; i < size; i+=2)
  //trigger overflow
  @autoreleasepool {
      [NSTextField textFieldWithString:[NSString stringWithUTF8String:argv[1]]];
  //check if any of the values are overflown
  for (int i = 1; i < size; i+=2)
      if (ptr[i]->len != 8)
          printf("addr=%p , len=%d\n", ptr[i], ptr[i]->len);

  return 0;


Next step: Code Execution?

The heap is overwritten at non-deterministic address and the value is still uncontrollable locally, and of-course much harder to control in a remote exploitation scenarios. The Proof of Concept (PoC) shows that theoretically, remote code execution (RCE) is possible if an attacker is able to trigger reliable allocations and deallocations.

So far, without leveraging additional vulnerabilities such as information disclosure, or other ways to massage the heap in a controllable way. Real-world exploitation of this issue is unlikely. We invite you to play with the POC and check it out by yourself.

Source code for POC


This bug was patched a while ago and simple update to the latest OS X and iOS would do the trick. If however you feel that you are being targeted with other bugs or experienced anomalous behavior, you are welcome to contact us HERE.

Partners, Innovative Security Teams, and Distributors:

We’re still in stealth mode, but… we are already working with leading organizations globally. If you want to learn more about what we do and what fresh vibes we bring to defensive cyber security, sign up HERE.

Researchers: If you get excited about bugs, vulnerabilities, exploits reproduction, and Digital Forensics and Incident Response (DFIR) like we do, don’t forget to register to ZecOps Reverse Bounty program HERE.


Share on facebook
Share on google
Share on twitter
Share on linkedin