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

+0x00cLdr              : Ptr32 _PEB_LDR_DATA

+0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS

+0x014 SubSystemData    : Ptr32 Void

+0x018 ProcessHeap      : Ptr32 Void

+0x01cFastPebLock      : Ptr32 _RTL_CRITICAL_SECTION

......

0:000>  dd 7ffd6000+0cL1

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

+0x00cInLoadOrderModuleList : _LIST_ENTRY

+0x014 InMemoryOrderModuleList : _LIST_ENTRY

+0x01cInInitializationOrderModuleList : _LIST_ENTRY

+0x024 EntryInProgress  : Ptr32 Void

0:000> dd 00181ea0+1cL1

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-1cL1

0006ffe4  7c839aa8

4.       Kernel32空间的大搜索:

0:000> db 7c839aa7 L4

7c839aa7  30 55 8b ec                                      0U..

......一直搞下去

0:000> db 7c800000 L4

7c800000  4d 5a90 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 5a90 00                                      MZ..

找到!

知其然,更要知其所以然!

利用FS寄存器获取KERNEL32.DLL基址算法的证明相关推荐

  1. 利用FS寄存器获取KERNEL32.DLL基址算法的证明(ZZ)

    转自:http://blog.csdn.net/int2e/archive/2008/01/09/2032732.aspx FS寄存器指向当前活动线程的TEB结构(线程结构) 偏移  说明 000  ...

  2. 获取kernel32.dll基址

    获取kernel32.dll基址 一 原理和概述 找kernel32基地址的方法一般有三种:暴力搜索法.异常处理链表搜索法.PEB法. 暴力搜索法是最早的动态查找kernel32基地址的方法.它的原理 ...

  3. Windows x64平台 获取PEB表,并获取kernel32.dll的基址,并获取它的函数

    参考了:https://www.cnblogs.com/aliflycoris/p/5185097.html 和另一位博主 话不多说,进入正题: 首先是获取PEB基址,先得懂怎么在64位平台嵌入汇编代 ...

  4. 重定位(搜索KERNEL32.DLL得到API地址)

    1 ;-------------------------------- 2 ;动态加载功能实现 3 ;moriarty 4 ;2012/04/13 5 ;----------------------- ...

  5. GetModuleHandle(NULL)获取当前DLL模块基址?

    做一项目想在DLL内部代码实现获取本DLL的模块基址,而且不知道本DLL名称 最简单的方法是想到GetModuleHandle(NULL),是否可以呢? 参看http://blog.csdn.net/ ...

  6. Python Pymem 游戏内存基址读取修改 - 获取游戏DLL模块基址

    运行环境 python3.9.0 - 64位 安装pymem pip install pymem Pymem 的文档 https://pymem.readthedocs.io/en/latest/ 读 ...

  7. 问C#高手: [DllImport(“kernel32.dll“)]是什么意思??

    这叫引入kernel32.dll这个动态连接库. 这个动态连接库里面包含了很多WindowsAPI函数,如果你想使用这面的函数,就需要这么引入.举个例子: [DllImport("kerne ...

  8. R3获取kernel32地址

    获取Kernel32地址 如果是搞PE变形或者PE重构,再或者代码注入,很多时候我们要动态获取Loadlibrary()以及GetPeocAddress()两个函数的地址,通过这两个函数再动态获取其他 ...

  9. c++ dll返回容器_Windows x86 Shellcode开发:寻找Kernel32.dll地址

    前言 针对一个已经学习了Linux Shellcode开发,并开始在Windows上尝试的研究人员来说,这一过程可能要比想象的更加艰难.Windows内核与Linux完全不同.尽管如此,但Linux内 ...

最新文章

  1. matplotlib如何把坐标轴一横一竖给绘制出来
  2. 如何用Curl 来post xml 数据
  3. ArcGIS License Manager 更新
  4. JZOJ 5462. 【NOIP2017提高A组冲刺11.8】好文章
  5. Libre OJ 「BalticOI 2013」非回文数 数位dp
  6. Linux 环境下搭建 Jenkins(Hudson)平台
  7. 学习微信公众号oauth2.0
  8. 重磅盘点!过去一年里最受欢迎的技术干货,全在这里了
  9. Onvif备忘录(2)----客户端端设备发现
  10. spring security oauth2_SpringBoot2 整合OAuth2实现统一认证
  11. python人脸识别库教程_OpenCV-最优秀的Python人脸识别库安装及入门教程
  12. 添加负载机_从 Coco 转向 Koko,Jumpserver 堡垒机 V1.5.3 发布
  13. 博文视点大讲堂第15期:猎头揭秘
  14. 将byte[]转为各种进制的字符串
  15. 靠,竟然有如此沙雕的代码注释!
  16. Kafka ACL使用实战
  17. 从零基础入门Tensorflow2.0 ----九、44.5 keras转换成具体函数
  18. Java的强、软、弱、虚四种引用类型
  19. VMware卸载不干净导致的重装失败(100%解决问题)
  20. 五款经典GPRS无线上网卡比拼

热门文章

  1. UNIX/Linux-进程控制(实例入门篇)
  2. 3、Python 基础类型 -- List 列表类型
  3. 1.记住密码 提示框
  4. Vue 路由知识三(过渡动画及路由钩子函数)
  5. [转]Create Custom Exception Filter in ASP.NET Core
  6. hiho1249 Xiongnu's Land
  7. 浅谈Python和VC中的编码问题(转)
  8. GridView RadioButton 解决办法(一) -- 实现单选
  9. 表单身份验证(受保护的目录)
  10. 图像中值处理MATLAB实现