hgame-week1-re
题目文件:
链接: https://pan.baidu.com/s/1BipiggCZM0YwpFyJrfGNtA 密码: uvbq
maze
题目本身提示这是一个迷宫,ida分析就是极为典型的迷宫:
我们看到增减的量会存在两个,4和64, 那么4就是我们的左右移动,64=4 × 16 ,为上下移动,且整个应该是一个16 × 16 的迷宫。
首先看到中间的数值都是0和1, 其中起点和中间也是如此,则我首先将起点设为4, 终点设为2, 然后使用ida-python脚本直接导出迷宫:
addr = 0x0000000000602080
arr = []
for i in range(16 * 16 ):
arr.append(Byte(addr+4 *i))
print(arr)
for i in range(0,16 * 16 , 16):
print(arr[i:i+16])
然后得到迷宫:
得到flag:
bitwise_operation2
首先函数上来就是判定flag的格式,
然后接下来就是将flag转化为对应的两个cipher数组,
然后对两个cipher进行加密:
然后最后进行一次异或,和明文的数据比较:
我们写出逆向脚本:
s_1 = 'e4sy_Re_'
s_2 = 'Easylif3'
data = [0x4C,0x3C,0xD6,0x36,0x50,0x88,0x20,0xCC]
data1 = []
data2 = []
for i in range(8):
data1.append(ord(s_1[i]) ^ data[i])
data2.append(ord(s_2[i]) ^ data1[i])
print(data1, data2)
for i in range(8):
data1[i] = ((data1[i] & 0x55) ^ ((data2[7 - i] & 0xaa) >> 1)) | (data1[i] & 0xaa)
data2[7 - i] = ((data2[7 - i] & 0xaa) ^ (2 * (data1[i] & 0x55))) | (data2[7 - i] & 0x55)
data1[i] = ((data1[i] & 0x55) ^ ((data2[7 - i] & 0xaa) >> 1)) | (data1[i] & 0xaa)
data1[i] = ((data1[i] & 7) << 5) | (data1[i] >> 3)
print(data1, data2)
for i in range(8):
print('%02x' %(data1[i]),end='')
for i in range(8):
print('%02x' %(data2[i]), end='')
值得注意的地方是逆中间两个cipher加密的位置,这个地方那一组数据,用ipython,多查看下其中的数据的二进制就很好理解,
按位与运算 配合 左右移 和 0xaa(0b10101010), 0x55(0b01010101),使得结果的对应位分别和两个数对应的位一致,只需要再和0xaa,0x55按位与运算即可
然后得到flag:
advance
首先在ida分析:
首先是取得flag长度, 然后函数encode( cipher, flag, len_flag )
中加密, 分析其中的处理是一个base64,
但是是变表base64,
得到脚本:
import base64
diy_base = 'abcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZ0'
base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
diy_cipher = "0g371wvVy9qPztz7xQ+PxNuKxQv74B/5n/zwuPfX"
cipher = ''
for i in diy_cipher :
cipher += base[diy_base.find(i)]
print (base64.b64decode(cipher))
然后得到flag:
cpp
首先是输入flag, 然后调用函数find( flag, str, 0 )
这个函数, 返回 flag 中的 str 的位置,所以我们可以看到flag最后一位 ‘}’ 在61位, 整个flag长度为62位。
接下来是取flag格式之内的部分, 然后按照 ’ _ ’ 获取flag中这个字符的位置,按照两个字符之间的距离,调用函数 set_tmp( flag , tmp , munber)
分割开,将中间的值保存到tmp中,然后调用函数 atoll( tmp )
将tmp中的数据转化为对应数值, 然后是set_cipher( cipher, munber )
保存到cipher中, 由此形成一个cipher数组,数组的每一位数值之间使用 '_'分割,
这个位置动调几次就可以确定了,要注意的是,不会读取十六进制, 只读取十进制, 且可以读取负数,
接下来设定好另外两个数组,arr_b, arr_a
并进行一个最后的判定。
这个运算位置, 一开始想用z3直接搞,但是发现总是 unsat
,比较不能理解,然后后面看到提示说线代?然后看出来是个矩阵运算,emmm,在线工具求逆阵,然后逆阵和另一个直接乘法,都可以在线工具搞出来, 然后结果有负数, 因此z3不管用了,然后试了下 Int
Real
BitVec
似乎是都不可以负数的样子:
这里可以使用矩阵计算的库 numpy也可以
得到flag:
hgame{-24840_-78193_51567_2556_-26463_26729_3608_-25933_25943}