当前位置:网站首页>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;
}
边栏推荐
- QT中,QTableWidget 使用示例详细说明
- 数据库治理利器:动态读写分离
- The shell specifies the parameter name to pass the parameter
- Linux(Centos7)服务器中配置Mysql主从数据库,以及数据库的安装,防火墙操作
- 【每日一题】1413. 逐步求和得到正数的最小值
- type-C 边充电边听歌(OTG) PD芯片方案,LDR6028 PD充电加OTG方案
- LeetCode 每日一题——1413. 逐步求和得到正数的最小值
- Sikuli's Automated Testing Technology Based on Pattern Recognition
- sql实战积累
- 2022年8月8日-2022年8月15日,ue4视频教程+插件源码()
猜你喜欢
随机推荐
【web渗透】SSRF漏洞超详细讲解
idea 删除文件空行
空间复杂度为O(1)的归并排序
Under pressure, there must be cowards
[论文阅读] Diverse Image-to-Image Translation via Disentangled Representations
.Net interview experience summary
Premint工具,作为普通人我们需要了解哪些内容?
《GB39732-2020》PDF download
C# 正则表达式分组查询
Solve the problem of sed replacement text containing special characters such as "/" and "#"
openpose脚部标注问题梳理
Open3D 网格均匀采样
【wpf】拖拽的简单实现
常用正则备查
进程管理和任务管理
OpenCV图像处理学习一,加载显示修改保存图像相关函数
unity 报错 Unsafe code may only appear if compiling with /unsafe. Enable “Allow ‘unsafe‘ code“ in Pla
Shader Graph学习各种特效案例
C# 单例模式
sql实战积累