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

windows内核研究(系统调用 1)

WindowsAPI函数的调用过程


什么是WindowsApi?

Windows API(Application Programming Interface,应用程序编程接口)是微软为Windows操作系统提供的一套系统级编程接口,允许开发者与操作系统内核、硬件、系统服务等进行交互。它是开发Windows应用程序的基础,几乎所有Windows软件(包括系统工具、驱动程序、桌面应用等)都直接或间接依赖于Windows API

WindowsApi主要存放在C:\Windows\system32下的所有.dll文件
几个重要的DLl:

  • Kernel32.dll:最核心的功能模块,比如管理内存,进程和线程相关的函数等
  • User32.dll:是Windows用户界面相关应用程序接口,如创建窗口和发送消息等。
  • GDI32.dll:图形设备接口,包含用于画图和显示
  • NTdll.dll:大多数的Api都会通过这个dll进入内核(0环)

分析ReadProcessMemory函数

使用IDA Pro打开Kernel32.dll,这个DLL中就有ReadProcessMemory
在这里插入图片描述

在windows7系统之后 ,微软把很多内部函数的实现细节放到了KernelBase.dll这个DLL当中,Kernel32.dll在后面的系统为了兼容任然存在,这里我们直接分析KernelBase.dll

x86

在这里插入图片描述
这里就是它32位的ReadProcessMemory的代码

.text:10152910 ; BOOL __stdcall ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead)
.text:10152910                 public _ReadProcessMemory@20
.text:10152910 _ReadProcessMemory@20 proc near         ; CODE XREF: EnumProcessModulesInternal(x,x,x,x,x)+55↑p
.text:10152910                                         ; EnumProcessModulesInternal(x,x,x,x,x)+74↑p ...
.text:10152910
.text:10152910 NumberOfBytesRead= dword ptr -4
.text:10152910 hProcess        = dword ptr  8
.text:10152910 lpBaseAddress   = dword ptr  0Ch
.text:10152910 lpBuffer        = dword ptr  10h
.text:10152910 nSize           = dword ptr  14h
.text:10152910 lpNumberOfBytesRead= dword ptr  18h
.text:10152910
.text:10152910 ; FUNCTION CHUNK AT .text:101E1E90 SIZE 0000000E BYTES
.text:10152910
.text:10152910                 mov     edi, edi        ; 热补丁占用
.text:10152912                 push    ebp             ; ebp入栈
.text:10152913                 mov     ebp, esp        ; 提升堆栈
.text:10152915                 push    ecx             ; 提升栈,相当于sub esp,4
.text:10152916                 lea     eax, [ebp+NumberOfBytesRead] ; 获取ebp-4位置的地址给eax
.text:10152919                 push    eax             ; NumberOfBytesRead 参数5: 实际读取字节数的指针
.text:1015291A                 push    [ebp+nSize]     ; NumberOfBytesToRead 参数4: 要读取的字节数
.text:1015291D                 push    [ebp+lpBuffer]  ; Buffer 参数3: 目标缓冲区
.text:10152920                 push    [ebp+lpBaseAddress] ; BaseAddress 参数2: 源内存地址
.text:10152923                 push    [ebp+hProcess]  ; ProcessHandle 参数1: 进程句柄
.text:10152926                 call    ds:__imp__NtReadVirtualMemory@20 ; 调用内核函数
.text:1015292C                 mov     edx, [ebp+lpNumberOfBytesRead] ; 取lpNumberOfBytesRead指针
.text:1015292F                 test    edx, edx        ; 判断参数lpNumberOfBytesRead是否为空
.text:10152931                 jnz     short loc_10152946 ; 不等于0则跳转
.text:10152933
.text:10152933 loc_10152933:                           ; CODE XREF: ReadProcessMemory(x,x,x,x,x)+3B↓j
.text:10152933                 test    eax, eax        ; 判断是否成功执行函数
.text:10152935                 js      loc_101E1E90    ; 为负数(失败)则跳转
.text:1015293B                 mov     eax, 1          ; 成功返回1
.text:10152940
.text:10152940 loc_10152940:                           ; CODE XREF: ReadProcessMemory(x,x,x,x,x)+8F589↓j
.text:10152940                 mov     esp, ebp        ; 还原栈底
.text:10152942                 pop     ebp             ; 恢复ebp
.text:10152943                 retn    14h             ; 栈内平衡
.text:10152946 ; ---------------------------------------------------------------------------
.text:10152946
.text:10152946 loc_10152946:                           ; CODE XREF: ReadProcessMemory(x,x,x,x,x)+21↑j
.text:10152946                 mov     ecx, [ebp+NumberOfBytesRead] ; 从局部变量加载实际读取的字节数
.text:10152949                 mov     [edx], ecx      ; 写入lpNumberOfBytesRead
.text:1015294B                 jmp     short loc_10152933 ; 返回
.text:1015294B _ReadProcessMemory@20 endp

在这里插入图片描述
x64

在这里插入图片描述
这里就是它64位的ReadProcessMemory的代码

.text:00000001800BBF70 ; 由于x64的调用约定,前4个参数是由rcx,rdx,r8,r9来传递的
.text:00000001800BBF70
.text:00000001800BBF70 ; BOOL __stdcall ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead)
.text:00000001800BBF70                 public ReadProcessMemory
.text:00000001800BBF70 ReadProcessMemory proc near             ; CODE XREF: WerpReadPeb32FromProcess+EA↓p
.text:00000001800BBF70                                         ; tip2::details::recover_vector<tip2::details::TestData *>(void * const,void const *,tip2::vector_nothrow<tip2::details::TestData *> &)+3D↓p ...
.text:00000001800BBF70
.text:00000001800BBF70 NumberOfBytesRead= qword ptr -28h
.text:00000001800BBF70 var_18          = qword ptr -18h
.text:00000001800BBF70 lpNumberOfBytesRead= qword ptr  28h
.text:00000001800BBF70
.text:00000001800BBF70                 sub     rsp, 48h        ; 分配48h(72)字节的栈空间
.text:00000001800BBF74                 lea     rax, [rsp+48h+var_18] ; 获取局部变量var_18的地址
.text:00000001800BBF79                 mov     [rsp+48h+var_18], 0 ; 初始化var_18为0
.text:00000001800BBF82                 mov     [rsp+48h+NumberOfBytesRead], rax ; NumberOfBytesRead
.text:00000001800BBF87                 call    cs:__imp_NtReadVirtualMemory ; 调用内核函数
.text:00000001800BBF8E                 nop     dword ptr [rax+rax+00h] ; 什么都不做(字节对齐)
.text:00000001800BBF93                 mov     rcx, [rsp+48h+lpNumberOfBytesRead] ; 获取lpNumberOfBytesRead地址值给rcx
.text:00000001800BBF98                 test    rcx, rcx        ; 是否为null
.text:00000001800BBF9B                 jz      short loc_1800BBFA5 ; 为null则跳过
.text:00000001800BBF9D                 mov     rdx, [rsp+48h+var_18] ; 获取实际读取的字节数
.text:00000001800BBFA2                 mov     [rcx], rdx      ; 保存到lpNumberOfBytesRead指针
.text:00000001800BBFA5
.text:00000001800BBFA5 loc_1800BBFA5:                          ; CODE XREF: ReadProcessMemory+2B↑j
.text:00000001800BBFA5                 test    eax, eax        ; 校验值
.text:00000001800BBFA7                 js      short loc_1800BBFB4 ; 为负数则跳转
.text:00000001800BBFA9                 mov     eax, 1          ; 设置eax为1
.text:00000001800BBFAE                 add     rsp, 48h        ; 堆栈平衡
.text:00000001800BBFB2                 retn                    ; 返回
.text:00000001800BBFB2 ; ---------------------------------------------------------------------------
.text:00000001800BBFB3                 align 4
.text:00000001800BBFB4
.text:00000001800BBFB4 loc_1800BBFB4:                          ; CODE XREF: ReadProcessMemory+37↑j
.text:00000001800BBFB4                 mov     ecx, eax
.text:00000001800BBFB6                 call    BaseSetLastNTError ; 调用方法
.text:00000001800BBFBB                 xor     eax, eax        ; eax清0
.text:00000001800BBFBD                 add     rsp, 48h        ; 堆栈平衡
.text:00000001800BBFC1                 retn                    ; 返回

在这里插入图片描述
函数真正的实现是在NtReadVirtualMemory


分析NtReadVirtualMemory

查看导出表,可以看到是由ntdll来提供的

在这里插入图片描述
打开ntdll,打到这个方法
在这里插入图片描述

真正的实现是在0环实现的,这里只是提供了一个接口给应用程序

http://www.dtcms.com/a/269814.html

相关文章:

  • 从传统项目管理到敏捷DevOps:如何转向使用DevOps看板工具进行工作流管理
  • 谁主沉浮:人工智能对未来信息技术发展路径的影响研究
  • 优化提示词提升VLLM准确率
  • K8s——配置管理(1)
  • 构建高效分布式系统:bRPC组合Channels与HTTP/H2访问指南
  • 从单体到微服务:Spring Cloud 开篇与微服务设计
  • 微前端框架对比
  • 无缝矩阵支持音频分离带画面分割功能的全面解析
  • ​AI赋能的自动驾驶革命:从安全架构到世界模型的系统性突破
  • 【操作系统】磁盘调度
  • hmall学习
  • 2025年模型与机器学习国际会议 (ICMML 2025)
  • BM9 删除链表的倒数第n个节点
  • 计算机网络4层架构怎么理解,分别把协议和对应的层用一些生活的例子形象说明一下
  • MyBatis完全学习指南
  • 算法题练习3-判定链表是否是回文串
  • 【踩坑随笔】PlatformIO导入Arduino项目出现的问题
  • STM32第十八天 ESP8266-01S和电脑实现串口通信
  • HTTP/3.x协议详解:基于QUIC的下一代Web传输协议
  • 小红书APP品牌升级,启用新品牌口号“你的生活兴趣社区”
  • 2025年社会学与安全科学国际会议 (ICSSS 2025)
  • 【AI News | 20250707】每日AI进展
  • C++ dijkstra 最短路径算法
  • c语言学习_函数递归
  • 数学建模:非线性规划:凸规划问题
  • 【AI智能体】智能音视频-基于乐鑫 ESP32 实现音视频通话
  • ICML 2025 | TimeBridge : 巧妙化解非平稳性难题,精准预测长短结合!
  • Redis:高性能内存数据库与缓存利器
  • 验证KANO问题时合适的行为指标(如点击率、转化率等)来匹配问卷目标的一些尝试
  • 【论文翻译】用于大感受野的小波卷积 Wavelet Convolutions for Large Receptive Fields