Programming 板


LINE

这篇文章整理几个名词的简介,以後看到时可以比较清楚状况。 KiFastSystemCall 在 ntdll.dll 内的一个函数,与 system call 有关 WinDbg 可能叫它 SharedUserData!SystemCallStub,是别名 sysenter 约 Pentium II 以後,x86 指令集新增的指令,与前项有关 IDT 每台 PC 开机後就会有的中断描述表,由 CPU 管理 有被人叫「中断向量表」(Interupt Vector Table) SSDT Windows Kernel 掌管的系统服务表,调用「内核函数」时使用 一切都是围绕在 user mode 切换到 kernel mode 的情景,且以 Windows 为主。 ######################### 我们替程式做侦错 (Debug、调试),偶尔会想要进入某个 Windows API 函数内, 於是一直做单步追踪,往往追到 ntdll!KiFastSystemCall 附近,就跟不下去了。 这是因为一般的 Debugger 只能调试 user mode 的程式, (除非用 Live KD 这类 Kernel Debugger,才能进去看) 而 ntdll.dll 可以称作「user mode 与 kernel mode 之墙」。 假设写 C 程式码,什麽事都不做,只呼叫了一个 kernel32!OpenProcess 函数。 编译并用 Dependency Walker 检查执行档的「汇入表」,可以发现这个 .exe 必须 相依於 kernel32.dll。 当再用 OllyDbg 或 WinDbg 去调试此执行档,并中断在 main() 开头, 此时检查「载入模组」,会发现 ntdll.dll 跟 kernel32.dll 都被载入了。 而且 RunTime 下,这些 dll 载入的记忆体位址,都是小於 0x80000000。 换言之,都只能待在 user address space 里面。 这是因为「开启行程」这个动作,必须操作 Windows Kernel 掌管的资料, 位於 user mode 者,无法存取这些记忆体, 於是 Windows 开放了「行程操作相关」的介面,并放到 kernel32.dll 里。 kernel32.dll 同样还是 user mode 的程式,当它做好一些前置工作後, (比如把 ANSI 字串转成 Unicode 字串,这类准备工作) 最终才会经由 ntdll.dll 这道墙切换到 kernel mode 里去。 就好像用 gdi32.dll 里的绘图函数,最终还是要相依於 ntdll.dll,才能切换到 kernel mode,才能让里面的显示卡 Driver 去控制硬体输出内容。 而 ntdll.dll 里面,负责切换至 kernel mode 工作的,就是 KiFastSystemCall 函数。 所以侦错往往只能追到这里,就跟不下去。 Ki 开头,可以理解此函数会接触到 Kernel, System Call 是指任何待在 Kernel Mode 里,某程式的某函数, 我们去调用该函数,就是调用 Sysyem Call。 以下来解释,这个 Fast 的意思为何。 在没有安装作业系统前,由主机板内的 BIOS 程式码负责开机,并且操控硬碟、显示卡 ...等硬体。 且正常的 BIOS 都会开放操纵介面, 使得只要利用 int 这个 cpu 指令,再搭配一个索引数字就能呼叫之。 比如 int 13h: 命令 BIOS 去读取某个硬碟 Sector 的内容,并且放到主记忆体的某处。 这段 BIOS 读取硬碟的函数,在开机时会载入到主记忆体, 先假设是放在位址 0x100, 然後 BIOS 再对 CPU 注册,说把第 19 号服务放在 0x100。 这个告知的动作,就是利用 CPU 的 IDTR 暂存器,来找出 IDT 表,并在第 19 项里, 填入 0x100 的内容,当下次 CPU 执行到 int 13h 时,就会跳去 0x100 来执行。 而 IDTR 暂存器的大小为 48 位元,前 32 位元记载「IDT」在主记忆体的存放处, 後 16 位元记载表格 Size。 IDT 全名为 Interrupt Descriptor Table (中断描述表),里面最多可以 记载 256 个中断服务的位址 (int 00h ~ int ffh)。而中断服务的英文 为 ISR (Interrupt Service Routine)。 IDT 详细解释,可参考〈IDT系列:(一)初探IDT,Interrupt Descriptor Table, 中断描述符表〉一文: http://blog.csdn.net/fwqcuc/archive/2010/09/01/5855460.aspx 如果在 Windows 下,想查看 IDT 的内容,想知道是不是还能用 int 13h 命令 BIOS 读取硬碟磁区,可以使用软体 SysReveal,并进入 IDT 页查看。进去後,预设 只会显示被 IDT hook 的项目,按右键把「Show hooks Only」取消即可。 事实上进入 Windows 後,这类系统操作都被 Windows Kernel 或各硬体 Driver 掌管, 原本的 IDT 都被改过了,指向 C:\WINDOWS\system32\ntoskrnl.exe 里的函数。 ntoskrnl.exe 全部都运行在 Kernel Address Space 里,比如在 C 程式码内写 inline assembly: __asm int 03h 并且用 Visual C++ 进行侦错,不设中断点。当 CPU 执行到该指令时, 就会由 IDT 查到目标为 ntoskrnl.exe 里的某函数,位址在 0x804E089D, 然後不透过 ntdll.dll 就跳到 Kernel Mode 里的 system call,呼叫 该目前负责该行程的 Debugger 中断在该行,让操作调试器者可以进行观察。 如果找不到 Debugger 就由 Windows 决定要如何处理。 这个 int 03h 是少数不用透过 ntdll.dll 呼叫 system call 的状况,因为你甚至 也没有调用 Windows API 函数,来达成目的。 而在 Windows 2000 (含) 以前的时代,透过某 Windows API 要进入 Kernel Mode 时, 也是使用 ntdll.dll,差别是,那时没有 KiFastSystemCall 这东西。 因为 KiFastSystemCall 的底层,是使用一个新的 IA-32 指令:sysenter 这个指令大约是在 Pentium II 时期,Intel 加入的 CPU 指令 (同时期的 AMD 是 K6)。 而直到 Windows XP,微软才把 OS 最低需求,设为 Pentium 家族 233 Mhz 以上。 (至少要有 Pentium II 以上等级,时脉才有 233 Mhz),因为 KiFastSystemCall 就是 在 Windows XP 以後出现。 在 Windows 2000 调用 System Call 是使用原始的 IDT 与 int 2Eh 这个方法。 假设今天调用 kernel32!ReadFile 要做动作,最後会来到 ntdll!NtReadFile 里: ntdll!NtReadFile: 77f8c552 mov eax, 0xA1 77f8c557 lea edx, [esp+0x4] 77f8c55b int 2E 77f8c55d ret 0x24 因为需要的参数都已经 push 到堆叠里去了, 所以透过 lea 指令,於 RunTime 算出参数区的起始位址,放到 edx 暂存器, 再指定目标 System Call 的编号到 eax 暂存器,此例为 A1h, 最後是利用 int 2Eh 触发,而 ret 0x24 是平衡堆叠,并回到上个 Stack Frame 去。 这个 int 2Eh 在 IDT 里记载的位址假设为 0x8053A2FB, 这是对应到 nt!KiSystemService 函数,进去後会查出 A1h 所指的 System Call 其实 是 nt!NtReadFile 函数,再透过其进行硬体的读取操作。 (nt! 里的 nt 不是指 nt.dll 而是专指 ntoskrnl.exe) 在 Windows XP 时,调用 System Call 是使用 ntdll!KiFastSystemCall,在这个函数 里面,会透过 CPU 新的 sysenter 指令,还有新的几个 MSR 暂存器记录相关资料, 来高速的从 user mode (ring 3) 切换到 kernel mode (ring 0), 并呼叫里面的 System Call。 sysenter 比较快的其中一个原因是,int 指令会先把当下某些暂存器的内容, 先存到记忆体去,然後才切换到目标 ISR,而 sysenter 有 MSR 暂存器的辅助, 就可以省略记忆体读取的动作。 以 kernel32!OpenProcess 举例,最终会来到 ntdll!NtOpenProcess: (有可能调试器是写 ntdll!ZwOpenProcess,总之位址应该一样,纯粹是别名; 好像 ntdll 里面,ZwXXX 跟 NtXXX 一定是指同个函数?) 1. mov eax, 7Ah 2. mov edx, 7FFE0300h 3. call dword ptr [edx] 4. retn 10h 5. mov edx, esp 6. sysenter 第四行的目的就不用讲了。 第一行的 7Ah 是将来指定 System Call 的识别号码用,稍後再谈。 第二行跟第三行指令的目的,就是为了要进入 KiFastSystemCall 函数, 也就是上面的第五行与第六行指令。 第五行指令的动作,就跟 Windows 2000 的版本的那个 lea 一样,是为了传送 System Call 所需的参数起始位址。因为 Kernel Mode 运行的程式,有自己的 Stack,这通常 是位於 Kernel Address Sapce 的某处。 所以要把现在 User Mode Stack 的顶端,从现在的 ESP 里拿出来,记於 edx 里。 而第六行的 sysenter 会利用 MSR 暂存器设置环境,而不再像 int 指令一样用记忆体。 设置环境後,就切换到 ring 0 执行 ntoskrnl.exe 里的 nt!NtOpenProcess。 在进入 ring 0 後,事实上会先到 ntoskrnl.exe (Windows Kernel) 里找出所谓的 SSDT (System Services Descriptor Table,系统服务描述符表)。 并从 SSDT 里查出识别号为 0x7A 时,也就是查询该表格的第 122 项,对应的是 哪个内核函数。 简单来说利用 KiFastSystemCall (sysenter) 帮助我们快速切换到 Ring 0,并利用 SSDT 来查询出 kernel32.dll 里的 OpenProcess 这个 user mode 函数,是对应 到 kernel mode 内的 (模组的) 哪个函数。 而所谓的 SSDT hook 是比如某个游戏防作弊的程式,他把自己写成 Driver 档, 於是可以运行在 Kernel Mode 里,而且他更改了 SSDT 里的表格项,比如第 n 项, 原本是用来让 kernel32!CreateProcess 转成 nt!NtCreateProcess 的。 被其修改掉,导向至他自己的 Driver,然後每次有程式调用 CreateProcess 时, 这个 Driver 就检查开启目标是否为该游戏,如果是该游戏,就禁止开启,返回 user mode,如果不是就放行。 使任何想要用 CreateProcess 开启游戏程式,并动手脚的软体都失效,这就是所谓的 SSDT hook。同样可以用 SysReveal 软体,查询 SSDT 的完整内容,以及有哪个表项 被人偷偷 SSDT hook 了。 ######################### 以下为参考来源与延伸资料,可找到更完整的技术细节: 城里城外看SSDT - 李马: http://blog.titilima.com/ssdt.html HOOK SYSENTER: http://kost0911.pixnet.net/blog/post/36476081 修正: 关於 〈HOOK SYSENTER〉一文,最早原创似乎来自 gotiger 的网站: http://hi.baidu.com/gotiger/blog/item/c6d8bb90fe834e13d31b705d.html 上面 kost0911 站的残月影,疑似转载,特於此补充说明。 sysenter/sysexit - 红尘万丈 - Yahoo!奇摩部落格: http://tw.myblog.yahoo.com/jw!tzeXibOaEQUcL.ja6fRpXFg-/article?mid=179 Windows XP/2003 系统调用(一): http://blog.csdn.net/better0332/archive/2009/06/15/4269554.aspx 有错麻烦指正,有建议或补充还请提出,谢谢。 保留文章出处,转载可。 --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 124.8.146.225
1F:推 akasan:好文推 虽然我不在MS的世界XD 61.60.218.62 03/27 01:15
谢谢 ※ 编辑: purpose 来自: 124.8.129.73 (03/27 07:32)
2F:推 horngsh:好文一篇! 赞! 112.104.148.1 03/27 11:12
3F:推 zha0:CVC ?220.135.121.210 03/29 10:40
4F:→ purpose:cvc? 124.8.139.17 03/29 12:11
5F:推 loteslogin:气质140.111.148.157 03/29 13:53
6F:推 VictorTom:推:)115.248.178.161 03/30 23:17
从CreateFile(APP)到NtCreateFile(Kernel Mode) http://blog.sina.com.cn/s/blog_61613a320100eg4d.html Using Nt and Zw Versions of the Native System Services Routines http://msdn.microsoft.com/en-us/library/ff565438.aspx ※ 编辑: purpose 来自: 124.8.143.166 (05/16 23:22)







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:BabyMother站内搜寻

TOP