NTSTATUS NewNtCreateThread(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ProcessHandle,
OUT PCLIENT_ID ClientId,
IN PCONTEXT ThreadContext,
IN PINITIAL_TEB InitialTeb,
IN BOOLEAN CreateSuspended)
{
NTSTATUS ResultStatus;
#pragma message("must verify user mode parameters before using")
if (
ThreadContext &&
CreateSuspended &&
ProcessHandle &&
ProcessHandle!=(void *)0xffffffff &&
FindLockProcessInQueue(ProcessHandle)
)
{
//kernel creates thread
//trying to get PEPROCESS
NTSTATUS ObjectStatus;
PEPROCESS pProcess;
POBJECT_TYPE PsProcessType;
DBGPRINT(("Kernel trying to CreateThread(from User Mode) for ProcessHandle = 0x%X\n",ProcessHandle));
PsProcessType = NULL;
ObjectStatus = ObReferenceObjectByHandle(
ProcessHandle,
PROCESS_ALL_ACCESS,
PsProcessType,
UserMode,
(PVOID *)&pProcess,
NULL);
if (ObjectStatus!=STATUS_SUCCESS)
{
DBGPRINT(("Fail to RefernceObject. Stopping Injecting Technique.\n"));
}
else
{
NTSTATUS AllocStatus;
UCHAR * BaseAddr;
SIZE_T RegionSize;
ULONG Win32StartAddr;
ULONG LoadLibraryAddr;
RegionSize = 100;
BaseAddr = NULL;
PsProcessType = NULL;
LoadLibraryAddr = (ULONG)((PDEVICE_EXTENSION)g_pDeviceObject->DeviceExtension)->AddrInfo.pfnLoadLibrary;
DBGPRINT(("Address of LoadLibraryW = 0x%08X\n",LoadLibraryAddr));
if (ThreadContext)
{
//remembering value of ThreadContext->Eax
//it contains process staring address in user mode
Win32StartAddr = ThreadContext->Eax;
if (!Win32StartAddr)
{
DBGPRINT(("--------------Win32StartAddr not set--------------------\n"));
}
else
{
//"jumping" to context of new process
KeDetachProcess();
KeAttachProcess((void *)pProcess);
//allocating memory with PAGE_EXECUTE_READWRITE access rights
AllocStatus = ZwAllocateVirtualMemory(
NtCurrentProcess(),
&BaseAddr,
0,
&RegionSize,
MEM_COMMIT ,
PAGE_EXECUTE_READWRITE);
if (AllocStatus!=STATUS_SUCCESS)
{
DBGPRINT(("---------------Fail to Allocate memory! AllocStatus = 0x%x\n",AllocStatus));
}
else
{
ULONG Offset = 0;
ULONG OffsetStrAddr = 0;
DBGPRINT(("---------------Memory allocation OK! BaseAddr = 0x%x\n",BaseAddr));
BaseAddr[Offset] = 0x68; //push
++Offset;
OffsetStrAddr = Offset;
Offset += 4; //reserving 4 byte for string address. will be filled late
BaseAddr[Offset] = 0xbb; //mov ebx,LoadLibraryAddr
++Offset;
*(ULONG *)(BaseAddr+Offset) = LoadLibraryAddr;
Offset += 4;
BaseAddr[Offset] = 0xff; //call ebx
++Offset;
BaseAddr[Offset] = 0xd3;
++Offset;
BaseAddr[Offset] = 0xb8; //mov eax,Win32StartAddr
++Offset;
*(ULONG *)(BaseAddr+Offset) = Win32StartAddr;
Offset += 4;
BaseAddr[Offset] = 0x50; //push eax
++Offset;
BaseAddr[Offset] = 0xc3; //ret
++Offset;
*(ULONG *)(BaseAddr+OffsetStrAddr) = (ULONG)(BaseAddr + Offset); // parameter for LoadLibraryW
//forming string with DLL name - tunew20.dll
BaseAddr[Offset] = 't';
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
BaseAddr[Offset] = 'u';
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
BaseAddr[Offset] = 'n';
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
BaseAddr[Offset] = 'e';
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
BaseAddr[Offset] = 'w';
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
BaseAddr[Offset] = '2';
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
BaseAddr[Offset] = '0';
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
BaseAddr[Offset] = '.';
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
BaseAddr[Offset] = 'd';
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
BaseAddr[Offset] = 'l';
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
BaseAddr[Offset] = 'l';
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
BaseAddr[Offset] = 0x0;
++Offset;
DBGPRINT(("---------------Old EAX Value = 0x%08x\n",Win32StartAddr));
Win32StartAddr = (ULONG)BaseAddr;
}
//"jumping" back to previos contex.
KeDetachProcess();
//setting process start address to allocated memory
ThreadContext->Eax = Win32StartAddr;
}
}
ObDereferenceObject(pProcess);
}
UnlockProcessQueue();
RemoveProcessFromQueue(ProcessHandle);
}
ResultStatus = OldNtCreateThread(
ThreadHandle,
DesiredAccess,
ObjectAttributes,
ProcessHandle,
ClientId,
ThreadContext,
InitialTeb,
CreateSuspended);
if (ResultStatus == STATUS_SUCCESS && CreateSuspended)
{
DBGPRINT(("Kernel sucessfully create new thread.\n----->ThreadHandle = 0x%xh for ProcessHandle = 0x%x\n",*ThreadHandle,ProcessHandle));
}
return ResultStatus;
}