mirror of
https://github.com/BeneficialCode/WinArk.git
synced 2026-10-18 05:36:10 +08:00
227 lines
5.8 KiB
C++
227 lines
5.8 KiB
C++
#include "pch.h"
|
|
#include "Section.h"
|
|
#include "Logging.h"
|
|
#include "Memory.h"
|
|
#include "ObjectAttributes.h"
|
|
#include "Common.h"
|
|
|
|
|
|
NTSTATUS Section::Initialize(SectionType type){
|
|
// Initialize this object
|
|
_type = type;
|
|
|
|
// Initialize our singleton
|
|
RtlRunOnceInitialize(&_sectionSingletonState);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// Get DLL section object
|
|
NTSTATUS Section::GetSection(DllStats** ppSectionInfo) {
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
// make sure that Initialize was called!
|
|
ASSERT(_type == SectionType::Native || _type == SectionType::Wow);
|
|
// Use the single approach
|
|
PVOID Context = nullptr;
|
|
do
|
|
{
|
|
status = RtlRunOnceBeginInitialize(&_sectionSingletonState, 0, &Context);
|
|
if (status == STATUS_PENDING) {
|
|
// We get here only during the first initialization
|
|
Context = nullptr;
|
|
|
|
// Allocate memory
|
|
DllStats* pDllState = new (PagedPool,'mSDk') DllStats;
|
|
if (pDllState) {
|
|
// Need to "trick" the system into creating a KnownDll section for us with the SD of
|
|
// the kernel32.dll section
|
|
|
|
// Temporarily attach the current thread to the address space of the system process
|
|
KAPC_STATE state;
|
|
KeStackAttachProcess(PsInitialSystemProcess, &state);
|
|
|
|
// Create our KnownDll section to bypass code integrity guard
|
|
status = CreateKnownDllSection(*pDllState);
|
|
|
|
// Revert back
|
|
KeUnstackDetachProcess(&state);
|
|
|
|
// Check the result
|
|
if (NT_SUCCESS(status)) {
|
|
Context = pDllState;
|
|
}
|
|
else {
|
|
LogError("ERROR: (0x%x), sectionType=%d", status, _type);
|
|
// Free memory
|
|
delete pDllState;
|
|
pDllState = nullptr;
|
|
}
|
|
|
|
}
|
|
else {
|
|
status = STATUS_MEMORY_NOT_ALLOCATED;
|
|
LogError("ERROR: (0x%x) , section type=%d", status, _type);
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
// Finilize our singleton
|
|
status = RtlRunOnceComplete(&_sectionSingletonState, 0, Context);
|
|
if (!NT_SUCCESS(status)) {
|
|
// Error
|
|
LogError("ERROR: (0x%x) RtlRunOnceComplete, section type=%d", status, _type);
|
|
ASSERT(nullptr);
|
|
|
|
// Free memory
|
|
if (pDllState) {
|
|
delete pDllState;
|
|
pDllState = nullptr;
|
|
}
|
|
Context = nullptr;
|
|
break;
|
|
}
|
|
}
|
|
else if (status != STATUS_SUCCESS) {
|
|
// Error
|
|
LogError("ERROR: (0x%x) RtlRunOnceBeginInitialize, section type=%d", status, _type);
|
|
}
|
|
} while (false);
|
|
|
|
|
|
if (ppSectionInfo)
|
|
*ppSectionInfo = (DllStats*)Context;
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS Section::FreeSection() {
|
|
// Release resources held for the mapped section
|
|
NTSTATUS status;
|
|
|
|
PVOID Context = nullptr;
|
|
status = RtlRunOnceBeginInitialize(&_sectionSingletonState, 0, &Context);
|
|
if (NT_SUCCESS(status)) {
|
|
// We have initilized our singleton
|
|
|
|
// do we have the context - otherwise there's nothing to delete
|
|
if (Context) {
|
|
LogInfo("FreeSection ,sectionType=%d", _type);
|
|
DllStats* pDllState = (DllStats*)Context;
|
|
|
|
// Free memory
|
|
delete pDllState;
|
|
Context = nullptr;
|
|
}
|
|
|
|
// Reset the singleton back
|
|
RtlRunOnceInitialize(&_sectionSingletonState);
|
|
}
|
|
else if (status == STATUS_UNSUCCESSFUL) {
|
|
// GetSection() wasn't called yet
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
else {
|
|
// Error
|
|
LogError("0x%x RtlRunOnceBeginInitialize", status);
|
|
ASSERT(nullptr);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS Section::CreateKnownDllSection(DllStats& dllState) {
|
|
// Create a known dll system section of our own
|
|
NTSTATUS status;
|
|
|
|
// Clear the return data (assuming only primitive data types)
|
|
memset(&dllState, 0, sizeof(dllState));
|
|
|
|
// need to steal a security descriptor from a existing KnownDll - we'll use kernel32
|
|
HANDLE hSectionK32;
|
|
|
|
#ifdef _WIN64
|
|
UNICODE_STRING name = RTL_CONSTANT_STRING(L"\\KnownDlls\\kernel32.dll");
|
|
ObjectAttributes attr(&name, ObjectAttributesFlags::Caseinsensive);
|
|
UNICODE_STRING objName = RTL_CONSTANT_STRING(INJECTED_DLL_FILE_NAME);
|
|
#else
|
|
UNICODE_STRING name = RTL_CONSTANT_STRING(L"\\KnownDlls32\\kernel32.dll");
|
|
ObjectAttributes attr(&name, ObjectAttributesFlags::Caseinsensive);
|
|
UNICODE_STRING objName = RTL_CONSTANT_STRING(INJECTED_DLL_FILE_NAME);
|
|
#endif // _WIN64
|
|
|
|
status = ZwOpenSection(&hSectionK32, READ_CONTROL, &attr);
|
|
if (NT_SUCCESS(status)) {
|
|
status = STATUS_GENERIC_COMMAND_FAILED;
|
|
// INFO: Make our section "permanent", which means that it won't be deleted if all of its handle are closed
|
|
// and we will need to call ZwMakeTemporaryObject() on it first to allow it.
|
|
|
|
ObjectAttributes objAttr(&objName, ObjectAttributesFlags::Caseinsensive | ObjectAttributesFlags::Permanent);
|
|
|
|
LogInfo("Got KnownDll Ok!\n");
|
|
ULONG size = 0;
|
|
for (;;) {
|
|
ULONG needSize = 0;
|
|
status = ZwQuerySecurityObject(hSectionK32, PROCESS_TRUST_LABEL_SECURITY_INFORMATION |
|
|
DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
|
|
objAttr.SecurityDescriptor, // SD
|
|
size, // mem size
|
|
&needSize);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
// Got it
|
|
break;
|
|
}
|
|
else if (STATUS_BUFFER_TOO_SMALL == status) {
|
|
// We need more memory
|
|
ASSERT(needSize > size);
|
|
if (objAttr.SecurityDescriptor) {
|
|
// Free previous memory
|
|
ExFreePool(objAttr.SecurityDescriptor);
|
|
objAttr.SecurityDescriptor = nullptr;
|
|
}
|
|
|
|
// Allocate mem
|
|
objAttr.SecurityDescriptor = ExAllocatePoolWithTag(PagedPool, needSize, 'm23k');
|
|
if (objAttr.SecurityDescriptor) {
|
|
// Need to retry
|
|
size = needSize;
|
|
}
|
|
else {
|
|
// Error
|
|
status = STATUS_MEMORY_NOT_ALLOCATED;
|
|
LogError("0x%x\n", status);
|
|
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
// Error
|
|
LogError("0x%x\n", status);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// Close section
|
|
status = ZwClose(hSectionK32);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
// Now we can create our own seciton for our injected DLL in the KnownDlls kernel object directory
|
|
|
|
}
|
|
|
|
// Free our memory
|
|
if (objAttr.SecurityDescriptor) {
|
|
ExFreePool(objAttr.SecurityDescriptor);
|
|
objAttr.SecurityDescriptor = nullptr;
|
|
}
|
|
}
|
|
else {
|
|
// Error
|
|
LogError("Error: 0x%x ZwOpenSection PID=%u sectionType=%d\n", status,
|
|
PsGetCurrentProcessId(),_type);
|
|
}
|
|
return status;
|
|
} |