├── README.md ├── Compiled ├── FuzzNDIS_x64.exe └── FuzzNDIS_x86.exe ├── Attacking_Windows_NDIS_Drivers.pdf ├── DeltaFuzzLib ├── DeltaFuzzLib │ ├── stdafx.h │ ├── stdafx.cpp │ ├── targetver.h │ ├── DeltaFuzzLib.vcxproj.filters │ ├── DeltaFuzz.h │ ├── DeltaFuzzLib.vcxproj │ └── DeltaFuzz.c └── DeltaFuzzLib.sln ├── Demo_WDI_Exploit ├── NDISExploit │ ├── stdafx.h │ ├── stdafx.cpp │ ├── targetver.h │ ├── NDISExploit.c │ ├── NDISExploit.vcxproj.filters │ └── NDISExploit.vcxproj └── NDISExploit.sln ├── FuzzNDIS ├── stdafx.cpp ├── targetver.h ├── stdafx.h ├── FuzzNDIS.vcxproj.filters ├── ReadMe.txt ├── Util.c ├── common.h ├── FuzzNDIS.vcxproj └── FuzzNDIS.c ├── FuzzNDIS.sln └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | # FuzzNDIS 2 | A Fuzzer for Windows NDIS Drivers OID Handlers 3 | -------------------------------------------------------------------------------- /Compiled/FuzzNDIS_x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IOActive/FuzzNDIS/HEAD/Compiled/FuzzNDIS_x64.exe -------------------------------------------------------------------------------- /Compiled/FuzzNDIS_x86.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IOActive/FuzzNDIS/HEAD/Compiled/FuzzNDIS_x86.exe -------------------------------------------------------------------------------- /Attacking_Windows_NDIS_Drivers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IOActive/FuzzNDIS/HEAD/Attacking_Windows_NDIS_Drivers.pdf -------------------------------------------------------------------------------- /DeltaFuzzLib/DeltaFuzzLib/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IOActive/FuzzNDIS/HEAD/DeltaFuzzLib/DeltaFuzzLib/stdafx.h -------------------------------------------------------------------------------- /DeltaFuzzLib/DeltaFuzzLib/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IOActive/FuzzNDIS/HEAD/DeltaFuzzLib/DeltaFuzzLib/stdafx.cpp -------------------------------------------------------------------------------- /DeltaFuzzLib/DeltaFuzzLib/targetver.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IOActive/FuzzNDIS/HEAD/DeltaFuzzLib/DeltaFuzzLib/targetver.h -------------------------------------------------------------------------------- /Demo_WDI_Exploit/NDISExploit/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IOActive/FuzzNDIS/HEAD/Demo_WDI_Exploit/NDISExploit/stdafx.h -------------------------------------------------------------------------------- /Demo_WDI_Exploit/NDISExploit/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IOActive/FuzzNDIS/HEAD/Demo_WDI_Exploit/NDISExploit/stdafx.cpp -------------------------------------------------------------------------------- /Demo_WDI_Exploit/NDISExploit/targetver.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IOActive/FuzzNDIS/HEAD/Demo_WDI_Exploit/NDISExploit/targetver.h -------------------------------------------------------------------------------- /Demo_WDI_Exploit/NDISExploit/NDISExploit.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IOActive/FuzzNDIS/HEAD/Demo_WDI_Exploit/NDISExploit/NDISExploit.c -------------------------------------------------------------------------------- /FuzzNDIS/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // FuzzNDIS.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /FuzzNDIS/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /FuzzNDIS/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | 13 | 14 | 15 | // TODO: reference additional headers your program requires here 16 | -------------------------------------------------------------------------------- /Demo_WDI_Exploit/NDISExploit/NDISExploit.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 6 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 7 | 8 | 9 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 10 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 11 | 12 | 13 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 14 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Resource Files\Source Files 28 | 29 | 30 | Resource Files\Source Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /DeltaFuzzLib/DeltaFuzzLib/DeltaFuzzLib.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | -------------------------------------------------------------------------------- /DeltaFuzzLib/DeltaFuzzLib.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2035 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeltaFuzzLib", "DeltaFuzzLib\DeltaFuzzLib.vcxproj", "{475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Debug|x64.ActiveCfg = Debug|x64 17 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Debug|x64.Build.0 = Debug|x64 18 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Debug|x86.ActiveCfg = Debug|Win32 19 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Debug|x86.Build.0 = Debug|Win32 20 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Release|x64.ActiveCfg = Release|x64 21 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Release|x64.Build.0 = Release|x64 22 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Release|x86.ActiveCfg = Release|Win32 23 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {FF049030-0383-43A2-9845-15B5A51FEBE0} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Demo_WDI_Exploit/NDISExploit.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2042 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NDISExploit", "NDISExploit\NDISExploit.vcxproj", "{3162B02F-1BED-4885-AF10-7D466B6BCB8C}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {3162B02F-1BED-4885-AF10-7D466B6BCB8C}.Debug|x64.ActiveCfg = Debug|x64 17 | {3162B02F-1BED-4885-AF10-7D466B6BCB8C}.Debug|x64.Build.0 = Debug|x64 18 | {3162B02F-1BED-4885-AF10-7D466B6BCB8C}.Debug|x86.ActiveCfg = Debug|Win32 19 | {3162B02F-1BED-4885-AF10-7D466B6BCB8C}.Debug|x86.Build.0 = Debug|Win32 20 | {3162B02F-1BED-4885-AF10-7D466B6BCB8C}.Release|x64.ActiveCfg = Release|x64 21 | {3162B02F-1BED-4885-AF10-7D466B6BCB8C}.Release|x64.Build.0 = Release|x64 22 | {3162B02F-1BED-4885-AF10-7D466B6BCB8C}.Release|x86.ActiveCfg = Release|Win32 23 | {3162B02F-1BED-4885-AF10-7D466B6BCB8C}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {E5421C03-3468-4B50-8064-F55E531437BB} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /FuzzNDIS/FuzzNDIS.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | -------------------------------------------------------------------------------- /FuzzNDIS/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : FuzzNDIS Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this FuzzNDIS application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your FuzzNDIS application. 9 | 10 | 11 | FuzzNDIS.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | FuzzNDIS.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | FuzzNDIS.cpp 25 | This is the main application source file. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other standard files: 29 | 30 | StdAfx.h, StdAfx.cpp 31 | These files are used to build a precompiled header (PCH) file 32 | named FuzzNDIS.pch and a precompiled types file named StdAfx.obj. 33 | 34 | ///////////////////////////////////////////////////////////////////////////// 35 | Other notes: 36 | 37 | AppWizard uses "TODO:" comments to indicate parts of the source code you 38 | should add to or customize. 39 | 40 | ///////////////////////////////////////////////////////////////////////////// 41 | -------------------------------------------------------------------------------- /FuzzNDIS/Util.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | char **parse_arguments(char *command_line, char arg_delim) { 8 | char delim[2] = { 0 }; 9 | if (arg_delim == NULL) { 10 | delim[0] = ' '; 11 | } 12 | else { 13 | delim[0] = arg_delim; 14 | } 15 | char **args = (char **)calloc(1, 0x40); 16 | char *token; 17 | char **p = args; 18 | unsigned int argc = 1; 19 | 20 | p++; 21 | token = strtok(command_line, delim); 22 | while (token != NULL) { 23 | *p = token; 24 | token = strtok(NULL, delim); 25 | p++; 26 | argc++; 27 | } 28 | 29 | *(unsigned int *)&args[0] = argc; 30 | 31 | return args; 32 | } 33 | 34 | void get_user_input(char *input, int size) { 35 | memset(input, 0x00, size); 36 | fgets(input, size, stdin); 37 | 38 | // clean the trailing '\n' 39 | char *pos; 40 | if ((pos = strchr(input, '\n')) != NULL) 41 | *pos = '\0'; 42 | } 43 | 44 | // Economou function 45 | void print_memory(unsigned long address, char *buffer, unsigned int bytes_to_print) 46 | { 47 | unsigned int cont; 48 | unsigned int i; 49 | const unsigned short bytes = 16; 50 | 51 | /* Print the lines */ 52 | for (cont = 0; cont < bytes_to_print; cont = cont + bytes) 53 | { 54 | printf("%p | ", (void *)address); 55 | address = address + bytes; 56 | 57 | for (i = 0; i < bytes; i++) 58 | { 59 | if (i < (bytes_to_print - cont)) 60 | { 61 | printf("%.2x ", (unsigned char)buffer[i + cont]); 62 | } 63 | else 64 | { 65 | printf(" "); 66 | } 67 | } 68 | 69 | //Space between two columns 70 | printf("| "); 71 | 72 | //Print the characters 73 | for (i = 0; i < bytes; i++) 74 | { 75 | if (i < (bytes_to_print - cont)) 76 | { 77 | printf("%c", (isgraph(buffer[i + cont])) ? buffer[i + cont] : '.'); 78 | } 79 | else 80 | { 81 | printf(" "); 82 | } 83 | } 84 | printf("\n"); 85 | } 86 | } 87 | 88 | void error(char *msg) { 89 | fprintf(stderr, "Error: %s\n", msg); 90 | exit(-1); 91 | } 92 | -------------------------------------------------------------------------------- /FuzzNDIS.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2042 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FuzzNDIS", "FuzzNDIS\FuzzNDIS.vcxproj", "{A231C4DB-2AA9-432A-9D2B-1EB9168BCFDF}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeltaFuzzLib", "D:\Projects\DeltaFuzzLib\DeltaFuzzLib\DeltaFuzzLib\DeltaFuzzLib.vcxproj", "{475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {A231C4DB-2AA9-432A-9D2B-1EB9168BCFDF}.Debug|x64.ActiveCfg = Debug|x64 19 | {A231C4DB-2AA9-432A-9D2B-1EB9168BCFDF}.Debug|x64.Build.0 = Debug|x64 20 | {A231C4DB-2AA9-432A-9D2B-1EB9168BCFDF}.Debug|x86.ActiveCfg = Debug|Win32 21 | {A231C4DB-2AA9-432A-9D2B-1EB9168BCFDF}.Debug|x86.Build.0 = Debug|Win32 22 | {A231C4DB-2AA9-432A-9D2B-1EB9168BCFDF}.Release|x64.ActiveCfg = Release|x64 23 | {A231C4DB-2AA9-432A-9D2B-1EB9168BCFDF}.Release|x64.Build.0 = Release|x64 24 | {A231C4DB-2AA9-432A-9D2B-1EB9168BCFDF}.Release|x86.ActiveCfg = Release|Win32 25 | {A231C4DB-2AA9-432A-9D2B-1EB9168BCFDF}.Release|x86.Build.0 = Release|Win32 26 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Debug|x64.ActiveCfg = Debug|x64 27 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Debug|x64.Build.0 = Debug|x64 28 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Debug|x86.ActiveCfg = Debug|Win32 29 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Debug|x86.Build.0 = Debug|Win32 30 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Release|x64.ActiveCfg = Release|x64 31 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Release|x64.Build.0 = Release|x64 32 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Release|x86.ActiveCfg = Release|Win32 33 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {1AEABFE3-6D22-4A78-9568-058E634B54D0} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /DeltaFuzzLib/DeltaFuzzLib/DeltaFuzz.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __DeltaFuzz_h__ 3 | #define __DeltaFuzz_h__ 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /* Definitions */ 12 | 13 | #define DEFAULT_FUZZ_POSSIBILITY 100 14 | #define DEFAULT_UNMAP_POSSIBILITY 0 15 | 16 | /* Structures and Variables */ 17 | 18 | typedef struct _FUZZER_OBJECT { 19 | UINT32 Seed; 20 | double FuzzPossibility; 21 | double UnmapPossibility; 22 | UINT64 Iterations; 23 | BOOL FuzzGenerate; 24 | BOOL FuzzMutate; 25 | int(*get_random)(void *fuzzer); 26 | void(*fuzz_blob)(void *fuzzer, UCHAR *blob, UINT32 size); 27 | unsigned int(*get_fuzzy_len)(void *fuzzer, unsigned int max); 28 | int (*gen_int)(void *fuzzer, unsigned long long *qp); 29 | } FUZZER_OBJECT, *PFUZZER_OBJECT; 30 | 31 | 32 | int wrapper_rand(FUZZER_OBJECT *fuzzer); 33 | void _swapValues_UINT(UINT32 *a, UINT32 *b); 34 | void _mutateNullRange(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end); 35 | void _mutateRangeSpecial(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end); 36 | void _mutateUnNullRange(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end); 37 | void _mutateRangeRandom(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end); 38 | void _mutateBitFlipping(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end); 39 | void _singleBitFlipping(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end); 40 | //BOOL FuzzDeallocateMemory(FUZZER_OBJECT *fuzzer, PVOID allocation, UINT size, BOOL virtualAllocated); 41 | 42 | void CreateFuzzerObject(FUZZER_OBJECT **fuzzer, UINT32 seed, BOOL FuzzGenerate, BOOL FuzzMutate); 43 | void DestroyFuzzerObject(FUZZER_OBJECT *fuzzer); 44 | 45 | void FuzzBlob(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 size); 46 | unsigned int get_fuzzy_len(FUZZER_OBJECT *fuzzer, unsigned int max); 47 | int genInt(FUZZER_OBJECT *fuzzer, unsigned long long *qp); 48 | unsigned int getOffset(FUZZER_OBJECT *fuzzer, UINT size, UINT SpaceNeeded, BOOLEAN *error); 49 | unsigned char getCharDelta(FUZZER_OBJECT *fuzzer); 50 | unsigned short getWordDelta(FUZZER_OBJECT *fuzzer); 51 | unsigned int getDwordDelta(FUZZER_OBJECT *fuzzer); 52 | unsigned long long getQwordDelta(FUZZER_OBJECT *fuzzer); 53 | unsigned char mutateBit(FUZZER_OBJECT *fuzzer, unsigned char b); 54 | unsigned char mutateBit(FUZZER_OBJECT *fuzzer, unsigned char b); 55 | unsigned short mutateWord(FUZZER_OBJECT *fuzzer, unsigned short w); 56 | unsigned int mutateDword(FUZZER_OBJECT *fuzzer, unsigned int dw); 57 | unsigned long long mutateQword(FUZZER_OBJECT *fuzzer, unsigned long long qw); 58 | 59 | #endif 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /FuzzNDIS/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | #include 4 | #include "DeltaFuzz.h" 5 | 6 | #include 7 | #include 8 | 9 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 10 | 11 | #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) 12 | #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) 13 | 14 | 15 | #define FUZZ_UNIT_MEM_SIZE 0x500000 16 | FUZZER_OBJECT *g_fuzzer; 17 | UINT32 g_seed; 18 | UINT32 tsc_aux1; 19 | 20 | /* FuzzNDIS */ 21 | BOOL GetInformationFromAdapters(WCHAR *matchDesc, char *pOutAdapterStr); 22 | DWORD getSupportedList(HANDLE h, LPVOID out, unsigned int outlen); 23 | unsigned int getOid(unsigned int max); 24 | HANDLE opendev(char *dev); 25 | 26 | /* Utils */ 27 | void error(char *msg); 28 | void print_memory(unsigned long address, char *buffer, unsigned int bytes_to_print); 29 | void get_user_input(char *input, int size); 30 | char **parse_arguments(char *command_line, char arg_delim); 31 | 32 | #define NDIS_CRASH_OID OID_PNP_SET_POWER //0xfd010101 33 | #define NDIS_CRASH_OID2 OID_PM_ADD_PROTOCOL_OFFLOAD //0xfd01010d 34 | #define OID_RECEIVE_FILTER_MOVE_FILTER 0x00010230 // set only 35 | #define NDIS_CRASH_OID3 OID_PM_ADD_WOL_PATTERN //0xfd01010a 36 | #define NDIS_CRASH_OID5 OID_RECEIVE_FILTER_CLEAR_FILTER //0x00010228 37 | #define NDIS_CRASH_OID6 OID_RECEIVE_FILTER_FREE_QUEUE //0x00010224 38 | 39 | 40 | // This is the header for the buffer passed during 0x17009C ndis IOCTL 41 | #define IOCTL_OID_INFO 0x17009C 42 | #define NDIS_OBJECT_TYPE_IOCTL_OID_INFO 0xb9 43 | typedef struct _NDIS_OID_INFO_OBJECT { 44 | NDIS_OBJECT_HEADER Header; 45 | //Type is 0xB9 46 | // Revision is 1 47 | // Size is 0x2C 48 | 49 | DWORD NdisRequestType; // This can be 0, 1, 2, or 0x0C 50 | /* 51 | NdisRequestType field: 52 | 53 | This value affects how the operation is going to happen. 54 | If is set to 0 or 2: 55 | then ndis sets the InOutBuffSize to OutputBuffLen - PayloadOffset and zero-outs the InOutBuffer in the InternalQuerySet parameter. 56 | If is set to 1: 57 | then ndis set InOutBuffSize to InputLen - PayloadOffset, it does not zero outs anything 58 | If is set to 0x0C: 59 | then ndis set InOutBuffSize to InputLen - PayloadOffset, Sets InternalQuerySet.UnkSize to OutputBuffLen - AuxLen and Sets InternalQuerySet.UnkVal to [Inputbuff+0x10] 60 | */ 61 | 62 | DWORD PortNumber; // This sets the PortNumber field of InternalQuerySet 63 | DWORD OID; // This is the OID for which to perform the call 64 | DWORD MethodId; // This sets the methodId of the NDIS_OID_REQUEST when RequestType is Method (AdminOnly) 65 | DWORD Timeout; // This sets Timeoud field of the InternalQUerySet -> goes in the range 0x00-0x3C 66 | DWORD OutUnkSize; 67 | // This holds the value of InternalQuerySet.UnkSize after the call of ndisQuerySetMiniport when Operation is 0 or 2 68 | // If NdisRequestType is 0x0C then this holds InternalQuerySet.Fill04 value 69 | DWORD OutUnkSize2; 70 | // This holds the value of InternalQuerySet.UnkSize after the call of ndisQuerySetMiniport when Operation is 1 71 | // If NdisRequestType is 0x0C then this holds InternalQuerySet.Fill051 value 72 | DWORD OutUnkVal; 73 | // This holds the value of InternalQuerySet.UnkVal after the call of ndisQuerySetMiniport 74 | // If NdisRequestType is 0x0C then this holds InternalQuerySet.fill052 value 75 | 76 | DWORD OutStatus; // This holds the EAX result of the call to ndisQuerySetMiniport 77 | DWORD PayloadOffset; // This value indicates where the data for the operation starts 78 | /* 79 | inputLen >= 0x2C 80 | OutputLen >= 0x2C 81 | PayloadOffset >= 0x2C 82 | PayloadOffset <= min(inputLen,OutputLen) // ndis checks this, so we cannot indicate a payloadOffset that it's out of bounds 83 | InternalQuerySet.InOutBuff = IRP.AssociatedIrp.SystemBuffer + PayloadOffset 84 | */ 85 | 86 | } NDIS_OID_INFO_OBJECT, *PNDIS_OID_INFO_OBJECT; 87 | 88 | 89 | 90 | 91 | typedef struct _HEADER_REQUEST_METHOD { 92 | DWORD OID; 93 | DWORD UnkDw1; 94 | DWORD UnkDw2; 95 | } HEADER_REQUEST_METHOD, *PHEADER_REQUEST_METHOD; 96 | 97 | 98 | 99 | #define IOCTL_NDIS_REQUEST_METHOD IOCTL_NDIS_RESERVED4 100 | 101 | 102 | 103 | typedef struct _NDIS_INTERNAL_IOCTL { 104 | char name[256]; 105 | DWORD Ioctl; 106 | } NDIS_INTERNAL_IOCTL, *PNDIS_INTERNAL_IOCTL; 107 | 108 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | 244 | # SQL Server files 245 | *.mdf 246 | *.ldf 247 | *.ndf 248 | 249 | # Business Intelligence projects 250 | *.rdl.data 251 | *.bim.layout 252 | *.bim_*.settings 253 | *.rptproj.rsuser 254 | 255 | # Microsoft Fakes 256 | FakesAssemblies/ 257 | 258 | # GhostDoc plugin setting file 259 | *.GhostDoc.xml 260 | 261 | # Node.js Tools for Visual Studio 262 | .ntvs_analysis.dat 263 | node_modules/ 264 | 265 | # Visual Studio 6 build log 266 | *.plg 267 | 268 | # Visual Studio 6 workspace options file 269 | *.opt 270 | 271 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 272 | *.vbw 273 | 274 | # Visual Studio LightSwitch build output 275 | **/*.HTMLClient/GeneratedArtifacts 276 | **/*.DesktopClient/GeneratedArtifacts 277 | **/*.DesktopClient/ModelManifest.xml 278 | **/*.Server/GeneratedArtifacts 279 | **/*.Server/ModelManifest.xml 280 | _Pvt_Extensions 281 | 282 | # Paket dependency manager 283 | .paket/paket.exe 284 | paket-files/ 285 | 286 | # FAKE - F# Make 287 | .fake/ 288 | 289 | # JetBrains Rider 290 | .idea/ 291 | *.sln.iml 292 | 293 | # CodeRush 294 | .cr/ 295 | 296 | # Python Tools for Visual Studio (PTVS) 297 | __pycache__/ 298 | *.pyc 299 | 300 | # Cake - Uncomment if you are using it 301 | # tools/** 302 | # !tools/packages.config 303 | 304 | # Tabs Studio 305 | *.tss 306 | 307 | # Telerik's JustMock configuration file 308 | *.jmconfig 309 | 310 | # BizTalk build output 311 | *.btp.cs 312 | *.btm.cs 313 | *.odx.cs 314 | *.xsd.cs 315 | 316 | # OpenCover UI analysis results 317 | OpenCover/ 318 | 319 | # Azure Stream Analytics local run output 320 | ASALocalRun/ 321 | 322 | # MSBuild Binary and Structured Log 323 | *.binlog 324 | 325 | # NVidia Nsight GPU debugger configuration file 326 | *.nvuser 327 | 328 | # MFractors (Xamarin productivity tool) working folder 329 | .mfractor/ -------------------------------------------------------------------------------- /FuzzNDIS/FuzzNDIS.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {A231C4DB-2AA9-432A-9D2B-1EB9168BCFDF} 23 | Win32Proj 24 | FuzzNDIS 25 | 10.0.17134.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v141 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v141 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v141 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v141 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | false 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | 100 | 101 | Level3 102 | Disabled 103 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | MultiThreaded 105 | Default 106 | CompileAsC 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | 117 | 118 | MaxSpeed 119 | true 120 | true 121 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 122 | D:\Projects\DeltaFuzzLib\DeltaFuzzLib\DeltaFuzzLib;%(AdditionalIncludeDirectories) 123 | MultiThreaded 124 | 125 | 126 | Console 127 | true 128 | true 129 | true 130 | 131 | 132 | 133 | 134 | Level3 135 | 136 | 137 | MaxSpeed 138 | true 139 | true 140 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 141 | MultiThreaded 142 | CompileAsC 143 | D:\Projects\DeltaFuzzLib\DeltaFuzzLib\DeltaFuzzLib;%(AdditionalIncludeDirectories) 144 | 145 | 146 | Console 147 | true 148 | true 149 | true 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | {475edda0-ea02-4d07-a4a3-b31ac7d026dd} 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /DeltaFuzzLib/DeltaFuzzLib/DeltaFuzzLib.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {475EDDA0-EA02-4D07-A4A3-B31AC7D026DD} 24 | Win32Proj 25 | DeltaFuzzLib 26 | 10.0.17134.0 27 | 28 | 29 | 30 | StaticLibrary 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | StaticLibrary 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | StaticLibrary 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | StaticLibrary 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | NotUsing 88 | Level3 89 | Disabled 90 | false 91 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Windows 96 | true 97 | 98 | 99 | 100 | 101 | NotUsing 102 | Level3 103 | Disabled 104 | false 105 | _DEBUG;_LIB;%(PreprocessorDefinitions) 106 | true 107 | MultiThreaded 108 | CompileAsC 109 | 110 | 111 | Windows 112 | true 113 | 114 | 115 | 116 | 117 | NotUsing 118 | Level3 119 | MaxSpeed 120 | true 121 | true 122 | true 123 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 124 | true 125 | MultiThreaded 126 | 127 | 128 | Windows 129 | true 130 | true 131 | true 132 | 133 | 134 | 135 | 136 | NotUsing 137 | Level3 138 | MaxSpeed 139 | true 140 | true 141 | true 142 | NDEBUG;_LIB;%(PreprocessorDefinitions) 143 | true 144 | CompileAsC 145 | MultiThreaded 146 | 147 | 148 | Windows 149 | true 150 | true 151 | true 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | Create 163 | Create 164 | Create 165 | Create 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /Demo_WDI_Exploit/NDISExploit/NDISExploit.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {3162B02F-1BED-4885-AF10-7D466B6BCB8C} 24 | Win32Proj 25 | NDISExploit 26 | 10.0.17134.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | false 75 | 76 | 77 | false 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | NotUsing 88 | Level3 89 | Disabled 90 | true 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | MultiThreaded 94 | 95 | 96 | Console 97 | true 98 | iphlpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 99 | 100 | 101 | 102 | 103 | NotUsing 104 | Level3 105 | MaxSpeed 106 | false 107 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | false 109 | MultiThreaded 110 | CompileAsC 111 | true 112 | Default 113 | true 114 | /FS %(AdditionalOptions) 115 | 116 | 117 | Console 118 | true 119 | iphlpapi.lib;%(AdditionalDependencies) 120 | /FS %(AdditionalOptions) 121 | 122 | 123 | 124 | 125 | NotUsing 126 | Level3 127 | MaxSpeed 128 | true 129 | true 130 | false 131 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | MultiThreaded 134 | %(AdditionalIncludeDirectories) 135 | 136 | 137 | Console 138 | true 139 | true 140 | true 141 | 142 | 143 | 144 | 145 | Use 146 | Level3 147 | MaxSpeed 148 | true 149 | true 150 | false 151 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 152 | true 153 | CompileAsC 154 | MultiThreaded 155 | 156 | 157 | Console 158 | true 159 | true 160 | true 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | Create 171 | Create 172 | Create 173 | Create 174 | 175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /FuzzNDIS/FuzzNDIS.c: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "common.h" 4 | 5 | #pragma comment(lib, "iphlpapi.lib") 6 | 7 | 8 | BOOL analyze_potential_leaks(DWORD oid, PVOID buffer, UINT size) { 9 | BOOL result = FALSE; 10 | int i; 11 | if (size < 8) { 12 | return FALSE; 13 | } 14 | 15 | for (i = 0; i < size; i += 8) { 16 | if (i > size) 17 | break; 18 | DWORD64 content = ((DWORD64 *)buffer)[i]; 19 | if ((content >= 0xFFFF800000000000 && content <= 0xFFFFFFFFFFFFFFFF) && content != 0xFFFFFFFFFFFFFFFF) 20 | printf("\nOID: %08x, LEAK? %i: %p\n", oid, i, content); 21 | result = TRUE; 22 | } 23 | 24 | return result; 25 | } 26 | 27 | 28 | void InitializeDeltaFuzz(UINT32 seed) { 29 | CreateFuzzerObject(&g_fuzzer, 0, TRUE, FALSE); 30 | } 31 | 32 | BOOL GetInformationFromAdapters(WCHAR *matchDesc, char *pOutAdapterStr) { 33 | DWORD outSize = 0; 34 | PIP_ADAPTER_ADDRESSES pAddresses = NULL; 35 | ULONG status = 0; 36 | BOOL result = FALSE; 37 | status = GetAdaptersAddresses(NULL, NULL, NULL, pAddresses, &outSize); 38 | if (status == ERROR_BUFFER_OVERFLOW) { 39 | pAddresses = (PIP_ADAPTER_ADDRESSES) MALLOC(outSize); 40 | PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; 41 | status = GetAdaptersAddresses(NULL, NULL, NULL, pAddresses, &outSize); 42 | pCurrAddresses = pAddresses; 43 | while (pCurrAddresses) { 44 | if (matchDesc == NULL || pOutAdapterStr == NULL) { 45 | printf("Description: %S\n", pCurrAddresses->Description); 46 | printf("Adapter: %s\n", pCurrAddresses->AdapterName); 47 | printf("FriendlyName: %S\n", pCurrAddresses->FriendlyName); 48 | puts("-------------\n"); 49 | } 50 | else { 51 | //printf("MatchDesc: %S - Description: %S\n", matchDesc, pCurrAddresses->Description); 52 | if (wcsstr(pCurrAddresses->Description, matchDesc)) { 53 | memset(pOutAdapterStr, 0x00, 256); 54 | memcpy(pOutAdapterStr, pCurrAddresses->AdapterName, strlen(pCurrAddresses->AdapterName)); 55 | result = TRUE; 56 | break; 57 | } 58 | } 59 | pCurrAddresses = pCurrAddresses->Next; 60 | } 61 | } 62 | FREE(pAddresses); 63 | return result; 64 | } 65 | 66 | HANDLE opendev(char *dev) { 67 | char buf[1024]; 68 | sprintf_s(buf, sizeof(buf), "\\\\.\\%s", dev); 69 | HANDLE h = CreateFileA(buf, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 70 | return h; 71 | } 72 | 73 | //IOCTL_NDIS_QUERY_GLOBAL_STATS 74 | void enum_oids(HANDLE h) { 75 | char in[5]; 76 | char out[100000]; 77 | 78 | int oid = OID_GEN_SUPPORTED_LIST; 79 | memcpy(in, &oid, 4); 80 | DWORD ret = 0; 81 | BOOL r = DeviceIoControl(h, IOCTL_NDIS_QUERY_GLOBAL_STATS, in, 4, out, sizeof(out), &ret, NULL); 82 | if (!r) { 83 | printf("-> Error: DeviceIoControl() failed\n"); 84 | printf(" -> code: %08x\n", GetLastError()); 85 | return; 86 | } 87 | 88 | printf("-> Supported oids:\n"); 89 | int i; 90 | unsigned int *uip = (unsigned int *)out; 91 | for (i = 0; i < ret / 4; i++) { 92 | printf(" -> [%d] 0x%x\n", i, *uip); 93 | uip++; 94 | } 95 | } 96 | 97 | DWORD getSupportedList(HANDLE h, LPVOID out, unsigned int outlen) { 98 | char in[5]; 99 | 100 | int oid = OID_GEN_SUPPORTED_LIST; 101 | memcpy(in, &oid, 4); 102 | DWORD ret = 0; 103 | BOOL r = DeviceIoControl(h, IOCTL_NDIS_QUERY_GLOBAL_STATS, in, 4, out, outlen, &ret, NULL); 104 | if (!r) { 105 | printf("DeviceIoControl() failed\n"); 106 | printf("getlasterror: 0x%x\n", GetLastError()); 107 | return 0; 108 | } 109 | 110 | return ret / 4; 111 | 112 | } 113 | 114 | unsigned int getOid(unsigned int max) { 115 | unsigned int idx = rand() % max; 116 | return idx; 117 | } 118 | 119 | 120 | void fuzz_ioctl_query_stats(HANDLE h, UINT iterations, BOOL nonull) { 121 | unsigned char oidlist[100000]; 122 | unsigned char outbuf[10000]; 123 | unsigned char inbuf[5]; 124 | unsigned int len = 0; 125 | int oid = 0; 126 | printf("-> oid var: %p - len: %p - buff: %p\n", &oid, &len, outbuf); 127 | 128 | Sleep(3000); 129 | DWORD nrOfOids = getSupportedList(h, oidlist, sizeof(oidlist)); 130 | if (!nrOfOids) { 131 | return; 132 | } 133 | 134 | unsigned int *oids = (unsigned int *)oidlist; 135 | unsigned int idx; 136 | 137 | unsigned int i = 0; 138 | if (iterations == 0) { 139 | iterations = 0xFFFFFFFF; 140 | } 141 | 142 | while (i < iterations) { 143 | 144 | idx = getOid(nrOfOids); 145 | oid = oids[idx]; 146 | 147 | len = g_fuzzer->get_fuzzy_len(g_fuzzer, sizeof(outbuf)); 148 | if (nonull) { 149 | while (len == 0) { 150 | len = g_fuzzer->get_fuzzy_len(g_fuzzer, sizeof(outbuf)); 151 | } 152 | } 153 | 154 | g_fuzzer->fuzz_blob(g_fuzzer, (UCHAR *)outbuf, len); 155 | g_fuzzer->fuzz_blob(g_fuzzer, (UCHAR *)0, 0x1000); 156 | 157 | memcpy(inbuf, &oid, 4); 158 | DWORD ret = 0; 159 | 160 | BOOL r = DeviceIoControl(h, IOCTL_NDIS_QUERY_GLOBAL_STATS, inbuf, 4, outbuf, len, &ret, NULL); 161 | printf("\r -> oid: %08x - len: %d", oid, len); 162 | 163 | if (iterations != 0xFFFFFFFF) { 164 | i++; 165 | } 166 | } 167 | 168 | return; 169 | } 170 | 171 | void fuzz_analyze_leaks(HANDLE h, UINT iterations) { 172 | unsigned char oidlist[100000]; 173 | unsigned char outbuf[10000]; 174 | unsigned int len = 0; 175 | int oid = 0; 176 | printf("-> Super dummy pointer leak analyzer...\n"); 177 | 178 | DWORD nrOfOids = getSupportedList(h, oidlist, sizeof(oidlist)); 179 | if (!nrOfOids) { 180 | return; 181 | } 182 | 183 | unsigned int *oids = (unsigned int *)oidlist; 184 | unsigned int idx; 185 | 186 | unsigned int i = 0; 187 | if (iterations == 0) { 188 | iterations = 0xFFFFFFFF; 189 | } 190 | 191 | while (i < iterations) { 192 | 193 | idx = getOid(nrOfOids); 194 | oid = oids[idx]; 195 | 196 | len = 0; 197 | while (len == 0) { 198 | len = g_fuzzer->get_fuzzy_len(g_fuzzer, sizeof(outbuf)); 199 | } 200 | 201 | DWORD ret = 0; 202 | 203 | memset(outbuf, 0x00, len); 204 | BOOL r = DeviceIoControl(h, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, 4, outbuf, len, &ret, NULL); 205 | printf("\r -> oid: %08x - len: %d", oid, len); 206 | 207 | analyze_potential_leaks(oid, outbuf, len); 208 | 209 | if (iterations != 0xFFFFFFFF) { 210 | i++; 211 | } 212 | 213 | } 214 | 215 | return; 216 | } 217 | 218 | void fuzz_oid(HANDLE h, unsigned int oid, UINT iterations, BOOL nonull) { 219 | unsigned char outbuf[10000]; 220 | 221 | int i = 0; 222 | if (iterations == 0) { 223 | iterations = 0xFFFFFFFF; 224 | } 225 | while (i < iterations) { 226 | unsigned int len = g_fuzzer->get_fuzzy_len(g_fuzzer, sizeof(outbuf)); 227 | if (nonull) { 228 | while (len == 0) { 229 | len = g_fuzzer->get_fuzzy_len(g_fuzzer, sizeof(outbuf)); 230 | } 231 | } 232 | 233 | g_fuzzer->fuzz_blob(g_fuzzer, (UCHAR *) outbuf, len); 234 | 235 | DWORD ret = 0; 236 | 237 | BOOL r = DeviceIoControl(h, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, 4, outbuf, len, &ret, NULL); 238 | printf("oid: 0x%x\tr: %d\tlen: %d\tretlen: %d\n", oid, r, len, ret); 239 | 240 | if (iterations != 0xFFFFFFFF) { 241 | i++; 242 | } 243 | } 244 | return; 245 | } 246 | 247 | //IOCTL_NDIS_QUERY_GLOBAL_STATS 248 | void enum_oids_fuzz(HANDLE h, UINT iterations, BOOL nonull) { 249 | char in[5]; 250 | char out[100000]; 251 | int oid = OID_GEN_SUPPORTED_LIST; 252 | memcpy(in, &oid, 4); 253 | DWORD ret = 0; 254 | BOOL r = DeviceIoControl(h, IOCTL_NDIS_QUERY_GLOBAL_STATS, in, 4, out, sizeof(out), &ret, NULL); 255 | if (!r) { 256 | printf("-> Error: DeviceIoControl() failed\n"); 257 | printf(" -> code: %08x\n", GetLastError()); 258 | return; 259 | } 260 | int i; 261 | unsigned int* uip = (unsigned int*)out; 262 | for (i = 0; i < ret / 4; i++) { 263 | printf(" -> Fuzzing OID: [%d] 0x%x\n", i, *uip); 264 | fuzz_oid(h, *uip, iterations, nonull); 265 | uip++; 266 | } 267 | return *uip; 268 | } 269 | 270 | void fuzz_ioctl_oid_info(HANDLE h, UINT iterations) { 271 | unsigned char oidlist[100000]; 272 | unsigned int *oids = (unsigned int *)oidlist; 273 | DWORD nrOfOids = getSupportedList(h, oidlist, sizeof(oidlist)); 274 | 275 | DWORD headerSize = sizeof(NDIS_OID_INFO_OBJECT); 276 | PNDIS_OID_INFO_OBJECT pHeader = NULL; 277 | int buffSize = 0x10000; 278 | PVOID inBuff = MALLOC(buffSize); 279 | PVOID outBuff = MALLOC(buffSize); 280 | int oid = 0; 281 | DWORD inLen, outLen = 0; 282 | printf("-> oid var: %p - inLen: %p - outLen: %p - inbuff: %p - outbuff: %p\n", 283 | &oid, &inLen, &outLen, inBuff, outBuff); 284 | 285 | int i = 0; 286 | if (iterations == 0) { 287 | iterations = 0xFFFFFFFF; 288 | } 289 | while (i < iterations) { 290 | 291 | inLen = g_fuzzer->get_fuzzy_len(g_fuzzer, (0x1000 - headerSize)) + headerSize; 292 | outLen = g_fuzzer->get_fuzzy_len(g_fuzzer, (0x1000 - headerSize)) + headerSize; 293 | 294 | unsigned int idx = getOid(nrOfOids); 295 | oid = oids[idx]; 296 | 297 | g_fuzzer->fuzz_blob(g_fuzzer, (UCHAR *) inBuff, inLen); 298 | g_fuzzer->fuzz_blob(g_fuzzer, (UCHAR *) outBuff, outLen); 299 | 300 | pHeader = (PNDIS_OID_INFO_OBJECT) inBuff; 301 | pHeader->Header.Type = 0xB9; 302 | pHeader->Header.Revision = 1; 303 | pHeader->Header.Size = 0x2C; 304 | pHeader->NdisRequestType = NdisRequestQueryInformation; 305 | pHeader->OID = oid; 306 | 307 | g_fuzzer->fuzz_blob(g_fuzzer, (UCHAR *)&pHeader->PortNumber, sizeof(DWORD)); 308 | //pHeader->PortNumber = 0x00; 309 | 310 | pHeader->Timeout = g_fuzzer->get_fuzzy_len(g_fuzzer, 0x3C); 311 | g_fuzzer->fuzz_blob(g_fuzzer, (UCHAR *)&pHeader->MethodId, sizeof(DWORD)); 312 | 313 | if (inLen == headerSize || outLen == headerSize) { 314 | pHeader->PayloadOffset = headerSize; 315 | } 316 | else if (inLen <= outLen) { 317 | pHeader->PayloadOffset = g_fuzzer->get_fuzzy_len(g_fuzzer, (inLen - headerSize)) + headerSize; 318 | } 319 | else { 320 | pHeader->PayloadOffset = g_fuzzer->get_fuzzy_len(g_fuzzer, (outLen - headerSize)) + headerSize; 321 | } 322 | /* 323 | inputLen >= 0x2C 324 | OutputLen >= 0x2C 325 | PayloadOffset >= 0x2C 326 | PayloadOffset <= min(inputLen,OutputLen) // ndis checks this, so we cannot indicate a payloadOffset that it's out of bounds 327 | InternalQuerySet.InOutBuff = IRP.AssociatedIrp.SystemBuffer + PayloadOffset 328 | */ 329 | 330 | DWORD ret = 0; 331 | BOOL r = DeviceIoControl(h, IOCTL_OID_INFO, inBuff, inLen, outBuff, outLen, &ret, NULL); 332 | printf( 333 | "\r -> oid: %08x\tr: %d\tlen: %d\tretlen: %d", 334 | oid, 335 | r, 336 | outLen, 337 | ret 338 | ); 339 | 340 | if (iterations != 0xFFFFFFFF) { 341 | i++; 342 | } 343 | } 344 | 345 | return; 346 | } 347 | 348 | // These seem to be the supported ones 349 | DWORD Request_Method_OID_Array[] = { 350 | OID_RECEIVE_FILTER_QUEUE_PARAMETERS, //0x10226, 351 | OID_RECEIVE_FILTER_ENUM_FILTERS, //0x10229, 352 | OID_RECEIVE_FILTER_PARAMETERS, //0x1022A, 353 | OID_NIC_SWITCH_PARAMETERS, //0x10238, 354 | OID_NIC_SWITCH_VPORT_PARAMETERS, //0x10242, 355 | OID_NIC_SWITCH_ENUM_VPORTS, //0x10243, 356 | OID_NIC_SWITCH_VF_PARAMETERS, //0x10247, 357 | OID_NIC_SWITCH_ENUM_VFS, //0x10248 358 | }; 359 | 360 | 361 | void fuzz_ioctl_method(HANDLE h, UINT iterations) { 362 | if (h == (HANDLE)-1 || h == NULL) { 363 | error("Handle wasn't opened\n"); 364 | } 365 | 366 | // Starts here 367 | DWORD headerSize = sizeof(HEADER_REQUEST_METHOD); 368 | int buffSize = 0x10000; 369 | PVOID inBuff = MALLOC(buffSize); 370 | PVOID outBuff = MALLOC(buffSize); 371 | PHEADER_REQUEST_METHOD pHeader = (PHEADER_REQUEST_METHOD)inBuff; 372 | DWORD inLen = 0; 373 | DWORD outLen = 0; 374 | int oid = 0; 375 | 376 | printf("oid var: %p - inLen: %p - outLen: %p - inBuff: %p - outBuff\n", 377 | &oid, &inLen, &outLen, inBuff, outBuff); 378 | 379 | Sleep(3000); 380 | 381 | int i = 0; 382 | if (iterations == 0) { 383 | iterations = 0xFFFFFFFF; 384 | } 385 | while (i < iterations) { 386 | 387 | inLen = g_fuzzer->get_fuzzy_len(g_fuzzer, (buffSize - sizeof(HEADER_REQUEST_METHOD))) + sizeof(HEADER_REQUEST_METHOD); 388 | outLen = g_fuzzer->get_fuzzy_len(g_fuzzer, buffSize); 389 | 390 | g_fuzzer->fuzz_blob(g_fuzzer, (UCHAR *)inBuff, inLen); 391 | g_fuzzer->fuzz_blob(g_fuzzer, (UCHAR *)outBuff, outLen); 392 | 393 | pHeader->OID = Request_Method_OID_Array[g_fuzzer->get_random(g_fuzzer) % 394 | (sizeof(Request_Method_OID_Array) / sizeof(Request_Method_OID_Array[0]))]; 395 | 396 | DWORD ret = 0; 397 | BOOL r = DeviceIoControl(h, IOCTL_NDIS_REQUEST_METHOD, inBuff, inLen, outBuff, outLen, &ret, NULL); 398 | printf("\roid: 0x%x\tr: %d\tlen: %d\tretlen: %d", oid, r, outLen, ret); 399 | 400 | if (iterations != 0xFFFFFFFF) { 401 | i++; 402 | } 403 | } 404 | 405 | return; 406 | } 407 | 408 | void fuzz_target(int argc, char **argv) { 409 | // argv: { querystats , , } 410 | UINT iterations = 0; 411 | BOOL nonull = FALSE; 412 | if (argc >= 2) { 413 | if (argc >= 3) { 414 | if (!strcmp(argv[2], "nonull")) { 415 | nonull = TRUE; 416 | } 417 | else { 418 | iterations = strtoul(argv[2], NULL, 10); 419 | } 420 | if (argc == 4) { 421 | if (!strcmp(argv[3], "nonull")) { 422 | nonull = TRUE; 423 | } 424 | } 425 | } 426 | HANDLE h = strtoul(argv[1], NULL, 16); 427 | if (!strcmp(argv[0], "querystats")) { 428 | fuzz_ioctl_query_stats(h, iterations, nonull); 429 | } 430 | else if (!strcmp(argv[0], "oidinfo")) { 431 | fuzz_ioctl_oid_info(h, iterations); 432 | } 433 | else if (!strcmp(argv[0], "method")) { 434 | fuzz_ioctl_method(h, iterations); 435 | } 436 | else if (!strcmp(argv[0], "leaks")) { 437 | fuzz_analyze_leaks(h, iterations); 438 | } 439 | } 440 | } 441 | 442 | 443 | void show_help() { 444 | printf("Commands:\n"); 445 | printf("list -> list all the interfaces\n"); 446 | printf("open {GUID} -> opens a handle to de miniport\n"); 447 | printf("enumoids \n"); 448 | printf("fuzz querystats \n"); 449 | printf("fuzz oidinfo \n"); 450 | printf("fuzz method \n"); 451 | printf("fuzz leaks \n"); 452 | //fuzzoid 453 | printf("fuzzoid \n"); 454 | printf("fuzzoids \n"); 455 | printf("--\n"); 456 | } 457 | 458 | 459 | int main() { 460 | InitializeDeltaFuzz(NULL); 461 | char command_line[512]; 462 | char **args; 463 | BOOL exit = FALSE; 464 | 465 | HANDLE h; 466 | while (exit != TRUE) { 467 | printf(">>> "); 468 | fflush(stdout); 469 | get_user_input(command_line, sizeof(command_line)); 470 | if (strlen(command_line) == 0) { 471 | continue; 472 | } 473 | args = parse_arguments(command_line, ' '); 474 | int argc = (int)args[0]; 475 | argc--; 476 | char **argv = &args[1]; 477 | 478 | if (!strcmp(argv[0], "list")) { 479 | GetInformationFromAdapters(NULL, NULL); 480 | } 481 | else if (!strcmp(argv[0], "open")) { 482 | h = opendev((char *)argv[1]); 483 | if (h == (HANDLE)-1 || h == NULL) { 484 | printf("-> Error: handle for device %s wasn't opened\n", argv[1]); 485 | } 486 | else { 487 | printf("-> Success: new handle %08x\n", h); 488 | } 489 | } 490 | else if (!strcmp(argv[0], "close")) { 491 | if (argc == 2) { 492 | h = strtoul(argv[1], NULL, 16); 493 | if (CloseHandle((HANDLE)h)) 494 | printf("-> closed handle %08x\n", h); 495 | else 496 | printf("-> Error: CloseHandle failed\n", h); 497 | } 498 | } 499 | else if (!strcmp(argv[0], "enumoids")) { 500 | if (argc == 2) { 501 | h = strtoul(argv[1], NULL, 16); 502 | enum_oids(h); 503 | } 504 | } 505 | else if (!strcmp(argv[0], "fuzz")) { 506 | argc--; 507 | fuzz_target(argc, &argv[1]); 508 | } 509 | else if (!strcmp(argv[0], "fuzzoid")) { 510 | // fuzzoid 511 | if (argc >= 3) { 512 | UINT iterations = 0; 513 | BOOL nonull = FALSE; 514 | if (argc >= 4) { 515 | if (!strcmp(argv[3], "nonull")) { 516 | nonull = TRUE; 517 | } 518 | else { 519 | iterations = strtoul(argv[3], NULL, 10); 520 | } 521 | if (argc == 5) { 522 | if (!strcmp(argv[4], "nonull")) { 523 | nonull = TRUE; 524 | } 525 | } 526 | } 527 | h = strtoul(argv[1], NULL, 16); 528 | UINT oid = strtoul(argv[2], NULL, 16); 529 | fuzz_oid(h, oid, iterations, nonull); 530 | } 531 | } 532 | else if (!strcmp(argv[0], "fuzzoids")) { 533 | h = strtoul(argv[1], NULL, 16); 534 | 535 | if (argc >= 2) { 536 | UINT iterations = 0; 537 | BOOL nonull = FALSE; 538 | if (argc >= 3) { 539 | if (!strcmp(argv[2], "nonull")) { 540 | nonull = TRUE; 541 | } 542 | else { 543 | iterations = strtoul(argv[2], NULL, 10); 544 | } 545 | if (argc == 4) { 546 | if (!strcmp(argv[3], "nonull")) { 547 | nonull = TRUE; 548 | } 549 | } 550 | 551 | enum_oids_fuzz(h, iterations, nonull); 552 | } 553 | } 554 | } 555 | 556 | else if (!strcmp(argv[0], "?") || !strcmp(argv[0], "help")) { 557 | show_help(); 558 | } 559 | else if (!strcmp(argv[0], "exit")) { 560 | exit = TRUE; 561 | } 562 | free(args); 563 | } 564 | 565 | return 0; 566 | } -------------------------------------------------------------------------------- /DeltaFuzzLib/DeltaFuzzLib/DeltaFuzz.c: -------------------------------------------------------------------------------- 1 | #include "DeltaFuzz.h" 2 | 3 | /** MUTATORS **/ 4 | 5 | /* Peach Mutators 6 | http://community.peachfuzzer.com/v3/Mutators/BlobMutator.html 7 | ExpandBuffer Chooses one of four ways to insert bytes into the blob. 8 | ReduceBuffer Removes a random number of bytes from the blob. 9 | ChangeRange Changes a sequence of bytes in the blob to random values. 10 | ChangeRangeSpecial Changes a sequence of bytes in the blob to some special characters. 11 | ChangeNullRange Changes a random range of bytes in the blob to null. 12 | ChangeUnNullRange Changes all null bytes in a random range to something else. 13 | BlobBitFlipperMutator will flip a percentage of the bits in a blob. 14 | */ 15 | 16 | 17 | UCHAR special_values[] = { '<','>', '?', '>', ')', '(', '*', '&', '^', '%', '$', '#', '@', '/', '-', '+', '?', '~', '`', '|', '\\' }; 18 | unsigned char chars[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0x3d, 0x3f, 0x40, 0x41, 0x7f, 0x80, 0x81, 0xfe, 0xff }; 19 | unsigned short shorts[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0x3f, 0x40, 0x41, 0x7f, 0x80, 0x81, 0xff, 0x100, 0x101, 0x3fff, 0x4000, 0x4001, 0x7fff, 0x8000, 0x8001, 0xffff }; 20 | unsigned int ints[] = { 0,1,2,3,4,5,6,7,8,9,10,11,0x3f, 0x40, 0x41, 0x7f, 0x80, 0x81, 0xff, 0x100, 0x101, 0x3fff, 0x4000, 0x4001, 0x7fff, 0x8000, 0x8001, 0xffff, 0x10000, 0x10001, 0x3fffffff, 0x40000000, 0x40000001, 0x7fffffff, 0x80000000, 0x80000001, 0xffffffff }; 21 | unsigned long long qwords[] = { 0,1,2,3,4,5,6,7,8,9,10,11,0x3f, 0x40, 0x41, 0x7f, 0x80, 0x81, 0xff, 0x100, 0x101, 0x3fff, 0x4000, 0x4001, 0x7fff, 0x8000, 0x8001, 0xffff, 0x10000, 0x10001, 0x3fffffff, 0x40000000, 0x40000001, 0x7fffffff, 0x80000000, 0x80000001, 0xffffffff, 0x100000000, 0x100000001, 0x3fffffffffffffff, 0x4000000000000000, 0x4000000000000001, 0x7fffffffffffffff, 0x8000000000000000, 0x8000000000000001, 0xffffffffffffffff }; 22 | 23 | UINT32 tsc_aux = 0; 24 | 25 | void(*fpMutatorsArray[6])() = { 26 | &_mutateNullRange, 27 | &_mutateUnNullRange, 28 | &_mutateRangeSpecial, 29 | &_mutateRangeRandom, 30 | &_mutateBitFlipping, 31 | &_singleBitFlipping 32 | }; 33 | 34 | int wrapper_rand(FUZZER_OBJECT *fuzzer) { 35 | fuzzer->Iterations++; 36 | return rand(); 37 | } 38 | 39 | void CreateFuzzerObject(FUZZER_OBJECT **fuzzer, UINT32 seed, BOOL FuzzGenerate, BOOL FuzzMutate) { 40 | *fuzzer = (PFUZZER_OBJECT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FUZZER_OBJECT)); 41 | (*fuzzer)->Seed = (seed) ? seed : __rdtscp(&tsc_aux); 42 | srand((*fuzzer)->Seed); 43 | (*fuzzer)->FuzzPossibility = DEFAULT_FUZZ_POSSIBILITY; 44 | (*fuzzer)->UnmapPossibility = DEFAULT_UNMAP_POSSIBILITY; 45 | (*fuzzer)->Iterations = 0; 46 | (*fuzzer)->FuzzGenerate = FuzzGenerate; 47 | (*fuzzer)->FuzzMutate = FuzzMutate; 48 | (*fuzzer)->get_random = &wrapper_rand; 49 | (*fuzzer)->fuzz_blob = &FuzzBlob; 50 | (*fuzzer)->get_fuzzy_len = &get_fuzzy_len; 51 | (*fuzzer)->gen_int = &genInt; 52 | } 53 | 54 | void DestroyFuzzerObject(FUZZER_OBJECT *fuzzer) { 55 | HeapFree(GetProcessHeap(), 0, fuzzer); 56 | } 57 | 58 | 59 | int genInt(FUZZER_OBJECT *fuzzer, unsigned long long *qp) { 60 | switch (fuzzer->get_random(fuzzer) % 4) { 61 | case 0: 62 | switch (fuzzer->get_random(fuzzer) % 2) { 63 | case 0: 64 | *qp = special_values[fuzzer->get_random(fuzzer) % (sizeof(special_values) / sizeof(special_values[0]))]; 65 | break; 66 | case 1: 67 | *qp = chars[fuzzer->get_random(fuzzer) % sizeof(chars)]; 68 | break; 69 | } 70 | return 1; 71 | break; 72 | case 1: 73 | *qp = shorts[fuzzer->get_random(fuzzer) % (sizeof(shorts) / sizeof(shorts[0]))]; 74 | return 2; 75 | break; 76 | case 2: 77 | *qp = ints[fuzzer->get_random(fuzzer) % (sizeof(ints) / sizeof(ints[0]))]; 78 | return 4; 79 | break; 80 | case 3: 81 | *qp = qwords[fuzzer->get_random(fuzzer) % (sizeof(qwords) / sizeof(qwords[0]))]; 82 | return 8; 83 | break; 84 | } 85 | return -1; 86 | } 87 | 88 | unsigned int getOffset(FUZZER_OBJECT *fuzzer, UINT size, UINT SpaceNeeded, BOOLEAN *error) { 89 | if (SpaceNeeded > size || SpaceNeeded == 0) { 90 | *error = TRUE; 91 | return 0; 92 | } 93 | 94 | unsigned int maxOffset = size - (SpaceNeeded - 1); 95 | return fuzzer->get_random(fuzzer) % maxOffset; 96 | } 97 | 98 | unsigned char getCharDelta(FUZZER_OBJECT *fuzzer) { 99 | unsigned char c = 0; 100 | switch (fuzzer->get_random(fuzzer) % 10) { 101 | case 0: 102 | case 1: 103 | case 2: 104 | case 3: 105 | case 4: 106 | case 5: 107 | case 6: 108 | case 7: 109 | case 8: 110 | c = fuzzer->get_random(fuzzer) % 10; 111 | break; 112 | case 9: 113 | switch (fuzzer->get_random(fuzzer) % 10) { 114 | case 0: 115 | case 1: 116 | case 2: 117 | case 3: 118 | case 4: 119 | c = fuzzer->get_random(fuzzer) % 20; 120 | break; 121 | case 5: 122 | case 6: 123 | case 7: 124 | c = fuzzer->get_random(fuzzer) % 50; 125 | break; 126 | case 8: 127 | c = fuzzer->get_random(fuzzer) % 100; 128 | break; 129 | case 9: 130 | c = fuzzer->get_random(fuzzer) % 200; 131 | break; 132 | } 133 | break; 134 | } 135 | return c; 136 | } 137 | 138 | unsigned short getWordDelta(FUZZER_OBJECT *fuzzer) { 139 | unsigned short w = 0; 140 | if (fuzzer->get_random(fuzzer) % 10) { 141 | return getCharDelta(fuzzer); 142 | } 143 | switch (fuzzer->get_random(fuzzer) % 10) { 144 | case 0: 145 | case 1: 146 | case 2: 147 | case 3: 148 | case 4: 149 | w = fuzzer->get_random(fuzzer) % 0x100; 150 | break; 151 | case 5: 152 | case 6: 153 | case 7: 154 | w = fuzzer->get_random(fuzzer) % 0x1000; 155 | break; 156 | case 8: 157 | case 9: 158 | w = fuzzer->get_random(fuzzer) % 0x10000; 159 | break; 160 | } 161 | return w; 162 | } 163 | 164 | unsigned int getDwordDelta(FUZZER_OBJECT *fuzzer) { 165 | unsigned int dw = 0; 166 | if (fuzzer->get_random(fuzzer) % 100) { 167 | return getWordDelta(fuzzer); 168 | } 169 | switch (fuzzer->get_random(fuzzer) % 10) { 170 | case 0: 171 | case 1: 172 | case 2: 173 | dw = fuzzer->get_random(fuzzer) % 0x100000; 174 | break; 175 | case 3: 176 | case 4: 177 | case 5: 178 | dw = fuzzer->get_random(fuzzer) % 0x1000000; 179 | break; 180 | case 6: 181 | case 7: 182 | case 8: 183 | dw = fuzzer->get_random(fuzzer) % 0x10000000; 184 | break; 185 | case 9: 186 | dw = fuzzer->get_random(fuzzer); 187 | break; 188 | 189 | } 190 | return dw; 191 | } 192 | 193 | 194 | unsigned long long getQwordDelta(FUZZER_OBJECT *fuzzer) { 195 | if (fuzzer->get_random(fuzzer) % 1000) { 196 | return getDwordDelta(fuzzer); 197 | } 198 | 199 | unsigned long long qw = fuzzer->get_random(fuzzer); 200 | qw <<= 32; 201 | qw |= fuzzer->get_random(fuzzer); 202 | 203 | switch (fuzzer->get_random(fuzzer) % 9) { 204 | case 0: 205 | case 1: 206 | qw %= 0x1000000000; 207 | break; 208 | case 2: 209 | qw %= 0x10000000000; 210 | break; 211 | case 3: 212 | qw %= 0x100000000000; 213 | break; 214 | case 4: 215 | qw %= 0x1000000000000; 216 | break; 217 | case 5: 218 | qw %= 0x10000000000000; 219 | break; 220 | case 6: 221 | qw %= 0x100000000000000; 222 | break; 223 | case 7: 224 | qw %= 0x1000000000000000; 225 | break; 226 | case 8: 227 | qw = qw; 228 | break; 229 | } 230 | return qw; 231 | } 232 | 233 | 234 | 235 | 236 | 237 | unsigned char mutateBit(FUZZER_OBJECT *fuzzer, unsigned char b) { 238 | b ^= 1 << (fuzzer->get_random(fuzzer) % 8); 239 | return b; 240 | 241 | } 242 | 243 | unsigned char mutateChar(FUZZER_OBJECT *fuzzer, unsigned char c) { 244 | unsigned char delta = getCharDelta(fuzzer); 245 | if (fuzzer->get_random(fuzzer) % 2) { 246 | c += delta; 247 | } 248 | else { 249 | c -= delta; 250 | } 251 | return c; 252 | } 253 | 254 | unsigned short mutateWord(FUZZER_OBJECT *fuzzer, unsigned short w) { 255 | unsigned short delta = getWordDelta(fuzzer); 256 | if (fuzzer->get_random(fuzzer) % 2) { 257 | w += delta; 258 | } 259 | else { 260 | w -= delta; 261 | } 262 | return w; 263 | } 264 | 265 | unsigned int mutateDword(FUZZER_OBJECT *fuzzer, unsigned int dw) { 266 | unsigned int delta = getDwordDelta(fuzzer); 267 | if (fuzzer->get_random(fuzzer) % 2) { 268 | dw += delta; 269 | } 270 | else { 271 | dw -= delta; 272 | } 273 | return dw; 274 | 275 | } 276 | 277 | unsigned long long mutateQword(FUZZER_OBJECT *fuzzer, unsigned long long qw) { 278 | unsigned long long delta = getQwordDelta(fuzzer); 279 | if (fuzzer->get_random(fuzzer) % 2) { 280 | qw += delta; 281 | } 282 | else { 283 | qw -= delta; 284 | } 285 | return qw; 286 | } 287 | 288 | 289 | 290 | void FuzzOnce(FUZZER_OBJECT *fuzzer, UCHAR *data, UINT32 size) { 291 | unsigned char c, *cp; 292 | unsigned short w, *wp; 293 | unsigned int dw, *dwp; 294 | unsigned long long qw, *qwp; 295 | unsigned int offset; 296 | BOOLEAN error = FALSE; 297 | /* 298 | - known ints (4/10) 299 | - random value (1/10) 300 | - mutate value (5/10) 301 | */ 302 | cp = (unsigned char *)data; 303 | switch (fuzzer->get_random(fuzzer) % 10) { 304 | case 0: 305 | case 1: 306 | case 2: 307 | case 3: 308 | switch (fuzzer->get_random(fuzzer) % 4) { 309 | case 0: // char 310 | switch (fuzzer->get_random(fuzzer) % 2) { 311 | case 0: //Normal 312 | c = chars[fuzzer->get_random(fuzzer) % (sizeof(chars) / sizeof(chars[0]))]; 313 | break; 314 | case 1: // Special 315 | c = special_values[fuzzer->get_random(fuzzer) % (sizeof(special_values) / sizeof(special_values[0]))]; 316 | } 317 | offset = getOffset(fuzzer, size, sizeof(c), &error); 318 | if (error) return; 319 | cp += offset; 320 | *cp = c; 321 | break; 322 | case 1: // word 323 | w = shorts[fuzzer->get_random(fuzzer) % (sizeof(shorts) / sizeof(shorts[0]))]; 324 | offset = getOffset(fuzzer, size, sizeof(w), &error); 325 | if (error) return; 326 | cp += offset; 327 | wp = (unsigned short *)cp; 328 | *wp = w; 329 | break; 330 | case 2: // dword 331 | dw = ints[fuzzer->get_random(fuzzer) % (sizeof(ints) / sizeof(ints[0]))]; 332 | offset = getOffset(fuzzer, size, sizeof(dw), &error); 333 | if (error) return; 334 | cp += offset; 335 | dwp = (unsigned int *)cp; 336 | *dwp = dw; 337 | break; 338 | case 3: // qword 339 | qw = qwords[fuzzer->get_random(fuzzer) % (sizeof(qwords) / sizeof(qwords[0]))]; 340 | offset = getOffset(fuzzer, size, sizeof(qw), &error); 341 | if (error) return; 342 | cp += offset; 343 | qwp = (unsigned long long *) cp; 344 | *qwp = qw; 345 | break; 346 | } 347 | break; 348 | case 4: 349 | case 5: 350 | case 6: 351 | case 7: 352 | case 8: 353 | switch (fuzzer->get_random(fuzzer) % 5) { 354 | case 0: 355 | offset = getOffset(fuzzer, size, sizeof(c), &error); 356 | cp += offset; 357 | c = *cp; 358 | c = mutateBit(fuzzer, c); 359 | *cp = c; 360 | break; 361 | case 1: 362 | offset = getOffset(fuzzer, size, sizeof(c), &error); 363 | cp += offset; 364 | c = *cp; 365 | c = mutateChar(fuzzer, c); 366 | *cp = c; 367 | break; 368 | case 2: 369 | offset = getOffset(fuzzer, size, sizeof(w), &error); 370 | cp += offset; 371 | wp = (unsigned short *)cp; 372 | w = *wp; 373 | w = mutateWord(fuzzer, w); 374 | *wp = w; 375 | break; 376 | case 3: 377 | offset = getOffset(fuzzer, size, sizeof(dw), &error); 378 | cp += offset; 379 | dwp = (unsigned int *)cp; 380 | dw = *dwp; 381 | dw = mutateDword(fuzzer, dw); 382 | *dwp = dw; 383 | break; 384 | case 4: 385 | offset = getOffset(fuzzer, size, sizeof(qw), &error); 386 | cp += offset; 387 | qwp = (unsigned long long *)cp; 388 | qw = *qwp; 389 | qw = mutateQword(fuzzer, qw); 390 | *qwp = qw; 391 | 392 | break; 393 | } 394 | break; 395 | case 9: 396 | switch (fuzzer->get_random(fuzzer) % 4) { 397 | case 0: // byte 398 | c = fuzzer->get_random(fuzzer) % 256; 399 | offset = getOffset(fuzzer, size, sizeof(c), &error); 400 | if (error) return; 401 | cp += offset; 402 | *cp = c; 403 | break; 404 | case 1: // word 405 | w = fuzzer->get_random(fuzzer) % 0x10000; 406 | offset = getOffset(fuzzer, size, sizeof(w), &error); 407 | if (error) return; 408 | cp += offset; 409 | wp = (unsigned short *)cp; 410 | *wp = w; 411 | break; 412 | case 2: // dword 413 | dw = fuzzer->get_random(fuzzer); 414 | offset = getOffset(fuzzer, size, sizeof(dw), &error); 415 | if (error) return; 416 | cp += offset; 417 | dwp = (unsigned int *)cp; 418 | *dwp = dw; 419 | break; 420 | case 3: // qword 421 | qw = fuzzer->get_random(fuzzer); 422 | qw <<= 32; 423 | qw |= fuzzer->get_random(fuzzer); 424 | offset = getOffset(fuzzer, size, sizeof(qw), &error); 425 | if (error) return; 426 | cp += offset; 427 | qwp = (unsigned long long *) cp; 428 | *qwp = qw; 429 | break; 430 | } 431 | break; 432 | } 433 | 434 | return; 435 | } 436 | 437 | void _mutateNullRange(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) 438 | { 439 | memset(blob + start, 0, (end - start)); 440 | } 441 | 442 | void _mutateUnNullRange(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) { 443 | int i; 444 | for (i = start; i <= end; i++) { 445 | if (blob[i] == '\x00') { 446 | blob[i] = (UCHAR)(fuzzer->get_random(fuzzer) % (UCHAR_MAX + 1)); 447 | } 448 | } 449 | } 450 | 451 | void _mutateRangeSpecial(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) { 452 | int i; 453 | for (i = start; i <= end; i++) { 454 | blob[i] = special_values[fuzzer->get_random(fuzzer) % sizeof(special_values)]; 455 | } 456 | } 457 | 458 | void _mutateRangeRandom(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) { 459 | int i; 460 | for (i = start; i <= end; i++) { 461 | blob[i] = (UCHAR)(fuzzer->get_random(fuzzer) % (UCHAR_MAX + 1)); 462 | } 463 | } 464 | 465 | void _singleBitFlipping(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) { 466 | UINT32 bit_to_change = fuzzer->get_random(fuzzer) % 8; 467 | UINT32 target_byte = fuzzer->get_random(fuzzer) % (end - start); 468 | blob[target_byte] = blob[target_byte] ^ (1 << bit_to_change); 469 | } 470 | 471 | void _mutateBitFlipping(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) { 472 | UINT32 bits_to_change = _getRandomRange(fuzzer, 0, (end - start) * 8); 473 | UINT32 index; 474 | int i; 475 | UCHAR bit; 476 | 477 | for (i = 0; i < bits_to_change; i++) { 478 | index = fuzzer->get_random(fuzzer) % (end - start); // random index 479 | bit = 1 << (fuzzer->get_random(fuzzer) % CHAR_BIT); // random bit 480 | blob[start + index] ^= bit; 481 | } 482 | } 483 | 484 | unsigned int get_fuzzy_len(FUZZER_OBJECT *fuzzer, unsigned int max) { 485 | unsigned int len; // = rand() % max; 486 | switch (fuzzer->get_random(fuzzer) % 5) { 487 | case 0: 488 | case 3: 489 | case 4: 490 | len = fuzzer->get_random(fuzzer) % 9; 491 | break; 492 | case 1: 493 | len = fuzzer->get_random(fuzzer) & 256; 494 | break; 495 | case 2: 496 | len = fuzzer->get_random(fuzzer) % max; 497 | break; 498 | } 499 | return len; 500 | } 501 | 502 | 503 | /** FUZZER PRIMITIVES **/ 504 | 505 | void _performBlobFuzzing(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 size) { 506 | void(*fpMutator)(FUZZER_OBJECT *, UCHAR *, UINT32, UINT32); 507 | UINT32 start = fuzzer->get_random(fuzzer) % size; 508 | UINT32 end = fuzzer->get_random(fuzzer) % size; 509 | // Cannot be equal 510 | while (start == end) { 511 | end = fuzzer->get_random(fuzzer) % size; 512 | } 513 | if (start > end) { 514 | _swapValues_UINT(&start, &end); 515 | } 516 | 517 | fpMutator = fpMutatorsArray[fuzzer->get_random(fuzzer) % (sizeof(fpMutatorsArray) / sizeof(PVOID))]; 518 | fpMutator(fuzzer, blob, start, end); 519 | } 520 | 521 | char fill_values[] = { 522 | 0x00, 0x01, 0x02, 0x03, 0x07, 0x0A, 0x0C, 523 | 0x1F, 0x2F, 0x3F, 0x4F, 0x6F, 0x7F, 0x40, 524 | 0x80, 0x0F, 0xCC, 0x90, 0xFF, 0xFE, 0x41 525 | }; 526 | 527 | void generate_content(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 size) { 528 | 529 | if ((fuzzer->get_random(fuzzer) % 100) < 20) { 530 | memset(blob, fill_values[fuzzer->get_random(fuzzer) % sizeof(fill_values)], size); 531 | } 532 | else { 533 | unsigned long long qw; 534 | int ilen = 0; 535 | int i = 0; 536 | for (i = 0; i < size;) { 537 | do { 538 | ilen = genInt(fuzzer, &qw); 539 | } while (ilen >(size - i)); 540 | 541 | switch (ilen) { 542 | case 1: 543 | *(char *)(blob + i) = (unsigned char)qw; 544 | i++; 545 | break; 546 | case 2: 547 | *(WORD *)(blob + i) = (unsigned short)qw; 548 | i += sizeof(WORD); 549 | break; 550 | case 4: 551 | *(DWORD *)(blob + i) = (unsigned int)qw; 552 | i += sizeof(DWORD); 553 | break; 554 | case 8: 555 | *(unsigned long long *)(blob + i) = (unsigned long long)qw; 556 | i += sizeof(unsigned long long); 557 | break; 558 | } 559 | } 560 | } 561 | 562 | } 563 | 564 | void FuzzBlob(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 size) { 565 | if (size > 0 && blob != NULL) { 566 | //if (((int)size) < 0) { 567 | // __debugbreak(); 568 | //} 569 | if (_shouldFuzz(fuzzer)) 570 | { 571 | if (fuzzer->FuzzGenerate) { 572 | generate_content(fuzzer, blob, size); 573 | } 574 | 575 | switch (fuzzer->get_random(fuzzer) % 2) { 576 | case 0: 577 | if (size > 1) { 578 | _performBlobFuzzing(fuzzer, blob, size); 579 | } 580 | else { 581 | FuzzOnce(fuzzer, blob, size); 582 | } 583 | break; 584 | case 1: 585 | FuzzOnce(fuzzer, blob, size); 586 | break; 587 | } 588 | } 589 | } 590 | } 591 | 592 | BOOL FuzzDeallocateMemory(FUZZER_OBJECT *fuzzer, PVOID allocation, UINT size, BOOL virtualAllocated) { 593 | /*Returns TRUE if deallocation is performed, otherwise returns FALSE*/ 594 | if (_shouldUnmap(fuzzer)) 595 | { 596 | if (virtualAllocated) 597 | VirtualFree(allocation, size, MEM_RELEASE); 598 | else { 599 | HeapFree(GetProcessHeap(), 0, allocation); 600 | } 601 | 602 | return TRUE; 603 | } 604 | return FALSE; 605 | } 606 | 607 | /** FUZZER_OBJECT Functions **/ 608 | 609 | BOOL _shouldFuzz(FUZZER_OBJECT *fuzzer) { 610 | double chance = fuzzer->get_random(fuzzer) % 100; 611 | if (chance < fuzzer->FuzzPossibility) { 612 | return TRUE; 613 | } 614 | return FALSE; 615 | } 616 | 617 | BOOL _shouldUnmap(FUZZER_OBJECT *fuzzer) { 618 | double chance = fuzzer->get_random(fuzzer) % 100; 619 | if (chance < fuzzer->UnmapPossibility) { 620 | return TRUE; 621 | } 622 | return FALSE; 623 | } 624 | 625 | 626 | 627 | UINT32 _getRandomRange(FUZZER_OBJECT *fuzzer, UINT32 min, UINT32 max) 628 | { 629 | return (UINT32)((fuzzer->get_random(fuzzer) % ((max - min) + 1)) + min); 630 | } 631 | 632 | void _swapValues_UINT(UINT32 *a, UINT32 *b) { 633 | *a ^= *b; 634 | *b ^= *a; 635 | *a ^= *b; 636 | } 637 | 638 | /* 639 | int WINAPI DllMain(HINSTANCE hDllHandle, DWORD nReason, LPVOID Reserved) { 640 | switch (nReason) 641 | { 642 | case DLL_PROCESS_ATTACH: 643 | case DLL_PROCESS_DETACH: 644 | case DLL_THREAD_ATTACH: 645 | case DLL_THREAD_DETACH: 646 | break; 647 | } 648 | return TRUE; 649 | } 650 | 651 | int main(void) { 652 | RunTests(); 653 | } 654 | */ --------------------------------------------------------------------------------