-
LEVEL 14 giant write-upSystem hacking training/Hackerschool LOB 2018. 5. 12. 19:45
bugbear -> giant
소스코드를 분석해보면
인자가 두개 이상인지 먼저 체크하고 맞다면 gain address of execve 부분을 통해서 execve()의 주소를 구해온다.
이 주소를 구하는 방법은
먼저 lib_addr에 libc의 base주소를 구하고, execve_offset에 execve()의 offset을 구하여
마지막 execve_addr에 lib_addr + (int)execve_offset을 하여
execve()의 주소를 구한다.
그리고 memcpy()를 이용하여 ret에 argv[1][44]의 값을 넣고 execve()의 주소와 같은지 확인한다.
다를경우 예외처리가 되고 같을 경우 strcpy()를 통해 bof가 터진다.
따라서 익스를 하기 위해서는 execve()의 주소를 argv[1][44]에 넣어줘야한다.
execve()의 주소를 구하는 방법은 여러가지가 있는데 위의 소스코드에서 구하는 방법을 그대로 해봤다.
ldd 명령어와 nm 명령어로 libc의 base 주소와 execve()의 offset을 구할 수 있었다.
이제 이 주소를 가지고 argv[1][44]의 위치에 넣어보면
이와같이 정확한 execve()의 주소가 들어가서 Segmentation fault가 뜬것을 볼 수 있었다.
스택을 그려보면
| char buffer[40] | SFP | ret |
인데 현재 ret 주소에 execve()의 주소가 들어가있으니 execve()가 실행되었을것이다.
하지만 왜 segmentation fault라는 오류를 뿜고 죽는다.
인자를 제대로 넣어주지 않아서 인것같다.
execve()가 어떤 행위를 하는지 확인할 필요가 있다.
int execve (const char filename, char const argv [], char *const envp[]);
execve()는 다른 프로그램을 실행하고 자신은 종료한다.
이러한 점을 이용하여 execve()의 첫번째 인자에 system()의 주소를 넣고, argv[]에 system()에 인자로 넣어줄 /bin/sh의 주소를 넣는다면 쉘을 띄울 수 있을것이다.
복사한 바이너리를 tmp 디렉토리에 옮기고 gdb로 system()의 주소를 구하고
objdump -s 옵션을 주어 /bin/sh의 주소를 구하고
페이로드를 구성해보면
./giant "python -c 'print "A"*44+"execve()_addr"+"system()_addr"+"dummy(4byte)"+"/bin/sh"'"
이렇게 구성하면 될것이다.
간단하게 execve()를 이용하여 system()를 불러오고 system()에 /bin/sh을 인자로 넣어줘야되서 dummy값 4byte를 넣어주고 /bin/sh의 주소를 인자로 넘겨주면 execve()로 인해서 system()가 실행되고 system()의 ret부분에 4byte의 dummy값이 들어가고 /bin/sh이 실행될 것이다.
또한 페이로드에 \x0a가 들어가는데 이를 \x00으로 인식하는 버그가 있어서 문자열 처리를 한번 더 해줬다.
그대로 익스해보면
된다.
giant의 권한을 얻은 쉘을 딸 수 있다.
반응형'System hacking training > Hackerschool LOB' 카테고리의 다른 글
LEVEL 16 zombie_assassin write-up (0) 2018.05.13 LEVEL 15 assassin write-up (0) 2018.05.13 LEVEL 13 bugbear write-up (0) 2018.04.26 LEVEL 12 darkknight write-up (0) 2018.04.22 LEVEL 11 golem write-up (0) 2018.04.20