_blackb3ard/pwn_exhibit$

pwn notes from an exploit dev wannabe

Home CTF Writeups

angstromCTF: I Like It

category: Reverse Engineering

Now I like dollars, I like diamonds, I like ints, I like strings. Make Cardi like it please.

These reversing challenges are part of angstromCTF which was held during the month of April. I’m taking a try at these now since I will be heavily focusing on learning android RE and malware analysis. First off we’re given a 64-bit binary which seems to take user input.

Disassembly

We load the binary into gdb and analyze the main function.

gdb-peda$ disas main 
Dump of assembler code for function main:
   0x00000000004007a6 <+0>:	push   rbp
   0x00000000004007a7 <+1>:   mov    rbp,rsp
   0x00000000004007aa <+4>:	sub    rsp,0x50
   0x00000000004007ae <+8>:	mov    DWORD PTR [rbp-0x44],edi
   0x00000000004007b1 <+11>:	mov    QWORD PTR [rbp-0x50],rsi
   0x00000000004007b5 <+15>:	mov    rax,QWORD PTR fs:0x28
   0x00000000004007be <+24>:	mov    QWORD PTR [rbp-0x8],rax
   0x00000000004007c2 <+28>:	xor    eax,eax
   0x00000000004007c4 <+30>:	mov    edi,0x400978
   0x00000000004007c9 <+35>:	call   0x400610 <puts@plt>
   0x00000000004007ce <+40>:	mov    rdx,QWORD PTR [rip+0x20089b]        # 0x601070 <stdin@@GLIBC_2.2.5>
   0x00000000004007d5 <+47>:	lea    rax,[rbp-0x20]
   0x00000000004007d9 <+51>:	mov    esi,0x14
   0x00000000004007de <+56>:	mov    rdi,rax
   0x00000000004007e1 <+59>:	call   0x400660 <fgets@plt>
   0x00000000004007e6 <+64>:	lea    rax,[rbp-0x20]
   0x00000000004007ea <+68>:	mov    rdi,rax
   0x00000000004007ed <+71>:	call   0x400620 <strlen@plt>
   0x00000000004007f2 <+76>:	sub    rax,0x1
   0x00000000004007f6 <+80>:	mov    BYTE PTR [rbp+rax*1-0x20],0x0
   0x00000000004007fb <+85>:	lea    rax,[rbp-0x20]
   0x00000000004007ff <+89>:	mov    esi,0x4009a1
   0x0000000000400804 <+94>:	mov    rdi,rax
   0x0000000000400807 <+97>:	call   0x400670 <strcmp@plt>
   0x000000000040080c <+102>:	test   eax,eax
   0x000000000040080e <+104>:	je     0x400824 <main+126>
   0x0000000000400810 <+106>:	mov    edi,0x4009ab
   0x0000000000400815 <+111>:	call   0x400610 <puts@plt>
   0x000000000040081a <+116>:	mov    edi,0x0
   0x000000000040081f <+121>:	call   0x400690 <exit@plt>
   0x0000000000400824 <+126>:	mov    edi,0x4009c2
   0x0000000000400829 <+131>:	call   0x400610 <puts@plt>
   0x000000000040082e <+136>:	mov    edi,0x4009e0
   0x0000000000400833 <+141>:	call   0x400610 <puts@plt>
   0x0000000000400838 <+146>:	mov    rdx,QWORD PTR [rip+0x200831]        # 0x601070 <stdin@@GLIBC_2.2.5>
   0x000000000040083f <+153>:	lea    rax,[rbp-0x30]
   0x0000000000400843 <+157>:	mov    esi,0xc
   0x0000000000400848 <+162>:	mov    rdi,rax
   0x000000000040084b <+165>:	call   0x400660 <fgets@plt>
   0x0000000000400850 <+170>:	lea    rcx,[rbp-0x34]
   0x0000000000400854 <+174>:	lea    rdx,[rbp-0x38]
   0x0000000000400858 <+178>:	lea    rax,[rbp-0x30]
   0x000000000040085c <+182>:	mov    esi,0x400a1d
   0x0000000000400861 <+187>:	mov    rdi,rax
   0x0000000000400864 <+190>:	mov    eax,0x0
   0x0000000000400869 <+195>:	call   0x400680 <__isoc99_sscanf@plt>
   0x000000000040086e <+200>:	mov    edx,DWORD PTR [rbp-0x38]
   0x0000000000400871 <+203>:	mov    eax,DWORD PTR [rbp-0x34]
   0x0000000000400874 <+206>:	add    eax,edx
   0x0000000000400876 <+208>:	cmp    eax,0x88
   0x000000000040087b <+213>:	jne    0x400897 <main+241>
   0x000000000040087d <+215>:	mov    edx,DWORD PTR [rbp-0x38]
   0x0000000000400880 <+218>:	mov    eax,DWORD PTR [rbp-0x34]
   0x0000000000400883 <+221>:	imul   eax,edx
   0x0000000000400886 <+224>:	cmp    eax,0xec7
   0x000000000040088b <+229>:	jne    0x400897 <main+241>
   0x000000000040088d <+231>:	mov    edx,DWORD PTR [rbp-0x38]
   0x0000000000400890 <+234>:	mov    eax,DWORD PTR [rbp-0x34]
   0x0000000000400893 <+237>:	cmp    edx,eax
   0x0000000000400895 <+239>:	jl     0x4008ab <main+261>
   0x0000000000400897 <+241>:	mov    edi,0x4009ab
   0x000000000040089c <+246>:	call   0x400610 <puts@plt>
   0x00000000004008a1 <+251>:	mov    edi,0x0
   0x00000000004008a6 <+256>:	call   0x400690 <exit@plt>
   0x00000000004008ab <+261>:	mov    edi,0x4009c2
   0x00000000004008b0 <+266>:	call   0x400610 <puts@plt>
   0x00000000004008b5 <+271>:	mov    ecx,DWORD PTR [rbp-0x34]
   0x00000000004008b8 <+274>:	mov    edx,DWORD PTR [rbp-0x38]
   0x00000000004008bb <+277>:	lea    rax,[rbp-0x20]
   0x00000000004008bf <+281>:	mov    rsi,rax
   0x00000000004008c2 <+284>:	mov    edi,0x400a23
   0x00000000004008c7 <+289>:	mov    eax,0x0
   0x00000000004008cc <+294>:	call   0x400640 <printf@plt>
   0x00000000004008d1 <+299>:	mov    eax,0x0
   0x00000000004008d6 <+304>:	mov    rcx,QWORD PTR [rbp-0x8]
   0x00000000004008da <+308>:	xor    rcx,QWORD PTR fs:0x28
   0x00000000004008e3 <+317>:	je     0x4008ea <main+324>
   0x00000000004008e5 <+319>:	call   0x400630 <__stack_chk_fail@plt>
   0x00000000004008ea <+324>:	leave  
   0x00000000004008eb <+325>:	ret    
End of assembler dump.

As we can see, after the first call to fgets, strcmp gets executed afterwards - comparing the user-supplied buffer stored at rax (which is moved to rdi) to a string from 0x4009a1 which is loaded into the edi register. Examining the value of the address reveals the string that is the answer of the first question.

gdb-peda$ x/s 0x4009a1
"okrrrrrrr"

Since we have provided the correct answer, the code flaw jumps to the address 400824 which then proceeds to get two space-separated integers, checks if their sum is equal to 0x88 and if multiplied results to 0xec7. A final check is done to determine if the first number is less than the second one. To solve this, I created a short script to generate the numbers for us and send it to the challenge server.

rev.py
from pwn import *

#: Connect to challenge server
binary = ELF('./i_like_it', checksec=False)
p = binary.process()
context.log_level = 'error'
print(p.recv())

#: Helper function
def cardi_numbers():

	multiply_res = 0xec7
	addition_res = 0x88

	for i in range(1, multiply_res // 2):
		factor1 = 0
		factor2 = 0

		if multiply_res % i == 0:
			factor1 = multiply_res // i
			factor2 = multiply_res // factor1

		if factor1 + factor2 == addition_res and factor1 < factor2:
			return(factor1, factor2)

cardi1, cardi2 = cardi_numbers()

#: Send payload
p.sendline('okrrrrrrr')
print(p.recv())
p.sendline('{} {}'.format(cardi1, cardi2))
print(p.recv())

Running the script gets us the flag composed of our answers.

$ python rev.py
I like the string that I'm thinking of: 

I said I like it like that!
I like two integers that I'm thinking of (space separated): 

I said I like it like that!
Flag: actf{okrrrrrrr_39_97}