In this article, I will demonstrate how to exploit GOM Player v2.1.33.5071 with a Unicode overflow.
Root Cause
The root cause of the vulnerability is that the software processes standard streaming protocols within a playlist file. When GOM Player parses an .asx playlist file, it improperly handles the href attribute of the <ref> element.
The application allocates a fixed-size buffer in the stack memory to store the URL string. However, it fails to validate the length of the string before copying it. As a result, it has a Unicode overflow vulnerability.
Open GOM Player in Immunity Debuggger, and then open the exploit.asx. Then, the application crashes:
We can see that the value of EIP is 0x00410041. Therefore, it is a buffer overflow that can overwrite EIP.
Next, we need to find the exact offset to EIP. Aftering crashing the application again with the pattern generated by mona, the value of EIP is 0x00710043.
As I mentioned in the previous article. We cannot directly use this value to find the offset. Unlike an SEH overflow, we cannot know the values that simultaneously overwrite both SEH and NSEH, and therefore find the full pattern.
In thie case, open pattern.txt, which was created by Immunity Debugger. Since the address uses little-endian order, the value that overwrote EIP should contain \x43\x71. After checking an ASCII table, we can see that these two bytes represent Cq. So, we can search for this pattern in pattern.txt:
The string Cq appears 30 times, starting at offset 2040. So, we can write a simple script to narrow down the range:
Aftering opening exploit.asx again, the value presented in EIP was 0x00330038. Why does it contain \x38, which does not exist in our junk data? The reason is that after jumping to 0x003300XX, the CPU might execute a number of instructions. Anyway, this is not the point. The most important point is that the value contains 0x33. Therefore, the exact offset should be 2040 plus 6, which is 2046.
We can write a simple Python script to verify the offset:
We can see that we have successfully jumped to the junk data:
Don’t forget, we need to use EAX to perform the Unicode overflow. (If this were an ASCII system, I would just insert the MessageBox payload into the junk data).
This part is actually similar to the last article. I wrote some NASM code to perform the action:
1 2 3 4 5 6 7 8 9
pushebp; push EBP into the stack popeax; pop value from the stack and store into EAX
; modify the value of EAX addeax, 0x11000200 subeax, 0x11000100
pusheax; store EAX into the stack ret; goto the shellcode
However, we need our opcode to be in the form of 00mm00nn..... Therefore, we need to add other instructions to pad it with zero bytes (\x00).
Murmur: The “standard answer” in my textbook does not really work… In addition, the author didn’t explain his code very clearly. Therefore, I wrote my jump code in my way!
; Init add [byteecx + 0], dh; padding pushebp; push EBP into the stack add [byteecx + 0], dh; padding popeax; pop value from the stack and store into EAX add [byteecx + 0], dh; padding
; modify the value of EAX addeax, 0x11000200 add [byteecx + 0], dh; padding subeax, 0x11000100 add [ecx], al; padding add [byteecx + 0], dh; padding pusheax; store EAX into the stack add [byteecx + 0], dh; padding ret; goto the shellcode
This shellcode allows us to forward the execution flow to our shellcode. Here, I chose the jump distance 0x100, which is 256 in decimal, but you can also choose your favorite number!
Since, the distance is 256, the length of the junk data should be 256 divided by 2 (because it is a Unicode system), which is 128.
The length of my jump code is 17; the length of WWW. is 4. The length of these two pieces of data is 21. Therefore, the final offset of our junk data should be 128 minus 21, which is 107.
Hence, the completed exploit script can be implemented as below:
This article is actually a follow-up to my previous article, where I learned the principles of Unicode overflow in detail. Therefore, the content of this article is relatively shorter than the previous one, since I can directly apply what I learned to a real vulnerable application.
However, I also finished this exploit much faster than the previous one. I think this is a good sign that I actually understand how Unicode overflow works, rather than simply following the “standard answer” from the textbook.
After learning Unicode overflow, I think I have almost finished learning the major buffer overflow techniques on Windows XP (except Integer overflow, but I keep it in future posts). The next topic will be MS08-67! After that, I can finally move on to Windows 7 and start learning techniques for bypassing modern protection mechanisms!
This is the end of this article. If you have any comments or suggestions, please feel free to leave them below!