强网杯-gamemaster-easyre
re
GameMaster
dnspy C# 导出到vs
观察到三个AchivePoint 反序列化出一个值
去vs里面改代码 调用
保存t的值
观察到MZ
保存后半段
将后半段加入dnspy
观察到flag相关算法
这个文件也导出到vs 方便调试
将T1里面的代码放到main
其中传入的三个数字是触发achivepoint时的balence值
逆向check1即可
import z3
from z3 import *
x = BitVec('x', 64)
y = BitVec('y', 64)
z = BitVec('z', 64)
keystream = [BitVec('keystream[%d]' % i, 8) for i in range(40)]
kt = [i for i in keystream]
s = Solver()
tx = x
ty = y
tz = z
num = -1
first = [101,
5,
80,
213,
163,
26,
59,
38,
19,
6,
173,
189,
198,
166,
140,
183,
42,
247,
223,
24,
106,
20,
145,
37,
24,
7,
22,
191,
110,
179,
227,
5,
62,
9,
13,
17,
65,
22,
37,
5]
for i in range(320):
tx = (((tx >> 29 ^ tx >> 28 ^ tx >> 25 ^ tx >> 23) & 1) | tx << 1)
ty = (((ty >> 30 ^ ty >> 27) & 1) | ty << 1)
tz = (((tz >> 31 ^ tz >> 30 ^ tz >> 29 ^ tz >> 28 ^ tz >> 26 ^ tz >> 24) & 1) | tz << 1)
tx=z3.simplify(tx)
ty=z3.simplify(ty)
tz=z3.simplify(tz)
if i % 8 == 0:
num += 1
t = (tz >> 32 & 1 & (tx >> 30 & 1)) ^ (((tz >> 32 & 1) ^ 1) & (ty >> 31 & 1))
# keystream[num]=ZeroExt(56,keystream[num])<<1
kt[num] = ((ZeroExt(56, kt[num]) << 1) | t)
kt[num] = Extract(7, 0, kt[num])
kt[num] = z3.simplify(kt[num])
# print(kt[num])
for i in range(len(first)):
s.add(kt[i] == first[i])
# print(s)
# print(kt)
print(s.check())
print(s.model())
然后丢进VS
getflag
easyapk
调用so的check
check又调用sub_544
直接拖到最底下 发现是tea算法
其中用了 2 * (a | b) - (a ^ b)
类似形式来代替a+b
逐步还原回去即可
其中将很多定值和time()挂钩
简单计算发现都只和time函数高几位有关 time返回时间戳 高几位是定值 所以带入当前时间戳就好
先计算相关定值 key相关来源复制原码即可
import time
time = (int(time.time()))
key = [0] * 4
v15 = time
key[0] = ((v15 & 0x20000000) - (v15 & 0xD0000000) + 2 * (v15 & 0x50000000) + 705251522) ^ 0xB93B79F2
v16 = time
key[1] = ((v16 & 0x10000000) - (v16 & 0xE0000000) + 2 * (v16 & 0x60000000) + 268614163) ^ 0x47348F27
v17 = time
key[2] = ((v17 & 0x50000000) - (v17 & 0xA0000000) + 2 * (v17 & 0x20000000) + 1598838216) ^ 0xDD2D6CF0
v18 = time
key[3] = (((v18 & 0x40000000) - (v18 & 0xB0000000) + 2 * (v18 & 0x30000000) + 1085702636) ^ 0x30240060 | 0x99A9B9D)+ 2 * (((v18 & 0x40000000) - (v18 & 0xB0000000) + 2 * (v18 & 0x30000000) + 1085702636) ^ 0x46D3E58F)
for index in range(len(key)):
key[index]=key[index]&0xFFFFFFFF
print(hex(key[index]))
print(key)
fuckT=time
r1 = (fuckT & 0x30000000) - (fuckT & 0xC0000000) + 2 * (fuckT & 0x40000000) + 0x35970C13
delta = (r1 ^ 0xF4170810 | 0x1C88647) + 2 * (r1 ^ 0xBA075AA)
print(hex(delta))
得到enc [858927408, 926299444, 1650538808, 1717920867]
delta 0x19e3779b9
然后脚本解密
#include <iostream>
#include <string>
#include <fstream>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
void teaaaa(unsigned int v[2], unsigned int key[4])
{
uint32_t delta = 0x19e3779b9;
uint32_t sum = delta * 32;
uint32_t v0 = v[0];
uint32_t v1 = v[1];
uint32_t K1 = key[1];
uint32_t K0 = key[0];
uint32_t K2 = key[2];
uint32_t K3 = key[3];
uint32_t v0_t;
for(int i=0;i<32;i++)
{
v1 -= (K3 + (v0 >> 5)) ^ (K2 + (16 * v0)) ^ (v0 + sum);
v0_t = v1;
v0-= (sum + v0_t) ^ (K0 + (v0_t * 16)) ^ (K1 + (v0_t >> 5));
sum -= delta;
}
v[0] = v0;
v[1] = v1;
}
int main(int argc, char const* argv[])
{
unsigned int enc[9] = {
0x5D94AA84, 0x14FA24A0, 0x2B560210, 0xB69BDD49, 0xAAEFEAD4, 0x4B8CF4C6, 0x097FB8C9, 0xB5EC51D2,0
};
unsigned int key[4] = {
858927408, 926299444, 1650538808, 1717920867 };
teaaaa(enc, key);
teaaaa(enc+2, key);
teaaaa(enc+4, key);
teaaaa(enc+6, key);
puts((char*)&enc);
}
有点凯撒 梭一把
get flag!