nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /*************************************************************************** |
2 | * * |
||
3 | * ########### ########### ########## ########## * |
||
4 | * ############ ############ ############ ############ * |
||
5 | * ## ## ## ## ## ## ## * |
||
6 | * ## ## ## ## ## ## ## * |
||
7 | * ########### #### ###### ## ## ## ## ###### * |
||
8 | * ########### #### # ## ## ## ## # # * |
||
9 | * ## ## ###### ## ## ## ## # # * |
||
10 | * ## ## # ## ## ## ## # # * |
||
11 | * ############ ##### ###### ## ## ## ##### ###### * |
||
12 | * ########### ########### ## ## ## ########## * |
||
13 | * * |
||
14 | * S E C U R E M O B I L E N E T W O R K I N G * |
||
15 | * * |
||
16 | * This file is part of NexMon. * |
||
17 | * * |
||
18 | * Based on: * |
||
19 | * * |
||
20 | * This code is based on the ldpreloadhook example by Pau Oliva Fora * |
||
21 | * <pofłeslack.org> and the idea of hooking ioctls to fake a monitor mode * |
||
22 | * interface, which was presented by Omri Ildis, Yuval Ofir and Ruby * |
||
23 | * Feinstein at recon2013. * |
||
24 | * * |
||
25 | * Copyright (c) 2016 NexMon Team * |
||
26 | * * |
||
27 | * NexMon is free software: you can redistribute it and/or modify * |
||
28 | * it under the terms of the GNU General Public License as published by * |
||
29 | * the Free Software Foundation, either version 3 of the License, or * |
||
30 | * (at your option) any later version. * |
||
31 | * * |
||
32 | * NexMon is distributed in the hope that it will be useful, * |
||
33 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
||
34 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
||
35 | * GNU General Public License for more details. * |
||
36 | * * |
||
37 | * You should have received a copy of the GNU General Public License * |
||
38 | * along with NexMon. If not, see <http://www.gnu.org/licenses/>. * |
||
39 | * * |
||
40 | **************************************************************************/ |
||
41 | |||
42 | #include <stdarg.h> |
||
43 | #include <dlfcn.h> |
||
44 | #include <stdio.h> |
||
45 | #include <stdlib.h> |
||
46 | #include <stdbool.h> |
||
47 | #include <sys/socket.h> |
||
48 | #include <linux/if_arp.h> |
||
49 | #include <linux/sockios.h> |
||
50 | #include <linux/wireless.h> |
||
51 | #include <monitormode.h> |
||
52 | #include <errno.h> |
||
53 | #include <net/if.h> |
||
54 | #include <nexioctls.h> |
||
55 | |||
56 | #define WLC_GET_MONITOR 107 |
||
57 | #define WLC_SET_MONITOR 108 |
||
58 | |||
59 | struct nexio { |
||
60 | struct ifreq *ifr; |
||
61 | int sock_rx_ioctl; |
||
62 | int sock_rx_frame; |
||
63 | int sock_tx; |
||
64 | }; |
||
65 | |||
66 | extern int nex_ioctl(struct nexio *nexio, int cmd, void *buf, int len, bool set); |
||
67 | extern struct nexio *nex_init_ioctl(const char *ifname); |
||
68 | |||
69 | #ifndef RTLD_NEXT |
||
70 | #define RTLD_NEXT ((void *) -1l) |
||
71 | #endif |
||
72 | |||
73 | #define REAL_LIBC RTLD_NEXT |
||
74 | |||
75 | typedef int request_t; |
||
76 | |||
77 | typedef void (*sighandler_t)(int); |
||
78 | |||
79 | static struct nexio *nexio = NULL; |
||
80 | |||
81 | static const char *ifname = "wlan0"; |
||
82 | |||
83 | static int (*func_sendto) (int, const void *, size_t, int, const struct sockaddr *, socklen_t) = NULL; |
||
84 | static int (*func_ioctl) (int, request_t, void *) = NULL; |
||
85 | static int (*func_socket) (int, int, int) = NULL; |
||
86 | static int (*func_bind) (int, const struct sockaddr *, int) = NULL; |
||
87 | static int (*func_write) (int, const void *, size_t) = NULL; |
||
88 | |||
89 | static void _libmexmon_init() __attribute__ ((constructor)); |
||
90 | static void _libmexmon_init() { |
||
91 | nexio = nex_init_ioctl(ifname); |
||
92 | |||
93 | if (! func_ioctl) |
||
94 | func_ioctl = (int (*) (int, request_t, void *)) dlsym (REAL_LIBC, "ioctl"); |
||
95 | |||
96 | if (! func_socket) |
||
97 | func_socket = (int (*) (int, int, int)) dlsym (REAL_LIBC, "socket"); |
||
98 | |||
99 | if (! func_bind) |
||
100 | func_bind = (int (*) (int, const struct sockaddr *, int)) dlsym (REAL_LIBC, "bind"); |
||
101 | |||
102 | if (! func_write) |
||
103 | func_write = (int (*) (int, const void *, size_t)) dlsym (REAL_LIBC, "write"); |
||
104 | |||
105 | if (! func_sendto) |
||
106 | func_sendto = (int (*) (int, const void *, size_t, int, const struct sockaddr *, socklen_t)) dlsym (REAL_LIBC, "sendto"); |
||
107 | } |
||
108 | |||
109 | int |
||
110 | ioctl(int fd, request_t request, ...) |
||
111 | { |
||
112 | va_list args; |
||
113 | void *argp; |
||
114 | int ret; |
||
115 | |||
116 | va_start (args, request); |
||
117 | argp = va_arg (args, void *); |
||
118 | va_end (args); |
||
119 | |||
120 | ret = func_ioctl(fd, request, argp); |
||
121 | //if (ret < 0) { |
||
122 | // printf("LIBNEXMON: original response: %d, request: 0x%x\n", ret, request); |
||
123 | //} |
||
124 | |||
125 | switch (request) { |
||
126 | case SIOCGIFHWADDR: |
||
127 | { |
||
128 | int buf; |
||
129 | struct ifreq* p_ifr = (struct ifreq *) argp; |
||
130 | if (!strncmp(p_ifr->ifr_ifrn.ifrn_name, ifname, strlen(ifname))) { |
||
131 | nex_ioctl(nexio, WLC_GET_MONITOR, &buf, 4, false); |
||
132 | |||
133 | if (buf & MONITOR_IEEE80211) p_ifr->ifr_hwaddr.sa_family = ARPHRD_IEEE80211; |
||
134 | else if (buf & MONITOR_RADIOTAP) p_ifr->ifr_hwaddr.sa_family = ARPHRD_IEEE80211_RADIOTAP; |
||
135 | else if (buf & MONITOR_DISABLED || buf & MONITOR_LOG_ONLY || buf & MONITOR_DROP_FRM || buf & MONITOR_IPV4_UDP) |
||
136 | p_ifr->ifr_hwaddr.sa_family = ARPHRD_ETHER; |
||
137 | |||
138 | ret = 0; |
||
139 | } |
||
140 | } |
||
141 | break; |
||
142 | |||
143 | case SIOCGIWMODE: |
||
144 | { |
||
145 | int buf; |
||
146 | struct iwreq* p_wrq = (struct iwreq*) argp; |
||
147 | |||
148 | if (!strncmp(p_wrq->ifr_ifrn.ifrn_name, ifname, strlen(ifname))) { |
||
149 | nex_ioctl(nexio, WLC_GET_MONITOR, &buf, 4, false); |
||
150 | |||
151 | if (buf & MONITOR_RADIOTAP || buf & MONITOR_IEEE80211 || buf & MONITOR_LOG_ONLY || buf & MONITOR_DROP_FRM || buf & MONITOR_IPV4_UDP) { |
||
152 | p_wrq->u.mode = IW_MODE_MONITOR; |
||
153 | } |
||
154 | |||
155 | ret = 0; |
||
156 | } |
||
157 | } |
||
158 | break; |
||
159 | |||
160 | case SIOCSIWMODE: |
||
161 | { |
||
162 | int buf; |
||
163 | struct iwreq* p_wrq = (struct iwreq*) argp; |
||
164 | |||
165 | if (!strncmp(p_wrq->ifr_ifrn.ifrn_name, ifname, strlen(ifname))) { |
||
166 | if (p_wrq->u.mode == IW_MODE_MONITOR) { |
||
167 | buf = MONITOR_RADIOTAP; |
||
168 | } else { |
||
169 | buf = MONITOR_DISABLED; |
||
170 | } |
||
171 | |||
172 | ret = nex_ioctl(nexio, WLC_SET_MONITOR, &buf, 4, true); |
||
173 | } |
||
174 | } |
||
175 | break; |
||
176 | |||
177 | case SIOCSIWFREQ: // set channel/frequency (Hz) |
||
178 | { |
||
179 | //if (ret < 0) |
||
180 | //printf("LIBNEXMON: SIOCSIWFREQ not implemented\n"); |
||
181 | } |
||
182 | break; |
||
183 | |||
184 | case SIOCGIWFREQ: // get channel/frequency (Hz) |
||
185 | { |
||
186 | //if (ret < 0) |
||
187 | //printf("LIBNEXMON: SIOCGIWFREQ not implemented\n"); |
||
188 | } |
||
189 | break; |
||
190 | } |
||
191 | return ret; |
||
192 | } |
||
193 | |||
194 | void |
||
195 | hexdump(const char *desc, const void *addr, int len) |
||
196 | { |
||
197 | int i; |
||
198 | unsigned char buff[17]; |
||
199 | unsigned char *pc = (unsigned char*)addr; |
||
200 | |||
201 | // Output description if given. |
||
202 | if (desc != 0) |
||
203 | printf ("%s:\n", desc); |
||
204 | |||
205 | // Process every byte in the data. |
||
206 | for (i = 0; i < len; i++) { |
||
207 | // Multiple of 16 means new line (with line offset). |
||
208 | |||
209 | if ((i % 16) == 0) { |
||
210 | // Just don't print ASCII for the zeroth line. |
||
211 | if (i != 0) |
||
212 | printf (" %s\n", buff); |
||
213 | |||
214 | // Output the offset. |
||
215 | printf (" %04x ", i); |
||
216 | } |
||
217 | |||
218 | // Now the hex code for the specific character. |
||
219 | printf (" %02x", pc[i]); |
||
220 | |||
221 | // And store a printable ASCII character for later. |
||
222 | if ((pc[i] < 0x20) || (pc[i] > 0x7e)) |
||
223 | buff[i % 16] = '.'; |
||
224 | else |
||
225 | buff[i % 16] = pc[i]; |
||
226 | buff[(i % 16) + 1] = '\0'; |
||
227 | } |
||
228 | |||
229 | // Pad out last line if not exactly 16 characters. |
||
230 | while ((i % 16) != 0) { |
||
231 | printf (" "); |
||
232 | i++; |
||
233 | } |
||
234 | |||
235 | // And print the final ASCII bit. |
||
236 | printf (" %s\n", buff); |
||
237 | } |
||
238 | |||
239 | static char sock_types[][16] = { |
||
240 | "SOCK_STREAM", |
||
241 | "SOCK_DGRAM", |
||
242 | "SOCK_RAW", |
||
243 | "SOCK_RDM", |
||
244 | "SOCK_SEQPACKET", |
||
245 | }; |
||
246 | |||
247 | static char domain_types[][16] = { |
||
248 | "AF_UNSPEC", |
||
249 | "AF_UNIX", |
||
250 | "AF_INET", |
||
251 | "AF_AX25", |
||
252 | "AF_IPX", |
||
253 | "AF_APPLETALK", |
||
254 | "AF_NETROM", |
||
255 | "AF_BRIDGE", |
||
256 | "AF_ATMPVC", |
||
257 | "AF_X25", |
||
258 | "AF_INET6", |
||
259 | "AF_ROSE", |
||
260 | "AF_DECnet", |
||
261 | "AF_NETBEUI", |
||
262 | "AF_SECURITY", |
||
263 | "AF_KEY", |
||
264 | "AF_NETLINK", |
||
265 | "AF_PACKET", |
||
266 | "AF_ASH", |
||
267 | "AF_ECONET", |
||
268 | "AF_ATMSVC", |
||
269 | "AF_RDS", |
||
270 | "AF_SNA", |
||
271 | "AF_IRDA", |
||
272 | "AF_PPPOX", |
||
273 | "AF_WANPIPE", |
||
274 | "AF_LLC", |
||
275 | "AF_IB", |
||
276 | "AF_MPLS", |
||
277 | "AF_CAN", |
||
278 | "AF_TIPC", |
||
279 | "AF_BLUETOOTH", |
||
280 | "AF_IUCV", |
||
281 | "AF_RXRPC", |
||
282 | "AF_ISDN", |
||
283 | "AF_PHONET", |
||
284 | "AF_IEEE802154", |
||
285 | "AF_CAIF", |
||
286 | "AF_ALG", |
||
287 | "AF_NFC", |
||
288 | "AF_VSOCK", |
||
289 | "AF_KCM", |
||
290 | "AF_QIPCRTR", |
||
291 | "AF_SMC" |
||
292 | }; |
||
293 | |||
294 | int socket_to_type[100] = { 0 }; |
||
295 | char bound_to_correct_if[100] = { 0 }; |
||
296 | |||
297 | int |
||
298 | socket(int domain, int type, int protocol) |
||
299 | { |
||
300 | int ret; |
||
301 | |||
302 | ret = func_socket(domain, type, protocol); |
||
303 | |||
304 | // save the socket type |
||
305 | if (ret < sizeof(socket_to_type)/sizeof(socket_to_type[0])) |
||
306 | socket_to_type[ret] = type; |
||
307 | |||
308 | //if ((type - 1 < sizeof(sock_types)/sizeof(sock_types[0])) && (domain - 1 < sizeof(domain_types)/sizeof(domain_types[0]))) |
||
309 | // printf("LIBNEXMON: %d = %s(%s(%d), %s(%d), %d)\n", ret, __FUNCTION__, domain_types[domain], domain, sock_types[type - 1], type, protocol); |
||
310 | |||
311 | return ret; |
||
312 | } |
||
313 | |||
314 | int |
||
315 | bind(int sockfd, const struct sockaddr *addr, int addrlen) |
||
316 | { |
||
317 | int ret; |
||
318 | struct sockaddr_ll *sll = (struct sockaddr_ll *) addr; |
||
319 | |||
320 | ret = func_bind(sockfd, addr, addrlen); |
||
321 | |||
322 | char sll_ifname[IF_NAMESIZE] = { 0 }; |
||
323 | if_indextoname(sll->sll_ifindex, sll_ifname); |
||
324 | |||
325 | if ((sockfd < sizeof(bound_to_correct_if)/sizeof(bound_to_correct_if[0])) && !strncmp(ifname, sll_ifname, sizeof(ifname))) |
||
326 | bound_to_correct_if[sockfd] = 1; |
||
327 | |||
328 | //printf("LIBNEXMON: %d = %s(%d, 0x%p, %d) sll_ifindex=%d ifname=%s\n", ret, __FUNCTION__, sockfd, addr, addrlen, sll->sll_ifindex, sll_ifname); |
||
329 | |||
330 | return ret; |
||
331 | } |
||
332 | |||
333 | struct inject_frame { |
||
334 | unsigned short len; |
||
335 | unsigned char pad; |
||
336 | unsigned char type; |
||
337 | char data[]; |
||
338 | }; |
||
339 | |||
340 | ssize_t |
||
341 | write(int fd, const void *buf, size_t count) |
||
342 | { |
||
343 | ssize_t ret; |
||
344 | |||
345 | // check if the user wants to write on a raw socket |
||
346 | if ((fd > 2) && (fd < sizeof(socket_to_type)/sizeof(socket_to_type[0])) && (socket_to_type[fd] == SOCK_RAW) && (bound_to_correct_if[fd] == 1)) { |
||
347 | struct inject_frame *buf_dup = (struct inject_frame *) malloc(count + sizeof(struct inject_frame)); |
||
348 | |||
349 | buf_dup->len = count + sizeof(struct inject_frame); |
||
350 | buf_dup->pad = 0; |
||
351 | buf_dup->type = 1; |
||
352 | memcpy(buf_dup->data, buf, count); |
||
353 | |||
354 | nex_ioctl(nexio, NEX_INJECT_FRAME, buf_dup, count + sizeof(struct inject_frame), true); |
||
355 | |||
356 | free(buf_dup); |
||
357 | |||
358 | ret = count; |
||
359 | } else { |
||
360 | // otherwise write the regular frame to the socket |
||
361 | ret = func_write(fd, buf, count); |
||
362 | } |
||
363 | |||
364 | return ret; |
||
365 | } |
||
366 | |||
367 | ssize_t |
||
368 | sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) |
||
369 | { |
||
370 | ssize_t ret; |
||
371 | |||
372 | // check if the user wants to write on a raw socket |
||
373 | if ((sockfd > 2) && (sockfd < sizeof(socket_to_type)/sizeof(socket_to_type[0])) && (socket_to_type[sockfd] == SOCK_RAW) && (bound_to_correct_if[sockfd] == 1)) { |
||
374 | struct inject_frame *buf_dup = (struct inject_frame *) malloc(len + sizeof(struct inject_frame)); |
||
375 | |||
376 | buf_dup->len = len + sizeof(struct inject_frame); |
||
377 | buf_dup->pad = 0; |
||
378 | buf_dup->type = 1; |
||
379 | memcpy(buf_dup->data, buf, len); |
||
380 | |||
381 | nex_ioctl(nexio, NEX_INJECT_FRAME, buf_dup, len + sizeof(struct inject_frame), true); |
||
382 | |||
383 | free(buf_dup); |
||
384 | |||
385 | ret = len; |
||
386 | } else { |
||
387 | // otherwise write the regular frame to the socket |
||
388 | ret = func_sendto(sockfd, buf, len, flags, dest_addr, addrlen); |
||
389 | } |
||
390 | |||
391 | return ret; |
||
392 | } |