转自:http://blog.csdn.net/int2e/archive/2008/01/09/2032732.aspx

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)相关推荐

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

    FS寄存器指向当前活动线程的TEB结构(线程结构) 偏移  说明 000  指向SEH链指针 004  线程堆栈顶部 008  线程堆栈底部 00C  SubSystemTib 010  FiberD ...

  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. AI 一分钟 | 微软推出全新人工智能平台;多名用户反映亚马逊 Echo 智能音箱突然发笑
  2. 对10个整数按由大到小顺序排序
  3. block之--- 基本使用
  4. 在Bash脚本中,如果发生某种情况,如何退出整个脚本?
  5. 1滴血,2小时,验13种癌症,精度99%!日本东芝新技术引热议
  6. python有道翻译-使用python2爬取有道翻译
  7. MySQL基本命令 (二)
  8. 学习SpringMVC——说说视图解析器
  9. Laravel 5.0 的新特性
  10. 动态规划算法-03背包问题
  11. fiddler如何filter_Fiddler工具的过滤功能介绍
  12. windows server搭建php mysql数据库_windows server 2008/2012安装php iis7 mysql环境搭建教程...
  13. Laravel——通过邮件找回密码
  14. xshell安装mysql步骤_xshell怎么搭建mysql
  15. Java异常处理之------Java方法中throws Exception使用案例!什么情况下使用throws Exception?...
  16. 手机上怎样转变图片格式?教你一键快速转格式
  17. vga焊接线顺序_vga线序是怎么排列的?
  18. 计算机用户帐号 MAC地址怎么查,mac地址怎么查
  19. Android自定义星星评分控件
  20. 高等数学——积分中值定理

热门文章

  1. 用计算机唱出惊雷,除了《惊雷》还有多少喊麦神曲?这十首神作你一定听过!...
  2. edtext 从右边开始输入 安卓_转换iOS和安卓的视频至任何格式
  3. Maven之搭建本地私服(nexus)仓库
  4. Oracle10g数据库的完全卸载:
  5. Linux实验三:Shell编程
  6. Redis:15---键迁移(move、dump、restore、migrate)
  7. C++基础学习(01)--(介绍,环境配置,基本语法,注释)
  8. 《Python Cookbook 3rd》笔记(5.10):内存映射的二进制文件
  9. C++primer 第 5 章语句 5.2语句作用域 5.3条件语句 5 . 4 迭代语句 5.5跳转语句 5.6 try语句块和异常处理
  10. 解决undefined reference to symbol ‘sem_close@@GLIBC_2.2.5‘问题