当前位置:网站首页>2022 Top Net Cup Quals Reverse Partial writeup
2022 Top Net Cup Quals Reverse Partial writeup
2022-08-10 02:51:00 【1mmorta1】
Game
nativeThe layer actually only has two functions for encryption and decryption,So nothing reversed,直接用frida hook
- 由于有root检测和frida检测,换个端口启动 ./frida-server-15.1.8-android-arm64 -l 0.0.0.0:27049
- Then you can directly call the encryption and decryption functions:
/* docs: https://frida.re/docs/javascript-api/ adb root adb shell cd /data/local ./frida-server py3 adb forward tcp:27049 tcp:27049 frida-ps -H 127.0.0.1:27049 frida -H 127.0.0.1:27049 -f com.silence.scoreboard -l try.js --no-pause */
var HttpRequest = Java.use('com.silence.scoreboard.http.HttpRequest');
var OOOO = Java.use('com.silence.utils.OooOoo0');
OOOO.decrypt("SWeH8ou9yuL8GLThYhY1QlDiWX880+uNZusmIll/Q4Q=");
// "&Od987$2sPa?>l<k^j"
OOOO.decrypt("IbaoQT/3eTXIjHDJ2L5TQE==");
//"admin"
Mainly in reversejava层的逻辑,All data are in sum47.93.244.181服务器进行交互,因此只要在com.silence.scoreboard.http.HttpRequest It is enough to understand the logic of a few interactions.
通过scoreboard http://47.93.244.181/re/ScoreBoard.php Find a high scoreadmin "IbaoQT/3eTXIjHDJ2L5TQE==”(a.k.a. admin)
Obtained by adding friendsadmin的account $.post(‘AddFriend.php’, {code:‘123125’})
获得flag username = ‘admin’; account = “&Od987$2sPa?>l<k^j”; $.post(‘GetFlag.php’, {code:‘123125’, account,username})
easyre
It can be known by reading the main program,The program writes a subroutinere3并ptrace它,It will be based on interruptionsRIP的内容解密、Re-encrypt a piece of code.
使用straceGet all system calls,(All writes to subroutines passptrace实现),解析PTRACE_POKETEXT并patch程序(Decrypted part only)
lines = open(r'stracedump.txt').read().splitlines() lines = [line for line in lines if line.startswith('ptrace(PTRACE_POKETEXT, ')] delta = 0x555555554000 lines = [(int(line[31:][:14], 16) - delta, int(line[47:-5].strip(), 16)) for line in lines] lines = lines[:0x27] [patch_qword(addr, value) for addr, value in lines]
setjmp和longjmpPart of the code should just write a loop comparison process
Hardware breakpoints on and off the two arrays to be compared,Notice that the subroutine starts by swapping the last two arrays compared.
用z3Solve the corresponding problem(队内4老师的脚本!I draw it by myself55):
linescan = bytes.fromhex('0605010302010100000000000000000000000000000000000008010101010101010100000000000000000000000000000000070301030104010100000000000000000000000000000000000801010102010101010000000000000000000000000000000007010401030201030000000000000000000000000000000000000000000000000000000000000000000000000000000000000604040401010100000000000000000000000000000000000008010202010201020100000000000000000000000000000000080101010103040301000000000000000000000000000000000A01010101010101010101000000000000000000000000000007030103010401010000000000000000000000000000000000010200000000000000000000000000000000000000000000000601010401010400000000000000000000000000000000000007080101010102010000000000000000000000000000000000080101010101010104000000000000000000000000000000000A0202010201010101010100000000000000000000000000000502050101030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060C0201010101000000000000000000000000000000000000090201010101010101010000000000000000000000000000000704070201010101000000000000000000000000000000000009010102010101010101000000000000000000000000000000020C02000000000000000000000000000000000000000000000401010101000000000000000000000000000000000000000004040201010000000000000000000000000000000000000000') assert 625 == len(linescan) linescan = [[linescan[i*25+j] for j in range(25)] for i in range(25)] cowscan = bytes.fromhex('050505030103000000000000000000000000000000000000000A0101010101010101010100000000000000000000000000000701010501030101000000000000000000000000000000000005010204050100000000000000000000000000000000000000070502010101010100000000000000000000000000000000000501010101050000000000000000000000000000000000000005010206010300000000000000000000000000000000000000070202010101010100000000000000000000000000000000000602050103010100000000000000000000000000000000000009010101010101010301000000000000000000000000000000070201010101010100000000000000000000000000000000000402050301000000000000000000000000000000000000000005030501010100000000000000000000000000000000000000080101010101010101000000000000000000000000000000000601010103050500000000000000000000000000000000000006010305010101000000000000000000000000000000000000030101030000000000000000000000000000000000000000000505010204010000000000000000000000000000000000000004010104030000000000000000000000000000000000000000050101020401000000000000000000000000000000000000000305040300000000000000000000000000000000000000000004020504010000000000000000000000000000000000000000050503010101000000000000000000000000000000000000000701020101010401000000000000000000000000000000000003010101000000000000000000000000000000000000000000') assert 625 == len(cowscan) cowscan = [[cowscan[i*25+j] for j in range(25)] for i in range(25)] def clean(v): u = [] for w in v: print(w) leng = w[0] re = w[1:][:leng] oth = w[leng+1:] #assert oth == [0]*len(oth) u.append(re) return u linescan = clean(linescan) cowscan = clean(cowscan) print(linescan) print(cowscan) from z3 import * mat = [[Bool(f'x_{ i},{ j}') for j in range(25)] for i in range(25)] x = [[If(mat[i][j], 1, 0) for j in range(25)] for i in range(25)] lines = [0]*25 linediff = [0]*25 cows = [0]*25 cowdiff = [0]*25 sol = Solver() def valIn(a, b): if len(b) == 0: return False b = b.copy() cond = a == b[0] for i in range(1, len(b)): b[i] += b[i-1] cond = Or(cond, a==b[i]) return cond for i in range(25): linediff[i] += x[i][0] + x[i][-1] cowdiff[i] += x[0][i] + x[-1][i] for j in range(24): linediff[i] += If(x[i][j] != x[i][j+1], 1, 0) cowdiff[i] += If(x[j][i] != x[j+1][i], 1, 0) for j in range(24): lines[i] += x[i][j] sol.add(Or(Or(x[i][j]!=1, x[i][j+1]!=0), valIn(lines[i], linescan[i]))) cows[i] += x[j][i] sol.add(Or(Or(x[j][i]!=1, x[j+1][i]!=0), valIn(cows[i], cowscan[i]))) for j in range(24, 25): lines[i] += x[i][j] cows[i] += x[j][i] for i in range(25): sol.add(lines[i] == sum(linescan[i])) sol.add(cows[i] == sum(cowscan[i])) sol.add(linediff[i] == 2*len(linescan[i])) sol.add(cowdiff[i] == 2*len(cowscan[i])) print('dd') print(sol.check()) mod = sol.model() x = [[int(str(mod.eval(mat[i][j])) == 'True') for j in range(25)] for i in range(25)] y = '\n'.join(''.join(map(str, x[i])) for i in range(25)) # 解中01Use spaces and All black frame █ 替代: for c in y: if c=='1': print('█',end='') elif c=='0': print(' ',end='') else: print()
█████ █ ███ ██ █ █ █ █ █ █ █ █ █ █ ███ █ ███ █ ████ █ █ █ █ █ ██ █ █ █ █ █ ████ █ ███ ██ █ ███ ████ ████ ████ █ █ █ █ ██ ██ █ ██ █ ██ █ █ █ █ █ ███ ████ ███ █ █ █ █ █ █ █ █ █ █ █ ███ █ ███ █ ████ █ █ ██ █ █ ████ █ █ ████ ████████ █ █ █ █ ██ █ █ █ █ █ █ █ █ ████ ██ ██ █ ██ █ █ █ █ █ █ ██ █████ █ █ ███ ████████████ ██ █ █ █ █ ██ █ █ █ █ █ █ █ █ ████ ███████ ██ █ █ █ █ █ █ ██ █ █ █ █ █ █ ████████████ ██ █ █ █ █ ████ ██ █ █
Notice that a bunch of empty columns are selectively turned into spaces(FLAG{I LOVE PLAY ctf_QWB2022})(The characters are well drawn,Don't draw next time)
彩蛋?(The result of solving the fake array)
██ ██ ███ █ █ █ █ █████ █ ██ ██ █ █ █ █ ███ ██ █ █ █ ████████████ ███████ ██ ██ ██████ ██ ██ █ █ █ ███ ██ █ █ ██ █ █████ ████ █ █████ █ ███ █ █ ████ █████ █ ██████████████ █ █ ██ ███ ████ ██ █ █ █ █████ ██ ██ █████ ██ ██ ██ █ ███████ ██ ████ █ █ █████ █ ███ █ █ ███████ ██ ██ ████ ██ █████ ██ ██ ██ ███ █ ████ █████ █████ ███ █ ███ ██ █ █ ██ ██ ███ ████████████████
easyapk
javaThe layers are obfuscated but it is still easy to find the correct logic,native层调用的check函数, It's confusing insidetea加密,差不多长这样(前面还有4个key的生成):
i = 0;
p_tmp_seed = v173;
while ( 1 )
{
p_len_1 = v179;
*p_i = i;
if ( i >= *p_len_1 )
break;
j = 0;
input = *p_input;
*p_p_input_i = &(*p_input)[i];
*v182 = seeds;
*p_l4b = *(_DWORD *)&input[i];
*p_r4b = *(_DWORD *)&input[i + 4];
*p_k = 0;
v148 = time(0);
p_seed2 = v174;
p_seed3 = v175;
p_seed1 = v176;
v152 = (v148 & 0x30000000) - (v148 & 0xC0000000) + 2 * (v148 & 0x40000000) + 0x35970C13;
p_l4b = v177;
*p_tmp_seed = (v152 ^ 0xF4170810 | 0x1C88647) + 2 * (v152 ^ 0xBA075AA);
seeds_1 = *v182;
seed0 = **v182;
*p_seed1 = seeds_1[1];
*p_seed2 = seeds_1[2];
*p_seed3 = seeds_1[3];
while ( 1 )
{
*p_j = j;
if ( j > 0x1F )
break;
r4b = *p_r4b;
k = 2 * (*p_k | *p_tmp_seed) - (*p_tmp_seed ^ *p_k);
*p_k = k;
v156 = (2 * (k | r4b) - (k ^ r4b)) ^ (2 * (seed0 | (0x10 * r4b)) - (seed0 ^ (0x10 * r4b))) ^ (2 * (*p_seed1 | (r4b >> 5))
- (*p_seed1 ^ (r4b >> 5)));
seed2 = *p_seed2;
enced_l4b = 2 * (v156 | *p_l4b) - (v156 ^ *p_l4b);
*p_l4b = enced_l4b;
v159 = (2 * (*p_seed3 | (enced_l4b >> 5)) - (*p_seed3 ^ (enced_l4b >> 5))) ^ (2 * (seed2 | (0x10 * enced_l4b))
- (seed2 ^ (0x10 * enced_l4b))) ^ (2 * (enced_l4b | *p_k) - (*p_k ^ enced_l4b));
*p_r4b = 2 * (v159 | *p_r4b) - (v159 ^ *p_r4b);
j = (*p_j | 0xFFFFFFFE) - (*p_j & 0xFFFFFFFE) + 2 * (*p_j | 1) + 1;// j ++
}
p_i = v178;
p_input_i = *p_p_input_i;
*p_input_i = *p_l4b;
p_input_i[1] = *p_r4b;
i = (*p_i | 0xFFFFFFF7) - (*p_i & 0xFFFFFFF7) + 2 * (*p_i | 8) + 1;// i+=8
}
The final decrypted output also needs to be decrypted by Virginia,密钥是n.
#include <stdio.h>
#include <stdint.h>
void decrypt (uint32_t v[2],const uint32_t k[4]) {
uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;/* set up; sum is (delta << 5) & 0xFFFFFFFF */
uint32_t delta=0x9E3779B9;/* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];/* cache key */
for (i=0; i<32; i++) {
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
}
v[0]=v0; v[1]=v1;
}
int main()
{
uint32_t v[9]= {
0x5D94AA84, 0x14FA24A0, 0x2B560210, 0xB69BDD49, 0xAAEFEAD4, 0x4B8CF4C6, 0x097FB8C9, 0xB5EC51D2,0};
uint32_t const k[4]= {
0x33323130,0x37363534,0x62613938,0x66656463};
for(int i=0;i<4;i++){
decrypt(&v[2*i],k);
}
printf("%s\n",v);
return 0;
}
边栏推荐
- [Swoole Series 3.5] Process Pool and Process Manager
- 【干货】集成学习原理总结
- 免费文档翻译软件电脑版软件
- 对修饰器的实验支持功能在将来的版本中可能更改。在 “tsconfig“ 或 “jsconfig“ 中设置 “experimentalDecorators“ 选项以删除此警告
- OpenCV图像处理学习一,加载显示修改保存图像相关函数
- RESOURCE_EXHAUSTED: etcdserver: mvcc: database space exceeded
- unity 报错 Unsafe code may only appear if compiling with /unsafe. Enable “Allow ‘unsafe‘ code“ in Pla
- 【每日一题】1413. 逐步求和得到正数的最小值
- T5:Text-toText Transfer Transformer
- 【web渗透】SSRF漏洞超详细讲解
猜你喜欢
QT中,QTableWidget 使用示例详细说明
JCMsuite—单模光纤传播模式
万字总结:分布式系统的38个知识点
按钮倒计时提醒
元素的盒子模型+标签的尺寸大小和偏移量+获取页面滚动距离
Nacos源码分析专题(五)-Nacos小结
Summary of Web Performance Testing Models
【论文笔记】基于深度学习的机器人抓取虚拟仿真实验教学系统
Experimental support for decorators may change in future releases.Set the "experimentalDecorators" option in "tsconfig" or "jsconfig" to remove this warning
进程管理和任务管理
随机推荐
Open3D 网格均匀采样
如何让数据库中的数据同步
【论文笔记】基于深度学习的机器人抓取虚拟仿真实验教学系统
常用正则备查
【干货】集成学习原理总结
color socks problem
C# rounding MidpointRounding.AwayFromZero
进程管理和任务管理
中级xss绕过【xss Game】
Interdepartmental Communication Skills
自动化测试中,测试数据与脚本分离以及参数化方法
Maya制作赛博朋克机器人模型
Open3D 中点细分(网格细分)
【UNR #6 C】稳健型选手(分治)(主席树)(二分)
OOD论文:Revisit Overconfidence for OOD Detection
unity 报错 Unsafe code may only appear if compiling with /unsafe. Enable “Allow ‘unsafe‘ code“ in Pla
SQL注入的order by ,limit与宽字节注入
LeetCode 每日一题——1413. 逐步求和得到正数的最小值
one of the variables needed for gradient computation has been modified by an inplace
实操|风控模型中常用的这三种预测方法与多分类场景的实现