电商网站排行榜,wordpress 微信二维码登录,深圳网站设计比较好的公司有哪些,网站怎样恶意刷文章目录 APC概念APC插入、执行过程逆向分析插入过程执行过程总结 代码演示参考资料 APC概念
APC全称叫做异步过程调用#xff0c;英文名是 Asynchronous Procedure Call#xff0c;在进行系统调用、线程切换、中断、异常时会进行触发执行的一段代码#xff0c;其中主要分为… 文章目录 APC概念APC插入、执行过程逆向分析插入过程执行过程总结 代码演示参考资料 APC概念
APC全称叫做异步过程调用英文名是 Asynchronous Procedure Call在进行系统调用、线程切换、中断、异常时会进行触发执行的一段代码其中主要分为内核APC与用户APC故名思意内核APC在执行时APC的代码在内核用户APC在执行时代码在用户层。
APC是依赖于线程的所以在线程的KTHREAD中可以找到关于APC的所有相关信息
APC插入、执行过程逆向分析
插入过程
因为APC的插入会调用KeInsertQueueApc我们逆向分析这个函数即可 插入过程很简单KeInsertQueueApc其实是在判断APC队列是否禁用或APC是否插入对应的WRK代码如下 继续跟入KiInsertQueueApc其中也是根据各种APC模式来进行插入位置的选择 对应的WRK代码如下 这里就不继续往下面跟了感兴趣可以仔细阅读WRK的代码和注释
执行过程
APC执行调用的是KiDeliverApc函数其中会先执行KernelRoutine中的代码如果NormalRoutine不为空则调用KiInitializeUserApc对用户APC进行初始化操作
KiInitializeUserApc通过KeContextFromKframes将KTRAP_FRAME保存一份以便后续返回使用 修改EIP使其跳转到三环的KeUserApcDispatcher执行用户的APC代码 以上分析对应的WRK代码如下也可以看出先执行KernelRoutine后执行NormalRoutine
总结
插入过程主要是根据参数决定APC插入链表的位置 执行过程主要是先执行参数的KernelRoutine的代码如果有NormalRoutine则跳到三环去遍历执行再回到内核以此往复将链表中的所有APC执行完毕
代码演示
用户层被插入代码
#includestdio.h
#includewindows.hvoid haha()
{printf(APC被执行了!\n);
}int main()
{printf(pid:%d 函数地址:%x \n, GetCurrentThreadId(), haha);while (1){SleepEx(30000,FALSE);printf(qqqqqqqqqqqq\n);}
}驱动头文件“test.h”
#pragma once
#includentifs.htypedef
VOID
(*PKNORMAL_ROUTINE) (IN PVOID NormalContext,IN PVOID SystemArgument1,IN PVOID SystemArgument2);typedef
VOID
(*PKRUNDOWN_ROUTINE) (IN struct _KAPC* Apc);typedef
VOID
(*PKKERNEL_ROUTINE) (IN struct _KAPC* Apc,IN OUT PKNORMAL_ROUTINE* NormalRoutine,IN OUT PVOID* NormalContext,IN OUT PVOID* SystemArgument1,IN OUT PVOID* SystemArgument2);typedef enum _KAPC_ENVIRONMENT {OriginalApcEnvironment,AttachedApcEnvironment,CurrentApcEnvironment,InsertApcEnvironment
} KAPC_ENVIRONMENT;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 ApcMode,__in_opt PVOID NormalContext
);BOOLEAN KeInsertQueueApc(__inout PRKAPC Apc,__in_opt PVOID SystemArgument1,__in_opt PVOID SystemArgument2,__in KPRIORITY Increment
);BOOLEAN
KeAlertThread(__inout PKTHREAD Thread,__in KPROCESSOR_MODE AlertMode
);驱动代码
#includentifs.h
#includetest.hVOID DriverUnload(_In_ struct _DRIVER_OBJECT* DriverObject)
{DbgPrint(--------------DRIVER_UNLOAD-----------------);
}VOID kernelRoutineFunc(IN struct _KAPC* Apc,IN OUT PKNORMAL_ROUTINE* NormalRoutine,IN OUT PVOID* NormalContext,IN OUT PVOID* SystemArgument1,IN OUT PVOID* SystemArgument2
)
{DbgPrintEx(77, 0, [db]:---------kernelRoutineFunc pid %d--------------\r\n, PsGetCurrentProcessId());DbgPrintEx(77, 0, [db]:kernelRoutineFunc\r\n);ULONG64 addr 0x401000;PsWrapApcWow64Thread(NULL, addr);*NormalRoutine addr;ExFreePool(Apc);
}NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
{PKAPC pApc ExAllocatePool(NonPagedPool, sizeof(KAPC));memset(pApc, 0, sizeof(KAPC));PETHREAD eThread NULL;PsLookupThreadByThreadId(2632, eThread);KeInitializeApc(pApc, eThread, OriginalApcEnvironment,kernelRoutineFunc, NULL, 0x401000, UserMode, (PVOID)1);DbgBreakPoint();*(PCHAR)((PCHAR)eThread 0x4c) | 0x20;BOOLEAN is KeInsertQueueApc(pApc, eThread, NULL, 0);if (!is){ExFreePool(pApc);}KeAlertThread(eThread, UserMode);pDriverObject-DriverUnload DriverUnload;return STATUS_SUCCESS;
}驱动代码中主要有两个新鲜的函数PsWrapApcWow64Thread与KeAlertThread
PsWrapApcWow64Thread为了将32位的地址进行转换到64位进行使用这样驱动就可以直接在64位下进行插入如果读者想修改成32位可以把这个函数删除并将eThread 0x4c改为eThread 0x3c
KeAlertThread可以立即执行我们插入的APC函数
参考资料
https://www.cnblogs.com/sanyimitian/p/14219541.html https://blog.csdn.net/hongduilanjun/article/details/126850904 火哥视频