oldschool

文章讲述了在遇到程序调试时出现异常情况,通过分析发现并修正了三个反调试点,利用ida动态调试工具,修改参数以通过检查。使用z3求解矩阵逆并进行异或操作,最终得到解密后的数据。强调在遇到类似问题时,应检查反调试机制。
摘要由CSDN通过智能技术生成
 

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='')

总结:下次遇到这种题目,如果很相信自己的逻辑和脚本,一直不对的话就去查看一下有无反调试。刚开始动态调试的时候显示终端过小,遇到这种情况我们只要点击终端上的那个设置,减号调小终端知直到合适即可。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值