Skip to content

Instantly share code, notes, and snippets.

@rbmm
Last active April 29, 2024 21:37
Show Gist options
  • Save rbmm/5d90a2cc4d716825c12f57475993450b to your computer and use it in GitHub Desktop.
Save rbmm/5d90a2cc4d716825c12f57475993450b to your computer and use it in GitHub Desktop.
PVOID AccessResource(_In_ PVOID hmod, _In_ PCWSTR pri[], _In_ DWORD level, _Out_opt_ PDWORD pcb)
{
if (pcb) *pcb = 0;
if (!level) return 0;
DWORD size;
PVOID resBase = RtlImageDirectoryEntryToData(hmod, FALSE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size);
PIMAGE_RESOURCE_DIRECTORY pird = (PIMAGE_RESOURCE_DIRECTORY)resBase;
PIMAGE_RESOURCE_DIRECTORY_ENTRY pirde, _pirde;
PIMAGE_RESOURCE_DATA_ENTRY pde = 0;
DWORD Offset;
do
{
if (!pird) return 0;
pirde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pird + 1);
DWORD a = 0, b = pird->NumberOfNamedEntries, o;
PCWSTR Id = *pri++;
BOOL Named = TRUE;
if (IS_INTRESOURCE(Id))
{
Named = FALSE;
pirde += pird->NumberOfNamedEntries;
b = pird->NumberOfIdEntries;
}
if (!b || ((ULONG_PTR)(pirde + b) - (ULONG_PTR)resBase) >= size) return 0;
do
{
int i;
_pirde = &pirde[o = (a + b) >> 1];
if (Named)
{
if (!_pirde->NameIsString) return 0;
PIMAGE_RESOURCE_DIR_STRING_U pu = (PIMAGE_RESOURCE_DIR_STRING_U)
RtlOffsetToPointer(resBase, _pirde->NameOffset);
UNICODE_STRING us1, us2 = { pu->Length * sizeof(WCHAR), us2.Length, pu->NameString };
RtlInitUnicodeString(&us1, Id);
i = RtlCompareUnicodeString(&us1, &us2, FALSE);
}
else
{
if (_pirde->NameIsString) return 0;
i = Id ? (ULONG)(ULONG_PTR)Id - _pirde->Id : 0;
}
if (!i) break;
if (i < 0) b = o; else a = o + 1;
} while(a < b);
if (b <= a) return 0;
if (_pirde->DataIsDirectory)
{
Offset = _pirde->OffsetToDirectory;
if ((size <= Offset) ||
(size - Offset < sizeof (IMAGE_RESOURCE_DIRECTORY))) return 0;
pird = (PIMAGE_RESOURCE_DIRECTORY)RtlOffsetToPointer(resBase, Offset);
}
else
{
Offset = _pirde->OffsetToData;
if ((size <= Offset) ||
(size - Offset < sizeof (IMAGE_RESOURCE_DATA_ENTRY))) return 0;
pde = (PIMAGE_RESOURCE_DATA_ENTRY )RtlOffsetToPointer(resBase, Offset);
pird = 0;
}
} while(--level);
if (!pde) return 0;
*pcb = pde->Size;
return RtlAddressInSectionTable(RtlImageNtHeader(hmod), hmod, pde->OffsetToData);
}
struct _MI
{
HANDLE hFile; // IDebugDataSpaces* pDataSpace
ULONG_PTR ImageBase;
ULONG ImageSize;
BOOL bFail;
};
#include "../inc/rtlframe.h"
typedef struct RTL_FRAME<_MI> MI;
LONG NTAPI OnVex(::PEXCEPTION_POINTERS pep)
{
::PEXCEPTION_RECORD ExceptionRecord = pep->ExceptionRecord;
if (STATUS_ACCESS_VIOLATION == ExceptionRecord->ExceptionCode &&
1 < ExceptionRecord->NumberParameters &&
0 == ExceptionRecord->ExceptionInformation[0])
{
if (_MI* p = MI::get())
{
ULONG_PTR addr = ExceptionRecord->ExceptionInformation[1];
union {
ULONG_PTR offset;
LARGE_INTEGER ByteOffset;
};
ULONG_PTR ImageBase = p->ImageBase;
offset = addr - ImageBase;
if (offset < p->ImageSize)
{
SIZE_T s = 1;
if (0 <= ZwAllocateVirtualMemory(NtCurrentProcess(), (void**)&addr, 0, &s, MEM_COMMIT, PAGE_READWRITE))
{
offset = addr - p->ImageBase;
IO_STATUS_BLOCK iosb;
// p->pDataSpace->ReadVirtual
if (0 > NtReadFile(p->hFile, 0, 0, 0, &iosb, (PBYTE)ImageBase + offset, (ULONG)s, &ByteOffset, 0))
{
p->bFail = TRUE;
}
return EXCEPTION_CONTINUE_EXECUTION;
}
}
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
void checkmem(PBYTE pb, ULONG cb)
{
if (cb)
{
do
{
if (*pb++)
{
__nop();
}
} while (--cb);
}
}
void yyy(PCWSTR pszFile)
{
HANDLE hFile = CreateFile(pszFile, FILE_GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (INVALID_HANDLE_VALUE != hFile)
{
enum { fImageSize = 0x8000000};
if (PVOID ImageBase = VirtualAlloc(0, fImageSize, MEM_RESERVE, PAGE_READWRITE))
{
MI m;
m.hFile = hFile;
m.ImageBase = (ULONG_PTR)ImageBase;
m.ImageSize = fImageSize;
m.bFail = FALSE;
if (PVOID h = AddVectoredExceptionHandler(TRUE, OnVex))
{
ULONG cb;
PCWSTR a[] = { RT_VERSION, MAKEINTRESOURCEW(1), MAKEINTRESOURCEW(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT)) };
PCWSTR c[] = { RT_RCDATA, L"FUNCTIONEXTENTLIST", 0 };
PCWSTR b[] = { RT_MESSAGETABLE, MAKEINTRESOURCEW(1), MAKEINTRESOURCEW(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT)) };
PVOID pv;
if ((pv = AccessResource(ImageBase, a, _countof(a), &cb)) && !m.bFail)
{
checkmem((PBYTE)pv, cb);
}
if ((pv = AccessResource(ImageBase, b, _countof(b), &cb)) && !m.bFail)
{
checkmem((PBYTE)pv, cb);
}
if ((pv = AccessResource(ImageBase, c, _countof(c), &cb)) && !m.bFail)
{
checkmem((PBYTE)pv, cb);
}
RemoveVectoredExceptionHandler(h);
}
VirtualFree(ImageBase, 0, MEM_RELEASE);
}
NtClose(hFile);
}
}
yyy(L"c:\\windows\\system32\\ntoskrnl.exe");
// https://github.com/rbmm/LIB/blob/master/INC/rtlframe.h
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment