Rootkit型木马内核ring0向用户态ring3注入代码原理

xingyun86 2017-7-15 4045


声明:原创文章,转载请注明出处(http://5e365.lofter.com/post/1d1aa3a8_660c2b6)

内核向用户态进程注入代码原理

通过KeInitializeApc、KeInsertQueueApc(未文档化函数)插入内核APC回调函数、ExQueueWorkItem插入WorkItem回调函数,附加用户进程,将注入代码复制到用户进程内存空间,最后通过一个用户APC指向注入代码,并异步得到执行。

详细流程如下:

1) PsSetLoadImageNotifyRoutine注册回调函数

2) 任意进程加载模块时,上步注册的回调函数得到执行

调用FsRtlIsNameInExpression,判断加载的是kernel32.dll,是继续执行,否则返回。
(TheFsRtlIsNameInExpression routine determines whether a Unicode string matches thespecified pattern.)


    FsRtlAllocatePool申请0x34字节内核非分页内存,用于后续APC对象及回调参数。将kernel32.dll基址存入0x34字节的最后一个DWORD中(用于APC回调函数入参)

调用KeGetCurrentThread得到当前线程对象(用于APC初始化的入参)

调用KeInitializeApc、KeInsertQueueApc(未文档化函数)插入内核APC回调函数(执行后续流程)

3) 上步插入的内核APC函数异步执行

调用ExFreePool释放APC结构体内存

FsRtlAllocatePool申请0x40字节非分页内核内存(用于后续EVENT对象、WORKITEM对象及其参数)

调用KeGetCurrentThread、PsGetCurrentProcess、PsGetCurrentThreadProcessId得到进程对象,线程对象,PID(存入上面申请的内存中,作为参数传给ExQueueWorkItem插入的回调函数)

调用KeInitializeEvent,用于同步,等待WorkItem执行完毕

调用ExQueueWorkItem插入后续流程的回调函数

调用KeWaitForMutexObject等待上面的WorkItem回调函数执行完毕

调用ExFreePool释放上面申请的0x40字节内核内存

4) 上步ExQueueWorkItem插入的回调函数执行

调用PsLookupProcessByProcessId得到EPROCESS

调用PsGetProcessImageFileName通过EPROCESS得到进程文件名

计算进程文件名的hash值与想要注入代码的进程列表做对比(包含在内继续执行,否则返回)

调用KeStackAttachProcess将当前线程附加到目标进程用户态地址空间

配置入参数ClientId,ObjectAttributes后,调用ZwOpenProcess打开目标进程

调用ZwAllocateVirtualMemory申请目标进程用户态内存

mov指令将内核中的注入代码拷贝到上步申请的用户态进程空间

调用FsRtlAllocatePool申请0x30字节内核非分页内存用于APC对象

调用KeInitializeApc,KeInsertQueueApc插入用户APC(注入代码在用户态进程执行

调用ZwClose,KeUnstackDetachProcess,ObDereferenceObject释放资源

末尾调用KeSetEvent设置事件,用于同步,通知WorkItem执行完毕

5) 上步插入的用户APC异步得到执行(注入的代码在目标进程执行)

 

至此,完成了内核态向目标用户进程注入代码并得到执行


×
打赏作者
最新回复 (1)
只看楼主
全部楼主
  • Jason 2017-8-4
    0 2
    Nothing  is  diffcult  for  a  willing  heart
返回