mirror of
https://github.com/ufrisk/pcileech.git
synced 2026-05-12 16:50:32 +08:00
151 lines
5.2 KiB
C
151 lines
5.2 KiB
C
// wx64_common.c : support functions used by Windows x64 KMDs started by stage3 EXEC.
|
|
// Compatible with Windows x64.
|
|
//
|
|
// (c) Ulf Frisk, 2016, 2017
|
|
// Author: Ulf Frisk, pcileech@frizk.net
|
|
//
|
|
|
|
#include "wx64_common.h"
|
|
|
|
DWORD HashROR13A(_In_ LPCSTR sz)
|
|
{
|
|
DWORD dwVal, dwHash = 0;
|
|
while(*sz) {
|
|
dwVal = (DWORD)*sz++;
|
|
dwHash = (dwHash >> 13) | (dwHash << 19);
|
|
dwHash += dwVal;
|
|
}
|
|
return dwHash;
|
|
}
|
|
|
|
QWORD PEGetProcAddressH(_In_ QWORD hModule, _In_ DWORD dwProcNameH)
|
|
{
|
|
PDWORD pdwRVAAddrNames, pdwRVAAddrFunctions;
|
|
PWORD pwNameOrdinals;
|
|
DWORD i, dwFnIdx, dwHash;
|
|
LPSTR sz;
|
|
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule; // dos header.
|
|
if(!dosHeader || dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return 0; }
|
|
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)(hModule + dosHeader->e_lfanew); // nt header
|
|
if(!ntHeader || ntHeader->Signature != IMAGE_NT_SIGNATURE) { return 0; }
|
|
PIMAGE_EXPORT_DIRECTORY exp = (PIMAGE_EXPORT_DIRECTORY)(ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + hModule);
|
|
if(!exp || !exp->NumberOfNames || !exp->AddressOfNames) { return 0; }
|
|
pdwRVAAddrNames = (PDWORD)(hModule + exp->AddressOfNames);
|
|
pwNameOrdinals = (PWORD)(hModule + exp->AddressOfNameOrdinals);
|
|
pdwRVAAddrFunctions = (PDWORD)(hModule + exp->AddressOfFunctions);
|
|
for(i = 0; i < exp->NumberOfNames; i++) {
|
|
sz = (LPSTR)(hModule + pdwRVAAddrNames[i]);
|
|
dwHash = HashROR13A(sz);
|
|
if(dwHash == dwProcNameH) {
|
|
dwFnIdx = pwNameOrdinals[i];
|
|
if(dwFnIdx >= exp->NumberOfFunctions) { return 0; }
|
|
return (QWORD)(hModule + pdwRVAAddrFunctions[dwFnIdx]);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// see http://alter.org.ua/docs/nt_kernel/procaddr/
|
|
QWORD KernelGetModuleBase(_In_ PKERNEL_FUNCTIONS fnk, _In_ LPSTR szModuleName)
|
|
{
|
|
PBYTE pbSystemInfoBuffer;
|
|
SIZE_T cbSystemInfoBuffer = 0;
|
|
PSYSTEM_MODULE_INFORMATION_ENTRY pSME;
|
|
QWORD i, qwAddrModuleBase = 0;
|
|
fnk->ZwQuerySystemInformation(11, NULL, 0, (PULONG)&cbSystemInfoBuffer);
|
|
if(!cbSystemInfoBuffer) { return 0; }
|
|
pbSystemInfoBuffer = (PBYTE)fnk->ExAllocatePool(0, cbSystemInfoBuffer);
|
|
if(!pbSystemInfoBuffer) { return 0; }
|
|
if(0 == fnk->ZwQuerySystemInformation(11, pbSystemInfoBuffer, (ULONG)cbSystemInfoBuffer, (PULONG)&cbSystemInfoBuffer)) {
|
|
pSME = ((PSYSTEM_MODULE_INFORMATION)(pbSystemInfoBuffer))->Module;
|
|
for(i = 0; i < ((PSYSTEM_MODULE_INFORMATION)(pbSystemInfoBuffer))->Count; i++) {
|
|
if(0 == fnk->_stricmp(szModuleName, pSME[i].ImageName + pSME[i].PathLength)) {
|
|
qwAddrModuleBase = pSME[i].Base;
|
|
}
|
|
}
|
|
}
|
|
if(pbSystemInfoBuffer) { fnk->ExFreePool(pbSystemInfoBuffer); }
|
|
return qwAddrModuleBase;
|
|
}
|
|
|
|
VOID InitializeKernelFunctions(_In_ QWORD qwNtosBase, _Out_ PKERNEL_FUNCTIONS fnk)
|
|
{
|
|
DWORD i = 0, NAMES[25];
|
|
NAMES[i++] = H__stricmp;
|
|
NAMES[i++] = H_ExAllocatePool;
|
|
NAMES[i++] = H_ExFreePool;
|
|
NAMES[i++] = H_IoCreateDriver;
|
|
NAMES[i++] = H_KeDelayExecutionThread;
|
|
NAMES[i++] = H_KeGetCurrentIrql;
|
|
NAMES[i++] = H_MmGetPhysicalAddress;
|
|
NAMES[i++] = H_MmLoadSystemImage;
|
|
NAMES[i++] = H_MmMapIoSpace;
|
|
NAMES[i++] = H_MmUnloadSystemImage;
|
|
NAMES[i++] = H_MmUnmapIoSpace;
|
|
NAMES[i++] = H_RtlAnsiStringToUnicodeString;
|
|
NAMES[i++] = H_RtlCopyMemory;
|
|
NAMES[i++] = H_RtlFreeUnicodeString;
|
|
NAMES[i++] = H_RtlInitAnsiString;
|
|
NAMES[i++] = H_RtlInitUnicodeString;
|
|
NAMES[i++] = H_RtlZeroMemory;
|
|
NAMES[i++] = H_ZwClose;
|
|
NAMES[i++] = H_ZwCreateFile;
|
|
NAMES[i++] = H_ZwOpenFile;
|
|
NAMES[i++] = H_ZwQueryDirectoryFile;
|
|
NAMES[i++] = H_ZwQuerySystemInformation;
|
|
NAMES[i++] = H_ZwSetSystemInformation;
|
|
NAMES[i++] = H_ZwReadFile;
|
|
NAMES[i++] = H_ZwWriteFile;
|
|
while(i) {
|
|
i--;
|
|
*((PQWORD)fnk + i) = (QWORD)PEGetProcAddressH(qwNtosBase, NAMES[i]);
|
|
}
|
|
}
|
|
|
|
DWORD PEGetImageSize(_In_ QWORD hModule)
|
|
{
|
|
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule; // dos header.
|
|
if(!dosHeader || dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return 0; }
|
|
PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((LONG_PTR)hModule + dosHeader->e_lfanew); // nt header
|
|
if(!ntHeader || ntHeader->Signature != IMAGE_NT_SIGNATURE) { return 0; }
|
|
return ntHeader->OptionalHeader.SizeOfImage;
|
|
}
|
|
|
|
VOID CommonSleep(_In_ PKERNEL_FUNCTIONS fnk, _In_ DWORD ms)
|
|
{
|
|
LONGLONG llTimeToWait = -10000LL * ms;
|
|
fnk->KeDelayExecutionThread(KernelMode, FALSE, &llTimeToWait);
|
|
}
|
|
|
|
BOOL _WriteLargeOutput_WaitForAck(_In_ PKERNEL_FUNCTIONS fnk, _In_ PKMDDATA pk)
|
|
{
|
|
PEXEC_IO pis = (PEXEC_IO)(pk->DMAAddrVirtual + EXEC_IO_DMAOFFSET_IS);
|
|
PEXEC_IO pos = (PEXEC_IO)(pk->DMAAddrVirtual + EXEC_IO_DMAOFFSET_OS);
|
|
while((pk->_op == KMD_CMD_EXEC_EXTENDED) && ((pis->magic != EXEC_IO_MAGIC) || (!pis->bin.fCompletedAck && (pis->bin.seqAck != pos->bin.seq)))) {
|
|
CommonSleep(fnk, 25);
|
|
}
|
|
return (pk->_op == KMD_CMD_EXEC_EXTENDED) && !pis->bin.fCompletedAck;
|
|
}
|
|
|
|
BOOL WriteLargeOutput_WaitNext(_In_ PKERNEL_FUNCTIONS fnk, _In_ PKMDDATA pk)
|
|
{
|
|
PEXEC_IO pos = (PEXEC_IO)(pk->DMAAddrVirtual + EXEC_IO_DMAOFFSET_OS);
|
|
pos->magic = EXEC_IO_MAGIC;
|
|
CacheFlush();
|
|
pos->bin.seq++;
|
|
pk->_op = KMD_CMD_EXEC_EXTENDED;
|
|
return _WriteLargeOutput_WaitForAck(fnk, pk);
|
|
}
|
|
|
|
VOID WriteLargeOutput_Finish(_In_ PKERNEL_FUNCTIONS fnk, _In_ PKMDDATA pk)
|
|
{
|
|
PEXEC_IO pos = (PEXEC_IO)(pk->DMAAddrVirtual + EXEC_IO_DMAOFFSET_OS);
|
|
WriteLargeOutput_WaitNext(fnk, pk);
|
|
pk->dataOutExtraLength = 0;
|
|
CacheFlush();
|
|
pos->bin.fCompleted = TRUE;
|
|
pos->bin.seq++;
|
|
_WriteLargeOutput_WaitForAck(fnk, pk);
|
|
pk->_op = KMD_CMD_EXEC;
|
|
}
|