1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Windows Filtering Platform Callout Driver for Capturing IPsec Packets on Windows Vista / 7 / Server 2008
3 //
4 // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
5 //
6 // Copyright (c) Daiyuu Nobori.
7 // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
8 // Copyright (c) SoftEther Corporation.
9 // Copyright (c) all contributors on SoftEther VPN project in GitHub.
10 //
11 // All Rights Reserved.
12 //
13 // http://www.softether.org/
14 //
15 // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
16 // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
17 //
18 // License: The Apache License, Version 2.0
19 // https://www.apache.org/licenses/LICENSE-2.0
20 //
21 // DISCLAIMER
22 // ==========
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 // SOFTWARE.
31 //
32 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
33 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
34 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
35 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
36 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
37 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
38 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
39 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
40 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
41 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
42 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
43 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
44 // LAW OR COURT RULE.
45 //
46 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
47 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
48 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
49 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
50 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
51 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
52 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
53 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
54 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
55 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
56 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
57 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
58 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
59 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
60 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
61 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
62 // STATEMENT FOR WARNING AND DISCLAIMER.
63 //
64 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
65 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
66 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
67 //
68 //
69 // SOURCE CODE CONTRIBUTION
70 // ------------------------
71 //
72 // Your contribution to SoftEther VPN Project is much appreciated.
73 // Please send patches to us through GitHub.
74 // Read the SoftEther VPN Patch Acceptance Policy in advance:
75 // http://www.softether.org/5-download/src/9.patch
76 //
77 //
78 // DEAR SECURITY EXPERTS
79 // ---------------------
80 //
81 // If you find a bug or a security vulnerability please kindly inform us
82 // about the problem immediately so that we can fix the security problem
83 // to protect a lot of users around the world as soon as possible.
84 //
85 // Our e-mail address for security reports is:
86 // softether-vpn-security [at] softether.org
87 //
88 // Please note that the above e-mail address is not a technical support
89 // inquiry address. If you need technical assistance, please visit
90 // http://www.softether.org/ and ask your question on the users forum.
91 //
92 // Thank you for your cooperation.
93 //
94 //
95 // NO MEMORY OR RESOURCE LEAKS
96 // ---------------------------
97 //
98 // The memory-leaks and resource-leaks verification under the stress
99 // test has been passed before release this source code.
100
101
102 // Wfp.c
103 // WFP Callout Driver
104
105 #include <GlobalConst.h>
106
107 #define WFP_DEVICE_DRIVER
108
109 #include "WfpInner.h"
110 #include "Wfp.h"
111
112 static WFP_CTX *wfp = NULL;
113 static bool g_is_win8 = false;
114 static POOL_TYPE g_pool_type = NonPagedPool;
115
116 // Dispatch function
DriverDispatch(DEVICE_OBJECT * device_object,IRP * irp)117 NTSTATUS DriverDispatch(DEVICE_OBJECT *device_object, IRP *irp)
118 {
119 NTSTATUS ret = STATUS_SUCCESS;
120 IO_STACK_LOCATION *stack;
121 void *buf;
122 bool ok;
123 // Validate arguments
124 if (wfp == NULL || device_object == NULL || irp == NULL || wfp->Halting)
125 {
126 return NDIS_STATUS_FAILURE;
127 }
128
129 // Get the IRP stack
130 stack = IoGetCurrentIrpStackLocation(irp);
131
132 // Initialize the number of bytes
133 irp->IoStatus.Information = 0;
134 irp->IoStatus.Status = STATUS_SUCCESS;
135
136 buf = irp->UserBuffer;
137
138 if (wfp->Halting != FALSE)
139 {
140 // Device driver is terminating
141 irp->IoStatus.Information = STATUS_UNSUCCESSFUL;
142 IoCompleteRequest(irp, IO_NO_INCREMENT);
143 return STATUS_UNSUCCESSFUL;
144 }
145
146 ok = false;
147
148 // Branch to each operation
149 switch (stack->MajorFunction)
150 {
151 case IRP_MJ_CREATE: // Open
152 ok = true;
153 break;
154
155 case IRP_MJ_CLOSE: // Close
156 ok = true;
157 break;
158
159 case IRP_MJ_READ: // Read
160 ResetEvent(wfp->Event);
161 break;
162
163 case IRP_MJ_WRITE: // Write
164 if ((stack->Parameters.Write.Length % sizeof(WFP_LOCAL_IP)) == 0)
165 {
166 // Address check
167 bool check_ok = true;
168 __try
169 {
170 ProbeForRead(buf, stack->Parameters.Write.Length, 1);
171 }
172 __except (EXCEPTION_EXECUTE_HANDLER)
173 {
174 check_ok = false;
175 }
176
177 if (check_ok)
178 {
179 MDL *mdl = IoAllocateMdl(buf, stack->Parameters.Write.Length, false, false, NULL);
180 UINT size = MIN(WFP_MAX_LOCAL_IP_COUNT * sizeof(WFP_LOCAL_IP), stack->Parameters.Write.Length);
181 UCHAR *copied_buf = Malloc(size);
182 UCHAR *old_buf;
183
184 if (mdl != NULL)
185 {
186 MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
187 }
188
189 Copy(copied_buf, buf, size);
190
191 SpinLock(wfp->LocalIPListLock);
192 {
193 old_buf = wfp->LocalIPListData;
194 wfp->LocalIPListData = copied_buf;
195 wfp->LocalIPListSize = size;
196 }
197 SpinUnlock(wfp->LocalIPListLock);
198
199 if (old_buf != NULL)
200 {
201 Free(old_buf);
202 }
203
204 if (mdl != NULL)
205 {
206 MmUnlockPages(mdl);
207 IoFreeMdl(mdl);
208 }
209 }
210 }
211 irp->IoStatus.Information = stack->Parameters.Write.Length;
212 ok = true;
213 break;
214 }
215
216 if (ok == false)
217 {
218 irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
219 ret = STATUS_UNSUCCESSFUL;
220 }
221
222 IoCompleteRequest(irp, IO_NO_INCREMENT);
223
224 return ret;
225 }
226
227 // Function to finish the insertion of the packet
CalloutInjectionCompleted(void * context,NET_BUFFER_LIST * net_buffer_list,BOOLEAN dispatch_level)228 void NTAPI CalloutInjectionCompleted(void *context, NET_BUFFER_LIST *net_buffer_list, BOOLEAN dispatch_level)
229 {
230 WFP_INJECTED_PACKET_CONTEXT *ctx = (WFP_INJECTED_PACKET_CONTEXT *)context;
231
232 if (ctx == NULL)
233 {
234 return;
235 }
236
237 FreeInjectionCtx(ctx);
238 }
239
240 // Release the injection data
FreeInjectionCtx(WFP_INJECTED_PACKET_CONTEXT * ctx)241 void FreeInjectionCtx(WFP_INJECTED_PACKET_CONTEXT *ctx)
242 {
243 // Validate arguments
244 if (ctx == NULL)
245 {
246 return;
247 }
248
249 if (ctx->CurrentNetBuffer != NULL)
250 {
251 Copy(ctx->CurrentNetBuffer, &ctx->OriginalNetBufferData, sizeof(NET_BUFFER));
252 }
253
254 if (ctx->AllocatedNetBufferList != NULL)
255 {
256 FwpsFreeCloneNetBufferList0(ctx->AllocatedNetBufferList, 0);
257 }
258
259 if (ctx->AllocatedMdl != NULL)
260 {
261 NdisFreeMdl(ctx->AllocatedMdl);
262 }
263
264 if (ctx->AllocatedMemory != NULL)
265 {
266 Free(ctx->AllocatedMemory);
267 }
268
269 Free(ctx);
270 }
271
272 // Calculate the checksum
IpChecksum(void * buf,UINT size)273 USHORT IpChecksum(void *buf, UINT size)
274 {
275 int sum = 0;
276 USHORT *addr = (USHORT *)buf;
277 int len = (int)size;
278 USHORT *w = addr;
279 int nleft = len;
280 USHORT answer = 0;
281
282 while (nleft > 1)
283 {
284 sum += *w++;
285 nleft -= 2;
286 }
287
288 if (nleft == 1)
289 {
290 *(UCHAR *)(&answer) = *(UCHAR *)w;
291 sum += answer;
292 }
293
294 sum = (sum >> 16) + (sum & 0xffff);
295 sum += (sum >> 16);
296
297 answer = ~sum;
298
299 return answer;
300 }
301
302 // Modify the IPsec ESP packet
ModificationOfIPsecESPPacket(UCHAR * ip_packet,UINT ip_packet_size,UINT ip_header_size,UINT * dst_size_ptr,bool isv6)303 UCHAR *ModificationOfIPsecESPPacket(UCHAR *ip_packet, UINT ip_packet_size, UINT ip_header_size, UINT *dst_size_ptr, bool isv6)
304 {
305 UINT ip_and_udp_header_size = ip_header_size + sizeof(WFP_UDP_HEADER);
306 UINT udp_packet_size;
307 UINT udp_payload_size;
308 UINT dst_udp_payload_size;
309 WFP_UDP_HEADER *src_udp;
310 WFP_UDP_HEADER *dst_udp;
311 UCHAR *src_udp_payload;
312 UCHAR *dst_data;
313 UINT dst_size;
314 // Validate arguments
315 if (ip_packet == NULL || ip_packet == 0 || ip_header_size == 0 || dst_size_ptr == NULL)
316 {
317 return NULL;
318 }
319
320 if (ip_packet_size <= ip_and_udp_header_size)
321 {
322 // There is no UDP header
323 return NULL;
324 }
325
326 // Get the UDP header
327 src_udp = (WFP_UDP_HEADER *)(ip_packet + ip_header_size);
328 udp_packet_size = Endian16(src_udp->PacketLength);
329 if (udp_packet_size < sizeof(WFP_UDP_HEADER))
330 {
331 // There is no UDP payload
332 return NULL;
333 }
334
335 // Get the UDP payload size
336 udp_payload_size = udp_packet_size - sizeof(WFP_UDP_HEADER);
337
338 if (ip_packet_size < (ip_and_udp_header_size + udp_payload_size))
339 {
340 // There is no UDP payload
341 return NULL;
342 }
343
344 // Get the UDP payload
345 src_udp_payload = ip_packet + ip_and_udp_header_size;
346
347 if (udp_payload_size < sizeof(UINT))
348 {
349 // The size of the UDP payload is less than 5 bytes
350 return NULL;
351 }
352
353 dst_udp_payload_size = udp_payload_size + sizeof(UINT) * 3;
354 if ((dst_udp_payload_size + sizeof(WFP_UDP_HEADER)) > 0xffff)
355 {
356 // UDP payload size overflows the 16bit
357 return NULL;
358 }
359
360 // Build a new packet
361 dst_size = ip_and_udp_header_size + sizeof(UINT) * 3 + udp_payload_size;
362 if (dst_size > 0xffff)
363 {
364 // IP total size overflows the 16bit
365 return NULL;
366 }
367
368 dst_data = Malloc(dst_size);
369 if (dst_data == NULL)
370 {
371 // Memory allocation failure
372 return NULL;
373 }
374
375 // Copy the IP header + UDP header
376 Copy(dst_data, ip_packet, ip_and_udp_header_size);
377
378 // Copy the original payload
379 Copy(dst_data + ip_and_udp_header_size + sizeof(UINT) * 3, src_udp_payload, udp_payload_size);
380
381 // Insert a tag
382 *((UINT *)(dst_data + ip_and_udp_header_size + sizeof(UINT) * 0)) = 0;
383 *((UINT *)(dst_data + ip_and_udp_header_size + sizeof(UINT) * 1)) = WFP_ESP_PACKET_TAG_1;
384 *((UINT *)(dst_data + ip_and_udp_header_size + sizeof(UINT) * 2)) = WFP_ESP_PACKET_TAG_2;
385
386 // Adjust the new IP header
387 if (isv6 == false)
388 {
389 WFP_IPV4_HEADER *ip = (WFP_IPV4_HEADER *)dst_data;
390
391 ip->TotalLength = Endian16(dst_size);
392 ip->Checksum = 0;
393 ip->Checksum = IpChecksum(ip, ip_header_size);
394 }
395 else
396 {
397 WFP_IPV6_HEADER *ip = (WFP_IPV6_HEADER *)dst_data;
398
399 ip->PayloadLength = Endian16(dst_size);
400 }
401
402 // Adjust the new UDP header
403 dst_udp = (WFP_UDP_HEADER *)(dst_data + ip_header_size);
404 dst_udp->Checksum = 0;
405 dst_udp->PacketLength = Endian16((USHORT)(dst_udp_payload_size + sizeof(WFP_UDP_HEADER)));
406
407 *dst_size_ptr = dst_size;
408 return dst_data;
409 }
410
411 // Insert the packet into the stack
InjectPacket(HANDLE hInjection,NET_BUFFER_LIST * nbl,UCHAR * dst_data,UINT dst_size,const FWPS_INCOMING_VALUES0 * inFixedValues,const FWPS_INCOMING_METADATA_VALUES0 * inMetaValues)412 bool InjectPacket(HANDLE hInjection, NET_BUFFER_LIST *nbl, UCHAR *dst_data, UINT dst_size, const FWPS_INCOMING_VALUES0* inFixedValues, const FWPS_INCOMING_METADATA_VALUES0* inMetaValues)
413 {
414 WFP_INJECTED_PACKET_CONTEXT *ctx;
415 bool block = false;
416 // Validate arguments
417 if (hInjection == NULL || nbl == NULL || dst_data == NULL || dst_size == 0 || inMetaValues == NULL || inFixedValues == NULL)
418 {
419 return false;
420 }
421
422 ctx = ZeroMalloc(sizeof(WFP_INJECTED_PACKET_CONTEXT));
423
424 if (ctx != NULL)
425 {
426 // Generate a modified packet
427 ctx->AllocatedMemory = dst_data;
428
429 if (dst_data != NULL)
430 {
431 NET_BUFFER_LIST *net_buffer_list;
432 NTSTATUS ret;
433
434 // Clone the original NET_BUFFER_LIST
435 ret = FwpsAllocateCloneNetBufferList0(nbl, NULL, NULL, 0, &net_buffer_list);
436
437 if (OK(ret) && net_buffer_list != NULL)
438 {
439 NET_BUFFER *net_buffer = NET_BUFFER_LIST_FIRST_NB(net_buffer_list);
440
441 ctx->AllocatedNetBufferList = net_buffer_list;
442 ctx->CurrentNetBuffer = net_buffer;
443
444 if (net_buffer != NULL)
445 {
446 MDL *mdl = NdisAllocateMdl(wfp->hNdis, dst_data, dst_size);
447 if (mdl != NULL)
448 {
449 NTSTATUS ret;
450
451 ctx->AllocatedMdl = mdl;
452
453 Copy(&ctx->OriginalNetBufferData, net_buffer, sizeof(NET_BUFFER));
454
455 NET_BUFFER_FIRST_MDL(net_buffer) = mdl;
456 NET_BUFFER_DATA_LENGTH(net_buffer) = dst_size;
457 NET_BUFFER_DATA_OFFSET(net_buffer) = 0;
458 NET_BUFFER_CURRENT_MDL(net_buffer) = mdl;
459 NET_BUFFER_CURRENT_MDL_OFFSET(net_buffer) = 0;
460
461 // Insert packets of receiving direction
462 ret = FwpsInjectNetworkReceiveAsync0(hInjection, NULL,
463 0,
464 (inMetaValues->currentMetadataValues & FWPS_METADATA_FIELD_COMPARTMENT_ID ? inMetaValues->compartmentId : UNSPECIFIED_COMPARTMENT_ID),
465 inFixedValues->incomingValue[FWPS_FIELD_INBOUND_IPPACKET_V4_INTERFACE_INDEX].value.uint32,
466 inFixedValues->incomingValue[FWPS_FIELD_INBOUND_IPPACKET_V4_SUB_INTERFACE_INDEX].value.uint32,
467 net_buffer_list,
468 CalloutInjectionCompleted,
469 (HANDLE)ctx);
470
471 if (NG(ret))
472 {
473 //CRUSH_WHERE;
474 }
475 else
476 {
477 block = true;
478 }
479 }
480 else
481 {
482 //CRUSH_WHERE;
483 }
484 }
485 else
486 {
487 //CRUSH_WHERE;
488 }
489 }
490 else
491 {
492 //CRUSH_WHERE;
493 }
494 }
495 else
496 {
497 //CRUSH_WHERE;
498 }
499
500 if (block == false)
501 {
502 FreeInjectionCtx(ctx);
503 }
504 }
505
506 return block;
507 }
508
509 // Function to be notified of arriving packet
CalloutClassify(const FWPS_INCOMING_VALUES0 * inFixedValues,const FWPS_INCOMING_METADATA_VALUES0 * inMetaValues,void * layerData,const FWPS_FILTER0 * filter,UINT64 flowContext,FWPS_CLASSIFY_OUT0 * classifyOut)510 void NTAPI CalloutClassify(const FWPS_INCOMING_VALUES0* inFixedValues,
511 const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
512 void* layerData,
513 const FWPS_FILTER0* filter,
514 UINT64 flowContext,
515 FWPS_CLASSIFY_OUT0* classifyOut)
516 {
517 NET_BUFFER_LIST *nbl = layerData;
518 FWPS_PACKET_INJECTION_STATE injecton_state;
519 bool block = false;
520 HANDLE hInjection = NULL;
521 UINT ip_header_len = 0;
522 bool isv6 = false;
523
524 if (wfp->Halting || nbl == NULL)
525 {
526 classifyOut->actionType = FWP_ACTION_CONTINUE;
527 return;
528 }
529
530 switch (inFixedValues->layerId)
531 {
532 case FWPS_LAYER_INBOUND_IPPACKET_V4:
533 hInjection = wfp->hInjectionIPv4;
534 ip_header_len = sizeof(WFP_IPV4_HEADER);
535 break;
536
537 case FWPS_LAYER_INBOUND_IPPACKET_V6:
538 hInjection = wfp->hInjectionIPv6;
539 ip_header_len = sizeof(WFP_IPV6_HEADER);
540 isv6 = true;
541 break;
542 }
543
544 if (hInjection != NULL)
545 {
546 injecton_state = FwpsQueryPacketInjectionState0(hInjection, nbl, NULL);
547
548 if (injecton_state == FWPS_PACKET_INJECTED_BY_SELF || injecton_state == FWPS_PACKET_PREVIOUSLY_INJECTED_BY_SELF)
549 {
550 //SetEvent(wfp->Event);
551 classifyOut->actionType = FWP_ACTION_CONTINUE; // continue
552 return;
553 }
554
555 if (nbl != NULL && NET_BUFFER_LIST_NEXT_NBL(nbl) == NULL)
556 {
557 NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
558
559 if (nb != NULL && NET_BUFFER_NEXT_NB(nb) == NULL && (NET_BUFFER_DATA_OFFSET(nb) >= inMetaValues->ipHeaderSize))
560 {
561 if (OK(NdisRetreatNetBufferDataStart(nb, inMetaValues->ipHeaderSize, 0, NULL)))
562 {
563 WFP_IPV4_HEADER *ipv4;
564 WFP_IPV6_HEADER *ipv6;
565 UCHAR *alloc_buf = Malloc(ip_header_len);
566
567 ipv4 = NdisGetDataBuffer(nb, ip_header_len, alloc_buf, 1, 0);
568 ipv6 = (WFP_IPV6_HEADER *)ipv4;
569
570 if (ipv4 != NULL)
571 {
572 if ((isv6 == false && ipv4->Protocol == WFP_ESP_RAW_PROTOCOL_ID))
573 {
574 if (IsIPv4AddressInList(&ipv4->DstIP))
575 {
576 UINT src_size = NET_BUFFER_DATA_LENGTH(nb);
577 UCHAR *src_data = Malloc(src_size);
578
579 if (src_data != NULL)
580 {
581 UCHAR *src_ptr = NdisGetDataBuffer(nb, src_size, src_data, 1, 0);
582
583 if (src_ptr != NULL)
584 {
585 UINT dst_size = src_size;
586 UCHAR *dst_data = Malloc(dst_size);
587
588 if (dst_data != NULL)
589 {
590 WFP_IPV4_HEADER *ipv4;
591
592 Copy(dst_data, src_ptr, dst_size);
593 ipv4 = (WFP_IPV4_HEADER *)dst_data;
594
595 ipv4->Protocol = WFP_ESP_RAW_PROTOCOL_ID_DST;
596 ipv4->Checksum = 0;
597 ipv4->Checksum = IpChecksum(ipv4, inMetaValues->ipHeaderSize);
598
599 block = InjectPacket(hInjection, nbl, dst_data, dst_size, inFixedValues, inMetaValues);
600 }
601 }
602
603 Free(src_data);
604 }
605 }
606 }
607 else if ((isv6 && ipv6->NextHeader == WFP_ESP_RAW_PROTOCOL_ID))
608 {
609 if (IsIPv6AddressInList(&ipv6->DestAddress))
610 {
611 UINT src_size = NET_BUFFER_DATA_LENGTH(nb);
612 UCHAR *src_data = Malloc(src_size);
613
614 if (src_data != NULL)
615 {
616 UCHAR *src_ptr = NdisGetDataBuffer(nb, src_size, src_data, 1, 0);
617
618 if (src_ptr != NULL)
619 {
620 UINT dst_size = src_size;
621 UCHAR *dst_data = Malloc(dst_size);
622
623 if (dst_data != NULL)
624 {
625 WFP_IPV6_HEADER *ipv6;
626
627 Copy(dst_data, src_ptr, dst_size);
628 ipv6 = (WFP_IPV6_HEADER *)dst_data;
629
630 ipv6->NextHeader = WFP_ESP_RAW_PROTOCOL_ID_DST;
631
632 block = InjectPacket(hInjection, nbl, dst_data, dst_size, inFixedValues, inMetaValues);
633 }
634 }
635
636 Free(src_data);
637 }
638 }
639 }
640
641 if ((isv6 == false && ipv4->Protocol == WFP_IP_PROTO_UDP) ||
642 (isv6 && ipv6->NextHeader == WFP_IP_PROTO_UDP))
643 {
644 UINT ip_and_udp_header_len = inMetaValues->ipHeaderSize + sizeof(WFP_UDP_HEADER);
645 UCHAR *ptr;
646 UCHAR *alloc_buf = Malloc(ip_and_udp_header_len);
647
648 ptr = NdisGetDataBuffer(nb, ip_and_udp_header_len, alloc_buf, 1, 0);
649 if (ptr != NULL)
650 {
651 WFP_UDP_HEADER *udp = (WFP_UDP_HEADER *)(ptr + inMetaValues->ipHeaderSize);
652
653 if (Endian16(udp->DstPort) == 4500)
654 {
655 if ((isv6 == false && IsIPv4AddressInList(&ipv4->DstIP)) ||
656 (isv6 && IsIPv6AddressInList(&ipv6->DestAddress)))
657 {
658 UINT packet_size = NET_BUFFER_DATA_LENGTH(nb);
659 UCHAR *packet_buf_allocated = Malloc(packet_size);
660 UCHAR *packet_data = NdisGetDataBuffer(nb, packet_size, packet_buf_allocated, 1, 0);
661
662 if (packet_data != NULL)
663 {
664 UCHAR *udp_payload = packet_data + ip_and_udp_header_len;
665 UINT udp_payload_size = packet_size - ip_and_udp_header_len;
666
667 if (udp_payload_size >= 4)
668 {
669 UINT *i = (UINT *)udp_payload;
670 if (*i != 0)
671 {
672 // Generate a modified packet
673 UINT dst_size;
674 UCHAR *dst_data = ModificationOfIPsecESPPacket(packet_data, packet_size,
675 inMetaValues->ipHeaderSize, &dst_size, isv6);
676
677 block = InjectPacket(hInjection, nbl, dst_data, dst_size, inFixedValues, inMetaValues);
678 }
679 }
680 }
681 else
682 {
683 //CRUSH_WHERE;
684 }
685
686 Free(packet_buf_allocated);
687 }
688 }
689 }
690 else
691 {
692 //CRUSH_WHERE;
693 }
694
695 Free(alloc_buf);
696 }
697 }
698
699 Free(alloc_buf);
700
701 NdisAdvanceNetBufferDataStart(nb, inMetaValues->ipHeaderSize, false, NULL);
702 }
703 else
704 {
705 //CRUSH_WHERE;
706 }
707
708 nb = NET_BUFFER_NEXT_NB(nb);
709 }
710
711 nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
712 }
713 }
714
715 classifyOut->actionType = FWP_ACTION_CONTINUE;
716
717 if (block)
718 {
719 // Block the packet
720 classifyOut->actionType = FWP_ACTION_BLOCK;
721 classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
722 classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
723 //SetEvent(wfp->Event);
724 }
725 }
726
727 // Function to receive notification from the WFP
CalloutNotify(FWPS_CALLOUT_NOTIFY_TYPE notifyType,const GUID * filterKey,FWPS_FILTER0 * filter)728 NTSTATUS NTAPI CalloutNotify(FWPS_CALLOUT_NOTIFY_TYPE notifyType,
729 const GUID* filterKey, FWPS_FILTER0* filter)
730 {
731 //Crush(1,0,0,0);
732 return 0;
733 }
734
735 // Scan whether the specified IP address is in the local IP address list
IsIPAddressInList(struct WFP_LOCAL_IP * ip)736 bool IsIPAddressInList(struct WFP_LOCAL_IP *ip)
737 {
738 bool ret = false;
739 // Validate arguments
740 if (ip == NULL)
741 {
742 return false;
743 }
744
745 SpinLock(wfp->LocalIPListLock);
746 {
747 if (wfp->LocalIPListData != NULL)
748 {
749 UINT num = wfp->LocalIPListSize / sizeof(WFP_LOCAL_IP);
750 WFP_LOCAL_IP *o = (WFP_LOCAL_IP *)wfp->LocalIPListData;
751 UINT i;
752
753 for (i = 0;i < num;i++)
754 {
755 if (Cmp(&o[i], ip, sizeof(WFP_LOCAL_IP)) == 0)
756 {
757 ret = true;
758 break;
759 }
760 }
761 }
762 }
763 SpinUnlock(wfp->LocalIPListLock);
764
765 return ret;
766 }
IsIPv4AddressInList(void * addr)767 bool IsIPv4AddressInList(void *addr)
768 {
769 WFP_LOCAL_IP ip;
770 // Validate arguments
771 if (addr == NULL)
772 {
773 return false;
774 }
775
776 Zero(&ip, sizeof(ip));
777 ip.IpVersion = 4;
778 Copy(ip.IpAddress.IPv4Address, addr, 4);
779
780 return IsIPAddressInList(&ip);
781 }
IsIPv6AddressInList(void * addr)782 bool IsIPv6AddressInList(void *addr)
783 {
784 WFP_LOCAL_IP ip;
785 // Validate arguments
786 if (addr == NULL)
787 {
788 return false;
789 }
790
791 Zero(&ip, sizeof(ip));
792 ip.IpVersion = 6;
793 Copy(ip.IpAddress.IPv6Address, addr, 16);
794
795 return IsIPAddressInList(&ip);
796 }
797
798 // Win32 driver entry point
DriverEntry(DRIVER_OBJECT * driver_object,UNICODE_STRING * registry_path)799 NTSTATUS DriverEntry(DRIVER_OBJECT *driver_object, UNICODE_STRING *registry_path)
800 {
801 NTSTATUS ret;
802 FWPM_SESSION0 t;
803 ULONG os_ver1 = 0, os_ver2 = 0;
804
805 if (wfp != NULL)
806 {
807 return STATUS_UNSUCCESSFUL;
808 }
809
810 g_is_win8 = false;
811 g_pool_type = NonPagedPool;
812
813 PsGetVersion(&os_ver1, &os_ver2, NULL, NULL);
814
815 if ((os_ver1 == 6 && os_ver2 >= 2) || (os_ver1 >= 7))
816 {
817 g_is_win8 = true;
818 g_pool_type = 512;
819 }
820
821 wfp = ZeroMalloc(sizeof(WFP_CTX));
822
823 RtlInitUnicodeString(&wfp->DeviceName, WFP_DEVICE_NAME);
824 RtlInitUnicodeString(&wfp->DeviceNameWin32, WFP_DEVICE_NAME_WIN32);
825 // Create a device
826 ret = IoCreateDevice(driver_object, 0, &wfp->DeviceName, FILE_DEVICE_NETWORK, 0, false, &wfp->DeviceObject);
827 if (NG(ret))
828 {
829 return ret;
830 }
831
832 // Open the NDIS handle
833 wfp->hNdis = NdisAllocateGenericObject(driver_object, MEMPOOL_TAG, 0);
834 if (wfp->hNdis == NULL)
835 {
836 DriverUnload(driver_object);
837 return STATUS_UNSUCCESSFUL;
838 }
839
840 // Create a symbolic device for Win32
841 ret = IoCreateSymbolicLink(&wfp->DeviceNameWin32, &wfp->DeviceName);
842 if (NG(ret))
843 {
844 DriverUnload(driver_object);
845 return ret;
846 }
847
848 driver_object->DriverUnload = DriverUnload;
849
850 // Create an Event
851 wfp->Event = NewEvent(WFP_EVENT_NAME);
852 if (wfp->Event == NULL)
853 {
854 DriverUnload(driver_object);
855 return STATUS_UNSUCCESSFUL;
856 }
857
858 // Open the WFP engine
859 Zero(&t, sizeof(t));
860 t.flags = FWPM_SESSION_FLAG_DYNAMIC;
861 ret = FwpmEngineOpen0(NULL, RPC_C_AUTHN_DEFAULT, NULL, &t, &wfp->hEngine);
862 if (NG(ret))
863 {
864 DriverUnload(driver_object);
865 return ret;
866 }
867 else
868 {
869 // Register itself as a Callout Driver
870 FWPS_CALLOUT0 s;
871 // FWPM_CALLOUT0 callout;
872
873 Zero(&s, sizeof(s));
874 s.calloutKey = GUID_WFP_CALLOUT_DRIVER_V4;
875 s.classifyFn = CalloutClassify;
876 s.notifyFn = CalloutNotify;
877
878 ret = FwpsCalloutRegister0(wfp->DeviceObject, &s, &wfp->CalloutIdIPv4);
879 if (NG(ret))
880 {
881 DriverUnload(driver_object);
882 return ret;
883 }
884
885 Zero(&s, sizeof(s));
886 s.calloutKey = GUID_WFP_CALLOUT_DRIVER_V6;
887 s.classifyFn = CalloutClassify;
888 s.notifyFn = CalloutNotify;
889
890 ret = FwpsCalloutRegister0(wfp->DeviceObject, &s, &wfp->CalloutIdIPv6);
891 if (NG(ret))
892 {
893 DriverUnload(driver_object);
894 return ret;
895 }
896
897 /*// Create the Callout Driver (IPv4)
898 Zero(&callout, sizeof(callout));
899 callout.calloutKey = GUID_WFP_CALLOUT_DRIVER_V4;
900 callout.applicableLayer = FWPM_LAYER_INBOUND_IPPACKET_V4;
901 callout.displayData.name = WFP_DRIVER_TITLE_V4;
902 ret = FwpmCalloutAdd0(wfp->hEngine, &callout, NULL, &wfp->CalloutObjIdIPv4);
903
904 // Create the Callout Driver (IPv6)
905 Zero(&callout, sizeof(callout));
906 callout.calloutKey = GUID_WFP_CALLOUT_DRIVER_V6;
907 callout.applicableLayer = FWPM_LAYER_INBOUND_IPPACKET_V6;
908 callout.displayData.name = WFP_DRIVER_TITLE_V6;
909 ret = FwpmCalloutAdd0(wfp->hEngine, &callout, NULL, &wfp->CalloutObjIdIPv6);*/
910
911 // Create an injection handle
912 FwpsInjectionHandleCreate0(AF_INET, FWPS_INJECTION_TYPE_NETWORK, &wfp->hInjectionIPv4);
913 if (NG(ret))
914 {
915 wfp->hInjectionIPv4 = NULL;
916 }
917 ret = FwpsInjectionHandleCreate0(AF_INET6, FWPS_INJECTION_TYPE_NETWORK,&wfp->hInjectionIPv6);
918 if (NG(ret))
919 {
920 wfp->hInjectionIPv6 = NULL;
921 }
922 }
923
924 // Create a lock
925 wfp->LocalIPListLock = NewSpinLock();
926
927 // Specify a service function
928 driver_object->MajorFunction[IRP_MJ_CREATE] =
929 driver_object->MajorFunction[IRP_MJ_CLOSE] =
930 driver_object->MajorFunction[IRP_MJ_READ] =
931 driver_object->MajorFunction[IRP_MJ_WRITE] = DriverDispatch;
932
933 return STATUS_SUCCESS;
934 }
935
936 // Unload the driver
DriverUnload(DRIVER_OBJECT * driver_object)937 void DriverUnload(DRIVER_OBJECT *driver_object)
938 {
939 // Validate arguments
940 if (wfp == NULL || driver_object == NULL)
941 {
942 return;
943 }
944
945 wfp->Halting = true;
946
947 // Delete the lock
948 FreeSpinLock(wfp->LocalIPListLock);
949
950 // Delete the injection handle
951 if (wfp->hInjectionIPv4 != NULL)
952 {
953 FwpsInjectionHandleDestroy0(wfp->hInjectionIPv4);
954 }
955 if (wfp->hInjectionIPv6 != NULL)
956 {
957 FwpsInjectionHandleDestroy0(wfp->hInjectionIPv6);
958 }
959
960 // Delete the Callout Object
961 if (wfp->hEngine != NULL)
962 {
963 //FwpmCalloutDeleteByKey0(wfp->hEngine, &GUID_WFP_CALLOUT_DRIVER_V4);
964 //FwpmCalloutDeleteByKey0(wfp->hEngine, &GUID_WFP_CALLOUT_DRIVER_V6);
965 }
966
967 if (wfp->CalloutIdIPv4 != 0)
968 {
969 // Delete the registration of Callout Driver (IPv4)
970 FwpsCalloutUnregisterById0(wfp->CalloutIdIPv4);
971 }
972
973 if (wfp->CalloutIdIPv6 != 0)
974 {
975 // Delete the registration of Callout Driver (IPv6)
976 FwpsCalloutUnregisterById0(wfp->CalloutIdIPv6);
977 }
978
979 FreeEvent(wfp->Event);
980
981 IoDeleteSymbolicLink(&wfp->DeviceNameWin32);
982
983 if (wfp->DeviceObject != NULL)
984 {
985 IoDeleteDevice(wfp->DeviceObject);
986 }
987
988 if (wfp->hEngine != NULL)
989 {
990 FwpmEngineClose0(wfp->hEngine);
991 }
992
993 if (wfp->LocalIPListData != NULL)
994 {
995 Free(wfp->LocalIPListData);
996 }
997
998 // Close the NDIS handle
999 if (wfp->hNdis != NULL)
1000 {
1001 NdisFreeGenericObject(wfp->hNdis);
1002 }
1003
1004 Free(wfp);
1005
1006 wfp = NULL;
1007 }
1008
1009 // Create an Event
NewEvent(wchar_t * name)1010 EVENT *NewEvent(wchar_t *name)
1011 {
1012 EVENT *e;
1013 KEVENT *ke;
1014 HANDLE h;
1015 UNICODE_STRING name_str;
1016 // Validate arguments
1017 if (name == NULL)
1018 {
1019 return NULL;
1020 }
1021
1022 RtlInitUnicodeString(&name_str, name);
1023
1024 ke = IoCreateNotificationEvent(&name_str, &h);
1025 if (ke == NULL)
1026 {
1027 return NULL;
1028 }
1029
1030 KeInitializeEvent(ke, NotificationEvent, false);
1031 KeClearEvent(ke);
1032
1033 e = ZeroMalloc(sizeof(EVENT));
1034
1035 e->EventObj = ke;
1036 e->Handle = h;
1037
1038 return e;
1039 }
1040
1041 // Delete the event
FreeEvent(EVENT * e)1042 void FreeEvent(EVENT *e)
1043 {
1044 // Validate arguments
1045 if (e == NULL)
1046 {
1047 return;
1048 }
1049
1050 ZwClose(e->Handle);
1051
1052 Free(e);
1053 }
1054
1055 // Set the event
SetEvent(EVENT * e)1056 void SetEvent(EVENT *e)
1057 {
1058 // Validate arguments
1059 if (e == NULL)
1060 {
1061 return;
1062 }
1063
1064 KeSetEvent(e->EventObj, 0, false);
1065 }
1066
1067 // Reset the event
ResetEvent(EVENT * e)1068 void ResetEvent(EVENT *e)
1069 {
1070 // Validate arguments
1071 if (e == NULL)
1072 {
1073 return;
1074 }
1075
1076 KeResetEvent(e->EventObj);
1077 }
1078
1079 // Allocate the memory
Malloc(UINT size)1080 void *Malloc(UINT size)
1081 {
1082 void *p;
1083
1084 p = ExAllocatePoolWithTag(g_pool_type, size + sizeof(UINT), MEMPOOL_TAG);
1085 *((UINT *)p) = size;
1086
1087 return ((UCHAR *)p) + sizeof(UINT);
1088 }
ZeroMalloc(UINT size)1089 void *ZeroMalloc(UINT size)
1090 {
1091 void *p = Malloc(size);
1092 Zero(p, size);
1093 return p;
1094 }
1095
1096 // Change the memory block size
ReAlloc(void * p,UINT size)1097 void *ReAlloc(void *p, UINT size)
1098 {
1099 void *ret;
1100 UINT oldsize;
1101 // Validate arguments
1102 if (p == NULL)
1103 {
1104 return NULL;
1105 }
1106
1107 ret = Malloc(size);
1108 if (ret == NULL)
1109 {
1110 Free(p);
1111 return NULL;
1112 }
1113
1114 oldsize = GetMemSize(p);
1115
1116 Copy(ret, p, MIN(size, oldsize));
1117
1118 Free(p);
1119
1120 return ret;
1121 }
1122
1123 // Copy memory
Copy(void * dst,void * src,UINT size)1124 void Copy(void *dst, void *src, UINT size)
1125 {
1126 // Validate arguments
1127 if (dst == NULL || src == NULL || size == 0)
1128 {
1129 return;
1130 }
1131
1132 memcpy(dst, src, size);
1133 }
1134
1135 // Get the memory block size
GetMemSize(void * p)1136 UINT GetMemSize(void *p)
1137 {
1138 // Validate arguments
1139 if (p == NULL)
1140 {
1141 return 0;
1142 }
1143
1144 return *(UINT *)(((UCHAR *)p) - sizeof(UINT));
1145 }
1146
1147 // Release the memory
Free(void * p)1148 void Free(void *p)
1149 {
1150 // Validate arguments
1151 if (p == NULL)
1152 {
1153 return;
1154 }
1155
1156 p = ((UCHAR *)p) - sizeof(UINT);
1157
1158 ExFreePoolWithTag(p, MEMPOOL_TAG);
1159 }
1160
1161 // Clear the memory to zero
Zero(void * p,UINT size)1162 void Zero(void *p, UINT size)
1163 {
1164 // Validate arguments
1165 if (p == NULL || size == 0)
1166 {
1167 return;
1168 }
1169
1170 memset(p, 0, size);
1171 }
1172
1173 // Comparison of memory
Cmp(void * p1,void * p2,UINT size)1174 UINT Cmp(void *p1, void *p2, UINT size)
1175 {
1176 UCHAR *c1 = (UCHAR *)p1;
1177 UCHAR *c2 = (UCHAR *)p2;
1178 UINT i;
1179
1180 for (i = 0;i < size;i++)
1181 {
1182 if (c1[i] != c2[i])
1183 {
1184 if (c1[i] > c2[i])
1185 {
1186 return 1;
1187 }
1188 else
1189 {
1190 return -1;
1191 }
1192 }
1193 }
1194
1195 return 0;
1196 }
1197
1198 // Create a spin lock
NewSpinLock()1199 SPINLOCK *NewSpinLock()
1200 {
1201 SPINLOCK *s = ZeroMalloc(sizeof(SPINLOCK));
1202
1203 KeInitializeSpinLock(&s->SpinLock);
1204
1205 return s;
1206 }
1207
1208 // Lock
SpinLock(SPINLOCK * s)1209 void SpinLock(SPINLOCK *s)
1210 {
1211 // Validate arguments
1212 if (s == NULL)
1213 {
1214 return;
1215 }
1216
1217 KeAcquireSpinLock(&s->SpinLock, &s->OldIrql);
1218 }
1219
1220 // Unlock
SpinUnlock(SPINLOCK * s)1221 void SpinUnlock(SPINLOCK *s)
1222 {
1223 // Validate arguments
1224 if (s == NULL)
1225 {
1226 return;
1227 }
1228
1229 KeReleaseSpinLock(&s->SpinLock, s->OldIrql);
1230 }
1231
1232 // Release the spin lock
FreeSpinLock(SPINLOCK * s)1233 void FreeSpinLock(SPINLOCK *s)
1234 {
1235 // Validate arguments
1236 if (s == NULL)
1237 {
1238 return;
1239 }
1240
1241 Free(s);
1242 }
1243
1244 // Sleep
Sleep(int milliSeconds)1245 void Sleep(int milliSeconds)
1246 {
1247 PKTIMER timer = ZeroMalloc(sizeof(KTIMER));
1248 LARGE_INTEGER duetime;
1249
1250 duetime.QuadPart = (__int64)milliSeconds * -10000;
1251 KeInitializeTimerEx(timer, NotificationTimer);
1252 KeSetTimerEx(timer, duetime, 0, NULL);
1253
1254 KeWaitForSingleObject (timer, Executive, KernelMode, FALSE, NULL);
1255
1256 Free(timer);
1257 }
1258
1259 // 16-bit swap
Swap16(USHORT value)1260 USHORT Swap16(USHORT value)
1261 {
1262 USHORT r;
1263 ((BYTE *)&r)[0] = ((BYTE *)&value)[1];
1264 ((BYTE *)&r)[1] = ((BYTE *)&value)[0];
1265 return r;
1266 }
1267
1268 // 32-bit swap
Swap32(UINT value)1269 UINT Swap32(UINT value)
1270 {
1271 UINT r;
1272 ((BYTE *)&r)[0] = ((BYTE *)&value)[3];
1273 ((BYTE *)&r)[1] = ((BYTE *)&value)[2];
1274 ((BYTE *)&r)[2] = ((BYTE *)&value)[1];
1275 ((BYTE *)&r)[3] = ((BYTE *)&value)[0];
1276 return r;
1277 }
1278
1279 // 64-bit swap
Swap64(UINT64 value)1280 UINT64 Swap64(UINT64 value)
1281 {
1282 UINT64 r;
1283 ((BYTE *)&r)[0] = ((BYTE *)&value)[7];
1284 ((BYTE *)&r)[1] = ((BYTE *)&value)[6];
1285 ((BYTE *)&r)[2] = ((BYTE *)&value)[5];
1286 ((BYTE *)&r)[3] = ((BYTE *)&value)[4];
1287 ((BYTE *)&r)[4] = ((BYTE *)&value)[3];
1288 ((BYTE *)&r)[5] = ((BYTE *)&value)[2];
1289 ((BYTE *)&r)[6] = ((BYTE *)&value)[1];
1290 ((BYTE *)&r)[7] = ((BYTE *)&value)[0];
1291 return r;
1292 }
1293
1294 // Endian conversion 16bit
Endian16(USHORT src)1295 USHORT Endian16(USHORT src)
1296 {
1297 int x = 1;
1298 if (*((char *)&x))
1299 {
1300 return Swap16(src);
1301 }
1302 else
1303 {
1304 return src;
1305 }
1306 }
1307
1308 // Endian conversion 32bit
Endian32(UINT src)1309 UINT Endian32(UINT src)
1310 {
1311 int x = 1;
1312 if (*((char *)&x))
1313 {
1314 return Swap32(src);
1315 }
1316 else
1317 {
1318 return src;
1319 }
1320 }
1321
1322 // Endian conversion 64bit
Endian64(UINT64 src)1323 UINT64 Endian64(UINT64 src)
1324 {
1325 int x = 1;
1326 if (*((char *)&x))
1327 {
1328 return Swap64(src);
1329 }
1330 else
1331 {
1332 return src;
1333 }
1334 }
1335
1336 // Crash
Crush(UINT a,UINT b,UINT c,UINT d)1337 void Crush(UINT a, UINT b, UINT c, UINT d)
1338 {
1339 KeBugCheckEx(0x00000061, (ULONG_PTR)a, (ULONG_PTR)b, (ULONG_PTR)c, (ULONG_PTR)d);
1340 }
1341