文章目录

  • 完善代码
  • 内核API调用
  • 修复一个潜在问题
    • 复现问题
  • 完整代码

前面几次实验我们已经完成了一个三环的程序调用零环API的必要条件。

  • 提升到零环权限
  • 使fs指向KPCR

完善代码

这次我们去掉之前的死循环代码,并且将函数地址写入到IDT表项,在虚拟机中运行一下程序,看看会有什么结果。

这里他抛出了一个内存访问异常。原因在于我们修改了fs寄存器之后,在iretd指令返回三环的时候,系统不会自动帮我们将FS寄存器还原。

所以我们在返回三环之前还需要将fs还原回去。代码如下:

__asm{push 0x30;pop fs;sti;push 0x3B;pop fs;iretd;}

再次运行我们的程序,

此时程序完全正常运行。

内核API调用

接下来我们在自己的代码中调用一个内核的API函数ExAllocatePool来分配一块内存。

首先在PC Hunter中将ntkrnlpa.exe拷贝出来,然后用IDA分析,接着设置基址和驱动模块的基地址一致。

在IDA中找到ExAllocatePool这个函数,并且记录下函数地址。

然后按Y键可以复制出函数原型,然后定义函数指针,并且将函数地址赋值给函数指针变量

typedef DWORD (__stdcall *EX_ALLOCATE)(DWORD PoolType, DWORD NumberOfBytes);
EX_ALLOCATE ExAllocatePool= (EX_ALLOCATE)0x83E51976;

接着编写调用代码如下:

void __declspec(naked) IdtEntry()
{__asm{push 0x30;pop fs;sti;}g_pool=ExAllocatePool(0, 4096);__asm{push 0x3B;pop fs;iretd;}
}

运行程序

看到这里将我们申请的内存首地址打印出来了,而且是一个内核的地址,符合我们的预期

然后我们可以尝试调用一下DbgPrint,同样的方法找到函数地址和原型进行调用

typedef DWORD ( __cdecl *DBGPRINT)(char* Format, ...);
DBGPRINT MyDbgPrint=(DBGPRINT)0x83E5541F;
char str[] = "Hello GuiShou!";void __declspec(naked) IdtEntry()
{__asm{push 0x30;pop fs;sti;}//g_pool=ExAllocatePool(0, 4096);MyDbgPrint(str);__asm{push 0x3B;pop fs;iretd;}
}

运行程序以后

在windbg窗口打印出了我们设置好的字符串,说明API调用成功

修复一个潜在问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bD6wu6Cl-1573908064431)(assets/1573905826474.png)]

仔细观察我们写的这几句还原FS段选择子返回三环的代码,实际上是有问题的。

在pop fs这句代码执行完成之后,iretd执行之前;依然是开启中断的状态,那么意味着这两行汇编指令之间CPU有可能收到时钟中断,造成线程切换。

而线程切换需要用的FS寄存器的值,然而FS这个时候是一个三环的段选择子,而我们现在却处在一个零环的环境下,FS需要指向KPCR,但是却没有指向那个位置。

就是说如果在指向这两句代码之间发生了线程切换,就会发生蓝屏。尽管产生这个问题的几率很小,但是依然不能忽视。

复现问题

接下来我们稍微修改一下代码,就能复现这个问题:

void go()
{while(1)__asm int 0x20;
}

我们在int 0x20指令加上一条死循环。当CPU产生int 20异常时,会进入到我们设置好的IdtEntry函数提权到零环,然后IdtEntry函数会重新返回到三环。接着由于int 0x20这条指令是在死循环里面。所以这个程序就会一直在三环和零环之前往返。这就会大大增加在push 0x2B;pop fs这两句代码之间发生线程切换的几率。

运行程序,在不连接调试器的情况下会直接蓝屏,如果连接上调试器则虚拟机会出现卡死现象。

解决的方法很简单,就是让CPU在执行这两句代码时不接收硬件中断

在恢复FS寄存器之前关闭中断,即可解决问题,事实上KiFastCallEntry也是这么做的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CHN5izUD-1573908064445)(assets/1573907354519.png)]

再次运行程序,此时依然是死循环,但是因为已经关闭了中断,所以循环往返三环和零环都是安全的,不会发生蓝屏和卡死的现象。

完整代码

最后附上完整的实验代码

#include "pch.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>typedef DWORD (__stdcall *EX_ALLOCATE)(DWORD PoolType, DWORD NumberOfBytes);
EX_ALLOCATE ExAllocatePool= (EX_ALLOCATE)0x83E51976;
DWORD g_pool;typedef DWORD ( __cdecl *DBGPRINT)(char* Format, ...);
DBGPRINT MyDbgPrint=(DBGPRINT)0x83E5541F;
char str[] = "Hello GuiShou!";void __declspec(naked) IdtEntry()
{__asm{push 0x30;pop fs;sti;}//g_pool=ExAllocatePool(0, 4096);//MyDbgPrint(str);__asm cli;__asm{push 0x3B;pop fs;iretd;}
} void go()
{while(1)__asm int 0x20;
}//eq 80b95500 0040ee00`00081040
int main()
{if ((DWORD)IdtEntry != 0x401040){printf("wrong addr:%p", IdtEntry);exit(-1);}go();//printf("%p\n", g_pool);system("pause");
}

Windows内核实验004 API调用相关推荐

  1. Windows内核--Rtl字符串API “不同IRQL“(3.2)

    本文将从最简单的rtl例程函数讲解不同IRQL的真正原因,其他IRQL类似. RtlCopyUnicodeString和RtlEqualUnicodeString看起来同属于rtl支持字符串例程,实际 ...

  2. Windows内核实验001 中断提权

    文章目录 实验环境 内核提权 IDT的基本知识 什么是中断 什么是IDT表 在PC Hunter中查看IDT表 中断提权的基本原理 写一个三环的小程序 修改IDT表 提权测试 本篇文章基于周壑老师的讲 ...

  3. Windows内核实验003 再次回到中断

    文章目录 两个实验 死循环 开启中断后的死循环 KiFastCallEntry 调用零环API的两个条件 分析KiFastCallEntry 什么是KPCR 完善代码 完整代码 之前的实验我们已经实现 ...

  4. Windows内核实验005 Inline Hook

    文章目录 准备工作 寻找Inline Hook的返回地址 编写代码 动态变化的返回地址 JmpTargetAddr Inline Hook基本框架 示例代码 实战HOOK KiTrap01 无需计算偏 ...

  5. Windows内核实验002 中断现场

    文章目录 如何获取中断现场环境 中段现场环境 观察中断现场堆栈环境 观察中断现场的寄存器环境 段选择子 段寄存器结构 变化的段寄存器的具体含义 遗留问题:SS段寄存器和栈顶指针来自于哪? 什么是TSS ...

  6. Windows 内核之双机调试与windbg命令大全

    在今后会有相当的实验环节,对于windows内核实验,调试环境是必不可少的,本章讲解双机调试的环境搭建与常见的WINDBG指令. 准备材料: VMware workstation : [https:/ ...

  7. Windows内核API HOOK 之 Inline Hook

    来源:CSDN   作者:daiwen 名字起得好,Inline hook,乍一听,似乎很高深.此处的Inline,我以为,意指将汇编代码直接写入内核API的内存区域.Inline Hook不像用户态 ...

  8. Windows恶意软件API调用特征分析

    本文讲的是Windows恶意软件API调用特征分析, 1.背景 目标: 1)找到病毒调用概率高的API 2)找到病毒调用概率不高,但是当调用频次高的时候,是病毒概率高的API. 通常对病毒使用API的 ...

  9. Tensorflow C++ API调用Keras模型实现RGB图像语义分割

    我的实验是基于PSPNet模型实现二维图像的语义分割,下面的代码直接从得到的h5文件开始往下做... 也不知道是自己的检索能力出现了问题还是咋回事,搜遍全网都没有可以直接拿来用的语义分割代码,东拼西凑 ...

最新文章

  1. HDU 5115 Dire Wolf 区间dp
  2. java蛮力法背包问题_[算法课]五种蛮力法解决01背包问题
  3. 使用Spring-hadoop小结
  4. html代码type,HTML中type是什么意思
  5. (王道408考研操作系统)第一章计算机系统概述-第一节3:操作系统的运行机制与体系结构
  6. 分布式训练PyTorch 源码解读
  7. JS 继承各种方法的优劣比较 ----JS 学习笔记(五)
  8. Python数据结构与算法(3.1)——栈
  9. html全屏代码怎么写,JS实现全屏的四种写法
  10. 连表查询 mysql实例_mysql中各种常见join连表查询实例总结
  11. 如何优化微信小程序排名?
  12. 机电一体化综合实训考核设备
  13. 熊猫头唱unravel——如何使图片人物表情动起来
  14. Python uniform() 函数
  15. PaddleClas预训练模型ResNet50_vd_ssld精度突破84%
  16. 李开复给大学生的第四封信---大学四年应是这样度过
  17. 剑网3 插件 取得服务器信息,剑网3服务器监控插件
  18. 虚拟服务器建网站苹果cms,苹果CMS系统建站安装步骤
  19. 第一章 程序设计与C语言
  20. 2021年广东省安全员C证第三批(专职安全生产管理人员)复审考试及广东省安全员C证第三批(专职安全生产管理人员)模拟考试

热门文章

  1. log4j.properties
  2. Appium录制脚本520-2
  3. JavaScript---事件详解
  4. 使用visualvm远程监控LINUX服务器JVM
  5. jQuery $.ajax传递数组的traditional参数传递必须true 对象的序列化
  6. POJ 1577 Falling Leaves (子母二叉树,给出叶子节点的删除序列,求前序遍历)
  7. C#---HTML 转文本及HTML内容提取
  8. Cordiality ERP MVC 3 测试作品
  9. C++成员函数在内存中的存储方式
  10. VC里的集合类、链表类、映射类