0day学习笔记(3)Windows定位API引起的惨案(原理)
段选择器FS与TEB
- WinNT内核下内存采用保护模式,段寄存器的意义与实模式汇编下的意义不同.另外,FS存的是段选择子,而不是实模式下的高16位基地址。 
- FS寄存器指向当前活动线程的TEB结构(线程结构) 
- 下面为FS寄存器下偏移的相关信息: - 偏移 说明 
 000h 指向SEH链指针
 004h 线程堆栈顶部
 008h 线程堆栈底部
 00Ch SubSystemTib
 010h FiberData
 014h ArbitraryUserPointer
 018h FS段寄存器在内存中的镜像地址
 020h 进程PID
 024h 线程ID
 02Ch 指向线程局部存储指针
 030h PEB结构地址(进程结构)
 034h 上个错误号
PEB
详细参考https://blog.csdn.net/weixin_44156885/article/details/100729365
- 使用汇编获取PEB地址的两种方法:
 方法1:MOV EAX,DWORD PTR FS:[30] ;FS:[30] = address of PEB
 方法2: MOV EAX,DWORD PTR FS:[18] ;FS[18] = address of TEB
 MOV EAX,DWORD PTR DS:[EAX+30] ;DS[EAX+30] = address of PEB
 
- PEB几个重要成员
+002	BeingDebugged 	;Uchar(可用于反调试技术)
...
+008	ImageBaseAddress 	 ;Ptr32 Void
...
+00c	Ldr 	 ;Ptr32 _PEB_LDR_DATA(可用于反调试技术)
...
+018	ProcessHeap 	 ;Ptr32 Void(可用于反调试技术)
...
+068	NtGlobalFlag 	  ;uint4B(可用于反调试技术)
PEB.Ldr
- PEB.Ldr成员是指向_PEB_LDR_DATA结构体的指针,_PEB_LDR_DATA结构体如下。 - +000 Length :Uint4B
 +004 Initialized :UChar
 +008 SsHandle :Ptr32 Void
 +00c InLoadOrderModulelist :_LIST_ENTRY
 +014 InMemoryOrderModulelist :_LIST_ENTRY
 +01c InInitializationOrderModulelist:_LIST_ENTRY
 +024 EntryInProgress :Ptr32 Void
 +028 ShutdownInProgress :UChar
 +02c ShutdownThreadId :Ptr32 Void
 
- 当模块(DLL)加载到进程后,通过PEB.Ldr成员可以直接获得该模块的加载基址,_PEB_LDR_DATA结构体中含有3个_LIST_ENTRY类型的成员,_LIST_ENTRY结构体如下。 - typedef struct LIST_ENTRY{
 struct _LIST_ENTRY *Flink;
 struct _LIST_ENTRY *Bink;
 }LIST_ENTRY,*PLIST_ENTRY;
 
- 从上述结构体可以看出,_LIST_ENTRY结构体提供双向链表机制。链表中保存的是_LDR_DATA_TABLE_ENTRY结构体的信息 
- 每个加载到进程中的DLL模块都对应一个_LDR_DATA_TABLE_ENTRY结构体,这些结构体相互链接,最终形成了_LIST_ENTRY双向链表。_PEB_LDR_DATA结构体中存在3种_LIST_ENTRY双向链表,也就是说,存在多个_LDR_DATA_TABLE_ENTRY结构体,并且有三种链接方法可以将它们链接起来。 
 结构体如下:
typedef struct _LDR_DATA_TABLE_ENTRY
{
     LIST_ENTRY InLoadOrderLinks;
     LIST_ENTRY InMemoryOrderLinks;
     LIST_ENTRY InInitializationOrderLinks;
     PVOID DllBase;
     PVOID EntryPoint;
     ULONG SizeOfImage;
     UNICODE_STRING FullDllName;
     UNICODE_STRING BaseDllName;
     ULONG Flags;
     WORD LoadCount;
     WORD TlsIndex;
     union
     {
          LIST_ENTRY HashLinks;
          struct
          {
               PVOID SectionPointer;
               ULONG CheckSum;
          };
     };
     union
     {
          ULONG TimeDateStamp;
          PVOID LoadedImports;
     };
     _ACTIVATION_CONTEXT * EntryPointActivationContext;
     PVOID PatchInformation;
     LIST_ENTRY ForwarderLinks;
     LIST_ENTRY ServiceTagLinks;
     LIST_ENTRY StaticLinks;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
- 模块初始化链表 InInitializationOrderModuleList中按顺序存放着 PE 装入运行时初始化模块的信息
正文
- 所有 win_32 程序都会加载 ntdll.dll 和 kernel32.dll 这两个最基础的动态链接库。如果想要在 win_32 平台下定位 kernel32.dll 中的 API 地址,可以采用如下方法:
(1)首先通过段选择字 FS 在内存中找到当前的线程环境块 TEB。
(2)线程环境块偏移位置为 0x30 的地方存放着指向进程环境块 PEB 的指针。
(3)进程环境块中偏移位置为 0x0C 的地方存放着指向 PEB_LDR_DATA 结构体的指针,
其中,存放着已经被进程装载的动态链接库的信息。
(4)PEB_LDR_DATA 结构体偏移位置为 0x1C 的地方存放着指向模块初始化链表的头指
针 InInitializationOrderModuleList。
(5)模块初始化链表 InInitializationOrderModuleList 中按顺序存放着 PE 装入运行时初始化
模块的信息,第一个链表结点是 ntdll.dll,第二个链表结点就是 kernel32.dll。
(6)找到属于 kernel32.dll 的结点后,在其基础上再偏移 0x08 就是 kernel32.dll 在内存中的
加载基地址。
(7)从 kernel32.dll 的加载基址算起,偏移 0x3C 的地方就是其 PE 头。
(8)PE 头偏移 0x78 的地方存放着指向函数导出表的指针。
(9)至此,我们可以按如下方式在函数导出表中算出所需函数的入口地址
- 如下图所示:

- 导出表偏移 0x1C 处的指针指向存储导出函数偏移地址(RVA)的列表。
- 导出表偏移 0x20 处的指针指向存储导出函数函数名的列表。
- 函数的 RVA 地址和名字按照顺序存放在上述两个列表中,我们可以在名称列表中定位到所需的函数是第几个,然后在地址列表中找到对应的 RVA。
- 获得 RVA 后,再加上前边已经得到的动态链接库的加载基址,就获得了所需 API 此刻在内存中的虚拟地址,这个地址就是我们最终在 shellcode 中调用时需要的地址。
- 按照上面的方法,我们已经可以获得 kernel32.dll 中的任意函数
- 类似地,我们已经具备了定位 ws2_32.dll 中的 winsock 函数来编写一个能够获得远程 shell 的真正的 shellcode 了。
- 在摸透了 kernel32.dll 中的所有导出函数之后,结合使用其中的两个函数 LoadLibrary()和 GetProcAddress(),有时可以让定位所需其他 API 的工作变得更加容易。
本文参考:0day安全,以及众多博客
0day学习笔记(3)Windows定位API引起的惨案(原理)的更多相关文章
- ASP.NET MVC Web API 学习笔记---第一个Web API程序
		http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ... 
- 并发编程学习笔记(6)----公平锁和ReentrantReadWriteLock使用及原理
		(一)公平锁 1.什么是公平锁? 公平锁指的是在某个线程释放锁之后,等待的线程获取锁的策略是以请求获取锁的时间为标准的,即使先请求获取锁的线程先拿到锁. 2.在java中的实现? 在java的并发包中 ... 
- DOCKER 学习笔记6 WINDOWS版尝鲜
		前言 经过前两节的学习,我们已经可以在Dokcer 环境下部署基本的主流环境有: Springboot 后端 MYSQL 持久化数据 以及Nginx 作为反向代理 虽说服务器上面的也没啥不好,但是毕竟 ... 
- redis学习笔记(一)——windows下redis的安装与配置
		前言 很久没有写东西了(.......我的水平就是记个笔记),北漂实习的我,每天晚上回来都不想动,但是做为社会主义接班人的我,还是要时刻给自己充充电,趁着年轻,趁着日渐脱发的脑袋还没有成为" ... 
- Python学习笔记 for windows
		学习来源 http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001374738136 ... 
- spring学习笔记---第三方SDK(Rest API)和Jaskson的巧用
		前言: 其实我以前一直不懂电商, 以及电商中所涉及的业务概念. 对于SKU等名词, 觉得有些玄乎. 对其背后的数据模型, 也有莫名的未知恐惧感: 庞大而理不清头绪. 不过最近有机会接触了微商(有赞), ... 
- 操作系统学习笔记(三) windows内存管理
		//系统物理页面是由 (Page Frame Number Database )简称PFN数据库来进行管理,实际上是一个数组,每个物理页面都对应一个PFN项. 进程的地址空间是通过VAD(Virtua ... 
- Appium学习笔记4_元素定位方法
		Appium之元素定位,如果对Android上如何使用工具获取页面元素有问题的,请转战到这:http://www.cnblogs.com/taoSir/p/4816382.html. 下面主要是针对自 ... 
- Django框架学习笔记(windows环境下安装)
		博主最近开始学习主流框架django 网上大部分的安装环境都linux的 由于博主在windows环境下已经有了 Pycharm编辑器 ,所以决定还是继续在windows环境下学习 首先是下载 链接 ... 
随机推荐
- Dockerfile极简入门与实践
			前文中,罗列了docker使用中用到的基本命令 此文,将会对怎样使用Dockerfile去创建一个镜像做简单的介绍 Dockerfile命令 要开始编写Dockerfile,首先要对相关的命令有个清晰 ... 
- JS获取HTML DOM元素的方法
			JS获取HTML DOM元素有八种方法: 1.根据id获取标签元素: document.getElementById("id名"); 2.根据标签名获取标签列表: document ... 
- JavaScript数组的基本操作
			数组的创建方式: 方式一:构造函数构建数组 var arr = new Array ( ); 如果传入的参数为一个数字,代表数组的长度,不包含内容 // 可以传入字符串和数字,用逗号隔开,作为数组中的 ... 
- 操作系统-1-存储管理之LFU页面置换算法(leetcode460)
			LFU缓存 题目:请你为 最不经常使用(LFU)缓存算法设计并实现数据结构.它应该支持以下操作:get 和 put. get(key) - 如果键存在于缓存中,则获取键的值(总是正数),否则返回 -1 ... 
- Centos7.x & RedHat7.x系统忘记 root 密码解决办法
			重启系统进入引导页面 先将机器重启 根据提示按下e进入内核编辑页面 找到linux16参数行,并在行尾加上rd.break,之后按下Ctrl+X重启 如上图所示,重启之后将进入救援模式. 这是依次输入 ... 
- spring05
			通过静态工厂的方法创建bean:和实例工厂方法: <?xml version="1.0" encoding="UTF-8"?> <beans ... 
- websocket聊天室
			目录 websocket方法总结 群聊功能 基于websocket聊天室(版本一) websocket方法总结 # 后端 3个 class ChatConsumer(WebsocketConsumer ... 
- 路由与交换,cisco路由器配置,基础知识点(一)
			基础知识点 1.路由器与交换机端口初始化区别 路由器的所有接口默认都是关闭的 交换机的所有接口默认都是打开的 2.路由器 fastEthernet 端口 fastEthernet 0/0 第一个0代表 ... 
- 安卓开发学习日记 DAY4——Button,ImageButton
			Button与ImageButton基本类似 也有类似于TextView和ImageView的区别 这里需要注意的是: 在你定义text属性的内容时,最好是在Values文件下的String.xml中 ... 
- Jquery 搜索等待用户输入完成时自动执行
			$('#fuzzySearchBox').on('keyup', function (event) { var searchStr = $(this).val().toLowerCase(); //i ... 
