PWN知识点整理(1)Shellcode

ShellCode

参考资料

0day安全:软件漏洞分析技术(第2版)
免杀的艺术:史上最全的汇编Shellcode的技巧(三)
ShellCode原理以及编写

基本的Shellcode编程

与Windows不同,为不同操作系统而编写的shellcode需要不同的编写方法,比如基于UNIX的操作系统提供了通过int 0x80接口与内核通信的直接方式。不过,Windows系统并没有直接的内核接口,这意味着系统调用必须有精确内存地址(函数指针),但经过硬编码的函数地址并不能完全解决这个问题,因为Windows系统的每个函数地址会因为版本中甚至配置不同发生变换,我们需要能在运行时动态地找到函数地址来实现。

Windows下编写过程
  • (1)获取kernel32.dll基地址
  • (2)定位GetProcAddress函数的地址
  • (3)使用GetProcAddress确定LoadLibrary函数的地址
  • (4)使用LoadLibrary加载DLL文件
  • (5)使用GetProcAddress查找某个函数的地址
  • (6)调用函数
编写注意事项
  • 不能使用字符串的直接偏移
    因为编译器会把字符串放置在一个特定的Section中
  • 不应该有确切的函数地址
    受ASLR(地址空间布局随机化)机制的影响,系统不会每次都把DLL文件加载到相同地址上。我们需要用LoadLibrary和GetProcAddress获取函数地址
  • 必须避免一些特定字符
    很多漏洞利用场景中,shellcode的内容将会受到限制,首先所有字符串函数都会对NULL字节进行限制,通常我们需要选择特殊指令避免在shellcode中出现NULL字节或字
    其次,有些函数还会要求shellcode必须为可见字符的ASCII值或Unicode值。
    最后,除了软件自身的限制之外,在进行网络攻击时,基于特征的IDS系统往往也会对常见的shellcode进行拦截。
  • shellcode应该尽可能精简
    除了对内容的限制之外,shellcode的长度,将也是其优劣性的重要衡量标准,短小精悍的shellcode除了可以宽松地布置在大缓冲区之外,还可以塞进狭小地内存缝隙,适应多种多样的缓冲区组织策略,具有更强的通用性。
shellcode编写技巧
shellcode瘦身

1.挑选短指令复合指令(如xchg,lods或stos)
X86指令集中指令所对应的机器码的长度时不一样的,有时候功能相似的指令的机器码长度差异会很大。以下是比较有用的单字节指令:

  • xchg eax,reg 交换eax和其他寄存器中的值
  • lodsd 把esi指向的一个dword装入eax,并增加esi
  • lodsb 把esi指向的一个byte装入al,并增加esi
  • stosd
  • stosb
  • pushad/popad 从栈中存储/恢复所有寄存器的值
  • cdq 用edx把eax扩展成四字
    2.另类的API调用方式
    有些API中很多参数都是NULL,通常的做法时向栈中压入NULL,如果我们换个思路,把栈中的一大片区域一次性全部置为NULL,在调用API的时候就可以只压入那些非NULL参数,从而节省许多压栈指令。
    健壮的API都可以允许两个结构题相互重叠,尤其当一个参数是输入结构体[in],另一个作为接收的结构体[out]时,如果让参数指向同一个[in]结构体,函数往往也能正确执行。这种情况下,仅仅用一个字节的短指令"push esp"就可以代替一大段初始化[out]结构体代码。
    3.调整栈顶回收数据
    在编译器看来,栈仅仅时用来保护函数调用断点,暂存函数输入参数和返回值等的场所。栈顶上的数据在逻辑上视为废弃数据,但物理内容往往未遭到破环,因此如果栈顶之上有需要的数据,可以调整esp的值将栈顶调高。
    4.hash编码
    实用的shellcode通常需要超过200甚至300字节的机器码,所以对原始二进制shellcode进行编码或压缩是值得的。
    ####### Shellcode免杀
    1.Hash API
    metasploit项目中几乎所有的shellcode都使用一个名为Hash API的汇编块,这个汇编块使得解析PEB结构更容易,它使用基本的PEB解析逻辑和一些额外的Hash算法来快速找到所需的函数,通过计算ROR13函数和模块名的哈希值,可以让这个汇编块的使用起来更加容易,Hash API的汇编块使用stdcall调用约定时,所需的函数参数需要包含ROR13函数名的哈希值和包含该函数的DLL名,在得到我们所需要的参数和函数哈希值之后,如前面所述,这时就该解析PEB块,并找到模块名称了,然后计算ROR13哈希值并将其保存到堆栈,最后再把这个哈希值移动到DLL的导出地址表并计算每个函数名称的ROR13哈希值,ROR13哈希值等于每个函数名称哈希值和模块名称哈希值的和,

如果匹配到我们要找的哈希值,意味着想要的函数被找到了,最后Hash API会使用栈上的参数跳转到找到的函数地址执行。虽然我们最后会得到一段非常简洁实用的代码,但由于其广泛的使用,一些杀毒软件已经可以检测到它了,甚至连一些杀毒软件已经把使用ROR13哈希的列入到恶意程序黑名单了,不过配合使用一些编码机制,目前该方法还是能绕过杀毒软件的。
2.干扰寄存器
在x86架构中,所有寄存器都有特定的用途,例如ECX代表扩展计数器寄存器,它通常用作循环计数器,当我们在任何编译语言中编写一个基本循环条件时,编译器可能使用ECX寄存器作为循环计数器变量,这样代码块内连续增加的ECX寄存器就很容易触发杀毒软件的启发式引擎检测机制,解决这个问题的方法很简单,不把ECX寄存器用作循环计数器,但是这个办法对于所有的其它类型的代码片段(如函数epilogue/prologue等)也非常有效。由于很多代码识别机制取决于寄存器使用,所以我们可以通过干扰寄存器的办法来降低编写汇编代码时被检测到的风险。
3.垃圾混淆代码
目前几乎每个杀毒软件都有办法来识别代码块内的解码器,据我们统计,大概有可能有几百种方法。但不管是哪种方法,最终都要生成用于静态地检查的代码块签名,所以为了避免被检测到,我们可以使用解码器代码内部的随机NOP指令来绕过静态签名分析,不过不一定非要使用NOP指令,可以是任何保持原始代码功能的指令,其目的最终是向代码块总添加垃圾指令,以打破代码块内的恶意签名,不过也要注意垃圾指令的大小,因为过多的垃圾混淆代码会让恶意程序的信息熵变大。
4.利用杀软的缓解技术
虽然可以用很多办法实现免杀,但杀软的防范漏洞缓解技术却将免杀的技术推向了一个全新的水平。微软在2009年发布了增强缓解体验工具包(EMET),EME是加固Windows防止恶意程序利用操作系统或软件安全漏洞的最有效方法之一,它有几个保护机制,

动态数据执行保护(DEP)
结构异常处理程序覆盖保护(SEHOP)
NullPage分配
堆喷射保护
导出地址表地址过滤(EAF)
强制ASLR
导出地址表访问过滤(EAF +)
ROP缓解措施
加载库检查
内存保护检查
调用者检查
堆栈翻转(Stack pivot)
Attack Surface Reduction(ASR)

在这些缓解中,EAF,EAF +和调用者检查是我们最关注的三种技术,如前所述,metasploit框架中几乎所有的shellcode都使用Stephen Fewer的Hash API,并且由于Hash API应用了PEB 及EAT解析技术,EMET可以轻松检测和阻止shellcodes的运行 。
5.绕过EMET
调用者检查可以检测到EMET内发生的Windows API调用,并阻止Win API函数中的RET和 JMP指令,以便阻止所有ROP方式的漏洞利用,在HASH API中,在找到需要的API函数地址后,会使用JMP指令执行函数,但这会触发EMET的调用者检查,所以为了绕过调用者检查,应该避免使用指向Win API函数的JMP和RET指令,我们要用CALL指令替换JMP指令来指向Win API函数,从理论上讲Hash API应该能绕过调用者检查,但是当我们查看EAF及EAF+缓解机制时,Hash API却使用被调用的代码阻止程序访问导出地址表(EAT),并且还会检查堆栈寄存器是否在允许的边界内,或者尝试检测特定代码块的MZ / PE报头和KERNELBASE,这是一种非常有效的用于防止EAT解析技术的方法,但EATEAT不是唯一一个包含函数地址的结构,由于导入地址表(IAT)也保存有应用程序使用的Win API函数地址,如果恶意应用程序获取了所需的函数,则可以收集IAT结构内的函数地址。一个名为Joshua Pitts的网络安全研究员最近开发了一种新的IAT解析方法,即在导入地址表中获取LoadLibraryA和GetProcAddress Windows API函数,在获取这些函数地址后,可以从任何库中提取任何函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值