由浅入深
1,Matrix_lib_1
给了一个class文件,用jadx打开,看源码
package defpackage;
import java.util.Scanner;
/* renamed from: Sekai reason: default package */
/* loaded from: Matrix_Lab_1.class */
public class Sekai {
private static int length;
static final /* synthetic */ boolean $assertionsDisabled;
static {
$assertionsDisabled = !Sekai.class.desiredAssertionStatus();
length = ((int) Math.pow(2.0d, 3.0d)) - 2;
}
public static void main(String[] strArr) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the flag: ");
String next = scanner.next();
if (next.length() != 43) {
System.out.println("Oops, wrong flag!");
return;
}
String substring = next.substring(0, length);
String substring2 = next.substring(length, next.length() - 1);
String substring3 = next.substring(next.length() - 1);
if (substring.equals("SEKAI{") && substring3.equals("}")) {
if (!$assertionsDisabled && substring2.length() != length * length) {
throw new AssertionError();
}
if (solve(substring2)) {
System.out.println("Congratulations, you got the flag!");
return;
} else {
System.out.println("Oops, wrong flag!");
return;
}
}
System.out.println("Oops, wrong flag!");
}
public static String encrypt(char[] cArr, int i) {
char[] cArr2 = new char[length * 2];
int i2 = length - 1;
int i3 = length;
for (int i4 = 0; i4 < length * 2; i4 = i4 + 1 + 1) {
int i5 = i2;
i2--;
cArr2[i4] = cArr[i5];
int i6 = i3;
i3++;
cArr2[i4 + 1] = cArr[i6];
}
for (int i7 = 0; i7 < length * 2; i7++) {
int i8 = i7;
cArr2[i8] = (char) (cArr2[i8] ^ ((char) i));
}
return String.valueOf(cArr2);
}
public static char[] getArray(char[][] cArr, int i, int i2) {
char[] cArr2 = new char[length * 2];
int i3 = 0;
for (int i4 = 0; i4 < length; i4++) {
cArr2[i3] = cArr[i][i4];
i3++;
}
for (int i5 = 0; i5 < length; i5++) {
cArr2[i3] = cArr[i2][(length - 1) - i5];
i3++;
}
return cArr2;
}
public static char[][] transform(char[] cArr, int i) {
char[][] cArr2 = new char[i][i];
for (int i2 = 0; i2 < i * i; i2++) {
cArr2[i2 / i][i2 % i] = cArr[i2];
}
return cArr2;
}
public static boolean solve(String str) {
char[][] transform = transform(str.toCharArray(), length);
for (int i = 0; i <= length / 2; i++) {
for (int i2 = 0; i2 < (length - (2 * i)) - 1; i2++) {
char c = transform[i][i + i2];
transform[i][i + i2] = transform[((length - 1) - i) - i2][i];
transform[((length - 1) - i) - i2][i] = transform[(length - 1) - i][((length - 1) - i) - i2];
transform[(length - 1) - i][((length - 1) - i) - i2] = transform[i + i2][(length - 1) - i];
transform[i + i2][(length - 1) - i] = c;
}
}
return "oz]{R]3l]]B#50es6O4tL23Etr3c10_F4TD2".equals(encrypt(getArray(transform, 0, 5), 2) + encrypt(getArray(transform, 1, 4), 1) + encrypt(getArray(transform, 2, 3), 0));
}
}
检查流程
- 先看长度是43,再查头尾
- 到solve
- 转成矩阵,说是矩阵但没用到行列式的任何功能,只能算是数组
- 作一个复杂的交换
- 分别取出05,14,23加密作异或
- 加密先将两行一正一逆交互连一起
- 再重排一下
其实就是排来排去,没多大难度,只是比较麻烦
o1 = [5,6,4,7,3,8,2,9,1,10,0,11]
cipher = b"oz]{R]3l]]B#50es6O4tL23Etr3c10_F4TD2"
arr = [0]*36
c1 = [v^2 for v in cipher[:12]]
d1 = [0]*12
for i in range(12):
d1[o1[i]] = c1[i]
for i in range(6):
arr[i] = d1[i]
arr[30+i] = d1[11-i]
c1 = [v^1 for v in cipher[12:24]]
d1 = [0]*12
for i in range(12):
d1[o1[i]] = c1[i]
for i in range(6):
arr[6+i] = d1[i]
arr[24+i] = d1[11-i]
c1 = [v for v in cipher[24:]]
d1 = [0]*12
for i in range(12):
d1[o1[i]] = c1[i]
for i in range(6):
arr[12+i] = d1[i]
arr[18+i] = d1[11-i]
o2 = [i for i in range(36)]
for i in range(6):
for j in range(6-i*2-1):
c = o2[i*6 + i + j]
o2[i*6 + i + j] = o2[(5-i -j)*6 + i]
o2[(5-i -j)*6 + i] = o2[ (5-i)*6 + 5-i -j ]
o2[ (5-i)*6 + 5-i -j ] = o2[(i+j)*6 + 5-i]
o2[(i+j)*6 + 5-i] = c
flag = [0]*36
for i in range(36):
flag[o2[i]] = arr[i]
print(bytes(flag))
#m4tr1x_d3cryP710N_15_Fun_M4T3_@2D2D!
#SEKAI{m4tr1x_d3cryP710N_15_Fun_M4T3_@2D2D!}
2,Matrix_Lib_2
看图标这是个python编译的exe文件,先用python_exe_unpack.py解包,再打开Matrix_Lab文件和struct文件,将struct前16字节加到Matrix_Lab文件的开头,保存扩展名为pyc,然后拿到网上反编译http://tool.lu/pyc/
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.7
print('Welcome to Matrix Lab 2! Hope you enjoy the journey.')
print('Lab initializing...')
try:
import matlab.engine as matlab
engine = matlab.engine.start_matlab()
flag = input('Enter the lab passcode: ').strip()
outcome = False
if len(flag) == 23 and flag[:6] == 'SEKAI{' and flag[-1:] == '}':
A = (lambda .0: [ ord(i) ^ 42 for i in .0 ])(flag[6:-1]) #^42
B = matlab.double((lambda .0: [ A[i:i + 4] for i in .0 ])(range(0, len(A), 4))) #每4个一组转double
X = (lambda .0: [ list(map(int, i)) for i in .0 ])(engine.magic(4))
Y = (lambda .0: [ list(map(int, i)) for i in .0 ])(engine.pascal(4))
C = (lambda .0: [ (lambda .0: [ None for _ in .0 ])(range(len(X))) for _ in .0 ]
)(range(len(X)))
for i in range(len(X)):
for j in range(len(X[i])):
C[i][j] = X[i][j] + Y[i][j]
C = matlab.double(C)
if engine.mtimes(C, engine.rot90(engine.transpose(B), 1337)) == matlab.double([
[
2094,
2962,
1014,
2102],
[
2172,
3955,
1174,
3266],
[
3186,
4188,
1462,
3936],
[
3583,
5995,
1859,
5150]]):
outcome = True
if outcome:
print('Access Granted! Your input is the flag.')
else:
print('Access Denied! Your flag: SADGE{aHR0cHM6Ly95b3V0dS5iZS9kUXc0dzlXZ1hjUQ==}')
except:
print('Unknown error. Maybe you are running the lab in an unsupported environment...')
print('Your flag: SADGE{ovg.yl/2M6pWQB}')
先是^42,然后每4字节一组转double(这个double可以不管它,最后比较的时候也按整形比较),然后调用matlab的两个函数,magic生成幻方,由于4阶幻方有多个,这里找matlab生成的那一个,后边是pascal在我国叫杨辉三解,这是两个固定的矩阵,最后输入的内容再转置,然后逆转90度(1337%4==1)与C相乘(不是直接乘,是矩阵乘法,这个拿到sage运算)
A = matrix([[2094,2962,1014,2102],
[2172,3955,1174,3266],
[3186,4188,1462,3936],
[3583,5995,1859,5150]])
#magic(4) 4阶幻方
#pascal(4) 帕斯卡矩阵,杨辉三角
X = matrix([[16,2,3,13],
[5,11,10,8],
[9,7,6,12],
[4,14,15,1]])
Y = matrix([[1,1,1,1],
[1,2,3,4],
[1,3,6,10],
[1,4,10,20]])
C = X+Y
B = C.solve_right(A)
#求出B,手工旋转和转置(顺转90+转置=行取反B[::-1]),
B = [[ 26, 103, 25, 11],
[ 30, 125, 25, 121],
[ 30, 104, 27, 31],
[103, 30, 29, 102]]
#转置
print(bytes([v^42 for v in [103,30,29,102,30,104,27,31,30,125,25,121,26,103,25,11]]))
#M47L4B154W3S0M3!
#SEKAI{M47L4B154W3S0M3!}
3,Matrix_Lib_3
这个比较麻烦,WP也没找到,一点点啃
先是读入和判断头尾
__isoc99_scanf("%64s", command);
if ( strlen(command) != 64 || strncmp(command, "SEKAI{", 6uLL) || command[63] != 125 )
{
puts("Incorrect command format. You cannot unlock the Matrix. :(");
exit(1);
}
然后生成一堆矩阵,输入放入8*8矩阵
A = init(8, command);
v_A = (vbx_ubyte_t *)vbx_sp_malloc_nodebug(num_elements_80484);
v_B = (vbx_ubyte_t *)vbx_sp_malloc_nodebug(num_elements_80484);
v_C = (vbx_ubyte_t *)vbx_sp_malloc_nodebug(num_elements_80484);
v_D = (vbx_ubyte_t *)vbx_sp_malloc_nodebug(num_elements_80484);
v_O = (vbx_ubyte_t *)vbx_sp_malloc_nodebug(num_elements_80484);
然后作了一些运算,看着挺难,其实跟进去看很简单就是个按字节的加减和赋值
vbx_dma_to_vector(v_A, A, num_elements_80484);
vbx_sync();
vbx_set_vl(num_elements_80484, 1, 1);
v15 = 1;
v16 = 3;
dest = v_A;
srcB = v_A;
vbxsim_SVBBBUUU(VXOR, v_A, 0x13u, v_A); // v_A^0x13
v13 = 1;
v14 = 0;
v32 = v_B;
v33 = 0LL;
vbxsim_SVBBBUUU(VMOV, v_B, 2u, 0LL); // v_B 填充2
v11 = 1;
v12 = 14;
v30 = v_D;
v31 = v_A;
vbxsim_SVBBBUUU(VSGT, v_D, 0x61u, v_A); // 小于0x61置1
v9 = 1;
v10 = 5;
v27 = v_B;
srcA = v_B;
v29 = v_D;
vbxsim_VVBBBUUU(VSUB, v_B, v_B, v_D); // B里本来是2现在减1,
v7 = 1;
v8 = 8;
v24 = v_C;
v25 = v_A;
v26 = v_B;
vbxsim_VVBBBUUU(VMUL, v_C, v_A, v_B); //按字节乘不是矩阵乘 小于0x61的不变,大的*2
manipulate(v_O, v_C, 8);
然后是另一条线,生成加密用的keys
先生成前16字节
rng.seed = 0xDEADBEEF;
for ( i = 0; i <= 15; ++i )
{
do
{
do
{
v3 = gen(&rng);
key[i] = v3;
}
while ( key[i] <= 0x20u );
}
while ( key[i] > 0x7Eu );
}
gen方法是LCG
unsigned int __cdecl gen(RNG *rng)
{
rng->seed = 110515245 * rng->seed + 114514;
return HIWORD(rng->seed) & 0x7FFF;
}
然后调用ks将key补充到176字节
__int64 __fastcall ks2(__int64 in, __int64 out)
{
__int64 i; // rax
__int64 result; // rax
int v4; // edx
int v5; // edx
bool v6; // zf
for ( i = 0LL; i != 16; i += 4LL )
*(_DWORD *)(out + i) = *(_DWORD *)(in + i);
for ( result = 4LL; result != 44; ++result )
{
v4 = *(_DWORD *)(out + 4 * result - 12) ^ __ROR4__(*(_DWORD *)(out + 4 * result - 4), 3);
v5 = v4 ^ *(_DWORD *)(out + 4 * result - 16) ^ __ROR4__(v4, 1);
v6 = byte_6573C[result] == 1;
*(_DWORD *)(out + 4 * result) = v5 ^ 0xFFFFFFFC;
if ( v6 )
*(_DWORD *)(out + 4 * result) = v5 ^ 0xFFFFFFFD;
}
return result;
}
这块可以跟进去(需要先把反调nop)dump
最后用enc调用encrypt每次加密8字节再比较
encrypt作22轮异或,像XXX一样
__int64 __fastcall encrypt(int *a1, __int64 a2, int a3)
{
__int64 v3; // r8
int v4; // ecx
int v5; // eax
int v6; // ecx
__int64 result; // rax
v3 = 0LL;
do
{
v4 = a1[1];
v5 = *(_DWORD *)(a2 + 4 * v3) ^ *a1 ^ __ROL4__(v4, 2) ^ __ROL4__(v4, 8) & __ROL4__(v4, 1);
*a1 = v5;
v6 = *(_DWORD *)(a2 + 4 * v3 + 4) ^ v4;
v3 += 2LL;
result = __ROL4__(v5, 2) ^ v6 ^ (unsigned int)(__ROL4__(v5, 1) & __ROL4__(v5, 8));
a1[1] = result;
}
while ( a3 > (int)v3 );
return result;
}
然后一点点逆,还好可以直接跟进去每一步都可以验证(主要是matlib那块是猜的得验证对不对)
先生成key
from pwn import u32,p32
#keys
seed = 0xdeadbeef
def gen():
global seed
seed = ((seed * 110515245 + 114514))&0xffffffff
return (seed>>16) % 32768
key = [0]*16
for i in range(16):
while True:
key[i] = gen()%256
if key[i] >= 33 and key[i] <=126:
break
def ror(v,n):
return ((v>>n)|(v<<(32-n)))& 0xffffffff
def rol(v,n):
return ((v<<n)|(v>>(32-n)))& 0xffffffff
#key->keys
byte_6573C = '00001101101110101100011001011110000001001000101001110011010000111'
keys = [0]*44
for i in range(4):
keys[i] = u32(bytes(key[i*4: i*4+4]))
for i in range(4,44):
v1 = keys[i-3]
v2 = keys[i-1]
v3 = keys[i-4]
v4 = v1 ^ ror(v2, 3)
v5 = v4 ^ v3 ^ ror(v4,1)
if byte_6573C[i] == '1':
keys[i] = v5 ^ 0xFFFFFFFD
else:
keys[i] = v5 ^ 0xFFFFFFFC
#okeys = b''.join([p32(i) for i in keys])
#print(okeys)
再用keys和secret得到encrypt前的output
secret = [0x1E,0xCB,0x87,0xC1,0xB4,0x76,0x70,0xB9,
0x99,0xAD,0xDF,0x84,0x1E,0x62,0x25,0x66,
0x38,0x50,0x72,0xE3,0xF1,0x5F,0x6C,0x00,
0x0C,0xEF,0xAF,0x94,0xC6,0x03,0xC4,0xB1,
0x7F,0x96,0x18,0xB3,0x7F,0x94,0x54,0x0A,
0xC7,0xF8,0xC2,0xF1,0x19,0xE5,0xDA,0xBF,
0xD7,0x8F,0xCE,0xBB,0x0E,0x7D,0xE8,0xDD,
0xC2,0xCA,0x29,0xCB,0xC1,0x23,0x03,0x66]
secret = bytes(secret)
#key 与secret 得到output
s2 = b''
for i in range(0,64,8):
p1 = u32(secret[i:i+4])
p2 = u32(secret[i+4:i+8])
for v3 in range(42,-2,-2):
p2 = p2 ^ keys[v3+1] ^ rol(p1,2) ^ rol(p1,8) & rol(p1,1)
p1 = p1 ^ keys[v3] ^ rol(p2,2) ^ rol(p2,8) & rol(p2,1)
s2 += p32(p1)+p32(p2)
print(s2.hex())
再转置除2和异或
#3, 转置
s3 = b''
for i in range(8):
for j in range(8):
s3 += s2[j*8+i: j*8+i+1]
print(s3.hex())
#2, >0x61 *2
#1, ^0x13
flag = ''
for v in s3:
if v>= 0x61*2 :
flag += chr(v//2 ^0x13)
else:
flag += chr(v ^0x13)
print(flag)
#SEKAI{y4y_u_p4ss3d_ScR4TcHp4D_t35t_w1th_V3ct0rB10x_4nd_51M0N_xD}