It is almost one year ago I found a heap overflow in Foxit Reader. I published a PoC exploit on exploit-db. Yesterday I decided to write a little explanation about the vulnerability and how I exploited it.
Foxit Reader offers the possibility to convert several file formats to PDF format. PNG is one of those file formats.
A PNG file consists of several data block called chunks. One of these chunks is a textual chunk (tEXt). This chunk type is used for meta data. You can use to set an author, a title or a discription for the PNG. This chunk type consists of three parts:
The keyword part indicates which kind of data contains the text part.
Foxit Reader uses a plugin to do the conversion. The code is located in ConvertToPdf_x86.dll. During the conversion Foxit Reader also parses the tEXt chunks of a PNG file to get timestamp. If a tIME chunk exists in the file, the tEXt chunks isn’t parsed. The function sub_101ab900 checks for the “Title” and the “Author” keyword.
Read more →
Unicorn is a multi-platform multi-architecture CPU emulator based on Qemu. It is written in C and has bindings for several programming languages e. g. python, ruby, Java, go.
A mode of modern x86 CPUs is called Protected Mode. This mode offers features such as virtual memory and paging. The memory is split into segments and the segment points to them. Since the segment registers are 16bit registers they ca
nnot hold the address of a segment. Instead of the addresses to the segments the segments registers hold segment selectors which are an indices of the global or local descriptor table (GDT, LDT). You can find here and here more information about these topics.
If you use Unicorn it is not needed to create a GDT and set the GDT register (GDTR). But in some cases the segment registers have to be set to a proper value, e. g. executing Linux or Windows binaries.
Here I showed how you can get information about the file using filebytes module. In this post I will show you how you can edit files.
All filetype classes have an attribute called _bytes. This is an array which holds the raw bytes of the file. You can edit those bytes and write it to a file. But also it is possible to edit easier specific bytes in the file. It is possible to edit all header fields which are available via the attribute header in every data container. If the header points to another region in the file those bytes are available via the attributes bytes and raw. The attribute raw can be used to edit the bytes of the file. To save the changes the bytes of the file have to be written to a file.
Here is a little example with an ELF file, but all that is also possible for PE, MachO and OAT.
This is a short introduction of the module filebytes. filebytes is a python module which can be used to read and write the following fileformats:
Executable and Linking Format (ELF),
Portable Executable (PE),
OAT (Android Runtime).
For each filetype (elf, pe, mach_o, oat) exists a separate module which has to be imported. Each module has all types defined needed for parsing that filetype. To open a file you can use the class corresponding to the filetype you want to read (ELF, PE, MachO, OAT).
This task is to retrieve the password to a login page.
In the source code we find a usleep(20000) which is executed when the checked letter of the input is correct.
To bruteforce the password we write a script which throws an exception if a given timeout is exceeded.
This challange shows us a webpage with a textfield for a username and a login button. We write some letters in the textfield and click login. After login we see a new page which shows us the message:
the key is only for the admin
So we go back and try to login as admin. But we see a message that the admin login is disabled. We use burp to do closer look. We login again and we see a cookie named username with some hex numbers. After some tests, it seems that the cookie is the username xored with something. So we try to login with "admina" and use burp to delete the last two hex numbers of the cookie.
With these words this challenge starts. We can download a gzipped archive which contains the plain text version of war and peace. So we extract this file. At google we find another plain text version of this book. Now we can compare both files, but this surprises us. Both files are completely the same.
Therefore we have to take a closer look at the archive file. At the first glance we cannot find any abnormalities. So we create a new archived version of the book and compare each other. Now we see that almost every byte is different. Ok, we know now that some information is possibly hidden in this archive file. The organizer gives us a little hint with one word - gzsteg.
A search with google shows us that gzsteg is an old steganography addition for gzip by Andy Brown and Ken Pizzini. We only find patches for the sources of gzip. So we try to patch the current version of gzip, but this fails. Therefore we download the version 1.2.4. Patching this sources causes no problems. After compiling the sources we have a gzip binary which can extract hidden files in gzipped archives. Ok, lets go.
The provided 7z-file contains the sources of the server-application as well as a client-application. Both applications are written in python. A lo
ok at the sources shows us the applications function. The client asks for text input in either plain-text or morse code
followed by the question on how to interpret the input. These Informations will be packed in a message object, serialized with pickle and sent to the server. The server deserializes this msg object, gives this object to a processor which
will encodes or decodes the message string and then the server sends back the answer to the client.
We don't know how we can get the flag, so we have to find a way list the files on the server to see if there exists a flag file. So we try to use the known pickle vulnerability to execute a system command. For this vulnerabilty we have
to write a class which has the method __reduce__. For the exploit __reduce__ has to return a tuple with a callable object and a tuple with the arguments for the callable object. To execute a system command we can use os.system as callabl
The tasks provides the python code of an encryption algorithm and the ciphertext of the flag with its encryption information (see below).
An according decryption service is running on a given server.
The decryption service asks for a ciphertext c as well as a special value of encryption information y which is used for generating the XOR-key and the length L (in bits).
Sadly the server will not decrypt any ciphertext using the provided encryption information of the flag.
This challenge provides us a file named poir. It is a pcap-ng file. Wireshark shows us more than 10k packages, mostly HTTP traffic. These packages are from the transfer of a file named "key.7z". But this is not only one transfer. This file was send in 500 different pieces, which overlaps and in wrong order.
We use the "Export Objects"-Option from Wireshark to save all 500 pieces. For the next step we have to think about how we can get all files in the right order. We could extract the "Range: bytes="-strings of the poir-file and save those to a new file. If we do this, we can sort the key.7z pieces based on the order of the range strings. Ok, lets do this.
We write a little python-script which sorts the files and combines them to one file in the one step.
Now we can extract the files of this archive. There is only one file named "key.png". It is a completely white picture.
We take a close look and see that not all pixels are completely white. We increase the visibility of these pixels.
"decrypt dat ass." - and a file to download named "smelf". That was the introduction to the current challenge. file reported a 64-bit elf binary.
The first execution without any arguments ends with a segmentation fault. A new try with "AAAA" for arguments prints "Wrong!". radare shows us the reason for this behavior. The bin needs an argument with a length of up to 29 characters.
If the length of the argument is in this range, some calculations are done with every character of this string. After each calculation the result is compared to a byte from a byte sequence. If all results are correct, "Done!" will be printed. So we hope that we can get the key if we can find the correct input-string.
We extract the byte sequence and the calculation and write a little script which brute forces a 29 character input string with a backtracking-algorithm.