oldschool
当时做的时候就很奇怪,为什么单步调试输入相应的用户名和密码就显示success,而直接运行程序提交相同的数据就是错误,更奇怪的是当时写的脚本能更正确解除第一组,而后面的矩阵用z3求逆都出现了问题,当时只是怀疑加了反调试修改了数据,但又不知从何处检查。。。。。。
查看交叉引用,发现第一处反调试
如果检查到正在调试该值加上7。
直接查看负责检查调试的那个函数的交叉引用,即可将所有的反调试一网打尽。
下一处是
如果检查到调试,会对选中的这个数组进行异或处理,正常情况下是异或上2,这里是异或上了4。
第三处在这里
找到这三处反调试,在运算之前下一个断点,ida动态调试,找的if——debug这个参数,可以看到他的值为1,我们直接将其改成0即可,后面的数据就全都是正确的了。
这个脚本和之前的脚本只有两处区别,其一是填充的matx矩阵不同,也就是v18的值,我们只要在v18之后设置断点,然后读出数据即可(v18的数据收到反调试的影响),其二就是xor_arr这个异或矩阵,这个异或矩阵也是收到了反调试的影响。
matx = [[0x12, 0x1D, 0x10, 0x13, 0x1B], [0x8, 0x1F, 0x8, 0x17, 0x1E], [0x1D, 0x3, 0x1C, 0xA, 0x15], [0x12, 0x1D, 0x08, 0x10, 0x1C], [0x0B, 0x1E, 0x07, 0x14, 0x07],] #这里填v18,username加密后的数据 from z3 import * rows = 5 cols = 5 arr = [[z3.BitVec(f'arr_{i}_{j}', 6) for j in range(cols)] for i in range(rows)] s = Solver() # for i in range(5): # for j in range(5): # s.add(arr[i][j] >= 0) # s.add(arr[i][j] <= 0x7f) for k in range(5): for m in range(5): v28 = 0 for i in range(5): v28 = ((arr[i][m]&0xff) * (matx[k][i]&0xff) + (v28&0xff)) & 0x1f if k == m: s.add(v28 == 1) if k != m: s.add(v28 == 0) inv = [] if s.check() == sat: model = s.model() for i in range(rows): row = [model.evaluate(arr[i][j]).as_long() for j in range(cols)] inv.append(row) else: print("err") print("v18的逆矩阵为:") print(inv) # 第n列循环右移n字节 for i in range(len(inv)): if i == 0: continue elif i == 4: inv[i][0], inv[i][1], inv[i][2], inv[i][3], inv[i][4] = inv[i][1], inv[i][2], inv[i][3], inv[i][4], inv[i][0] elif i == 3: inv[i][0], inv[i][1], inv[i][2], inv[i][3], inv[i][4] = inv[i][2], inv[i][3], inv[i][4], inv[i][0], inv[i][1] elif i == 2: inv[i][0], inv[i][1], inv[i][2], inv[i][3], inv[i][4] = inv[i][3], inv[i][4], inv[i][0], inv[i][1], inv[i][2] elif i == 1: inv[i][0], inv[i][1], inv[i][2], inv[i][3], inv[i][4] = inv[i][4], inv[i][0], inv[i][1], inv[i][2], inv[i][3] print("调换位置后的逆矩阵:") print(inv) xor_arr = [[0x1B, 0x00, 0x0A, 0x0D, 0x08], [0x18, 0x0F, 0x1C, 0x06, 0x07], [0x12, 0x05, 0x0C, 0x02, 0x04], [0x1D, 0x1F, 0x09, 0x13, 0x01], [0x1E, 0x11, 0x0B, 0x16, 0x19]] for k in range(5): for m in range(5): inv[k][m] ^= xor_arr[k][m] print("异或后的矩阵:") print(inv) index_arr = [0x00000010, 0x0000000E, 0x0000000D, 0x00000002, 0x0000000B, 0x00000011, 0x00000015, 0x0000001E, 0x00000007, 0x00000018, 0x00000012, 0x0000001C, 0x0000001A, 0x00000001, 0x0000000C, 0x00000006, 0x0000001F, 0x00000019, 0x00000000, 0x00000017, 0x00000014, 0x00000016, 0x00000008, 0x0000001B, 0x00000004, 0x00000003, 0x00000013, 0x00000005, 0x00000009, 0x0000000A, 0x0000001D, 0x0000000F] for k in range(5): for m in range(5): inv[k][m] = index_arr.index(inv[k][m]) print("索引:") print(inv) chr_arr = [0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A] for i in range(5): for j in range(5): print(chr(chr_arr[inv[i][j]]), end='') print('-', end='')
总结:下次遇到这种题目,如果很相信自己的逻辑和脚本,一直不对的话就去查看一下有无反调试。刚开始动态调试的时候显示终端过小,遇到这种情况我们只要点击终端上的那个设置,减号调小终端知直到合适即可。