吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2773|回复: 1
收起左侧

[会员申请] 会员申请 99118822

[复制链接]
吾爱游客  发表于 2015-7-3 09:22
1、申 请 I D:99118822
2、个人邮箱:lsy05505100@sina.com
3、原创技术文章:如何让你的shellcode在漏洞中跑起来

如何让你的shellcode在漏洞中跑起来
背景
   不熟悉shellcode的小伙伴,本期可以先阅读安华金和数据库攻防实验室前期文章《windows缓冲区溢出原理(栈)》,做一下初步了解。shellcode 一词语起源于Aleph One Underground 发表的著名论文《SMASHING THE STACK FOR FUN AND PROFIT》。shellcode 是一段可执行特定功能的独立代码。它伴随缓冲区溢出攻击代码出现,在其中扮演劫持程序后执行恶意代码的角色。shellcode一般由汇编语言完成,功能有:窃取关键数据、上传木马病毒、打开后门等。在网上有很多经典的shellcode脚本,尽管如此,小伙伴们经常还是无法正确使用。
本文重点讲述如何让你的shellcode在漏洞中跑起来。文中实例采用Oracle经典漏洞tns_service_name_too_long。该漏洞被发现于oracle监听(TNS)上,由于数据库客户端向数据库监听(TNS)发送的连接串:"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)
                           (HOST=#{数据库机器IP}(PORT=#{数据库机器端口}))
                                              (CONNECT_DATA=(SERVICE_NAME=#{数据库服务名})
                                                               (CID=(PROGRAM=MSF))))"
其中数据库服务名如果输入一个过长的串会造成缓冲区溢出。(建议使用脚本测试,不要用数据库客户端。因为数据库客户端会对过长的数据库服务名进行处理,不会形成缓冲区溢出)。本文为了防止不必要的危险,选取打开计算器的shellcode
                              
入侵成功会直接在目标机器上打开一个计算器
shellcode的问题
    最基本的缓冲区溢出攻击串是如下图构造的:
  
....
  
nop
nop
nop
ret
shellcode
shellcode
......
首先通过NOP填充缓冲区,直到接近函数返回的地方。用shellcode所在第一个四字节地址值覆盖返回地址,覆盖RET,返回函数后进入shellcode。完成整个入侵过程。在整个过程中会出现很多风险导致shellcode执行失败。
   其中shellcode有三个难点将决定你的入侵是否成功:
.动态定位shellcode 问题
    如上图所示,当我们可以用越界的字符完全控制返回地址后,需要将返回地址改写成shellcode在内存中的起始地址。由于大部分漏洞所在函数处于动态库中,因此即便在一台机器上,由于动态库在程序运行时的装入和卸载。会导shellcode地址出现变化。
  
                                            STACKE DATA
  
STACKE DATA
STACKE DATA
     SHELLCODE(0x0012FAF8)
SHELLCODE
SHELLCODE
EBP
返回地址(0x0012FAF8
  
STACKEDATA (0x0012FAF8)
  
STACKE DATA
STACKE DATA
SHELLCODE
SHELLCODE
SHELLCODE
EBP
返回地址(0x0012FAF8
如上图所示:shellcode 的地址发生了偏移,导致虽然控制了返回地址,但是并未跳入到shellcode中,无法执行shellcode代码。
    场景1:无参数只shellcode发生偏移
为了解决这种shellcode偏移,咱们可以采用call/jmp sep的方式,来帮助跳入shellcode中。如图所示:
  
                                                                file:///C:/Users/LIUSIC~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.pngSTACKE DATA
  
NOP
NOP
           
            
API中的jump/call esp 地址覆盖函数返回所指向地址
      
      前栈帧(被覆盖)
  
           
            
当函数返回时,esp指向shellcode头地址,会直接从jump跳入esp
      
           Ret(jump esp)
  
     Shellcode
Shellcode
Shellcode
在系统API中(windows下建议在kernel32.dll)查找jmp espcall esp 所在地址。当函数返回(ret)的时候,ESP恰好指向栈帧中返回地址的后一个位置(shellcode地址)正好准确跳入shellcode
核心代码:
buff = #在缓冲区中为了到ret而填充的NOP
buff  =#jmp esp from kernel32.dll
buff =#shellcode
sploit ="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=#{rhost}(PORT=#{rport}))(CONNECT_DATA=(SERVICE_NAME=#{buff}) (CID=(PROGRAM=MSF))))"
同样如果搜不到jmp/call esp 地址可以通过 push/pop return地址,利用原理类似。这是最经典、最常见的跳入shellcode方法
    场景2:有参数shellcode偏移
如果shellcode 不但偏移了,而且在shellcode前有参数,导致shellcode esp变到了esp+8的位置,此时就不能单纯采用jmp/call esp需要配合使用pop ret。一个pop指令将弹出栈顶4字节,指针将指向esp+4。在运行一个pop指令,会从栈顶中再弹出4字节。此时esp将直接指向shellcode的其实地址。后面可以利用jmp esp 来完成跳入shellcode
具体如下
  
            file:///C:/Users/LIUSIC~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.pngSTACKE DATA
  
NOP
NOP
前栈帧(被覆盖)
Pop
           
            
NOP EIP         NOP       ...  NOP  jmp esp             shellcode
      
         =POPPOPRET   8字节       =esp now point      here
      
      pop
  
Ret(jump esp)
Shellcode
EIPpop pop ret 覆盖掉,ESP指向SHELLCODE偏移8字节。pop pop ret被执行,连续弹出8字节的栈。EIP又被jmp esp 地址覆盖,因此第二个跳转被执行,然后跳入shellcode
核心代码
buff = #在缓冲区中为了到ret而填充的NOP
buff=#pop pop ret 地址
buff  =#jmp esp from kernel32.dll
buff=#添加8个字节作为参数(本函数没有这个变量,手工添加上+
buff =#shellcode
sploit ="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=#{rhost}(PORT=#{rport}))(CONNECT_DATA=(SERVICE_NAME=#{buff}) (CID=(PROGRAM=MSF))))"
执行结果
   场景3:大偏移esp
场景2pop pop ret 是针对esp+8这种特殊情况的,对于shellcode偏移多个字节的情况,我们一般采用jmp[reg]+[offset]这种方式处理。(这种方式一样可以处理偏移8个字节只是jmp esp+8的地址不如pop pop ret 多)。
类似场景2先查找jmp esp+字节个数或大于字节个数的地址。利用该地址覆盖EIP.通过在shellcode 入口前添加NOP来调整jmp 跳过的范围,来确保jmp能跳入shellcode
场景4一次移动32ESP
popad指令可以帮助我们跳转到shellcode,popad从栈中弹出DWRD数据,并赋予各通用寄存器,它会按照固定顺序加载各个寄存器。每次加载寄存器都会引起ESP的递增。一次popad会用掉ESP中的32字节,并按固定顺序pop如到各个寄存器中。同样可以用类似场景3的方式用nop帮助跳入shellcode中。
场景5模糊定位shellcode
前面4种场景都是在能够使用跳转指令精确定位shellcode的,而有些时候shellcode无法被精确定位,那么可以采用喷射的方式。淹没大片的内存区域,将shellcode 部署在一片nop之后。只要ret能命中这一片nop中任何一个。shellcode一样可以最终得到执行。如下图所示
  
                                     Nop
  
nop
nop
     nop
nop
shellcode
shellcode
ret
...
.shellcode 被破坏问题
    在解决shellcode的定位问题后,接踵而来的就是把shellcode放在哪的问题。如果我们不把shellcode放入被入侵的缓冲区中,shellcode会覆盖掉更多前置的栈帧,这可能给系统带来不可预测的结果,也导致缓冲区溢出的破坏无法通过修复寄存器的值来修复。所以一般我们都把shellcode放入缓冲区中,于是我们需要在代码中jmp esp 后的esp区放入的是shellcode header 来引导处理器跳转到shellcode中。整体结构变为:
  
Shellcode
  
Shellcode
nop
nop
nop
ret
Shellcode header
......
    虽然这种方式有这么多利处,但同时也带来了一个隐患shellcode容易被破坏。函数返回后,栈被弹出虽然逻辑上ESP以上的内存空间中数据已经失效。但实际上这些数据并没有销毁。如果shellcode 中有压栈指令,向栈中写入数据。则压栈数据很可能会破坏shellcode
  
         file:///C:/Users/LIUSIC~1/AppData/Local/Temp/msohtmlclip1/01/clip_image005.png                                                     file:///C:/Users/LIUSIC~1/AppData/Local/Temp/msohtmlclip1/01/clip_image006.png.....
  
shellcode
shellcode
New data
New data
New data
Shellcode header
....
    于是请注意在shellcode开始就大范围太高栈顶,把shellcode 藏在栈内保证shellcode 不被破坏。
  
..
  
New data
...
shellcode
shellcode
ret
Shellcode header
...
   
.注意shellcode选择的字符
    在很多漏洞的利用场景中,shellcode的内容会受到限制。所有的字符串函数都会对NULL字节进行限制。通常我们选择特殊的指令来避免在shellcode中直接出现null字节,甚至有时候函数还要求shellcode必须为可见字符。除去软件的限制外,基于特征值的IDS系统也会对带有某些特征的shellcode进行拦截。这都是需要注意的地方。往往这部分我们采用的解决办法是给shellcode加壳。在编码后的shellcode前加入解码指令。帮助shellcode通过重重检查,直到在内存中运行的时候才解开,保证shellcode的不被拦截。
   至此,相信只要你克服以上三点shellcode的问题,绝对可以修改出适合你自己漏洞的shellcode了。在下一期我们将和大家探讨如何优化你的shellcode

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Hmily 发表于 2015-7-8 11:24
【开放注册公告】吾爱破解论坛2015年7月21日暑假开放注册公告
http://www.52pojie.cn/thread-381155-1-1.html


最近开放注册,自己开放注册的时候来注册吧。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-5 12:42

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表