会员: 密码:  免费注册 | 忘记密码 | 会员登录 网页功能: 加入收藏 设为首页 网站搜索  
 安全技术技术文档
  · 安全配制
  · 工具介绍
  · 黑客教学
  · 防火墙
  · 漏洞分析
  · 破解专题
  · 黑客编程
  · 入侵检测
 安全技术论坛
  · 安全配制
  · 工具介绍
  · 防火墙
  · 黑客入侵
  · 漏洞检测
  · 破解方法
  · 杀毒专区
 安全技术工具下载
  · 扫描工具
  · 攻击程序
  · 后门木马
  · 拒绝服务
  · 口令破解
  · 代理程序
  · 防火墙
  · 加密解密
  · 入侵检测
  · 攻防演示
安全防线 > 漏洞分析
Serv-U "MDTM"命令远程溢出分析
发表日期:2006-03-12 14:31:41作者:p 出处:安全焦点  

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

返回顶部】 【打印本页】 【关闭窗口

关于我们 / 给我留言 / 版权举报 / 意见建议 / 网站编程QQ群   
Copyright ©2003- 2024 Lihuasoft.net webmaster(at)lihuasoft.net 加载时间 0.00158