FS获取KERNEL32基址的三种方法
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 eax,[eax];win7要加
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..
找到!
知其然,更要知其所以然!
FS获取KERNEL32基址的三种方法的更多相关文章
- Java中获取键盘输入值的三种方法
Java中获取键盘输入值的三种方法 Java程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值 ...
- 获取class对象的三种方法以及通过Class对象获取某个类中变量,方法,访问成员
public class ReflexAndClass { public static void main(String[] args) throws Exception { /** * 获取Clas ...
- shell获取本地ip的三种方法
第一种方法:ifconfig|grep inet |awk '{print $2}'|sed '2d'|awk -F : '{print $2}'第二种方法:ifconfig|grep inet|se ...
- javascript 获取html元素的三种方法
操作HTML元素 你首先找到该元素. 三种方法来做这件事: 通过id找到HTML元素 通过标签名找到HTML元素 通过类名找到HTML元素 通过id查找HTML元素 在DOM中查找HTML元素的最简单 ...
- php获取POST数据的三种方法
方法一,$_POST $_POST或$_REQUEST存放的是PHP以key=>value的形式格式化以后的数据. $_POST方式是通过 HTTP POST 方法传递的变量组成的数组,是自动全 ...
- Java入门:Java中获取键盘输入值的三种方法
Java程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值的现成函数!Java没有提供这样的函数也不代 ...
- Javascript获取value值的三种方法及注意点
JavaScript获取value值,主要有以下三种: 1.用document.getElementById(“id名”).value来获取(例1): 2.通过form表单中的id名或者name名来获 ...
- python获取网页信息的三种方法
import urllib.request import http.cookiejar url = 'http://www.baidu.com/' # 方法一 print('方法一') req_one ...
- JavaScript获取鼠标位置的三种方法
在一些DOM操作中我们经常会跟元素的位置打交道,鼠标交互式一个经常用到的方面,令人失望的是不同的游览器下会有不同的结果甚至是有的游览器下没结果,这篇文章就鼠标点击位置坐标获取做一些简单的总结. 获取鼠 ...
随机推荐
- STM32串口USART通信总结
一.GPIO设置USART的初始化 /**************************实现函数******************************************** *函数原型: ...
- paper 140:TLD视觉跟踪算法(超棒)
我是看了这样的一个视频:http://www.56.com/u83/v_NTk3Mzc1NTI.html 然后在准备针对TLD视觉跟踪算法来个小的总结. 以下博文转自:http://blog.csdn ...
- paper 136:ARM ADS集成开发环境的使用(新版)
[转载]:http://blog.csdn.net/yhmhappy2006/article/details/1673203 ARM ADS集成开发环境的使用 在这里,将介绍ARM开发软件ADS(AR ...
- Spring核心——Bean的依赖注入
依赖注入在设计模式与IoC这篇文章中,介绍了Spring基础的三大支柱的两项内容——IoC.Bean.本篇将继续围绕着Bean的创建时的注入方式来介绍Spring的核心思想与设计模式. 天底下所有面向 ...
- mysql 用户权限管理详细
用户管理 mysql>use mysql; 查看 mysql> select host,user,password from user ; 创建 mysql> create user ...
- Linux命令 shutdown
1. 简介 shutdown是用来让计算机处于暂停,关机,重启的指令 2.语法 shutdown [krhHPc] [时间] [警告信息] 时间的格式: hh:mm 表示多长时间以后执行 ...
- 在Linux终端命令行下播放音乐的命令
现在的 Linux 桌面已经发展的很好了,在桌面下播放音乐操作起来也很简单.那么我们还记得在桌面不是那么好的时候我们是怎么播放音乐的么?哎,我是想不起来了,实在是太难了. 不过现在我们可以先安装一个小 ...
- T1212:LETTERS
[题目描述] 给出一个R * S的大写字母矩阵,一开始的位置为左上角,你可以向上下左右四个方向移动,并且不能移向曾经经过的字母.问最多可以经过几个字母.roe× [输入] 第一行,输入字母矩阵行数R和 ...
- js基本函数和基本方法
日期时间函数(需要用变量调用): var b = new Date(); //获取当前时间 b.getTime() //获取时间戳 b.getFullYear() //获取年份 b.getMonth( ...
- JS轻松实现单击文本框弹出选择日期
我的开发工具是vs2005,你们可选择自己合适的开发工具 首先创建个文本框<input id="txFDate" name="txFDate" type= ...