我注入explorer.exe会崩溃
其他services.exe也是
只有注入第三方程序才正常运行
上代码
/*
* 使用APC在Winlogon进程的线程队列里面,运行指定程序
*/
NTSTATUS RunProcess(LPSTR lpProcess)
{
PRKAPC pApc = NULL; //Our APC
PVOID pMappedAddress = NULL; //This is where the UserMode routine's code will be placed at
ULONG dwSize = 0; //Size of code to be executed in Explorer's address space
ULONG *data_addr=0; //just a helper to change the address of the 'push' instruction in the ApcCreateProcess routine
ULONG dwMappedAddress = 0; //same as above
PKTHREAD pTargetThread = NULL;
PKAPC_STATE pApcState = NULL;
PLIST_ENTRY pTempList = NULL;
PLIST_ENTRY pCurrentList = NULL;
//PUCHAR lpThreadAlertable = NULL;
PULONG lpThreadAlertable = NULL;
PUCHAR lpTargetPath = NULL;
ULONG u ,un;
if (!g_EProcessWinlogon || !g_WinExec)
return STATUS_UNSUCCESSFUL;
//枚举线程
pCurrentList = (PLIST_ENTRY)((PUCHAR)(ULONG)g_EProcessWinlogon + 0x188/*BASE_KPROCESS_THREAD_OFFSET*/);
pTempList = pCurrentList;
do {
//lpThreadAlertable = /*(PUCHAR)*/(PULONG)pTempList - g_KThreadOffset.wOffsetThreadListEntry + g_KThreadOffset.wOffsetAlertable;
lpThreadAlertable = /*(PUCHAR)*/(PULONG)((ULONG)pTempList - 0x268 + 0x3c);
u = (ULONG)*lpThreadAlertable;
un = (ULONG)((u &0x0000003f)&0x20);//(a &0x0000003f)&0x20
//如果此线程的Alertable为 1 就拿它来开刀
if (un == 0x20)
{
pTargetThread = (PKTHREAD)(((ULONG)lpThreadAlertable - 0x3c/*g_KThreadOffset.wOffsetAlertable*/));
KdPrint(("Alert Thread: %08x\n", pTargetThread));
break;
}
pTempList = pTempList->Flink;
} while(pTempList != pCurrentList);
//////////////////////////////////////////////////////////////////////////
//pTargetThread = ForceTerminateProcess(g_EProcessWinlogon);
if (!pTargetThread)
return STATUS_UNSUCCESSFUL;
KdPrint(("g_EProcessWinlogon:%08x\n", g_EProcessWinlogon));
//Allocate memory for our APC
pApc = ExAllocatePool(NonPagedPool, sizeof (KAPC));
if (!pApc)
{
DbgPrint("KernelExec -> Failed to allocate memory for the APC structure");
return STATUS_INSUFFICIENT_RESOURCES;
}
//Get the size of our UserMode code
dwSize = (PUCHAR)ApcCreateProcessEnd - (PUCHAR)ApcCreateProcess;
//Allocate an MDL describing our ApcCreateProcess' memory
pMdl = IoAllocateMdl(ApcCreateProcess, dwSize, FALSE, FALSE, NULL);
if (!pMdl)
{
DbgPrint("KernelExec -> Failed to allocate MDL");
ExFreePool (pApc);
return STATUS_INSUFFICIENT_RESOURCES;
}
__try
{
//Probe the pages for Write access and make them memory resident
MmProbeAndLockPages (pMdl, KernelMode, IoWriteAccess);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("KernelExec -> Exception during MmProbeAndLockPages");
IoFreeMdl (pMdl);
ExFreePool (pApc);
return STATUS_UNSUCCESSFUL;
}
//Attach to the winlogon's address space
KeAttachProcess((PKPROCESS)g_EProcessWinlogon);
//Now map the physical pages (our code) described by 'pMdl'
pMappedAddress = MmMapLockedPagesSpecifyCache (pMdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority);
if (!pMappedAddress)
{
DbgPrint("KernelExec -> Cannot map address");
//KeUnstackDetachProcess (&ApcState);
KeDetachProcess();
IoFreeMdl (pMdl);
ExFreePool (pApc);
return STATUS_UNSUCCESSFUL;
}
else
DbgPrint("KernelExec -> UserMode memory at address: 0x%p",pMappedAddress);
dwMappedAddress = (ULONG)pMappedAddress;
lpTargetPath = (PUCHAR)(dwMappedAddress + 0x12); //执行路径的首地址
_asm
{
//CLI; //dissable interrupt
PUSH EAX;
MOV EAX, CR0; //move CR0 register into EAX
AND EAX, NOT 10000H; //disable WP bit
MOV CR0, EAX; //write register back
POP EAX;
}
memcpy((PUCHAR)pMappedAddress + 1, &g_WinExec, 4); //填写winexec地址
memset(lpTargetPath, 0, 40); //
memcpy(lpTargetPath, lpProcess, strlen(lpProcess)); //拷贝执行路径(注意长度限制40)
*(PULONG)((PUCHAR)pMappedAddress + 0x8) = (ULONG)lpTargetPath;
_asm
{
PUSH EAX;
MOV EAX, CR0;
OR EAX, 10000H;
MOV CR0, EAX;
POP EAX;
//STI;
}
//all done, detach now
KeDetachProcess();
//Initialize the APC...
KeInitializeApc(pApc,
pTargetThread,
OriginalApcEnvironment,
&ApcKernelRoutine, NULL,
pMappedAddress, UserMode, (PVOID) NULL);
//set ApcQueueable
pApcState = (PKAPC_STATE)((PUCHAR)pTargetThread + /*g_KThreadOffset.wOffsetApcState*/0x40); //just for 2003 sp1
pApcState->_PADDING0_[0] = TRUE;
pApcState->UserApcPending = TRUE;
//*(ULONG*)((ULONG)pTargetThread+0x3c) = 1;
//...and queue it
if (!KeInsertQueueApc(pApc, NULL, NULL, IO_NO_INCREMENT))
{
DbgPrint("KernelExec -> Failed to insert APC");
MmUnlockPages(pMdl);
IoFreeMdl (pMdl);
ExFreePool (pApc);
return STATUS_UNSUCCESSFUL;
}
else
{
DbgPrint("KernelExec -> APC delivered");
}
//is this a non-alertable thread?
// if(!pApcState->UserApcPending)
// {
// //if yes then alert it
// pApcState->UserApcPending = TRUE;
// }
return STATUS_SUCCESS;
}
//===================================================================//
//Name: VOID ApcKernelRoutine() //
// //
//Descripion: This routine gets called after the APC routine returns //
// (our process should have been executed by then) //
// It frees all the memory allocated by InstallUserModeApc//
// (APC and MDL) //
//===================================================================//
void ApcKernelRoutine(
IN PKAPC Apc,
IN OUT PKNORMAL_ROUTINE *NormalRoutine,
IN OUT PVOID *NormalContext,
IN OUT PVOID *SystemArgument1,
IN OUT PVOID *SystemArgument2
)
{
//这里都可以正常执行到
if (Apc)
ExFreePool(Apc);
if(pMdl)
{
MmUnlockPages(pMdl);
IoFreeMdl (pMdl);
pMdl = NULL;
}
DbgPrint("KernelExec -> ApcKernelRoutine called. Memory freed.");
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)