[CISCN 2021初赛]babybc
LLVM是那个控制流平坦化混淆,bc是IR指令文件
得到64位elf文件
然后就慢慢分析,感觉太妙了我靠
一个数独游戏,用二个二维数组添加约束,一个二维数组作地图,慢慢看
最后用 z3 来解数独,也是 vary nice
from z3 import *
from hashlib import md5
# 限制条件
rowss = [[0x00, 0x00, 0x00, 0x01],
[0x01, 0x00, 0x00, 0x00],
[0x02, 0x00, 0x00, 0x01],
[0x00, 0x00, 0x00, 0x00],
[0x01, 0x00, 0x01, 0x00]]
# 限制条件
colnms = [[0x00, 0x00, 0x02, 0x00, 0x02],
[0x00, 0x00, 0x00, 0x00, 0x00],
[0x00, 0x00, 0x00, 0x01, 0x00],
[0x00, 0x01, 0x00, 0x00, 0x01]]
s = Solver()
# 初始化题目
map = [[None] * 5,
[None] * 5,
[None] * 5,
[None] * 5,
[None] * 5]
for i in range(5):
for j in range(5):
map[i][j] = Int("x%d%d" % (i, j)) # 先初始化设置未知数
s.add(map[2][2] == 4)
s.add(map[3][3] == 3) # 添加条件: 有两个位置已知
# 设置限制条件
for i in range(5):
for j in range(5):
s.add(map[i][j] >= 1)
s.add(map[i][j] <= 5) # 添加条件: 填的数字为1-5
for i in range(5):
for j in range(5):
for k in range(j):
s.add(map[i][j] != map[i][k]) # 添加条件: 一行中不能有相同
for j in range(5):
for i in range(5):
for k in range(i):
s.add(map[i][j] != map[k][j]) # 添加条件: 一列中不能有相同
for i in range(5):
for j in range(4):
if rowss[i][j] == 1:
s.add(map[i][j] > map[i][j + 1])
elif rowss[i][j] == 2:
s.add(map[i][j] < map[i][j + 1]) # 根据题目分析添加条件
for i in range(4):
for j in range(5):
if colnms[i][j] == 2:
s.add(map[i][j] > map[i + 1][j])
elif colnms[i][j] == 1:
s.add(map[i][j] < map[i + 1][j]) # 根据题目分析添加条件
answer = s.check()
if answer == sat:
print(s.model())
m = s.model()
flag = []
for i in map:
for j in i:
flag.append(m[j].as_long())
print(flag)
for i in range(len(flag)):
flag[i] += 48
flag[12] = 48
flag[18] = 48
flag = bytes(flag)
print("CISCN{%s}" % md5(flag).hexdigest())
# Flag=CISCN{8a04b4597ad08b83211d3adfa1f61431}
[HNCTF 2022 WEEK4]ez_maze
uncompyle6不能反编译pyc
pycdc打开,就是一个简单的31*31的maze,不过需要注意的是只能走0
学着写了一个 DFS 解密脚本
from hashlib import md5
map1 = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1],
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]
# record go track
map2=[[0 for _ in range(len(map1))] for _ in range(len(map1))]
flag=""
def DFS(row,col):
global flag
go=0
if row==29 and col==29: # finally
print(flag)
res=flag
return res
# first check next row whether can go and be noticed
if map1[row+1][col]==go and map2[row+1][col]==0:
# if can,go and notice and 递归
map2[row][col]=1
flag+='s'
DFS(row+1,col)
# 回溯操作
flag=flag[:-1]
map2[row][col]=0
if map1[row-1][col]==go and map2[row-1][col]==0:
map2[row][col]=1
flag+='w'
DFS(row-1,col)
flag=flag[:-1]
map2[row][col]=0
if map1[row][col-1]==go and map2[row][col-1]==0:
map2[row][col]=1
flag+='a'
DFS(row,col-1)
flag=flag[:-1]
map2[row][col]=0
if map1[row][col+1]==go and map2[row][col+1]==0:
map2[row][col]=1
flag+='d'
DFS(row,col+1)
flag=flag[:-1]
map2[row][col]=0
if __name__ == '__main__':
start_row=1
start_col=1
DFS(start_row,start_col)
enc='ssssddssaassddddwwwwddwwddddddwwddddddssddwwddddddddssssaawwaassaassaassddssaassaawwwwwwaaaaaaaassaassddddwwddssddssssaassddssssaaaaaawwddwwaawwwwaassssssssssssddddssddssddddddddwwaaaaaawwwwddssddwwwwwwwwddssddssssssssddddss'
enc=enc.encode()
print(md5(enc).hexdigest())
[GDOUCTF 2023]L!s!
两个 64位的elf文件
一个应该是 patch 了
两个程序的main好像差不多都是一千多行代码,前面有很多case语句
结合文件的名字,这两个文件可能只有一点细微的差异,其他内容都是一样的
识别二进制文件中的差异,可以使用 IDA 的 BinDiff 插件
工具下的有点问题,烦 jdk 0.0
算了,反正来学一下解密
厨子的使用
感觉自己很多都不会用啊,学学
记一下:
def little_endian(num, width_num): # 将小端序转换为正序
global buffer
hex_str = hex(num) # 将int数据转换为十六进制的字符串
while len(hex_str) != width_num + 2:
hex_str = "0x" + "0" * (width_num - len(hex_str[2:])) + hex_str[2:] # 位数不足width的用0凑齐
index = width_num
while index >= 2:
tmp = int((hex_str[index: index + 2]), 16) # 每两位string转换为十六进制int型数据
buffer.append(tmp) # 将int型作为char存入buffer
index -= 2
return buffer
buffer = [] # 存放结果的列表
lmao1 = 0x7D2E370A180F1604
lmao2 = 0x3F7D132A2A252822
lmao3 = 0x392A7F3F39132D13
lmao4 = 0x31207C7C381320
little_endian(lmao1, 16)
little_endian(lmao2, 16)
little_endian(lmao3, 16)
little_endian(lmao4, 14)
print(buffer)
# [4, 22, 15, 24, 10, 55, 46, 125, 34, 40, 37, 42, 42, 19, 125, 63, 19, 45, 19, 57, 63, 127, 42, 57, 32, 19, 56, 124, 124, 32, 49]
for key in range(256): # 直接爆破key
flag = ""
print("key = ", key)
for k in range(len(buffer)):
tmp = buffer[k] ^ key # 逐个与key异或
flag += chr(tmp) # 对应的字符存入flag
print(flag)
if 'HZCTF' in flag or 'NSSCTF' in flag: # 只输出包含'HZCTF'或'NSSCTF'的结果
break
注意学习了那个端序的处理
也还有一种,不过不太好记
import struct
stack_bytes = [
0x7d2e370a180f1604,
0x3f7d132a2a252822,
0x392a7f3f39132d13,
0x31207c7c381320
]
# 将stack_bytes中的数据按照小端字节序打包为二进制数据
xored_bytes = struct.pack("<4Q", *stack_bytes)
# 其中,< 表示小端序,Q代表一个无符号长整型
# 每个无符号长整型整数占8个字节,所以总共打包出来的字符串长度为32个字节
# b'\x04\x16\x0f\x18\n7.}"(%**\x13}?\x13-\x139?\x7f*9 \x138|| 1\x00'
for xorkey in range(256):
output = bytes(byte ^ xorkey for byte in xored_bytes)
if b"HZCTF{" in output:
print(output)
# b'HZCTF{b1ndiff_1s_a_us3ful_t00l}L'
# (因为在lmao4的高位补了一个0,所以多输出了一个L)
Art
angr 跑了半天没出来
只能爆破了
flag=[0]*27+[125]
enc=[2, 24, 15, 248, 25, 4, 39, 216, 235, 0,
53, 72, 77, 42, 69, 107, 89, 46, 67, 1,
24, 92,9, 9, 9, 9, 181, 125]
# for i in range(1,len(enc),1):
# Str1[i - 1] ^= (Str1[i - 1] % 17 + Str1[i]) ^ 25
# str[i-1]=sre[i-1]^25^(str[i-1]%17+str[i])
# str[26]=str[26]^25^(str[26]%17+str[27])
def dfs(index):
if index ==0:
for j in flag:
print(chr(j),end='')
print()
else:
for i in range(32,128,1):
if (i^25)^(i%17+flag[index])==enc[index-1]:
flag[index-1]=i
dfs(index-1)
dfs(27)
# (i^25)^(i%17+flag[27])==enc[26]
对于逆向来说,算法还是很重要的
不可大意
要注意顺序
z3使用
from z3 import *
s=Solver()
charArray=[BitVec(f"charArray[{i}]",8) for i in range(9)]
s.add((charArray[0] * 4778) + (charArray[1] * 3659) + (charArray[2] * 9011) + (charArray[3] * 5734) + (charArray[4] * 4076) + (charArray[5] * 6812) + (charArray[6] * 8341) + (charArray[7] * 6765) + (charArray[8] * 7435) == 5711942)
s.add((charArray[0] * 4449) + (charArray[1] * 5454) + (charArray[2] * 4459) + (charArray[3] * 5800) + (charArray[4] * 6685) + (charArray[5] * 6120) + (charArray[6] * 7357) + (charArray[7] * 3561) + (charArray[8] * 5199) == 4885863 )
s.add((charArray[0] * 3188) + (charArray[1] * 6278) + (charArray[2] * 9411) + (charArray[3] * 5760) + (charArray[4] * 9909) + (charArray[5] * 7618) + (charArray[6] * 7184) + (charArray[7] * 4791) + (charArray[8] * 8686) == 6387690)
s.add( (charArray[0] * 8827) + (charArray[1] * 7419) + (charArray[2] * 7033) + (charArray[3] * 9306) + (charArray[4] * 7300) + (charArray[5] * 5774) + (charArray[6] * 6588) + (charArray[7] * 5541) + (charArray[8] * 4628) == 6077067)
s.add( (charArray[0] * 5707) + (charArray[1] * 5793) + (charArray[2] * 4589) + (charArray[3] * 6679) + (charArray[4] * 3972) + (charArray[5] * 5876) + (charArray[6] * 6668) + (charArray[7] * 5951) + (charArray[8] * 9569) == 5492294)
s.add((charArray[0] * 9685) + (charArray[1] * 7370) + (charArray[2] * 4648) + (charArray[3] * 7230) + (charArray[4] * 9614) + (charArray[5] * 9979) + (charArray[6] * 8309) + (charArray[7] * 9631) + (charArray[8] * 9272) == 7562511)
s.add( (charArray[0] * 6955) + (charArray[1] * 8567) + (charArray[2] * 7949) + (charArray[3] * 8699) + (charArray[4] * 3284) + (charArray[5] * 6647) + (charArray[6] * 3175) + (charArray[7] * 8506) + (charArray[8] * 6552) == 5970432)
s.add( (charArray[0] * 4323) + (charArray[1] * 4706) + (charArray[2] * 8081) + (charArray[3] * 7900) + (charArray[4] * 4862) + (charArray[5] * 9544) + (charArray[6] * 5211) + (charArray[7] * 7443) + (charArray[8] * 5676) == 5834523)
s.add((charArray[0] * 3022) + (charArray[1] * 8999) + (charArray[2] * 5058) + (charArray[3] * 4529) + (charArray[4] * 3940) + (charArray[5] * 4279) + (charArray[6] * 4606) + (charArray[7] * 3428) + (charArray[8] * 8889) == 4681110)
if s.check()==sat:
m=s.model()
print(m)
print(len(m))
data=[]
for i in range(9):
data.append((m[charArray[i]].as_long()))
for i in range(9):
print(chr(data[i]),end='')
TEA_Apk
还有一个 base64
最外面函数
看的太头疼了
中间函数
也是大致清楚了,就是将 byte 转 int
barr.length & 3 (11) == 0
相当于 / 4 ,算出 int 的长度
然后根据 z 来 new int 数组空间,如果 true ,长度加一,最后元素为原计算长度
,false 就是原长度
( bArr[i] & 255) << ( ( i & 3) << 3 ) | iArr[i2]
byte - int 关键, &255 确保在 0-255 之间, ( ( i & 3) << 3 ) 算偏移
>>> 无符号右移
里面
这个应该只是检查长度是否是16
wp 看了一下,原来一整个是 XXTEA 加密,工具直接可以解,不过还是分析了一下,确实很难逆
翻半天,就只有一个大佬的脚本
import base64
from ctypes import c_uint32
import libnum
DELTA = 0x9E3779B9
def decrypt(v, n, k):
rounds = 6 + int(52 / n)
sum = c_uint32(rounds * DELTA)
y = v[0].value
while rounds > 0:
e = (sum.value >> 2) & 3
p = n - 1
while p > 0:
z = v[p - 1].value
v[p].value -= (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum.value ^ y) + (k[(p & 3) ^ e] ^ z)))
y = v[p].value
p -= 1
z = v[n - 1].value
v[0].value -= (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum.value ^ y) + (k[(p & 3) ^ e] ^ z)))
y = v[0].value
sum.value -= DELTA
rounds -= 1
enc = "vlgg9nNjUcYuWzBSSOwKxbMD2rhFgf4zuiyMpLxpNkM="
key = "ABvWW7hqwNvHUhfP"
enc = base64.b64decode(enc.encode())
print(enc)
e = list(map(lambda i: c_uint32(int(enc[i:i + len(enc) // 8][::-1].hex(), 16)), range(0, len(enc), len(enc) // 8)))
print(e)
k = list(map(lambda i: int(key[i:i + len(key) // 4].encode()[::-1].hex(), 16), range(0, len(key), len(key) // 4)))
print(k)
decrypt(e, len(e), k)
print(b''.join(map(lambda x: libnum.n2s(x.value)[::-1], e)))
研究一下
[长城杯 2021 院校组]Just_cmp-re
估计是 hook strcmp 了吧
运行到 call 报错了
翻到了这个函数
额,就很逆向
data=[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x07, 0x0A, 0x37, 0x0A,
0x08, 0x0A, 0x06, 0x06, 0x0B, 0x38, 0x07, 0x0A, 0x3B, 0x08,
0x38, 0x0E, 0x0F, 0x3B, 0x3A, 0x0A, 0x0B, 0x06, 0x09, 0x07,
0x3B, 0x37, 0x0D, 0x0F, 0x07, 0x38, 0x0F, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
enc='flag{********************************}'
flag=''
for i in range(len(enc)):
flag+=chr(ord(enc[i])+data[i])
print(flag)