Analysis of a Heap Overflow in Foxit Reader

written on May 15, 2016 by

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:

- Keyword:        1-79 bytes (character string)
- Null separator: 1 byte
- Text:           n bytes (character string)

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 →

Set up a Global Descriptor Table in Unicorn-Engine

written on March 27, 2016 by

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.

To write more readable code I use some constants:

F_GRANULARITY = 0x8	# If set block=4KiB otherwise block=1B
F_PROT_32 = 0x4		# Protected Mode 32 bit
F_LONG = 0x2		# Long Mode
F_AVAILABLE = 0x1 	# Free Use
A_PRESENT = 0x80	# Segment active
A_PRIV_3 = 0x60		# Ring 3 Privs
A_PRIV_2 = 0x40		# Ring 2 Privs
A_PRIV_1 = 0x20		# Ring 1 Privs
A_PRIV_0 = 0x0		# Ring 0 Privs
A_CODE = 0x10		# Code Segment
A_DATA = 0x10		# Data Segment
A_TSS = 0x0		# TSS
A_GATE = 0x0		# GATE
A_EXEC = 0x8		# Executable
S_GDT = 0x0		# Index points to GDT
S_LDT = 0x4		# Index points to LDT
S_PRIV_3 = 0x3		# Ring 3 Privs
S_PRIV_2 = 0x2		# Ring 2 Privs
S_PRIV_1 = 0x1		# Ring 1 Privs
S_PRIV_0 = 0x0		# Ring 0 Privs
Read more →

FileBytes - How to edit files

written on March 23, 2016 by

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.

from filebytes.elf import *

ls = ELF('/bin/ls')

# change entry point
ls.elfHeader.header.e_entry = 0x8048AAA

# change code
text_section = [s for s in ls.sections if == '.text'][0]

main_func_addr = 0x8049f30                                          # found with disassembler 
main_func_offset = main_func_addr - text_section.header.sh_addr

text_section.raw[main_func_offset] = 0xc3                           # write ret at beginning of main

# another possibility
text_segment = [s for s in ls.segments if s.header.p_type == PT.LOAD and s.header.p_flags & PF.EXEC][0]

main_func_offset = main_func_addr - text_segment.header.p_vaddr
text_segment.raw[main_func_offset] = 0xc3

with open('new_ls','wb') as f:
Read more →

FileBytes - Introduction

written on March 03, 2016 by

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),
  • MachO and
  • OAT (Android Runtime).

Open files

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).

from filebytes.elf import *

fileName = 'afile'
elffile = ELF(fileName)

# It is also possible to use bytes of a file.
data = open(fileName, 'rb').read()
elffile = ELF('any filename', data) # The filename is not used
Read more →

backdoorCTF 2014 WriteUp - web250

written on March 23, 2014 by

We are presented with an online Markdown to HTML converter supporting yaml and the link to the source code.

In the source code on we find the variable process.env.FLAG in the file app.js.

To read the variable we create a javascript function exploiting a vulnerability of the load() function of js-yaml (CVE2013-4660).

a: !!js/function function(){ return(process.env.FLAG) }()

Converting this prints out the flag:


Read more →

backdoorCTF 2014 WriteUp - web200

written on March 23, 2014 by

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.

#!/usr/bin/env python
import urllib2
import string


for i in range(5):
	for a in alpha:
			r=urllib2.urlopen(url+test_key, timeout=t)
			if len(password)<=i:
			print password
Read more →

backdoorCTF 2014 WriteUp - misc250

written on March 23, 2014 by

We get a picture file which can be used to login to a website as user backdoor.The task is to login as user sdslabs.

In a hexeditor we find the following suspicious data in the picture:

This looks like the following bits

01100010 (=b)
01100001 (=a)
01100011 (=c)
01101011 (=k)
01100100 (=d)
01101111 (=o)
01101111 (=o)
01110010 (=r)

We change the data to "sdslabs":

And are rewarded with the following message:
Congrats the flag is practice_makes_one_perfect

Read more →

backdoorCTF 2014 WriteUp - crypto200

written on March 23, 2014 by

To find the flag in this task we needed to decode the given hexstring

Read more →

DEF CON CTF 2013 WriteUp - 3dub 1

written on June 17, 2013 by


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.

Voilà! We have the key.

who wants oatmeal rasin anyways twumpAdby

Read more →

VolgaCTF 2013 WriteUp - stegasic 500

written on May 05, 2013 by

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.

gunzip -s hidden WarandPeace.tar.gz
Read more →

VolgaCTF 2013 WriteUp - exploit 100

written on May 03, 2013 by

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 e object.

class Exploit(object):

        def __reduce__(self):
                return (os.system,('/bin/ls',))
Read more →

PlaidCTF 2013 WriteUp - cyrpto

written on April 22, 2013 by

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.

The given python code is shown below.

import math
import random
# bleh, figuring out how to decrypt stuff is hard...
# good thing there's a service running at wherever the problem description says

ciphertext = \
(19139950631257094109974817512950844945236146526899325826152393111265339856332117664760030665587057736341341088217L, 698145134021698598302443232564752607941576857199606106641450906890460571956580687935633542046758257396595842
622837937744732920113344374182219623260691576508226597259307160898152603847317630021751538L, 375)
pubkey = \

def numbits(k):
    if k == 1:
        return 1
    return int(math.ceil(math.log(k,2))) + (1 if k % 2 == 0 else 0)

def strtoint(s):
        if len(s) == 0:
                return 0
        if len(s) == 1:
                return ord(s[0])
        return (ord(s[0]) << (8 * len(s[1:]))) | strtoint(s[1:])

def inttostr(s):
        if s == 0:
                return ""
        c = chr(s & 0xFF)
        return inttostr(s >> 8) + c

def encrypt(m, N):
    L = numbits(m)
    r = random.randint(2, N-1)
    x = pow(r, 2, N)
    y = x
    l = 0
    print "orig y:", y
    for k in range(0, L):

        l = l << 1
        l |= y & 1
        y = pow(y, 2, N)

    return (m ^ l, y, L)
Read more →

ForbiddenBITS CTF 2013 WriteUp - poir

written on March 23, 2013 by

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.

#!/usr/bin/env python
for l in f:
	s= l.split("=")[1]

for key,val in d.items():
	name="key(%d).7z" % val
	print key,val
	with open(name,"rb") as src:
		while buf:

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.

#!/usr/bin/env python
import Image

image ='key.png')
new ='RGB',(image.size))
for x in range(image.size[0]):
	for y in range(image.size[1]):
		pixel = image.getpixel((x,y))
		if pixel == (255,255,255):

The result shows a png with the key.

Read more →

ForbiddenBITS CTF 2013 WriteUp - smelf

written on March 19, 2013 by

"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.

push rbp
mov rbp, rsp
push rbx
sub rsp, 0x28
mov [rbp-0x28], rdi
mov [rbp-0x2c], esi ; (0x000000d4)
mov rax, [rbp-0x28]
mov rdi, rax
call 0x4004c0  ; 1 = imp.strlen
cmp rax, 0x1d
jbe 0x40063f  ; 2 = 0x0040063f

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.

Read more →