Windows内核中的执行体层暴露了大量执行体中的对象给Windows用户层的API来操作,那么用户层的API是怎么调用这些功能的呢,比如说创建一个文件,文件是一个内核对象必须得有内核层来处理,所以肯定有一个从用户层到内核层然后内核层解决再返回到用户层的一个流程。
这里以CreateFile举例:(大致流程如下)
#include<iostream>
#include<Windows.h>
using namespace std;
int main()
{
cout << "Begin" << endl;
auto hFile =CreateFileW(
L"temp.txt",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
return NULL;
}
可以看到在调用CreateFile时,是直接采用的Kernel32中的CreateFileW函数:
然后跟进Kernel32.CreateFileW函数中:
会跳转到KernelBase中的CreateFileW函数中,继续步入查看:
一直往下翻才能看到NtCreateFile函数,前面的我猜是给创建新文件所需进行初始化的一些代码。
正所谓前人栽树后人乘凉,书上的大牛写的是调用ntdll中的NtCreateFile我们就不要怀疑了,然后步入Ntdll.NtCreateFile查看:
这里的call esi就是调用NtCreateFile的地方,然后继续步入查看:
就成了这样子,这个我也不知道什么意思,就继续call dword ptr ds:[edx]查看:
最后的最后是由三个汇编指令为结尾:
mov edx,esp
sysenter
retn
retn是返回指令,表示已经执行完成。
sysenter在od中无法看到,不管是步入还是步过只会直接执行完跳过。
所以目前而言的API调用过程是这样的:
现在不理解的就是NtCreateFile函数内部的代码逻辑:
mov eax,xx
mov edx,xxx
call dword ptr ds:[edx]
retn xxx
...
mov edx,esp
sysenter
这几行汇编代码是什么意思。
首先是NtCreateFile中的第一层汇编代码:
mov eax,xx
mov edx,xx
call dword ptr ds:[edx]
retn xxx
这附近的汇编代码都是这样的样式:
这里的eax叫做系统服务号,它代表进入0环后,调用那一个API,就类似于数组和下标的关系,根据下标一对一对应内核中的某一个API,然后内核调用内核的对应的API。
也就是说由eax的值来决定内核API的调用。
所有通过ntdll调用的函数,给edx所传递的值都是一样的,这里都是0x7FFE0300。
该值是_KUSER_SHARED_DATA结构体的一个成员,该结构体所在的内存空间是一个提供给User层和Kernel层共享的一个内存空间,该空间主要用来在User和Kernel之间快速传递信息。
该结构体所在的内存空间是固定的:User层下:0x7FFE0000,Kernel层下:0xFFDF0000。
//0x5f0 bytes (sizeof)
struct _KUSER_SHARED_DATA
{
ULONG TickCountLowDeprecated; //0x0
ULONG TickCountMultiplier; //0x4
volatile struct _KSYSTEM_TIME InterruptTime; //0x8
volatile struct _KSYSTEM_TIME SystemTime; //0x14
volatile struct _KSYSTEM_TIME TimeZoneBias; //0x20
USHORT ImageNumberLow; //0x2c
USHORT ImageNumberHigh; //0x2e
WCHAR NtSystemRoot[260]; //0x30
ULONG MaxStackTraceDepth; //0x238
ULONG CryptoExponent; //0x23c
ULONG TimeZoneId; //0x240
ULONG LargePageMinimum; //0x244
ULONG Reserved2[7]; //0x248
enum _NT_PRODUCT_TYPE NtProductType; //0x264
UCHAR ProductTypeIsValid; //0x268
ULONG NtMajorVersion; //0x26c
ULONG NtMinorVersion; //0x270
UCHAR ProcessorFeatures[64]; //0x274
ULONG Reserved1; //0x2b4
ULONG Reserved3; //0x2b8
volatile ULONG TimeSlip; //0x2bc
enum _ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; //0x2c0
ULONG AltArchitecturePad[1]; //0x2c4
union _LARGE_INTEGER SystemExpirationDate; //0x2c8
ULONG SuiteMask; //0x2d0
UCHAR KdDebuggerEnabled; //0x2d4
UCHAR NXSupportPolicy; //0x2d5
volatile ULONG ActiveConsoleId; //0x2d8
volatile ULONG DismountCount; //0x2dc
ULONG ComPlusPackage; //0x2e0
ULONG LastSystemRITEventTickCount; //0x2e4
ULONG NumberOfPhysicalPages; //0x2e8
UCHAR SafeBootMode; //0x2ec
union
{
UCHAR TscQpcData; //0x2ed
struct
{
UCHAR TscQpcEnabled:1; //0x2ed
UCHAR TscQpcSpareFlag:1; //0x2ed
UCHAR TscQpcShift:6; //0x2ed
};
};
UCHAR TscQpcPad[2]; //0x2ee
union
{
ULONG SharedDataFlags; //0x2f0
struct
{
ULONG DbgErrorPortPresent:1; //0x2f0
ULONG DbgElevationEnabled:1; //0x2f0
ULONG DbgVirtEnabled:1; //0x2f0
ULONG DbgInstallerDetectEnabled:1; //0x2f0
ULONG DbgSystemDllRelocated:1; //0x2f0
ULONG DbgDynProcessorEnabled:1; //0x2f0
ULONG DbgSEHValidationEnabled:1; //0x2f0
ULONG SpareBits:25; //0x2f0
};
};
ULONG DataFlagsPad[1]; //0x2f4
ULONGLONG TestRetInstruction; //0x2f8
ULONG SystemCall; //0x300
ULONG SystemCallReturn; //0x304
ULONGLONG SystemCallPad[3]; //0x308
union
{
volatile struct _KSYSTEM_TIME TickCount; //0x320
volatile ULONGLONG TickCountQuad; //0x320
ULONG ReservedTickCountOverlay[3]; //0x320
};
ULONG TickCountPad[1]; //0x32c
ULONG Cookie; //0x330
ULONG CookiePad[1]; //0x334
LONGLONG ConsoleSessionForegroundProcessId; //0x338
ULONG Wow64SharedInformation[16]; //0x340
USHORT UserModeGlobalLogger[16]; //0x380
ULONG ImageFileExecutionOptions; //0x3a0
ULONG LangGenerationCount; //0x3a4
ULONGLONG Reserved5; //0x3a8
volatile ULONGLONG InterruptTimeBias; //0x3b0
volatile ULONGLONG TscQpcBias; //0x3b8
volatile ULONG ActiveProcessorCount; //0x3c0
volatile USHORT ActiveGroupCount; //0x3c4
USHORT Reserved4; //0x3c6
volatile ULONG AitSamplingValue; //0x3c8
volatile ULONG AppCompatFlag; //0x3cc
ULONGLONG SystemDllNativeRelocation; //0x3d0
ULONG SystemDllWowRelocation; //0x3d8
ULONG XStatePad[1]; //0x3dc
struct _XSTATE_CONFIGURATION XState; //0x3e0
};
edx是该结构体中的SystemCall成员,该结构体成员指定了从User层到Kernel层的调用方式,这里我们可以通过WinDbg来查看一下:
kd> dt nt!_KUSER_SHARED_DATA 0xFFDF0000
+0x000 TickCountLowDeprecated : 0
+0x004 TickCountMultiplier : 0xf99a027
+0x008 InterruptTime : _KSYSTEM_TIME
+0x014 SystemTime : _KSYSTEM_TIME
+0x020 TimeZoneBias : _KSYSTEM_TIME
+0x02c ImageNumberLow : 0x14c
+0x02e ImageNumberHigh : 0x14c
+0x030 NtSystemRoot : [260] "C:\Windows"
+0x238 MaxStackTraceDepth : 0
+0x23c CryptoExponent : 0
+0x240 TimeZoneId : 0
+0x244 LargePageMinimum : 0x200000
+0x248 Reserved2 : [7] 0
+0x264 NtProductType : 1 ( NtProductWinNt )
+0x268 ProductTypeIsValid : 0x1 ''
+0x26c NtMajorVersion : 6
+0x270 NtMinorVersion : 1
+0x274 ProcessorFeatures : [64] ""
+0x2b4 Reserved1 : 0x7ffeffff
+0x2b8 Reserved3 : 0x80000000
+0x2bc TimeSlip : 0
+0x2c0 AlternativeArchitecture : 0 ( StandardDesign )
+0x2c4 AltArchitecturePad : [1] 0
+0x2c8 SystemExpirationDate : _LARGE_INTEGER 0x0
+0x2d0 SuiteMask : 0x110
+0x2d4 KdDebuggerEnabled : 0x3 ''
+0x2d5 NXSupportPolicy : 0x2 ''
+0x2d8 ActiveConsoleId : 1
+0x2dc DismountCount : 0
+0x2e0 ComPlusPackage : 0xffffffff
+0x2e4 LastSystemRITEventTickCount : 0
+0x2e8 NumberOfPhysicalPages : 0x3ff7e
+0x2ec SafeBootMode : 0 ''
+0x2ed TscQpcData : 0 ''
+0x2ed TscQpcEnabled : 0y0
+0x2ed TscQpcSpareFlag : 0y0
+0x2ed TscQpcShift : 0y000000 (0)
+0x2ee TscQpcPad : [2] ""
+0x2f0 SharedDataFlags : 0xe
+0x2f0 DbgErrorPortPresent : 0y0
+0x2f0 DbgElevationEnabled : 0y1
+0x2f0 DbgVirtEnabled : 0y1
+0x2f0 DbgInstallerDetectEnabled : 0y1
+0x2f0 DbgSystemDllRelocated : 0y0
+0x2f0 DbgDynProcessorEnabled : 0y0
+0x2f0 DbgSEHValidationEnabled : 0y0
+0x2f0 SpareBits : 0y0000000000000000000000000 (0)
+0x2f4 DataFlagsPad : [1] 0
+0x2f8 TestRetInstruction : 0xc3
+0x300 SystemCall : 0x76f46c00
+0x304 SystemCallReturn : 0x76f46c04
+0x308 SystemCallPad : [3] 0
+0x320 TickCount : _KSYSTEM_TIME
+0x320 TickCountQuad : 0x9806
+0x320 ReservedTickCountOverlay : [3] 0x9806
+0x32c TickCountPad : [1] 0
+0x330 Cookie : 0xccc8c182
+0x334 CookiePad : [1] 0
+0x338 ConsoleSessionForegroundProcessId : 0n1504
+0x340 DEPRECATED_Wow64SharedInformation : [16] 0
+0x380 UserModeGlobalLogger : [16] 0
+0x3a0 ImageFileExecutionOptions : 0
+0x3a4 LangGenerationCount : 1
+0x3a8 Reserved5 : 0
+0x3b0 InterruptTimeBias : 0
+0x3b8 TscQpcBias : 0
+0x3c0 ActiveProcessorCount : 1
+0x3c4 ActiveGroupCount : 1
+0x3c6 Reserved4 : 0
+0x3c8 AitSamplingValue : 0
+0x3cc AppCompatFlag : 1
+0x3d0 DEPRECATED_SystemDllNativeRelocation : 0
+0x3d8 DEPRECATED_SystemDllWowRelocation : 0
+0x3dc XStatePad : [1] 0
+0x3e0 XState : _XSTATE_CONFIGURATION
+0x300 SystemCall : 0x76f46c00,该字段存放着函数的调用地址,结合前面的内容可以看到确实是该地址:
//然后反汇编查看一下该函数的内容:
kd> u 0x76f46c00
ntdll!KiFastSystemCall:
76f46c00 ?? ???
^ Memory access error in 'u 0x76f46c00'
这个函数的名字叫做KiFastSystemCall
那么这一段汇编代码:
mov eax,xx
mov edx,xx
call dword ptr ds:[edx]
retn xxx
就可以抽象成一个函数:
KiFastSystemCall()//当然里面肯定有参数
那么图就可以变成这样子:
然后重点就来到了剩下的两个。
这个其实就是函数传参,参数在栈里面,然后把栈的首地址交给edx。
sysenter才是整个调用的关键。
整个调用方式最关键的就是通过sysenter从User层到达Kernel层,可以说前面的都是在给这一步做铺垫。
sysenter叫做快速系统调用,叫快速是因为之前的系统调用不快,在Pentium II(奔腾2代CPU)之后才有的sysenter,在其之前是采用的 KiIntSystemCall函数来处理的。
在IDA下查看:该函数:
; Exported entry 109. KiIntSystemCall
; _DWORD __stdcall KiIntSystemCall()
public _KiIntSystemCall@0
_KiIntSystemCall@0 proc near
arg_4= byte ptr 8
lea edx, [esp+arg_4]
int 2Eh ; DOS 2+ internal - EXECUTE COMMAND
; DS:SI -> counted CR-terminated command string
retn
_KiIntSystemCall@0 endp
这里的int 2Eh,采用的就是一种CPU机制,叫做中断门:
Windows内核中的CPU架构-6-中断门(32-Bit Interrupt Gate) - Sna1lGo - 博客园 (cnblogs.com)(https://www.cnblogs.com/Sna1lGo/p/15515746.html)
这样调用会用到内存,比较麻烦,所以就引入了快速系统调用:
sysenter/sysexit 两个函数和三个MSR寄存器。
MSR寄存器比较类似内存,直接根据序号来命名,没有像通用寄存器EAX,EBX一样,单独命名。
和sysenter连用的是MSR174和,MSR175,MSR176三个寄存器。
sysenter内部逻辑为:
//1:设置寄存器
CS = IA32_SYSENTER_CS
SS = IA32_SYSENTER_CS+8
eip = IA32_SYSENTER_EIP
esp = IA32_SYSENTER_ESP
//2:切换特权级
切换到0环特权级,(其实设置了寄存器就是切换了)
//3:切换CPU模式
清楚eflags寄存器中的虚拟8086模式(VM标志)
//4:执行
执行系统例程调用
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/8bY6ldO2qNdEB3oU8Vnk3A
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。