前话:这题要用到ida64位远程调试先记录一下配置方法,因为本人使用的是ida7.6版本差异可能导致问题。
application与input file填linux路径下的题目文件路径
dictionary填linu下题目文件所在文件夹的路径(即题目文件的父级)
Paramater不填
Hostname用ifconfig填自己的ip,Port端口固定
Password虚拟机密码
运行一下:
去找个地方下个断点:
这里的strcmp函数比较值的结果决定回显,所以在这里下个断点看看能不能直接找到a2【1】相关信息
跑完之后依旧直接结束证明断点没被运行到
状态栏中显示主函数返回0了?
据此可以推断出a1的值<=1,所以在a1判断时下断点。查看a1的值
此次调试卡在断点处,预发确定a1就是<=1,鼠标悬停在a1处可以查看a1的值,因为不好截图就不演示了。那么如何修改a1的值呢?
看到汇编语言这里,这里将edi赋值给内存中的一个位置,随后该位置与1进行cmp(即比较,具体作用自行百度)。所以edi寄存器存放的就是a1的值。
对着其直接改值就行了,不用太大,够用就行
然后继续向后运行就可以,走进if判断内了
然后在步入(一定要步入,不要步过)strcmp函数的时候,发现这个函数变样了
他静态调试是可不是这样的:
所以推断出strcmp是个障眼法真正的其实在sub_561A114BA6EA
然后就静态分析这个函数
也就是对字符串“zer0pts{CENSORED}”进行操作,而数组中第一个值与最后一个值为0,所有前8位与最后8位未进行处理,也就是说只对“CENSORED”进行处理。
很明显是小端序。
此程序在电脑中运行时便是以小端序运行,所以在编写脚本时要注意将字符串逆序处理后与数组进行相加后,再将得到的flag逆向。如果将数组的值变回大端序与正向的字符运算会导致第一个数字存在进位导致数据溢出。总之脚本编写要严格按照计算机底层运算的逻辑(这里卡了好久。。)
enc = "********CENSORED********"
m = ['410A4335494A0942', '0B0EF2F50BE619F0', '4F0A3A064A35282B']
enc = enc[::-1]
flag = ''
for i in range(3):
c = ''
n = enc[8*i:8*(i+1)]
for j in range(8):
a = hex(ord(n[j]))
c += a[2::]
d = int(('0x' + c), 16)
b = int(('0x' + m[i]), 16)
e = str(hex(d+b)[2::])
c = ''
for j in range(8):
f = '0x' + e[j*2] + e[j*2+1]
c += chr(int(f, 16))
flag += c[::-1]
print(flag)
做完之后才发现大佬的脚本如此精简,学习了。地址在这。不得不说大佬脚本写的tql。
enc = "********CENSORED********"
m = [0x410A4335494A0942, 0x0B0EF2F50BE619F0, 0x4F0A3A064A35282B]
import binascii
flag = b'' #以字节为单位进行运算
for i in range(3):
p = enc[i * 8:(i + 1) * 8] #将字符串每8位一分割
a = binascii.b2a_hex(p.encode()[::-1]) #p.encode()将p由字符串转为byte形式并倒叙,binascii.b2a_hex()函数将byte内的字符转为16进制
b = binascii.a2b_hex(hex(int(a, 16) + m[i])[2:])[::-1] #int(a, 16)将byte类型中16进制转为int型16进制,加上m【i】,因为是小端序所以倒过来即为flag
flag += b
print(flag)
该脚本出处:https://blog.csdn.net/qq_39542714/article/details/106834947