1
2
3
4
5
6 import logging
7 import socket
8 import threading
9
10 from ctypes import create_string_buffer, c_uint, byref, sizeof
11
12 from lib.common.defines import KERNEL32, PIPE_ACCESS_INBOUND, ERROR_MORE_DATA
13 from lib.common.defines import PIPE_TYPE_BYTE, PIPE_WAIT, ERROR_PIPE_CONNECTED
14 from lib.common.defines import PIPE_UNLIMITED_INSTANCES, INVALID_HANDLE_VALUE
15 from lib.common.defines import FILE_FLAG_WRITE_THROUGH, PIPE_READMODE_BYTE
16 from lib.common.defines import ERROR_BROKEN_PIPE, PIPE_TYPE_MESSAGE
17 from lib.common.defines import PIPE_ACCESS_DUPLEX, PIPE_READMODE_MESSAGE
18
19 log = logging.getLogger(__name__)
20
21 BUFSIZE = 0x10000
22
24 """The Pipe Forwarder forwards all data received from a local pipe to
25 the Cuckoo server through a socket."""
26 sockets = {}
27 active = {}
28
29 - def __init__(self, pipe_handle, destination):
30 threading.Thread.__init__(self)
31 self.pipe_handle = pipe_handle
32 self.destination = destination
33
35 buf = create_string_buffer(BUFSIZE)
36 bytes_read = c_uint()
37 pid = c_uint()
38
39
40
41
42
43
44 success = KERNEL32.ReadFile(self.pipe_handle,
45 byref(pid), sizeof(pid),
46 byref(bytes_read), None)
47
48 if not success or bytes_read.value != sizeof(pid):
49 log.warning("Unable to read the process identifier of this "
50 "log pipe instance.")
51 KERNEL32.CloseHandle(self.pipe_handle)
52 return
53
54 if self.active.get(pid.value):
55 log.warning("A second log pipe handler for an active process is "
56 "being requested, denying request.")
57 KERNEL32.CloseHandle(self.pipe_handle)
58 return
59
60 if pid.value not in self.sockets:
61 self.sockets[pid.value] = \
62 socket.create_connection(self.destination)
63
64 sock = self.sockets[pid.value]
65 self.active[pid.value] = True
66
67 while True:
68 success = KERNEL32.ReadFile(self.pipe_handle,
69 byref(buf), sizeof(buf),
70 byref(bytes_read), None)
71
72 if success or KERNEL32.GetLastError() == ERROR_MORE_DATA:
73 sock.sendall(buf.raw[:bytes_read.value])
74
75
76
77
78
79 elif KERNEL32.GetLastError() == ERROR_BROKEN_PIPE:
80 break
81 else:
82 log.warning("The log pipe handler has failed, last error %d.",
83 KERNEL32.GetLastError())
84 break
85
86 self.active[pid.value] = False
87
89 """Receives commands through a local pipe, forwards them to the
90 dispatcher, and returns the response."""
91 - def __init__(self, pipe_handle, dispatcher):
92 threading.Thread.__init__(self)
93 self.pipe_handle = pipe_handle
94 self.dispatcher = dispatcher
95 self.do_run = True
96
98 """Reads a message."""
99 bytes_read = c_uint()
100 ret = ""
101
102 while True:
103 success = KERNEL32.ReadFile(self.pipe_handle,
104 byref(buf), sizeof(buf),
105 byref(bytes_read), None)
106
107 if KERNEL32.GetLastError() == ERROR_MORE_DATA:
108 ret += buf.raw[:bytes_read.value]
109 elif success:
110 return ret + buf.raw[:bytes_read.value]
111 else:
112 return
113
115 """Run the pipe dispatcher."""
116 buf = create_string_buffer(BUFSIZE)
117 bytes_written = c_uint()
118
119 while self.do_run:
120 message = self._read_message(buf)
121 if not message:
122 break
123
124 response = self.dispatcher.dispatch(message) or "OK"
125
126 KERNEL32.WriteFile(self.pipe_handle, response, len(response),
127 byref(bytes_written), None)
128
129 KERNEL32.CloseHandle(self.pipe_handle)
130
132 """The Pipe Server accepts incoming pipe handlers and initializes
133 them in a new thread."""
134 - def __init__(self, pipe_handler, pipe_name, message=False, **kwargs):
135 threading.Thread.__init__(self)
136 self.pipe_handler = pipe_handler
137 self.pipe_name = pipe_name
138 self.message = message
139 self.kwargs = kwargs
140 self.do_run = True
141
143 while self.do_run:
144 flags = FILE_FLAG_WRITE_THROUGH
145 if self.message:
146 pipe_handle = KERNEL32.CreateNamedPipeA(
147 self.pipe_name, PIPE_ACCESS_DUPLEX | flags,
148 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
149 PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, 0, None)
150 else:
151 pipe_handle = KERNEL32.CreateNamedPipeA(
152 self.pipe_name, PIPE_ACCESS_INBOUND | flags,
153 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
154 PIPE_UNLIMITED_INSTANCES, 0, BUFSIZE, 0, None)
155
156 if pipe_handle == INVALID_HANDLE_VALUE:
157 log.warning("Error opening logging pipe server.")
158 continue
159
160 if KERNEL32.ConnectNamedPipe(pipe_handle, None) or \
161 KERNEL32.GetLastError() == ERROR_PIPE_CONNECTED:
162 handler = self.pipe_handler(pipe_handle, **self.kwargs)
163 handler.daemon = True
164 handler.start()
165 else:
166 KERNEL32.CloseHandle(pipe_handle)
167
170