雪魔王遗风 发表于 2019-9-16 16:10

一起读反汇编代码之条件表达式

不知道小白有没有这样的困惑,就是单独一条的汇编语句能读懂,但是好几条组合到一起就感觉云里雾里了
那你就适合跟我们一起来读反汇编代码了,把基础指令的反汇编代码读懂才能逆向出一些更难的算法,今天我们一起来读的就是C++里的三元运算符———条件表达式


这里将C++的条件表达式分为5种情况,别觉得1种C++指令分为5种情况就觉得很难,不想看了,静下心来慢慢看,你一定能发现其中的规律{:1_921:}
用的IDE是VC++6.0,程序是debug版的,release版的反汇编代码差别不大,调试器就是论坛的OD



1.简单比较并且最后两种结果的差为1,例如printf("%d\n",num==5?5:6);
此时反汇编代码:
00401058|xor edx,edx ;条件表达.00427A60       
0040105A|cmp ,0x5                //直接进行比较
0040105E|setne dl        //如果相等的话此时dl为0,不相等则为1   如果A比B大呢??
00401061|add edx,0x5                //加上5,则可确定最后的值
00401064| push edx;条件表达.00427A60
00401065|push 条件表达.0042501C;ASCII "%d\n"
0040106A|call 条件表达.00401120
0040106F|add esp,0x8

2.简单比较并且最后两种结果的差大于1,例如printf("%d\n",num==5?5:10);
此时反汇编代码:
00401072| mov eax,
00401075| sub eax,0x5                //先让自变量减去5
00401078|neg eax        //这是个求补指令,用在这里很巧妙,只要参数不为5,此时的EAX就不为0,一求补,符号位必然发生改变,那么影响的就是CF标志位,就会影响接下来的sbb指令
0040107A|sbb eax,eax                //带借位的减法指令,sbb就相当于eax-eax-CF,如果之前的CF为1那么现在eax就等于FFFF FFFF
0040107C|and eax,0x5//如果前面的相等eax为0,这条语句执行完后eax仍然为0,如果之前是FFFF FFFF那么执行完这条语句之后就变成5了
0040107F|add eax,0x5 //这里再加上A和B的差值,最后EAX就保存着结果了
00401082| push eax
00401083|push 条件表达.0042501C ;ASCII "%d\n"
00401088|call 条件表达.00401120
0040108D|add esp,0x8

3.复杂的比较且最后两种结果的差值大于1,例如printf("%d\n",num<6?5:10);
此时的反汇编代码:
00401090|xor ecx,ecx;条件表达.00427A60
00401092|cmp ,0x6
00401096|setge cl //这个setge应该就是setg命令,大于等于置位命令 , 就是此时参数大于6时cl会被置为1
00401099|dec ecx;条件表达.00427A60//此时ECX减1,那么ECX的值就只有0跟FFFF FFFF两种情况
0040109A| and ecx,-0x5 //这里and -5其实就是A-B的差,为的就是区分出来前面的值,0的话此时不变FFFF FFFF的话变为-5
0040109D|add ecx,0xA //再加上10,就能出结果了
004010A0|push ecx;条件表达.00427A60
004010A1|push 条件表达.0042501C;ASCII "%d\n"
004010A6| call 条件表达.00401120
004010AB| add esp,0x8
走一遍啊:刚开始输入5,接下来的cmp命令就是跟setge命令一起比较条件是否成立,成立的话cl就赋值为0,不成立的话就赋为1。再将这个值减去1(此时为的就是接下来做and运算),然后and A和
B的差,因为输入的5条件成立,所以此时ECX为FFFF FFFF,一and那么ECX变为-5,之后再加上10,就出结果了
这个代码多看几遍,再好好想想如果是复杂的比较且最后两种结果的差值等于1呢

4.A或者B是参数的,例如:printf("%d\n",num==5?k:10);
此时的反汇编代码:
004010AE|cmp ,0x5
004010B2| jnz short 条件表达.004010BC
004010B4| mov edx,
004010B7|mov ,edx ;条件表达.00427A60
004010BA|jmp short 条件表达.004010C3
004010BC|mov ,0xA
004010C3|mov eax,
004010C6|push eax
004010C7|push 条件表达.0042501C ;ASCII "%d\n"
004010CC|call 条件表达.00401120
004010D1|add esp,0x8
这时的代码才是正常的,先比较然后跳转赋值的代码

5.复杂的比较且最后两种结果的差值等于1,例如:printf("%d\n",num<6?5:6);
此时的汇编代码:
004010AB|add esp,0x8
004010AE|xor edx,edx;条件表达.00427A60
004010B0|cmp ,0x6
004010B4|setge dl
004010B7|add edx,0x5 //哈哈,其实在获取dl之后再加上A就好了
004010BA| push edx;条件表达.00427A60
004010BB|push 条件表达.0042501C ;ASCII "%d\n"
004010C0|call 条件表达.00401120
004010C5|add esp,0x8
到这的话,再想想,如果是A>B呢,现在再加上A的值不就错了嘛,num<6?6:5是不是等价于num>=6?5:6呢,那么其实就是把setge命令换成setl(小于置位命令就好了)

最后再附上源码跟程序好了:https://www.lanzouj.com/i675dij
好了,到这里今天的学习就结束了,能力有限,可能会有疏漏之处,欢迎在评论区指出。
感谢各位看官!







whyida 发表于 2019-9-19 12:16

E_eYYF 发表于 2019-9-19 12:15
英文的倒是有,中文的在哪设置,请教一下!

https://www.52pojie.cn/thread-729108-1-1.html

LoongKing 发表于 2019-9-19 12:15

whyida 发表于 2019-9-16 20:49
x64dbg 有中文汇编帮助,打开就可以了。

英文的倒是有,中文的在哪设置,请教一下!{:17_1068:}

155club 发表于 2019-9-16 16:29

正常正常正常正常正常

故人寻故人 发表于 2019-9-16 17:14

可以学可以学有用,有时间可以从简单的入手

可可乐乐 发表于 2019-9-16 17:28

虽然看不太懂感觉可以学可以学有用

冰雪冬樱250 发表于 2019-9-16 17:59

虽然看不懂,但是可以学习一下

a1545515 发表于 2019-9-16 18:20

太难了我太难了

god321 发表于 2019-9-16 18:25

感谢分享!!!学习!!!

whyida 发表于 2019-9-16 20:49

x64dbg 有中文汇编帮助,打开就可以了。

yzxqhdx 发表于 2019-9-16 22:46

多弄点呗。。。这个可以都讲下

LoongKing 发表于 2019-9-17 08:50

建议用图片+注释的方式,这样形象点
页: [1] 2
查看完整版本: 一起读反汇编代码之条件表达式