当前位置: 首页 > news >正文

APC学习记录

文章目录

  • 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执行完毕

代码演示

用户层被插入代码

#include<stdio.h>
#include<windows.h>void 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
#include<ntifs.h>typedef
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
);

驱动代码

#include<ntifs.h>
#include"test.h"VOID 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;
}

驱动代码中主要有两个新鲜的函数PsWrapApcWow64ThreadKeAlertThread

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
火哥视频

http://www.lryc.cn/news/210466.html

相关文章:

  • 前端将图片储存table表格中,页面回显
  • [论文阅读]Ghost-free High Dynamic Range Imaging with Context-aware Transformer
  • react高阶成分(HOC)例子效果
  • 【24种设计模式】工厂模式(Factory Pattern)
  • 树——对称二叉树
  • 拉扎维模拟CMOS集成电路设计西交张鸿老师课程P10~13视频学习记录
  • 3.线性神经网络
  • python常用内置函数的介绍和使用
  • 2023辽宁省赛E
  • visual studio 启用C++11
  • 获取某个抖音用户的视频列表信息
  • 【C语言】strcpy()函数(字符串拷贝函数详解)
  • 机器学习之IV编码,分箱WOE编码
  • 区块链技术与应用 【全国职业院校技能大赛国赛题目解析】第六套区块链系统部署与运维
  • 山西电力市场日前价格预测【2023-10-30】
  • win10虚拟机安装教程
  • 2011-2021年“第四期”数字普惠金融与上市公司匹配(根据城市匹配)/上市公司数字普惠金融指数匹配数据
  • CSP-J 2023 T3 一元二次方程 解题报告
  • 中颖单片机SH367309全套量产PCM,专用动力电池保护板开发资料
  • Android数据对象序列化原理与应用
  • Linux cp命令:复制文件和目录
  • SpringBoot 接收不到 post 请求数据与接收 post 请求数据
  • vue3学习(十四)--- vue3中css新特性
  • Python爬虫基础之Requests详解
  • C++求根节点到叶子节点数字之和
  • C++搜索二叉树
  • 软件工程17-18期末试卷
  • 课题学习(九)----阅读《导向钻井工具姿态动态测量的自适应滤波方法》论文笔记
  • 阿里云服务器—ECS快速入门
  • Hive简介及核心概念