mirror of
https://github.com/rbmm/INJECT
synced 2026-06-08 17:02:59 +00:00
481 lines
12 KiB
C++
481 lines
12 KiB
C++
BOOL IsKeySz(PKEY_VALUE_PARTIAL_INFORMATION pkvpi)
|
|
{
|
|
ULONG DataLength = pkvpi->DataLength;
|
|
return (pkvpi->Type == REG_SZ || pkvpi->Type == REG_EXPAND_SZ) &&
|
|
(DataLength - 1 < MAXUSHORT) && !(DataLength & (sizeof(WCHAR) - 1)) &&
|
|
!((PWSTR)RtlOffsetToPointer(pkvpi->Data, DataLength))[-1];
|
|
}
|
|
|
|
NTSTATUS RegGetValue(
|
|
HANDLE hKey,
|
|
PCUNICODE_STRING ValueName,
|
|
BOOL (*Validate)(PKEY_VALUE_PARTIAL_INFORMATION),
|
|
PKEY_VALUE_PARTIAL_INFORMATION* ppkvpi
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
DWORD cb = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR);
|
|
|
|
union {
|
|
PVOID buf;
|
|
PKEY_VALUE_PARTIAL_INFORMATION pkvpi;
|
|
};
|
|
|
|
do
|
|
{
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
if (buf = LocalAlloc(0, cb))
|
|
{
|
|
if (0 <= (status = ZwQueryValueKey(hKey, ValueName, KeyValuePartialInformation, pkvpi, cb, &cb)))
|
|
{
|
|
if (Validate(pkvpi))
|
|
{
|
|
*ppkvpi = pkvpi;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
status = STATUS_OBJECT_TYPE_MISMATCH;
|
|
}
|
|
LocalFree(pkvpi);
|
|
}
|
|
|
|
} while (status == STATUS_BUFFER_OVERFLOW);
|
|
|
|
DbgPrint("GetValue(%wZ)=%x\n", ValueName, status);
|
|
|
|
return status;
|
|
}
|
|
|
|
#pragma intrinsic(_lrotr, _lrotl)
|
|
|
|
#define RUN_ONCE_STATUS_TO_CONTEXT(status) ((PVOID)(ULONG_PTR)(_lrotl(status, 4) & ~((1 << RTL_RUN_ONCE_CTX_RESERVED_BITS) - 1)))
|
|
#define RUN_ONCE_CONTEXT_TO_STATUS(Context) ((NTSTATUS)_lrotr((ULONG)(ULONG_PTR)Context, 4))
|
|
|
|
struct DLL_INFORMATION
|
|
{
|
|
RTL_RUN_ONCE SectionStatus;
|
|
PVOID Section, PreferredAddress;
|
|
ULONG rva_1, SizeOfImage;
|
|
|
|
NTSTATUS CreateDllSection();
|
|
|
|
NTSTATUS GetSection(PVOID* pSection)
|
|
{
|
|
union {
|
|
PVOID Context;
|
|
NTSTATUS status;
|
|
};
|
|
|
|
if (RtlRunOnceBeginInitialize(&SectionStatus, 0, &Context) == STATUS_PENDING)
|
|
{
|
|
RtlRunOnceComplete(&SectionStatus, 0, Context = RUN_ONCE_STATUS_TO_CONTEXT(CreateDllSection()));
|
|
}
|
|
|
|
status = RUN_ONCE_CONTEXT_TO_STATUS(Context);
|
|
|
|
*pSection = Section;
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS MapSection(HANDLE hProcess, PVOID& hmod)
|
|
{
|
|
PVOID ReservedAddress = PreferredAddress, BaseAddress = 0;
|
|
SIZE_T RegionSize = SizeOfImage, ViewSize = 0;
|
|
NTSTATUS status = ZwAllocateVirtualMemory(hProcess, &ReservedAddress, 0, &RegionSize, MEM_RESERVE, PAGE_NOACCESS);
|
|
|
|
bool bFreeMemory = false;
|
|
switch (status)
|
|
{
|
|
case STATUS_SUCCESS:
|
|
bFreeMemory = true;
|
|
case STATUS_CONFLICTING_ADDRESSES:
|
|
static LARGE_INTEGER ZeroOffset;
|
|
|
|
if (0 <= (status = ZwMapViewOfSection(Section, hProcess, &BaseAddress,
|
|
0, 0, &ZeroOffset, &ViewSize, ViewUnmap, 0, PAGE_EXECUTE)))
|
|
{
|
|
hmod = BaseAddress;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
DbgPrint("MapSection[%x]: %x %p\n", status, bFreeMemory, BaseAddress);
|
|
|
|
if (bFreeMemory)
|
|
{
|
|
ZwFreeVirtualMemory(hProcess, &ReservedAddress, &RegionSize, MEM_RELEASE);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
};
|
|
|
|
namespace DLL_32
|
|
{
|
|
#include "../dlldemo/md5_32.h" // autogenerated file, on post-build step for DllDemo
|
|
|
|
DLL_INFORMATION di {};
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
|
|
namespace DLL_64
|
|
{
|
|
#include "../dlldemo/md5_64.h" // autogenerated file, on post-build step for DllDemo
|
|
|
|
DLL_INFORMATION di {};
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef _WIN64
|
|
#define NATIVE_DLL DLL_64
|
|
#define WOW_DLL DLL_32
|
|
#else
|
|
#define NATIVE_DLL DLL_32
|
|
#endif
|
|
|
|
NTSTATUS MapPeAsData(HANDLE hFile, PVOID* BaseAddress, PSIZE_T ViewSize)
|
|
{
|
|
HANDLE hSection;
|
|
|
|
NTSTATUS status = ZwCreateSection(&hSection, SECTION_MAP_READ, 0, 0, PAGE_READONLY, SEC_COMMIT, hFile);
|
|
|
|
if (0 <= status)
|
|
{
|
|
status = ZwMapViewOfSection(hSection, NtCurrentProcess(), BaseAddress, 0, 0, 0, ViewSize, ViewUnmap, 0, PAGE_READONLY);
|
|
}
|
|
|
|
ZwClose(hSection);
|
|
|
|
return status;
|
|
}
|
|
|
|
PVOID AddressInSectionTable
|
|
(
|
|
PIMAGE_NT_HEADERS NtHeaders,
|
|
PVOID Base,
|
|
ULONG Rva
|
|
)
|
|
{
|
|
if (ULONG NumberOfSections = NtHeaders->FileHeader.NumberOfSections)
|
|
{
|
|
PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(NtHeaders);
|
|
|
|
do
|
|
{
|
|
ULONG o = Rva - pish->VirtualAddress;
|
|
if (o < pish->Misc.VirtualSize)
|
|
{
|
|
return (PBYTE)Base + pish->PointerToRawData + o;
|
|
}
|
|
|
|
} while (pish++, --NumberOfSections);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
NTSTATUS IsFileOk(HANDLE hFile, PVOID _md5, ULONG FileSize, PULONG rva, PULONG AddressOfEntryPoint, PULONG SizeOfImage)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
BCRYPT_ALG_HANDLE hAlgorithm;
|
|
|
|
if (0 <= (status = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_MD5_ALGORITHM, 0, 0)))
|
|
{
|
|
union {
|
|
ULONG64 align;
|
|
UCHAR md5[16];
|
|
};
|
|
BCRYPT_HASH_HANDLE hHash;
|
|
|
|
if (0 <= (status = BCryptCreateHash(hAlgorithm, &hHash, 0, 0, 0, 0, 0)))
|
|
{
|
|
PVOID BaseAddress = 0;
|
|
SIZE_T ViewSize = 0;
|
|
|
|
if (0 <= (status = MapPeAsData(hFile, &BaseAddress, &ViewSize)))
|
|
{
|
|
status = FileSize > ViewSize ? STATUS_INVALID_IMAGE_HASH : BCryptHashData(hHash, (PUCHAR)BaseAddress, FileSize, 0);
|
|
|
|
if (0 <= status && 0 <= (status = BCryptFinishHash(hHash, md5, sizeof(md5), 0)))
|
|
{
|
|
DbgPrint("md5_0: %016I64x%016I64x\nmd5_1: %016I64x%016I64x\n",
|
|
*(1 + (PULONG64)_md5), *(PULONG64)_md5,
|
|
*(1 + (PULONG64)md5), *(PULONG64)md5);
|
|
|
|
if (memcmp(md5, _md5, sizeof(md5)))
|
|
{
|
|
status = STATUS_INVALID_IMAGE_HASH;
|
|
}
|
|
else
|
|
{
|
|
status = STATUS_INVALID_IMAGE_FORMAT;
|
|
|
|
if (PIMAGE_NT_HEADERS pinth = RtlImageNtHeader(BaseAddress))
|
|
{
|
|
status = STATUS_PROCEDURE_NOT_FOUND;
|
|
|
|
ULONG size, Ordinal = 1;
|
|
PIMAGE_EXPORT_DIRECTORY pied = (PIMAGE_EXPORT_DIRECTORY)
|
|
RtlImageDirectoryEntryToData(BaseAddress, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size);
|
|
|
|
if (pied && size >= sizeof(IMAGE_EXPORT_DIRECTORY) && (Ordinal -= pied->Base) < pied->NumberOfFunctions)
|
|
{
|
|
if (PULONG AddressOfFunctions = (PULONG)AddressInSectionTable(pinth, BaseAddress, pied->AddressOfFunctions))
|
|
{
|
|
*rva = AddressOfFunctions[Ordinal];
|
|
*AddressOfEntryPoint = pinth->OptionalHeader.AddressOfEntryPoint;
|
|
*SizeOfImage = pinth->OptionalHeader.SizeOfImage;
|
|
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
|
|
}
|
|
|
|
BCryptDestroyHash(hHash);
|
|
}
|
|
|
|
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS CreateKnownSection(HANDLE hFile, PCOBJECT_ATTRIBUTES poaKernel32, PCUNICODE_STRING My, PVOID* pTransferAddress, PVOID *pSection)
|
|
{
|
|
ULONG cb = 0, rcb = 64;
|
|
|
|
static volatile UCHAR guz;
|
|
|
|
PVOID stack = alloca(guz);
|
|
|
|
HANDLE hSection;
|
|
|
|
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, const_cast<PUNICODE_STRING>(My), OBJ_CASE_INSENSITIVE };
|
|
|
|
// look for system (smss.exe) assigned SD for known dlls
|
|
|
|
NTSTATUS status = ZwOpenSection(&hSection, READ_CONTROL, const_cast<POBJECT_ATTRIBUTES>(poaKernel32));
|
|
|
|
if (0 <= status)
|
|
{
|
|
do
|
|
{
|
|
if (cb < rcb)
|
|
{
|
|
cb = RtlPointerToOffset(oa.SecurityDescriptor = alloca(rcb - cb), stack);
|
|
}
|
|
|
|
status = ZwQuerySecurityObject(hSection,
|
|
PROCESS_TRUST_LABEL_SECURITY_INFORMATION|
|
|
DACL_SECURITY_INFORMATION|LABEL_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION,
|
|
oa.SecurityDescriptor, cb, &rcb);
|
|
|
|
} while (status == STATUS_BUFFER_TOO_SMALL);
|
|
|
|
NtClose(hSection);
|
|
|
|
if (0 <= status)
|
|
{
|
|
// not use &oa - no access to \\KnownDlls as result S-1-19-512-8192 label
|
|
// SECURITY_PROCESS_TRUST_AUTHORITY - SECURITY_PROCESS_PROTECTION_TYPE_LITE_RID - SECURITY_PROCESS_PROTECTION_LEVEL_WINTCB_RID
|
|
status = ZwCreateSection(&hSection, SECTION_MAP_EXECUTE|SECTION_QUERY, /*&oa*/0, 0, PAGE_EXECUTE, SEC_IMAGE, hFile);
|
|
|
|
if (0 <= status)
|
|
{
|
|
SECTION_IMAGE_INFORMATION sii;
|
|
|
|
status = ZwQuerySection(hSection, SectionImageInformation, &sii, sizeof(sii), 0);
|
|
|
|
DbgPrint("[%08x]:%wZ<%p> at %p\n", status, My, hSection, sii.TransferAddress);
|
|
|
|
if (0 <= status)
|
|
{
|
|
*pTransferAddress = sii.TransferAddress;
|
|
*pSection = hSection;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ZwClose(hSection);
|
|
}
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS DLL_INFORMATION::CreateDllSection()
|
|
{
|
|
ULONG FileSize;
|
|
PVOID md5;
|
|
PCOBJECT_ATTRIBUTES poaKernel32, poaDLL;
|
|
PCUNICODE_STRING pMy;
|
|
|
|
#ifdef _WIN64
|
|
if (this == &WOW_DLL::di)
|
|
{
|
|
STATIC_UNICODE_STRING(My, "\\KnownDlls32\\{EBB50DDB-F6AA-492d-94E3-1D51B299F627}.DLL");
|
|
STATIC_OBJECT_ATTRIBUTES(oaKernel32, "\\KnownDlls32\\kernel32.dll");
|
|
STATIC_OBJECT_ATTRIBUTES(oaDLL, "\\systemroot\\syswow64\\{EBB50DDB-F6AA-492d-94E3-1D51B299F627}.DLL");
|
|
|
|
poaKernel32 = &oaKernel32, pMy = &My, poaDLL = &oaDLL;
|
|
FileSize = WOW_DLL::FileSize;
|
|
md5 = &WOW_DLL::md5;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
STATIC_UNICODE_STRING(My, "\\KnownDlls\\{EBB50DDB-F6AA-492d-94E3-1D51B299F627}.DLL");
|
|
STATIC_OBJECT_ATTRIBUTES(oaKernel32, "\\KnownDlls\\kernel32.dll");
|
|
STATIC_OBJECT_ATTRIBUTES(oaDLL, "\\systemroot\\system32\\{EBB50DDB-F6AA-492d-94E3-1D51B299F627}.DLL");
|
|
|
|
poaKernel32 = &oaKernel32, pMy = &My, poaDLL = &oaDLL;
|
|
FileSize = NATIVE_DLL::FileSize;
|
|
md5 = &NATIVE_DLL::md5;
|
|
}
|
|
|
|
HANDLE hFile;
|
|
IO_STATUS_BLOCK iosb;
|
|
|
|
NTSTATUS status = ZwOpenFile(&hFile, FILE_GENERIC_READ|FILE_EXECUTE,
|
|
const_cast<POBJECT_ATTRIBUTES>(poaDLL), &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
|
|
|
|
DbgPrint("OpenFile(%wZ)=%x\n", poaDLL->ObjectName, status);
|
|
|
|
if (0 <= status)
|
|
{
|
|
FILE_STANDARD_INFORMATION fsi;
|
|
|
|
if (0 <= (status = ZwQueryInformationFile(hFile, &iosb, &fsi, sizeof(fsi), FileStandardInformation)))
|
|
{
|
|
DbgPrint("EndOfFile=%I64x\n_FileSize=%x\n", fsi.EndOfFile.QuadPart, FileSize);
|
|
|
|
if (fsi.EndOfFile.QuadPart == FileSize)
|
|
{
|
|
ULONG AddressOfEntryPoint;
|
|
if (0 <= (status = IsFileOk(hFile, md5, FileSize, &rva_1, &AddressOfEntryPoint, &SizeOfImage)))
|
|
{
|
|
PVOID TransferAddress;
|
|
status = CreateKnownSection(hFile, poaKernel32, pMy, &TransferAddress, &Section);
|
|
PreferredAddress = (PBYTE)TransferAddress - AddressOfEntryPoint;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
status = STATUS_INVALID_IMAGE_HASH;
|
|
}
|
|
}
|
|
|
|
ZwClose(hFile);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
void FreeLoadImageData()
|
|
{
|
|
PVOID Context;
|
|
|
|
if (STATUS_SUCCESS == RtlRunOnceBeginInitialize(&NATIVE_DLL::di.SectionStatus, RTL_RUN_ONCE_CHECK_ONLY, &Context))
|
|
{
|
|
if (0 <= RUN_ONCE_CONTEXT_TO_STATUS(Context))
|
|
{
|
|
DbgPrint("delete section %p\n", NATIVE_DLL::di.Section);
|
|
NtClose(NATIVE_DLL::di.Section);
|
|
}
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
if (STATUS_SUCCESS == RtlRunOnceBeginInitialize(&WOW_DLL::di.SectionStatus, RTL_RUN_ONCE_CHECK_ONLY, &Context))
|
|
{
|
|
if (0 <= RUN_ONCE_CONTEXT_TO_STATUS(Context))
|
|
{
|
|
DbgPrint("delete section %p\n", WOW_DLL::di.Section);
|
|
NtClose(WOW_DLL::di.Section);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DoInject(BOOL Wow, HANDLE hProcess, HANDLE hThread)
|
|
{
|
|
DLL_INFORMATION* pdi = Wow ? &DLL_32::di : &DLL_64::di;
|
|
|
|
HANDLE hSection;
|
|
if (0 <= pdi->GetSection(&hSection))
|
|
{
|
|
PVOID BasseAddress;
|
|
union {
|
|
PVOID pvNormalRoutine;
|
|
PKNORMAL_ROUTINE NormalRoutine;
|
|
};
|
|
|
|
if (0 <= pdi->MapSection(hProcess, BasseAddress))
|
|
{
|
|
pvNormalRoutine = (PBYTE)BasseAddress + pdi->rva_1;
|
|
|
|
if (0 > (Wow ? RtlQueueApcWow64Thread : ZwQueueApcThread)(hThread, NormalRoutine, BasseAddress, NtCurrentProcess(), BasseAddress))
|
|
{
|
|
ZwUnmapViewOfSection(hProcess, BasseAddress);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DoInject(HANDLE hProcess, HANDLE hThread)
|
|
{
|
|
DoInject(FALSE, hProcess, hThread);
|
|
|
|
#ifdef _WIN64
|
|
BOOL Wow;
|
|
if (IsWow64Process(hProcess, &Wow) && Wow)
|
|
{
|
|
DoInject(TRUE, hProcess, hThread);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void WINAPI EpZ(void*)
|
|
{
|
|
PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY cfg {};
|
|
cfg.EnableControlFlowGuard = 1;
|
|
cfg.EnableExportSuppression = 1;
|
|
cfg.StrictMode = 1;
|
|
|
|
if (SetProcessMitigationPolicy(::ProcessControlFlowGuardPolicy, &cfg, sizeof(cfg)))
|
|
{
|
|
DoInject(NtCurrentProcess(), NtCurrentThread());
|
|
ZwTestAlert();
|
|
|
|
STARTUPINFO si = { sizeof(si) };
|
|
PROCESS_INFORMATION pi;
|
|
|
|
if (CreateProcessW(L"c:/windows/syswow64/notepad.exe", 0, 0, 0, 0, CREATE_SUSPENDED, 0, 0, &si, &pi))
|
|
{
|
|
DoInject(pi.hProcess, pi.hThread);
|
|
ResumeThread(pi.hThread);
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
}
|
|
|
|
if (CreateProcessW(L"c:/windows/notepad.exe", 0, 0, 0, 0, CREATE_SUSPENDED, 0, 0, &si, &pi))
|
|
{
|
|
DoInject(pi.hProcess, pi.hThread);
|
|
ResumeThread(pi.hThread);
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
}
|
|
|
|
FreeLoadImageData();
|
|
}
|
|
} |