Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

【技术分享】Shellcode编程之特征搜索定位GetProcAddress

$
0
0
【技术分享】Shellcode编程之特征搜索定位GetProcAddress

2017-06-27 11:34:29

阅读:555次
点赞(0)
收藏
来源: modexp.wordpress.com





【技术分享】Shellcode编程之特征搜索定位GetProcAddress

作者:myswsun





【技术分享】Shellcode编程之特征搜索定位GetProcAddress

译者:myswsun

预估稿费:100RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿


0x00 前言

最近, Alex lonescu表明windows的发布版本中将包含将增强缓解措施工具包(EMET)编译到内核中。


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

因为更多的缓解措施出现于MSVC和Windows操作系统中,定位API来利用内存崩溃漏洞变得越来越困难。

我就在想,如果导入地址表和导出地址表都不能访问了,是否有其他的方式来获得GetProcAddress?

下面你看到的就是我几个小时研究的成果,但没有铺开来研究IAT和EAT无法访问时如何获得GetProcAddress。


0x01 特征检测

用于检测恶意软件的每种算法可以重新利用来检测包括GetProcAddress在内的任何代码。

恶意代码的检测范围可以从简单的搜索字符串、常量(包括加密)或者代码字节序列到类似仿真和统计分析的高级方式。

通过特征定位GetProcAddress是一种尝试,因为它是唯一的返回错误码STATUS_ORDINAL_NOT_FOUND的函数。

从WindowsNT到Windows10,使用这个常量搜索kernel32.dll或者kernelbase.dll来定位GetProcAddress是很有可能的。


0x02 搜索算法

搜索算法的伪代码如下:

【技术分享】Shellcode编程之特征搜索定位GetProcAddress

理论上很简单,并且对于32位是有效的。

然而,如果对于一些DLL(尤其是64位的版本)中GetProcAddress使用函数块,那么就无效了。

在Windows7中,在kernelbase中定位我们的常量,是在代码块中。


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

减去0x3FFFFEC8得到0xC0000138。

在Windows10中,常量在相同的GetProcAddress代码中,因此入口通过简单的搜索就能找到。


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

为了能适应Windows7,我建议使用一个长度反汇编引擎(LDE)来模拟相关的跳转知道你定位到GetProcAddress,但是没有64位版本的LDE能独立的操作内存。也可能不需要?

因为我们搜索kernel32或者kernelbase的节,我们检查下PE节头结构,有个有趣的成员。


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

Misc.VirtualSize

加载到内存的节的大小(字节),如果这个值大于SizeOfRawData,节将被填充0。这个字段只针对可执行映像有效,并且对于obj文件应该置为0.

VirtualAddress

加载到内存的节的第一个字节的地址(RVA)。对于obj文件,这是在重定位之前的第一个字节的地址。

Characteristics

映像的特征。因为我们搜索可执行代码,我们能测试这个值是否有IMAGE_SCN_CNT_CODE 或 IMAGE_SCN_MEM_EXECUTE。

一旦我们找到一个可执行区域,我们简单的搜索我们的特征,是一个4字节的序列:0x38, 0x01, 0x00, 0xC0。

如果找到了,我们假设我们在GetProcAddress的代码中,因此我们往回扫描内存来找到函数序言0x55, 0x8B, 0xEC(32位)和0x48, 0x89, 0x5C, 0x24, 0x08(64位)。


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

尽管从XP SP2开始大部分的32位的API在序言前有mov edi,edi以便热补丁,但是我们可以跳过它。


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

64位上找到入口点的另一种方式是搜索编译器添加的填充(不同的编译器填充不同)。

函数是16字节对齐,会在GetProcAddress前后填充。

在Windows7上,使用0x90,在x86上是NOP指令。


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

在Windows10中,使用0xCC,是软件中断(INT 3)。


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

我提到它是因为在不同的搜索算法中这会很有用。


0x03 C代码

对于PEB中的每个DLL;

找到kernel32或者kernelbase;


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

针对这个dll的每个节;


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

找到特征,并反向扫描函数序言。


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

0x04 总结

对于大部分32位的操作系统,他都能很好的工作,因为STATUS_ORDINAL_NOT_FOUND是在GetProcAddress函数的序言和结语之间的。但是在Windows7 x64上不能起作用,因为常量在外面。

Windows7 32位(可以)


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

第一个地址偏了2字节,但是那是mov edi,edi指令,可以安全跳过

Windows7 64位(不可以)


【技术分享】Shellcode编程之特征搜索定位GetProcAddress

Windows10 64位(可以)


【技术分享】Shellcode编程之特征搜索定位GetProcAddress



【技术分享】Shellcode编程之特征搜索定位GetProcAddress
【技术分享】Shellcode编程之特征搜索定位GetProcAddress
本文由 安全客 翻译,转载请注明“转自安全客”,并附上链接。
原文链接:https://modexp.wordpress.com/2017/06/21/shellcode-getprocaddress/

Viewing all articles
Browse latest Browse all 12749

Latest Images

Trending Articles





Latest Images