#include "remotecall.h" #include "../ExportFunc.h" #include "../SearchCode.h" #include "../tools.h" typedef struct _FreeMemoryInfo { ULONG64 IsExecuteAddr; ULONG64 freeSize; ULONG64 baseAddr; WORK_QUEUE_ITEM workitem; HANDLE pid; }FreeMemoryInfo, * PFreeMemoryInfo;
VOID ExFreeMemoryWorkItem(PVOID);
NTSTATUS NTAPI ZwGetNextThread( __in HANDLE ProcessHandle, __in HANDLE ThreadHandle, __in ACCESS_MASK DesiredAccess, __in ULONG HandleAttributes, __in ULONG Flags, __out PHANDLE NewThreadHandle ) {
typedef NTSTATUS(NTAPI* ZwGetNextThreadPtr)( __in HANDLE ProcessHandle, __in HANDLE ThreadHandle, __in ACCESS_MASK DesiredAccess, __in ULONG HandleAttributes, __in ULONG Flags, __out PHANDLE NewThreadHandle ); static ZwGetNextThreadPtr ZwGetNextThreadFunc = NULL; if (!ZwGetNextThreadFunc) { ZwGetNextThreadFunc = (ZwGetNextThreadPtr)searchCode("ntoskrnl.exe", ".text", "50 9C 6A ?? 48 ?? ?? ?? ?? ?? ?? 50 B8 F3 ?? ?? ?? E9 ?? ?? ?? ??", -0x8 ); } if (ZwGetNextThreadFunc) { return ZwGetNextThreadFunc(ProcessHandle, ThreadHandle, DesiredAccess, HandleAttributes, Flags, NewThreadHandle); }
}
PETHREAD NtGetProcessMainThread(PEPROCESS eprocess) {
PEPROCESS ethread = NULL; KAPC_STATE apcState = { 0 }; KeStackAttachProcess(eprocess, &apcState);
HANDLE hThread = NULL; NTSTATUS status = ZwGetNextThread(NtCurrentProcess(), NULL, THREAD_ALL_ACCESS, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 0, &hThread); if (!NT_SUCCESS(status)) { KeUnstackDetachProcess(&apcState); return NULL; } else { status = ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, ðread, NULL); NtClose(hThread); } KeUnstackDetachProcess(&apcState); return ethread;
}
NTSTATUS PsSuspendThread(IN PETHREAD Thread, OUT PULONG PreviousSuspendCount OPTIONAL ) { typedef NTSTATUS(NTAPI* PsSuspendThreadPtr)(IN PETHREAD Thread, OUT PULONG PreviousSuspendCount OPTIONAL); static PsSuspendThreadPtr PsSuspendThreadFunc = NULL; if (!PsSuspendThreadFunc) { PsSuspendThreadFunc = (PsSuspendThreadPtr)searchCode("ntoskrnl.exe", "PAGE", "65 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 ?? ?? ?? 66 ?? ?? ?? ?? ?? ?? 4C 8D ?? ?? ?? ?? ?? 4C 89 ?? ?? ?? 49 8B CF E8 ?? ?? ?? ?? 84 C0 0F ?? ?? ?? ?? ?? 8B 87 ?? ?? ?? ??", -0x20 ); } if (PsSuspendThreadFunc) { return PsSuspendThreadFunc(Thread, PreviousSuspendCount); } return STATUS_NOT_IMPLEMENTED; } NTSTATUS PsResumeThread(IN PETHREAD Thread, OUT PULONG PreviousSuspendCount OPTIONAL ) { typedef NTSTATUS(NTAPI* PsResumeThreadPtr)(IN PETHREAD Thread, OUT PULONG PreviousSuspendCount OPTIONAL); static PsResumeThreadPtr PsResumeThreadFunc = NULL; if (!PsResumeThreadFunc) { PsResumeThreadFunc = (PsResumeThreadPtr)searchCode("ntoskrnl.exe", "PAGE", "48 8B DA 48 8B F9 E8 ?? ?? ?? ?? 65 ?? ?? ?? ?? ?? ?? ?? ?? 8B F0 83 ?? ?? 75 ?? 4C 8B ?? ?? ?? ?? ?? B8 ?? ?? ?? ?? 41 8B ?? ?? ?? ??", -0xf ); } if (PsResumeThreadFunc) { return PsResumeThreadFunc(Thread, PreviousSuspendCount); } return STATUS_NOT_IMPLEMENTED; }
NTSTATUS RemoteCall(HANDLE pid, PVOID shellCode, ULONG shellCodeSize) {
NTSTATUS status = STATUS_UNSUCCESSFUL; PEPROCESS eprocess = NULL; status = PsLookupProcessByProcessId(pid, &eprocess); if (!NT_SUCCESS(status) || NULL == eprocess) { return status; } if (PsGetProcessExitStatus(eprocess) != 0x103) { ObDereferenceObject(eprocess); return STATUS_UNSUCCESSFUL; }
PETHREAD ethread = NtGetProcessMainThread(eprocess); if (NULL == ethread) { return STATUS_UNSUCCESSFUL; } PUCHAR kShellcode = ExAllocatePool(PagedPool, shellCodeSize); memcpy(kShellcode, shellCode, shellCodeSize);
BOOLEAN isWow64 = PsGetProcessWow64Process(eprocess); KAPC_STATE apcState = { 0 }; KeStackAttachProcess(eprocess, &apcState); PVOID baseAddr = 0; SIZE_T regionSize = shellCodeSize + PAGE_SIZE; PUCHAR flagAd = 0; do { status = ZwAllocateVirtualMemory(NtCurrentProcess(), &baseAddr, NULL, ®ionSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!NT_SUCCESS(status) || baseAddr == 0 || regionSize == 0) { break; } memset(baseAddr, 0, regionSize); PUCHAR shellCodeAd = (PUCHAR)baseAddr + PAGE_SIZE; flagAd = (PUCHAR)baseAddr + PAGE_SIZE / 2; memcpy(shellCodeAd, kShellcode, shellCodeSize); status = PsSuspendThread(ethread, NULL); if (!NT_SUCCESS(status)) { break; } if (isWow64) {
char bufcode[] = { 0x60, 0xB8, 0x78, 0x56, 0x34, 0x12, 0x83, 0xEC, 0x40, 0xFF, 0xD0, 0x83, 0xC4, 0x40, 0xB8, 0x78, 0x56, 0x34, 0x12, 0xC7, 0x00, 0x01, 0x00, 0x00,0x00, 0x61, 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; PUCHAR teb64 = (PUCHAR)PsGetThreadTeb(ethread); SIZE_T retProc = NULL; MmCopyVirtualMemory(eprocess, (PULONG64)(teb64 + 0x1488), eprocess, (PULONG64)(teb64 + 0x1488), 8, UserMode, &retProc);
PUCHAR WowContext = (PUCHAR) * (PULONG64)(teb64 + 0x1488); *(PULONG)&bufcode[2] = shellCodeAd; *(PULONG)&bufcode[15] = (ULONG)(flagAd); *(PULONG)&bufcode[32] = *(PULONG)(WowContext + 0xbc);
memcpy(baseAddr, bufcode, sizeof(bufcode)); *(PULONG)(WowContext + 0xbc) = baseAddr; } else {
char bufcode[] = { 0x50, 0x51, 0x52, 0x53, 0x55, 0x56, 0x57, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41, 0x53, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0xB8, 0x99, 0x89, 0x67, 0x45, 0x23, 0x01, 0x00,0x00, 0x48, 0x81, 0xEC, 0xA0, 0x00, 0x00, 0x00, 0xFF, 0xD0, 0x48, 0x81, 0xC4, 0xA0, 0x00, 0x00, 0x00, 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5D, 0x41, 0x5C, 0x41, 0x5B, 0x41, 0x5A, 0x41, 0x59, 0x41, 0x58, 0x5F, 0x5E, 0x5D, 0x5B, 0x5A, 0x59, 0x48, 0xB8, 0x89, 0x67, 0x45, 0x23, 0x01, 0x00, 0x00, 0x00, 0xC7, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; ULONG64 initStackAddr = *(PULONG64)((PUCHAR)ethread + 0x28); PKTRAP_FRAME ptrap = (PKTRAP_FRAME)(initStackAddr - sizeof(KTRAP_FRAME)); *(PULONG64)&bufcode[25] = (ULONG64)shellCodeAd; *(PULONG64)&bufcode[73] = (ULONG64)flagAd; *(PULONG64)&bufcode[94] = ptrap->Rip;
memcpy(baseAddr, bufcode, sizeof(bufcode)); ptrap->Rip = baseAddr; } PFreeMemoryInfo freeMemInfo = (PFreeMemoryInfo)ExAllocatePool(NonPagedPool, sizeof(FreeMemoryInfo)); freeMemInfo->freeSize = regionSize; freeMemInfo->baseAddr = baseAddr; freeMemInfo->pid = pid; freeMemInfo->IsExecuteAddr = flagAd; ExInitializeWorkItem(&freeMemInfo->workitem, ExFreeMemoryWorkItem, freeMemInfo); ExQueueWorkItem(&freeMemInfo->workitem, DelayedWorkQueue);
PsResumeThread(ethread, NULL);
} while (0); KeUnstackDetachProcess(&apcState); ObDereferenceObject(eprocess); ObDereferenceObject(ethread); ExFreePool(kShellcode); return status; } VOID ExFreeMemoryWorkItem(PVOID info) {
PFreeMemoryInfo freeMemInfo = (PFreeMemoryInfo)info;
PEPROCESS eprocess = NULL; NTSTATUS status = PsLookupProcessByProcessId(freeMemInfo->pid,&eprocess); if (!NT_SUCCESS(status)) { return; } if (PsGetProcessExitStatus(eprocess) != 0x103) { ObDereferenceObject(eprocess); return; }
ULONG32 exeValue = 0; SIZE_T cped = 0; int count = 0; BOOLEAN isSuccess = FALSE;
while (1) { if (count > 10000) break; status=MmCopyVirtualMemory(eprocess,freeMemInfo->IsExecuteAddr,IoGetCurrentProcess(),&exeValue,sizeof(exeValue), KernelMode,&cped); if (NT_SUCCESS(status) && exeValue == 1) { isSuccess = TRUE; break; }
KernelSleep(10, FALSE); count++;
} KAPC_STATE kApcState = { 0 }; KeStackAttachProcess(eprocess, &kApcState);
if (isSuccess) { ZwFreeVirtualMemory(NtCurrentProcess(), &freeMemInfo->baseAddr, &freeMemInfo->freeSize, MEM_RELEASE); }
KeUnstackDetachProcess(&kApcState); ExFreePool(freeMemInfo); ObDereferenceObject(eprocess);
}
|