当前位置:网站首页>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;
}
边栏推荐
猜你喜欢
随机推荐
OpenCV图像处理学习二,图像掩膜处理
[论文阅读] Diverse Image-to-Image Translation via Disentangled Representations
【web渗透】SSRF漏洞超详细讲解
.Net interview experience summary
多线程之自定义线程池
Chip Information|Semiconductor revenue growth expected to slow to 7%, Bluetooth chip demand still growing steadily
Maya制作赛博朋克机器人模型
数据库治理利器:动态读写分离
Experimental support for decorators may change in future releases.Set the "experimentalDecorators" option in "tsconfig" or "jsconfig" to remove this warning
type-C 边充电边听歌(OTG) PD芯片方案,LDR6028 PD充电加OTG方案
中文NER的SOTA:RICON
ImportError: Unable to import required dependencies: numpy
Visual low-code system practice based on design draft identification
组件的使用
不是吧,连公司里的卷王写代码都复制粘贴,这合理?
Not, even the volume of the king to write code in the company are copying and pasting it reasonable?
mysql -sql编程
月薪35K,靠八股文就能做到的事,你居然不知道
【UNR #6 B】机器人表演(DP)
gbase 8a数据库如何查看数据或数据文件是否正常?