APC Injection of Windows 7 x86 in R0
APC Injection of Windows 7 x86 in R0IntroductionWhen running in kernel mode,it may be necessary to inject code into a User-land process. We can use the Asynchronous Procedure Calls(APCs) to accomplish this goal. An APC can "borrow" a process thread that is in an idle alertable state,and while it relies on structures whose offset change between versions of Microsoft Windows,it is one of the most reliable and easiest way to exit kernel mode and enter user mode. In this article,I write some basic knowledge of APC and finished a sample of APC injection which can pop a calculator in windows 7 x86. Base code is shamelessly stolen from Justgoon .For more information,you can click the link to see his original article : x64与x64下内核APC注入(有码)
What is APCs? According to the MSND: An asynchronous procedure call (APC) is a function that executes asynchronously in the context of a particular thread. When an APC is queued to a thread,the system issues a software interrupt. The next time the thread is scheduled,it will run the APC function. An APC generated by the system is called a kernel-mode APC. An APC generated by an application is called a user-mode APC. A thread must be in an alertable state to run a user-mode APC. ? Each thread has its own APC queue. When a user-mode APC is queued,the thread to which it is queued is not directed to call the APC function unless it is in an alertable state. A thread enters an alertable state when it calls the SleepEx,SingnalObjectAndWait,MsgWaitForMultipleObjectsEx,WaitForMultipleObjetsEx,or WaitForSingleObjectEx function. If the wait is satisfied before the APC is queued,the thread is no longer in an alertable state so the APC function will not be executed. However,the APC is still queued,so the APC function will be executed when the thread calls another alertable wait function. We can use the The _KAPC structure. This is the Kernel Object of the APC. kd> dt _kapc ntdll!_KAPC +0x000 Type : //Type of ApcObject +0x001 SpareByte0 : +0x002 Size : +0x003 SpareByte1 : +0x004 SpareLong0 : +0x008 Thread : //_KTHREAD of current thread +0x00c ApcListEntry : //APC queue of current thread +0x014 KernelRoutine : +0x018 RundownRoutine : +0x01c NormalRoutine : +0x020 NormalContext : // +0x024 SystemArgument1 : +0x028 SystemArgument2 : +0x02c ApcStateIndex : // Apc State +0x02d ApcMode : // UserMode or KernelMode +0x02e Inserted : // inserted into the queue? APC queue information in the _KTHREAD kd> dt _kthread ntdll!_KTHREAD ... +0x040 ApcState : _KAPC_STATE +0x040 ApcStateFill : [23] UChar ... In the _KAPC_STATE,the last filed determined if the user APC function be called. kd> dt _KAPC_STATE ntdll!_KAPC_STATE +0x000 ApcListHead : [2] _LIST_ENTRY +0x010 Process : Ptr32 _KPROCESS +0x014 KernelApcInProgress : UChar +0x015 KernelApcPending : UChar +0x016 UserApcPending : UChar // work when set to 1 How to Insert a APC into a processTo insert a APC in the process from r0 to r3,essentially performs the following:
CodeHeader.h #include<ntifs.h> #include<ntddk.h> //Some type #define POINTER ULONG //EPROCESS OFFSET #define OBJECTTABLE_OFFSET 0xf4 #define IMAGEFILENAME_OFFSET 0x16c #define ACTIVEPROCESSLINKS_OFFSET 0xb8 #define THREADLISTHEAD_OFFSET 0x188 //ETHREAD OFFSET #define THREADLISTENTRY_OFFSET 0x268 //KTHREAD OFFSET #define TEB_OFFSET 0x88 #define USERAPCPENDING_OFFSET 0x56 // typedef enum _KAPC_ENVIRONMENT { OriginalApcEnvironment,AttachedApcEnvironment,CurrentApcEnvironment } KAPC_ENVIRONMENT; // VOID DriverUnload(IN PDRIVER_OBJECT pDrvObj); VOID ThreadFunc(IN PVOID pParam); BOOLEAN InsertApc(POINTER tarEthread,POINTER addrAllocMem,PKEVENT pKevent); BOOLEAN FindTargetEProcessAndEthread(POINTER* ptarEprocess,POINTER* ptarEthread); void UserExec(); void UserExec_end(VOID); /* Function prototypes for APCs */ VOID KeInitializeApc( PKAPC Apc,PKTHREAD Thread,CCHAR ApcStateIndex,PVOID KernelRoutine,PVOID RundownRoutine,PVOID NormalRoutine,KPROCESSOR_MODE ApcMode,PVOID NormalContext ); INT KeInsertQueueApc( PKAPC Apc,PVOID SystemArgument1,PVOID SystemArgument2,UCHAR unknown ); VOID KernelApcCallback(PKAPC Apc,PVOID *NormalRoutine,PVOID *NormalContext,PVOID* SystemArg1,PVOID* SystemArg2); (编辑:ASP站长网) |