利用FS寄存器获取KERNEL32.DLL基址算法的证明(ZZ)
FS寄存器指向当前活动线程的TEB结构(线程结构)
偏移 说明
000 指向SEH链指针
004 线程堆栈顶部
008 线程堆栈底部
00C SubSystemTib
010 FiberData
014 ArbitraryUserPointer
018 FS段寄存器在内存中的镜像地址
020 进程PID
024 线程ID
02C 指向线程局部存储指针
030 PEB结构地址(进程结构)
034 上个错误号
在shellcode中用它来找KERNEL32.DLL基地址是常见的算法了,经典的三种算法都用到了FS寄存器!她们是:
1. 通过PEB(FS:[30])获取KERNEL32.DLL基地址
2. 通过TEB(FS:[18])获取KERNEL32.DLL基地址
3. 通过SEH(FS:[00])获取KERNEL32.DLL基地址
下面分别证明之。
命题一:通过PEB(FS:[30])获取KERNEL32.DLL基地址
算法描述:
mov eax,fs:[30h] ;得到PEB结构地址
mov eax,[eax + 0ch] ;得到PEB_LDR_DATA结构地址
mov esi,[eax + 1ch]
lodsd ; 得到KERNEL32.DLL所在LDR_MODULE结构的
; InInitializationOrderModuleList地址
mov edx,[eax + 8h] ;得到BaseAddress,既Kernel32.dll基址
证明:
1. 随便open一个exe,内存中的KERNEL32.DLL基地址是不变的;
2. 获取PEB基地址,
0:000> dd fs:30 L1
003b:00000030 7ffd6000
看到了,7ffd6000
3. 获取PEB_LDR_DATA结构地址7ffd6000+0c
peb的结构定义:
ntdll!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 SpareBool : UChar
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA
+0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
+0x014 SubSystemData : Ptr32 Void
+0x018 ProcessHeap : Ptr32 Void
+0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION
......
0:000> dd 7ffd6000+0c L1
7ffd600c 00181ea0
PEB_LDR_DATA-> 00181ea0
4. 获取InInitializationOrderModuleList的地址
说一下这个PEB_LDR_DATA,她是ntdll.dll中的undocumented的一个结构,PEB_LDR_DATA的结构定义:
0:000> dt _PEB_LDR_DATA
+0x000 Length : Uint4B
+0x004 Initialized : UChar
+0x008 SsHandle : Ptr32 Void
+0x00c InLoadOrderModuleList : _LIST_ENTRY
+0x014 InMemoryOrderModuleList : _LIST_ENTRY
+0x01c InInitializationOrderModuleList : _LIST_ENTRY
+0x024 EntryInProgress : Ptr32 Void
0:000> dd 00181ea0+1c L1
00181ebc 00181f58
InInitializationOrderModuleList->00181f58
5. 获取kernel32的基地址
0:000> dd 00181f58+8 L1
00181f60 7c920000
7c920000就是了?
check一下:
0:000> dd kernel32 L1
7c800000 00905a4d
啊!竟然不是啊,7c920000是ntdll.dll的,哈哈。
不过,算法命题仍然是正确的。因为在shellcode中模块列表的第一个就是kernel32了,当然可以通过镜像名称来check的,不过shellcode的空间不允许的,这就是shellcode的艺术了。我用来测试的exe恰好先加载了ntdll.dll。
命题二:通过TEB(FS:[18])获取KERNEL32.DLL基地址
算法描述:
本地线程的栈里偏移18H的指针指向kernel32.dll内部,而fs :[ 0x18 ] 指向当前线程而且往里四个字节指向线程栈,结合栈顶指针进行对齐遍历,找到PE文件头(DLL的文件格式)的“MZ”MSDOS标志,就拿到了kernel32.dll基址。
xor esi , esi
mov esi , fs :[ esi + 0x18 ] // TEB
mov eax , [ esi + 4 ] // 这个是需要的栈顶
mov eax , [ eax - 0x1c ] // 指向Kernel32.dll内部
find_kernel32_base :
dec eax // 开始地毯式搜索Kernel32空间
xor ax , ax
cmp word ptr [ eax ], 0x5a4d // "MZ"
jne find_kernel32_base // 循 环遍 历 ,找到 则 返回 eax
证明:
1. 找到TEB,这个好办:
0:000> dd fs:18 L1
003b:00000018 7ffdd000
TEB->7ffdd000
2. 找到栈顶指针:
0:000> dd 7ffdd000+4 L1
7ffdd004 00070000
3. 进入Kernel32空间:
0:000> dd 00070000-1c L1
0006ffe4 7c839aa8
4. Kernel32空间的大搜索:
0:000> db 7c839aa7 L4
7c839aa7 30 55 8b ec 0U..
......一直搞下去
0:000> db 7c800000 L4
7c800000 4d 5a 90 00 MZ..
找到了吧,哈哈。有点效率问题,shellcode有时候是要牺牲效率的,没办法,还是艺术问题。
命题三:通过SEH(FS:[00])获取KERNEL32.DLL基地址
算法描述:
注意:FS:[ 0 ] 指向的是SHE,它指向kernel32.dll内部链,这样就可以顺藤摸瓜了。FS:[ 0 ] 指向的是SHE的内层链,为了找到顶层异常处理,我们向外遍历找到prev成员等于 0xffffffff 的EXCEPTION_REGISTER结构,该结构的handler值就是系统 默 认的处理例程;这里有个细节,DLL的装载是64K边界对齐的,所以需要利用遍历到的指向最后的异常处理的指针进行页查找,再结合PE文件MSDOS标志部分,只要在每个 64K 边界查找 “MZ ”字符就能找到kernel32.dll基址。
xor ecx , ecx
mov esi , fs :[ ecx ]
find_seh :
mov eax ,[ esi ]
mov esi , eax
cmp [ eax ], ecx
jns find_seh // 0xffffffff
mov eax , [ eax + 0x04 ] // handler
find_kernel32_base :
dec eax
xor ax , ax
cmp word ptr [ eax ], 0x5a4d
jne find_kernel32_base
证明:
1. 找到当前SEH:
0:000> dd fs:0 L1
003b:00000000 0006fedc
2. 找到最外层SEH:
round 1:
0:000> dd 0006fedc L1
0006fedc 0006ffb0 ; esi
0:000> dd 0006ffb0 L1
0006ffb0 0006ffe0 ; [eax]
round 2:
0:000> dd 0006ffb0 L1
0006ffb0 0006ffe0 ; esi
0:000> dd 0006ffe0 L1
0006ffe0 ffffffff ; [eax]
不错,第二趟就找到了!此时,eax=0006ffe0
3. 找到MZ:
0:000> dd 0006ffe0+4 L1
0006ffe4 7c839aa8
0:000> db 7c839aa7 L4
7c839aa7 30 55 8b ec 0U..
......又是一直搞下去
0:000> db 7c800000 L4
7c800000 4d 5a 90 00 MZ..
找到!
知其然,更要知其所以然!
转载于:https://www.cnblogs.com/fanzi2009/archive/2009/03/19/1416805.html
利用FS寄存器获取KERNEL32.DLL基址算法的证明(ZZ)相关推荐
- 利用FS寄存器获取KERNEL32.DLL基址算法的证明
FS寄存器指向当前活动线程的TEB结构(线程结构) 偏移 说明 000 指向SEH链指针 004 线程堆栈顶部 008 线程堆栈底部 00C SubSystemTib 010 FiberD ...
- 获取kernel32.dll基址
获取kernel32.dll基址 一 原理和概述 找kernel32基地址的方法一般有三种:暴力搜索法.异常处理链表搜索法.PEB法. 暴力搜索法是最早的动态查找kernel32基地址的方法.它的原理 ...
- Windows x64平台 获取PEB表,并获取kernel32.dll的基址,并获取它的函数
参考了:https://www.cnblogs.com/aliflycoris/p/5185097.html 和另一位博主 话不多说,进入正题: 首先是获取PEB基址,先得懂怎么在64位平台嵌入汇编代 ...
- 重定位(搜索KERNEL32.DLL得到API地址)
1 ;-------------------------------- 2 ;动态加载功能实现 3 ;moriarty 4 ;2012/04/13 5 ;----------------------- ...
- GetModuleHandle(NULL)获取当前DLL模块基址?
做一项目想在DLL内部代码实现获取本DLL的模块基址,而且不知道本DLL名称 最简单的方法是想到GetModuleHandle(NULL),是否可以呢? 参看http://blog.csdn.net/ ...
- Python Pymem 游戏内存基址读取修改 - 获取游戏DLL模块基址
运行环境 python3.9.0 - 64位 安装pymem pip install pymem Pymem 的文档 https://pymem.readthedocs.io/en/latest/ 读 ...
- 问C#高手: [DllImport(“kernel32.dll“)]是什么意思??
这叫引入kernel32.dll这个动态连接库. 这个动态连接库里面包含了很多WindowsAPI函数,如果你想使用这面的函数,就需要这么引入.举个例子: [DllImport("kerne ...
- R3获取kernel32地址
获取Kernel32地址 如果是搞PE变形或者PE重构,再或者代码注入,很多时候我们要动态获取Loadlibrary()以及GetPeocAddress()两个函数的地址,通过这两个函数再动态获取其他 ...
- c++ dll返回容器_Windows x86 Shellcode开发:寻找Kernel32.dll地址
前言 针对一个已经学习了Linux Shellcode开发,并开始在Windows上尝试的研究人员来说,这一过程可能要比想象的更加艰难.Windows内核与Linux完全不同.尽管如此,但Linux内 ...
最新文章
- AI 一分钟 | 微软推出全新人工智能平台;多名用户反映亚马逊 Echo 智能音箱突然发笑
- 对10个整数按由大到小顺序排序
- block之--- 基本使用
- 在Bash脚本中,如果发生某种情况,如何退出整个脚本?
- 1滴血,2小时,验13种癌症,精度99%!日本东芝新技术引热议
- python有道翻译-使用python2爬取有道翻译
- MySQL基本命令 (二)
- 学习SpringMVC——说说视图解析器
- Laravel 5.0 的新特性
- 动态规划算法-03背包问题
- fiddler如何filter_Fiddler工具的过滤功能介绍
- windows server搭建php mysql数据库_windows server 2008/2012安装php iis7 mysql环境搭建教程...
- Laravel——通过邮件找回密码
- xshell安装mysql步骤_xshell怎么搭建mysql
- Java异常处理之------Java方法中throws Exception使用案例!什么情况下使用throws Exception?...
- 手机上怎样转变图片格式?教你一键快速转格式
- vga焊接线顺序_vga线序是怎么排列的?
- 计算机用户帐号 MAC地址怎么查,mac地址怎么查
- Android自定义星星评分控件
- 高等数学——积分中值定理
热门文章
- 用计算机唱出惊雷,除了《惊雷》还有多少喊麦神曲?这十首神作你一定听过!...
- edtext 从右边开始输入 安卓_转换iOS和安卓的视频至任何格式
- Maven之搭建本地私服(nexus)仓库
- Oracle10g数据库的完全卸载:
- Linux实验三:Shell编程
- Redis:15---键迁移(move、dump、restore、migrate)
- C++基础学习(01)--(介绍,环境配置,基本语法,注释)
- 《Python Cookbook 3rd》笔记(5.10):内存映射的二进制文件
- C++primer 第 5 章语句 5.2语句作用域 5.3条件语句 5 . 4 迭代语句 5.5跳转语句 5.6 try语句块和异常处理
- 解决undefined reference to symbol ‘sem_close@@GLIBC_2.2.5‘问题