一起读反汇编代码之条件表达式
不知道小白有没有这样的困惑,就是单独一条的汇编语句能读懂,但是好几条组合到一起就感觉云里雾里了那你就适合跟我们一起来读反汇编代码了,把基础指令的反汇编代码读懂才能逆向出一些更难的算法,今天我们一起来读的就是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
好了,到这里今天的学习就结束了,能力有限,可能会有疏漏之处,欢迎在评论区指出。
感谢各位看官!
E_eYYF 发表于 2019-9-19 12:15
英文的倒是有,中文的在哪设置,请教一下!
https://www.52pojie.cn/thread-729108-1-1.html whyida 发表于 2019-9-16 20:49
x64dbg 有中文汇编帮助,打开就可以了。
英文的倒是有,中文的在哪设置,请教一下!{:17_1068:} 正常正常正常正常正常 可以学可以学有用,有时间可以从简单的入手 虽然看不太懂感觉可以学可以学有用 虽然看不懂,但是可以学习一下 太难了我太难了 感谢分享!!!学习!!! x64dbg 有中文汇编帮助,打开就可以了。 多弄点呗。。。这个可以都讲下 建议用图片+注释的方式,这样形象点
页:
[1]
2