攻防世界逆向高手题之babymips
继续开启全栈梦想之逆向之旅~
这题是攻防世界逆向高手题的babymips
下载附件,照例扔入exeinfope中查看信息:
.
.
32位无壳,照例扔入IDA32中查看伪代码,有main函数看main函数:
.
.
(这里积累第一个经验)
第一个框是对用户输入进行每位的异或操作,因为i的地址
和input_flag的地址在main函数栈
中相差4而已。
第二个框就是取异或后的前五个字符与明文比较,如果相同就继续对剩下的27个字符继续操作。这里要注意的是sub_4007F0(input_flag)函数是在前面对input_flag异或后的基础上进一步操作,也就是双层操作
,而input_flag是单层
的对前5个字符的异或操作。
我犯的错误就是逆向后面27位字符后忘记
了前面还有一层异或操作,以至于生成错误的答案。
.
.
.
跟踪sub_4007F0函数,一个移位一个比较:
.
.
(这里积累第二个经验)
逻辑就是移位操作,但是我是真不知道这里的或运算符 ‘|’ 的作用是前后移位双向进行。我一直以为是算术运算操作,所以我一开始的思路是把或运算符 ‘|’ 变成与运算符 ‘&’ ,结果怎么逆都不对。
现在知道了,这里以8位为一个单位,高2位
往右移动6位
变成底2位
。同时底6位
往左移动2位
变成高6位
,相当于循环右移,000000_11变成 11_0000。(如图一样,是交叉进行的。)
下面的(4 * input_flag[i])是一个迷惑,其实也是(2<<input_flag[i])。
.
附上移位的汇编指令笔记:
.
.
.
(这里积累第三个经验)
然后移完位之后和数组off_410D04内容比较,这里嵌入IDA脚本dump下来:
这里.byte一开始我也懵了一下,后来发现用Byte也可以获取,.byte可能是MIPS的一个特性吧:
addr=0x400B98
list1=[]
for i in range(0x400BB3-0x400B98):
list1.append(Byte(addr+i))
print(list1)
print(len(list1))
.
.
.
.
(这里积累第四个经验)
知道是移位操作之后就可以写脚本了,原代码逻辑中(i&1)其实是判断奇数还是偶数来的,照抄即可,然后移位逻辑是以8位为一个循环的,所以我们要用&FF来限制在8位才行:
key1="Q|j{g"
flag=list(map(ord,key1))
flag+=[82, 253, 22, 164, 137, 189, 146, 128, 19, 65, 84, 160, 141, 69, 24, 129, 222, 252, 149, 240, 22, 121, 26, 21, 91, 117, 31]
print(flag)
for a in range(5,32,1):
if (a&1)!=0:
flag[a]=((flag[a]<<2)|(flag[a]>>6))&0xFF
else:
flag[a]=((flag[a]>>2)|(flag[a]<<6))&0xFF
for i in range(32,):
flag[i]=chr(flag[i]^(32-i))
print(''.join(flag))
说到这种用&限制位数的,不得不回顾一下以前做题中类似的操作来加深记忆。
总结:
1:
(这里积累第一个经验)
第一个框是对用户输入惊醒每位的异或操作,因为i的地址
和input_flag的地址在main函数栈
中相差4而已。
第二个框就是取异或后的前五个字符与明文比较,如果相同就继续对剩下的27个字符继续操作。这里要注意的是sub_4007F0(input_flag)函数是在前面对input_flag异或后的基础上进一步操作,也就是双层操作
,而input_flag是单层
的对前5个字符的异或操作。
我犯的错误就是逆向后面27位字符后忘记
了前面还有一层异或操作,以至于生成错误的答案。
2:
(这里积累第二个经验) 逻辑就是移位操作,但是我是真不知道这里的或运算符 ‘|’ 的作用是前后移位双向进行。我一直以为是算术运算操作,所以我一开始的思路是把或运算符 ‘|’ 变成与运算符 ‘&’ ,结果怎么逆都不对。
现在知道了,这里以8位为一个单位,高2位
往右移动6位
变成底2位
。同时底6位
往左移动2位
变成高6位
,相当于循环右移,000000_11变成 11_0000。(如图一样,是交叉进行的。)
下面的(4 * input_flag[i])是一个迷惑,其实也是(2<<input_flag[i])。
.
附上移位的汇编指令笔记:
3:
(这里积累第三个经验) 然后移完位之后和数组off_410D04内容比较,这里嵌入IDA脚本dump下来:
这里.byte一开始我也懵了一下,后来发现用Byte也可以获取,.byte可能是MIPS的一个特性吧:
4:
(这里积累第四个经验)
知道是移位操作之后就可以写脚本了,原代码逻辑中(i&1)其实是判断奇数还是偶数来的,照抄即可,然后移位逻辑是以8位为一个循环的,所以我们要用&FF来限制在8位才行。
.
说到这种用&限制位数的,不得不回顾一下以前做题中类似的操作来加深记忆。
解毕!敬礼!