Saturday, 29 December 2018

Permute Writeup - 35C3 CTF

The binary given in this challenge is a 32-bit ELF file.

$ file program
program: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.32, dynamically linked, interpreter \004, stripped

When we execute the binary, it asks us for a flag byte as an input:

$ ./program
Usage: ./program <flag byte>

In the screenshot below, we can see the requirements for the input of the binary:

1. argc == 2
2. strlen(argv[1]) == 1

So, we need to send a single character as an input.

When we execute the binary with a single character input, we notice that the MD5 hash of the binary changes as shown below:

$ md5sum program
817daa25ea4048e31a9703f53ff7c15a  program

$ ./program 3

$ md5sum program
80021d00fc812bbd9ccd3c76bdf0fcd1  program

When we pass 3 as an input to the binary, it changed the original binary itself.

Now, let's analyze further.

1. The binary is using libcapstone library to modify the disassembly of the binary at runtime.
2. The changes are written to a tmp file and the original file is overwritten. This results in the change in MD5 hash.
3. Disassembly of the binary is modified in such a way that the original logic of the program does not change.

We can observe in the screenshots below the similarity as well as the difference in the disassemblies between the original binary and after the binary was passed an input of 3.

Original binary:

Modified Binary:

Now, let's check how the input byte is being processed by the binary.

1. The subroutine, sub_804A1EE returns the value in eax.
2. This value is used to perform an XOR with the input byte as shown below:

LOAD:08049FF9                 call    sub_804A1EE
LOAD:08049FFE                 add     esp, 10h
LOAD:0804A001                 mov     [ebp+var_A], al
LOAD:0804A004                 mov     eax, [ebp+arg_C]
LOAD:0804A007                 add     eax, 4
LOAD:0804A00A                 mov     eax, [eax]
LOAD:0804A00C                 movzx   edx, byte ptr [eax]
LOAD:0804A00F                 movzx   eax, [ebp+var_A]
LOAD:0804A013                 xor     eax, edx
LOAD:0804A015                 mov     [ebp+var_B], al

3. We observe that the result of this XOR operation is equal to 0 only when the correct flag byte is passed as an input.

So, to solve this challenge, we need to do the following:

1. Bruteforce the flag byte till we get the XOR result as 0.
2. Pass the correct flag byte to the binary so that it overwrites itself and we get a new binary.
3. Do step 1 with the new binary.

And we need to continue this process till the binary prints "WIN" which indicates that we have completed processing all the flag bytes.

The flag we get is: 35C3_tempuemr_temupre


No comments:

Post a Comment