能力值:
( LV9,RANK:3410 )
2 楼
新兵学习还是从简单的东西开始吧
角度不是太好把握
能力值:
(RANK:570 )
3 楼
先看看效果吧
这里的代码量已经很少了
能力值:
( LV2,RANK:10 )
4 楼
感谢笨笨老大的题,用这种方式促进学习,很有好处啊。我做了一个多小时,虽然有很多不足,有一点收获吧,愿先回一帖,支持下
第一题有点理解了,有些收获, 特别是自己对于堆栈进行了思考,对于堆栈指针代表的意思有了体会,如:
77F9566E 8B7C24 0C mov edi, dword ptr [esp+C]
77F95672 8B5424 08 mov edx, dword ptr [esp+8]
中的“esp+C和esp+8”的指向含义
在书本中,也看过,但记得并不深,通过这里,我切实体会到了
第二题关键应当在最后:
shr eax,4
and edx,0f0f0f0f
and eax,0f0f0f0f
shl edx,4
or eax,edx
无论EAX最初设为多少,结果都为ffffffff,再经过BSWAP(交换32位寄存器里字节的顺序),还是应当为ffffffff
第三题跟踪了半天,虽然老大说很简单,我打开一个软件,也看到了这些东东:
0012FFC4 7C816FD7 返回到 kernel32.7C816FD7
0012FFC8 7C930738 ntdll.7C930738
0012FFCC FFFFFFFF
0012FFD0 7FFDE000
0012FFD4 80544DFD
0012FFD8 0012FFC8
0012FFDC 82969020
0012FFE0 FFFFFFFF SEH 链尾部
0012FFE4 7C839AA8 SE处理程序
0012FFE8 7C816FE0 kernel32.7C816FE0
0012FFEC 00000000
0012FFF0 00000000
0012FFF4 00000000
0012FFF8 005D4F13 srgui.<模块入口点>
0012FFFC 00000000
但调试起来,却找不到在哪里有代码对它进行了数据压入
总的说来,我觉得用这种方式促进学习非常不错呀。以做题带动学习,是我以前常用的学习方法。
希望老大继续出题,把这个训练场办好
一晃就到两点了,我是个夜猫子型的,晚上精力充沛啊,但也太晚了
好,睡觉了
期待老大明天的指点
能力值:
( LV9,RANK:1140 )
5 楼
可惜~~我是真的看不懂!
能力值:
( LV2,RANK:10 )
6 楼
俺是真的不懂怎么看```
汇编不懂```
学习^^^^^^^^
能力值:
(RANK:570 )
7 楼
回4楼:
第一题
分析的关键是要理解数据结构和函数与其他代码的交互方式。
看你的回帖,我想你已经知道其他代码是以堆栈的方式将参数传递给函数了,那里下一个你要理解的问题就是函数是以什么方式来传出参数。
如题目给出的条件,调用这个函数之前先把字符指针压栈,然后是一个没有占用的内存结构。
那么在函数中esp+C就是取该字符指针,而esp+8是没有占用的内存指针。
77F95672 8B5424 08 mov edx, dword ptr [esp+8]
77F95676 C702 00000000 mov dword ptr [edx], 0
77F9567C 897A 04 mov dword ptr [edx+4], edi
注意到这里,函数在取得内存指针后便对该内存结构进行初始化。
在该指针的内存中写入
DWORD 0
DWORD 字符指针
显然这便是函数传出处理数据的方式,不过凭开头几段代码还不知道那个DWORD代表些什么,还需要对后面代码分析。
单看你的回帖还不知道你分析到哪一部分不明白,没解出来的地方还是直接说吧。
第二题你还是用草稿纸写写吧,这是一个位操作的算法。有一部分数据处理的优化算法是用逻辑运算指令实现的,能理解这段代码对你以后理解其他优化算法有好处,当然也可以凭特征去记。
注意到第二题里面进行逻辑运算的字符都是有一定规律,其实你可以将过程简化为一个8位的数据,将逻辑运算的立即数看成是33,55,0F。这样你就不必写32位的2进制数来分析了。8位就够了。例如 01101001 ,自己模拟指令的操作,在纸上写写,看看1和0位置的变化。
第三题再给点提示吧。堆栈随着数据的增加是负增长的,所以你在堆栈中能看到的数据都是在你来到这段代码之前得到的。如何通过观察堆栈找到之前的代码?OD已经很大提示了
能力值:
( LV2,RANK:10 )
8 楼
我只能看懂一点点
能力值:
( LV2,RANK:10 )
9 楼
回楼主:
我在算第二题,我想应该明白你的意思了,昨天我是只注重求结果了。你出这题的目的是想让我们对于用逻辑运算指令来实现数据处理的优化算法有深入地理解吧,只有经过计算,那么以后就可以看到这些特征数据,直接知道实现功能。此处共有三种优化吧。按你说的,用al=01101001计算
1、mov edx,eax
shr eax,1
and edx,55555555
and eax,55555555
shl edx,1
or eax,edx
最后al=01101001
2、mov edx,eax
shr eax,2
and edx,33333333
and eax,33333333
shl edx,2
or eax,edx
最后al=10010110
3、mov edx,eax
shr eax,4
and edx,0f0f0f0f
and eax,0f0f0f0f
shl edx,4
or eax,edx
最后al=11111111
不明白的是:
1、请具体讲讲有什么好处?
2、bswap eax交换32位寄存器里字节的顺序,在这又有什么好处?
多谢
对于第三题,我也明白了些。如:
0006FFC4 77E687F5 返回到 KERNEL32.77E687F5
0006FFC8 005916A8
0006FFCC 00000056
0006FFD0 7FFDF000
0006FFD4 00000200
0006FFD8 0006FFC8
0006FFDC 00000200
0006FFE0 FFFFFFFF SEH 链尾部
0006FFE4 77E7F0B4 SE处理程序
0006FFE8 77E68EC8 KERNEL32.77E68EC8
0006FFEC 00000000
0006FFF0 00000000
0006FFF4 00000000
0006FFF8 01006420 NOTEPAD.<模块入口点>
0006FFFC 00000000
要反查,用OD,在
0006FFE8 77E68EC8 KERNEL32.77E68EC8一句上点右键,选择“反汇编窗口中跟随”,来到77E68EC8,在它上面不远处的PUSH指令即是。
对否,请指点
午休结束,下线了
能力值:
( LV2,RANK:10 )
10 楼
老大,你得说出我们做这些题需要具备什么知识点,不然,我们还是看不懂.我们不怕学,就是不知学什么
能力值:
(RANK:570 )
11 楼
第二题,将问题化简为8位,设使用的寄存器为AL和DL,那么
mov edx,eax
shr eax,1
and edx,55555555
and eax,55555555
shl edx,1
or eax,edx
可以看成
mov DL,AL
shr AL,1
and DL,55
and AL,55
shl DL,1
or AL,DL
假设AL=01101001(二进制),55(十六进制)=01010101(二进制),下面出现数字全部都是二进制
mov DL,AL
DL=01101001
shr AL,1
AL=00110100
and DL,01010101
DL=01000001
AND AL,01010101
AL=00010100
shl DL,1
DL=10000010
or AL,DL
得数是10010110
你算错了。逻辑运算一般作为位操作,AND是用来屏蔽某些位的
例:1111 AND 0001=0001,如果是1110 AND 0001=0000
通过将一个控制功能开关的数据跟0001进行AND操作,然后对比答案是否为0,我们就可以知道最后一个位是开还是关了。
在这个例子中
数据:10010110
排位:12345678
先将数据右移,然后AND 01010101
这样就把偶数位全部屏蔽,得到的是1357位上的数据。
在进行运算之前,EAX先将自己复制到EDX。然后AND 01010101
这样得到的是偶数位2468的数据。最后将2468左移1位。
OR运算之后便是2 1 4 3 6 5 8 7了。该算法同样可以用于简单的加密,象XOR一样,用原式就可以将密文解出来了。
剩下的就不多解释了,作为练习,继续理解一下吧。
第三题答对了。记住以后有可能要运用这样的技巧去找出目标代码的,这也是堆栈窗口的其中一个用途。
还有第一题,继续努力吧
能力值:
(RANK:570 )
12 楼
最初由 cqhhwz 发布 老大,你得说出我们做这些题需要具备什么知识点,不然,我们还是看不懂.我们不怕学,就是不知学什么
汇编指令参考,然后试着做,有什么不懂就问
老实说,我就算给你说是哪本书有详细的描述,估计你也没耐心看
当然我没耐心不代表你没耐心
有本书名字叫汇编语言的艺术,第二题就是抄里面的代码。
我3天把那本400多页还是500多页,A4纸大小的书看完。不是我看得快,而是实在没耐性,很多内容都跳过了,感兴趣的地方细看,不感兴趣的知道那书有那些内容,以后需要的时候方便查找就算了。
JUST TRY,还有就是看看别人在学习过程中有什么问题,顺便看看我的解答
能力值:
( LV2,RANK:10 )
13 楼
哎,不小心竟然算错了,刚检查一下,确实如此。
楼主的解释真是简明,受教了。
我再来解第一题
由于每天发帖量有限制,只好在这里编辑了,见谅
第二题
中间部分:
数据:10010110
排位:12345678
先将数据右移,然后AND 00110011
这样就得到的是00120056位上的数据。
在进行运算之前,EAX先将自己复制到EDX。然后AND 01010101
这样得到的是00340078的数据。最后左移2位。
OR运算之后便是34127856了
为01101001
最后部分:
数据:01101001
排位:12345678
先将数据右移,然后AND 00001111
这样就得到的是00001234位上的数据。
在进行运算之前,EAX先将自己复制到EDX。然后AND 00001111
这样得到的是00005678的数据。最后左移2位。
OR运算之后便是56781234了
再经过bswap,相对于此处就是34127856了
最后为10010110
不知对否
能力值:
(RANK:570 )
14 楼
我只是解释了1/3的代码,还有2/3,为什么有最后那个指令
整段代码是如何对数据操作的,你还没解出来
能力值:
( LV4,RANK:50 )
15 楼
最初由 冷血书生 发布 可惜~~我是真的看不懂!
完全不懂~
能力值:
(RANK:570 )
16 楼
回15楼:
不懂也欢迎一起玩
回13楼:
继续努力,还剩一题了
能力值:
( LV2,RANK:10 )
17 楼
对第一题的一些分析:
77F9566D > 57 push edi
77F9566E 8B7C24 0C mov edi, dword ptr [esp+C] ;把ebx存入edi
77F95672 8B5424 08 mov edx, dword ptr [esp+8] ;把eax存入edx
77F95676 C702 00000000 mov dword ptr [edx], 0 ;edx内存地址中写入0
77F9567C 897A 04 mov dword ptr [edx+4], edi ;edx+4的内存地址中载入edx
77F9567F 0BFF or edi, edi ;CF清0
77F95681 74 21 je short 77F956A4 ;IF edi的值为0,则返回参数为0
77F95683 83C9 FF or ecx, FFFFFFFF ;取字符串长度极值ffffffff
77F95686 33C0 xor eax, eax ;eax=0,cf清0
77F95688 F2:66:AF repne scas word ptr es:[edi] ;es:[edi]字符串段值加偏移,串扫描,搜索结束标志
77F9568B F7D1 not ecx ;得字符串包括结束标志在内的长度
77F9568D D1E1 shl ecx, 1 ;逻辑左移一位,相当于乘以2
77F9568F 81F9 FEFF0000 cmp ecx, 0FFFE ;比较是否在cx范围即65535内溢出,如溢出,则按0FFFE计算
77F95695 0F87 1BBB0100 ja 77FB11B6
77F9569B 66:894A 02 mov word ptr [edx+2], cx ;把字符串的长度存入该指针的内存中的+2字节处
77F9569F 49 dec ecx
77F956A0 49 dec ecx
77F956A1 66:890A mov word ptr [edx], cx ;把减去了结束标志的字符串的长度存入该指针的内存处
77F956A4 5F pop edi
77F956A5 C2 0800 retn 8
77FB11B6 B9 FEFF0000 mov ecx, 0FFFE
77FB11BB ^ E9 DB44FEFF jmp 77F9569B
总的说来,也就是该函数先取得内存指针,对该内存结构进行初始化,然后计算字符串长度,查看是否溢出,然后输出长度值。
应该是这样吧。
看了好一会的《80X86汇编程序设计教程》,学到不少东西啊,感谢老大
肯定还有不到位的地方,还请老大指点
回复第18楼:
谢谢老大啊,通过这一天来,我学到很多呢。谢谢
我一定继续努力
(发帖量用完了,只能在这编辑了
不好意思
我要赶快写个精华帖出来
能力值:
(RANK:570 )
18 楼
不错,这样你静态分析就过关了,我去准备下一期。主要是锻炼寻找目标代码的能力和综合分析的运用。
我希望你在静态分析的过程中,还学会总结一些算法的特征,在日后遇到类似情况,能快速识别它
http://bbs.pediy.com/showthread.php?threadid=28717
http://bbs.pediy.com/showthread.php?threadid=28798
上面两个连接,没看过就去看看。
希望你记住,你成功分析了NATIVE API,假如以后你碰到某个API,可能是系统的可能不是系统的,当你找不到资料的时候,你应该勇于去自己分析出该API的用途
软件逆向工程就是探索未知的工具。
能力值:
( LV2,RANK:10 )
19 楼
看懂命令是什么意思,可是再一块就不知道说的是什么了,
能力值:
(RANK:570 )
20 楼
最初由 星夜明宇 发布 看懂命令是什么意思,可是再一块就不知道说的是什么了,
举例说明一下,例如看懂那行,不懂哪一行
能力值:
( LV2,RANK:10 )
21 楼
最初由 playx 发布 完全不懂~
拉着胡子过河--还真是很谦虚滴说
能力值:
( LV2,RANK:10 )
22 楼
第1题的问题
77F8BB8C 53 push ebx
77F8BB8D 8D86 DC010000 lea eax, dword ptr [esi+1DC]
77F8BB93 50 push eax
77F8BB94 E8 D49A0000 call RtlInitUnicodeString
上面是它的调用过程,EBX是某字符的指针,EAX指向一个空内存地址
77F9566D > 57 push edi //保护现场EDI
77F9566E 8B7C24 0C mov edi, dword ptr [esp+C] //EBX值到EDI
77F95672 8B5424 08 mov edx, dword ptr [esp+8] //EAX值到EDX
77F95676 C702 00000000 mov dword ptr [edx], 0 //初始化内存
77F9567C 897A 04 mov dword ptr [edx+4], edi //字串指针到EDX+4,紧接着EDX的4BYTE
77F9567F 0BFF or edi, edi
77F95681 74 21 je short 77F956A4 //指向字串的指针如果为0则跳
77F95683 83C9 FF or ecx, FFFFFFFF
77F95686 33C0 xor eax, eax
77F95688 F2:66:AF repne scas word ptr es:[edi]
77F9568B F7D1 not ecx
77F9568D D1E1 shl ecx, 1
77F9568F 81F9 FEFF0000 cmp ecx, 0FFFE
77F95695 0F87 1BBB0100 ja 77FB11B6
77F9569B 66:894A 02 mov word ptr [edx+2], cx
77F9569F 49 dec ecx
77F956A0 49 dec ecx
77F956A1 66:890A mov word ptr [edx], cx
77F956A4 5F pop edi //字串指针为0,跳到这里,EAX返回0
77F956A5 C2 0800 retn 8
77FB11B6 B9 FEFF0000 mov ecx, 0FFFE
77FB11BB ^ E9 DB44FEFF jmp 77F9569B
问题:
关于repne scas这个指令我不是太明白,查看了一下简明手册这个指令太模糊了。我只能知道这个指令是把 es:[edi]与ax进行比较,此处ax=0,即比对字符串的\0结尾字符,但不知道ecx的值是知道增长的,初始时ecx=-1??
还有后面得知ECX即是字符串的长度,但我确实不了解这个过程,还请指教一下
第3个问题:
按照我这个初学者,我只能知道程序进入口点初时化了异常链,但还是不能得到笨笨雄的结果啊,还要讲明白一点才行啊
能力值:
( LV2,RANK:10 )
23 楼
回22楼,这个问题我来解答下:
“关于repne scas这个指令我不是太明白,查看了一下简明手册这个指令太模糊了。我只能知道这个指令是把 es:[edi]与ax进行比较,此处ax=0,即比对字符串的\0结尾字符,但不知道ecx的值是知道增长的,初始时ecx=-1??”
repne每重复一次,先把ecx减1,再分析是否结束。因此,我们先设定ecx=ffffffff,然后运行,循环结束时,看ecx为多少了,对它取反,即为重复的次数。举个例子:设cl=1111,重复一次,cl-1,为1110,第二次,cl-1,为1101,重复第三次,为1100。假设第三次时结束,那么,对cl取反,为0011,也就是3次。
如果你有清华大学《80X86汇编语言程序设计教程》,可以看207页的例子,相信会更清楚
第三题可以看9楼嘛
共勉
能力值:
(RANK:570 )
24 楼
对于22楼的问题,我再补充一下:
在逆向分析中,请将
77F95676 C702 00000000 mov dword ptr [edx], 0 //初始化内存
77F9567C 897A 04 mov dword ptr [edx+4], edi //字串指针到EDX+4,紧接着EDX的4BYTE
看成是对一个数据结构的操作,从代码可知,EDX指向一个数据结构。那么该数据结构每个元素的长度如何呢?
留意到伪指令dword。也就是说以暂时的信息来看,该数据结构是
DWORD 元素1 ;以这两段代码来看,只知道长度是DWORD被初始化为0。
DWORD 元素2 ;字符指针,OD里面的字符参考实际就是通过字符指针找到该字符的。
假如以后还有对该数据结构的操作,那么你应该用记事本或者什么的记下该数据结构的指针。数据在内存中相对稳定,而在寄存器中则不断变化。一般把它理解成数据结构便于记忆。
所谓的指针,其实就是指向某数据(或者数据结构)起始的内存地址
在函数的内部,请把esp+C或者esp+8(类似的获得通过堆栈传递数据的过程),解释成传入参数。 23楼,谢谢你一直的支持
能力值:
( LV2,RANK:10 )
25 楼
呵呵,老大不必言谢啊,要谢也是我谢谢你呢。这两天来还是学习到了不少东西。我这个人最喜欢的学习方法就是通过做题来进行学习,为了做出题目,就需要参考不少资料,同时,将这些知识点运用于实践,也加深了理解。这样效率很高啊!
人有了目标,才会有动力的。
当然,这也需要个人确实具备较高的自学能力、独立分析解决问题能力以及能够触类旁通、举一反三。还要有耐性
我很支持老大的做法,人,需要靠自己,内因最重要。我目前水平也不高,这些题目我拿到后,自己翻书、看函数的描述等等,慢慢理解过来的。比如说这个 repne scas,我是翻过书,仔细看了,才知道它是算长度的,以前也看过,但没有动手试过,都忘了。同时,知道了这个,也就对这题的整个要旨把握住了。
所以,我相信,只要自己努力,新人还是可以做出来的。而如果自己偷懒了,简单的不想做,想当然地认为会做,稍难一点的遇到点困难就放掉不做。是永远成不了事的
只是有的题确实难度大了些,比如说二期的这个第三题,为了解决它,我需要学、看的知识面多了一些,不是短暂就能领会的。当然,我不会放弃,一定会做出来的
多谢老大的指路作用啊!