鹏城杯2022 writeup
reverse
rota
rota
1.base64码表替换
2.自定义取码表字符,逆向回去。
code 1
do // 换表的base64
{
q0 = input[j];
enc2 += 4;
q1 = input[j + 1];
*(enc2 - 4) = aXiizduaoglak6j[(unsigned __int64)q0 >> 2];
qj = q0;
q2 = (unsigned __int8)input[j + 2];
j += 3i64;
*(enc2 - 3) = aXiizduaoglak6j[(16i64 * (qj & 3)) | ((unsigned __int64)q1 >> 4)];
*(enc2 - 2) = aXiizduaoglak6j[(4i64 * (q1 & 0xF)) | ((unsigned __int64)q2 >> 6)];
*(enc2 - 1) = aXiizduaoglak6j[q2 & 0x3F];
}
while ( j < 30 );
code2
i1 = 0;
while ( (unsigned __int8)v4[offset - 1] != aXiizduaoglak6j[i1] )// enc[i] != aXiizduaoglak6j[ii]
{
if ( ++i1 >= 64 )
{
LOBYTE(i1) = 0;
break;
}
}
v11 = s2;
v12 = (s2 + m[(s1 + (_BYTE)i1) & 63]) & 0x3F;// &63, m[0-63]中取第一个
v13 = (s1 + 1) & 0x3F;
// m[v12+64] [64-128]区域取
// m[xx+128] [128-192]区域取
v14 = (unsigned __int8)m[((s3 + m[v12 + 64]) & 0x3F) + 128];
m[192] = v13; // s1 = v13
*(v4 - 1) = aXiizduaoglak6j[v14]; // enc[i] 置换为 table[i]
base64table
XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb=
爆破法1
patch rota,最后打印输出加密字符。进行爆破
main结尾处patch
sub_7FF6477510E0((__int64)m); // v23未初始化--- 一堆0
sub_7FF647751E10(m, (__int64)enc1, (__int64)tmp);
sub_7FF647751020("%s\n", tmp);
# 取自qq群的朋友,不知道哪个战队
from itertools import product
from alive_progress import alive_bar
import os
table = "0123456789abcdef"
enc_flag = "ksPhS/34MXifj+Ibtjud2Tikj5HkA7iTpbaNELBebOaIm"
flag = ""
while len(flag) < 32:
with alive_bar(len(table) ** 3) as bar:
for i in product(table, repeat=3):
s = "".join(i)
tmp = os.popen(f"echo {(flag+s)[:32]}|.\\rota.exe").readlines()[0]
n = len(flag) // 3
l = n * 4
r = (n + 1) * 4
if tmp[l:r] == enc_flag[l:r]:
flag += s
flag = flag[:32]
break
bar()
print(flag)
不会弄GetModuleHandleA和compute 未定义 。有会的教我一下。
char p_base_table[] = "XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb=";
char key[] =
{
0x33, 0x34, 0x2C, 0x36, 0x1D, 0x12, 0x1E, 0x0C, 0x1A, 0x3C, 0x29, 0x10, 0x20, 0x14, 0x3D, 0x3B,
0x19, 0x08, 0x0E, 0x1F, 0x30, 0x05, 0x38, 0x03, 0x11, 0x1B, 0x17, 0x21, 0x2E, 0x04, 0x18, 0x23,
0x2B, 0x02, 0x27, 0x37, 0x1C, 0x24, 0x39, 0x3F, 0x35, 0x2D, 0x26, 0x13, 0x2A, 0x0A, 0x00, 0x07,
0x3E, 0x01, 0x28, 0x2F, 0x32, 0x22, 0x0D, 0x06, 0x25, 0x3A, 0x09, 0x0F, 0x16, 0x0B, 0x15, 0x31,
0x0C, 0x2C, 0x0D, 0x21, 0x22, 0x09, 0x02, 0x39, 0x31, 0x17, 0x1A, 0x33, 0x06, 0x24, 0x10, 0x04,
0x1B, 0x0B, 0x34, 0x12, 0x38, 0x27, 0x0E, 0x20, 0x2B, 0x2E, 0x00, 0x13, 0x3E, 0x3A, 0x05, 0x1E,
0x36, 0x08, 0x32, 0x29, 0x19, 0x23, 0x3D, 0x3B, 0x3C, 0x3F, 0x37, 0x30, 0x18, 0x16, 0x35, 0x25,
0x0A, 0x2D, 0x28, 0x26, 0x15, 0x11, 0x07, 0x1D, 0x2A, 0x0F, 0x1F, 0x14, 0x01, 0x1C, 0x03, 0x2F,
0x13, 0x0D, 0x35, 0x31, 0x07, 0x11, 0x1B, 0x23, 0x0B, 0x0C, 0x10, 0x25, 0x2B, 0x21, 0x33, 0x18,
0x27, 0x29, 0x02, 0x2F, 0x28, 0x30, 0x0E, 0x19, 0x3C, 0x08, 0x34, 0x20, 0x3D, 0x2E, 0x05, 0x15,
0x2C, 0x1C, 0x36, 0x22, 0x1E, 0x24, 0x38, 0x0A, 0x3F, 0x1A, 0x04, 0x26, 0x16, 0x2A, 0x3A, 0x1F,
0x2D, 0x32, 0x06, 0x37, 0x03, 0x3B, 0x00, 0x17, 0x1D, 0x12, 0x09, 0x01, 0x3E, 0x39, 0x0F, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
auto a = GetModuleHandleA("rota.exe");
compute func = (compute)((long long)a + 0x1E10);
char input[] = "6/GEJz9SXGXCXXXXXXXXXiPIXXXXXXXXXXXXXXXXXXX=";
char passwd[] = "ksPhS/34MXifj+Ibtjud2Tikj5HkA7iTpbaNELBebOaIm";
char result[256] = { 0 };
for (int i = 0; i < 45; ++i)
{
for (int j = 0; j <= sizeof(p_base_table); ++j)
{
memcpy(input, result, i);
input[i] = p_base_table[j];
char out[256] = { 0 };
char temp_key[sizeof(key)] = { 0 };
memcpy(temp_key, key, sizeof(key));
func(temp_key, input, out);
if (0 == memcmp(passwd, out, i + 1))
{
result[i] = p_base_table[j];
break;
}
}
}
printf("%s", result);
逆向法:
加密过程
Maps = bytearray(b'XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb=')
sbox = [0x33, 0x34, 0x2C, 0x36, 0x1D, 0x12, 0x1E, 0x0C, 0x1A, 0x3C, 0x29, 0x10, 0x20, 0x14, 0x3D, 0x3B, 0x19, 0x08, 0x0E, 0x1F, 0x30, 0x05, 0x38, 0x03, 0x11, 0x1B, 0x17, 0x21, 0x2E, 0x04, 0x18, 0x23, 0x2B, 0x02, 0x27, 0x37, 0x1C, 0x24, 0x39, 0x3F, 0x35, 0x2D, 0x26, 0x13, 0x2A, 0x0A, 0x00, 0x07,
0x3E, 0x01, 0x28, 0x2F, 0x32, 0x22, 0x0D, 0x06, 0x25, 0x3A, 0x09, 0x0F, 0x16, 0x0B, 0x15, 0x31, 0x0C, 0x2C, 0x0D, 0x21, 0x22, 0x09, 0x02, 0x39, 0x31, 0x17, 0x1A, 0x33, 0x06, 0x24, 0x10, 0x04, 0x1B, 0x0B, 0x34, 0x12, 0x38, 0x27, 0x0E, 0x20, 0x2B, 0x2E, 0x00, 0x13, 0x3E, 0x3A, 0x05, 0x1E,
0x36, 0x08, 0x32, 0x29, 0x19, 0x23, 0x3D, 0x3B, 0x3C, 0x3F, 0x37, 0x30, 0x18, 0x16, 0x35, 0x25, 0x0A, 0x2D, 0x28, 0x26, 0x15, 0x11, 0x07, 0x1D, 0x2A, 0x0F, 0x1F, 0x14, 0x01, 0x1C, 0x03, 0x2F, 0x13, 0x0D, 0x35, 0x31, 0x07, 0x11, 0x1B, 0x23, 0x0B, 0x0C, 0x10, 0x25, 0x2B, 0x21, 0x33, 0x18,
0x27, 0x29, 0x02, 0x2F, 0x28, 0x30, 0x0E, 0x19, 0x3C, 0x08, 0x34, 0x20, 0x3D, 0x2E, 0x05, 0x15, 0x2C, 0x1C, 0x36, 0x22, 0x1E, 0x24, 0x38, 0x0A, 0x3F, 0x1A, 0x04, 0x26, 0x16, 0x2A, 0x3A, 0x1F, 0x2D, 0x32, 0x06, 0x37, 0x03, 0x3B, 0x00, 0x17, 0x1D, 0x12, 0x09, 0x01, 0x3E, 0x39, 0x0F, 0x14,
0x00, 0x00, 0x00, 0x3F, 0xFB, 0x7F, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0xFB, 0x7F, 0x00, 0x00, 0x6B, 0x73, 0x50, 0x68, 0x53, 0x2F, 0x33, 0x34, 0x4D, 0x58, 0x69, 0x66, 0x6A, 0x2B, 0x49, 0x62, 0x74, 0x6A, 0x75, 0x64, 0x32, 0x54, 0x69, 0x6B, 0x6A, 0x35, 0x48, 0x6B, 0x41, 0x37, 0x69, 0x54,
0x70, 0x62, 0x61, 0x4E, 0x45, 0x4C, 0x42, 0x65, 0x62, 0x4F, 0x61, 0x49, 0x6D, 0x00, 0x00, 0x00]
box1 = sbox[0:64]
box2 = sbox[64:128]
box3 = sbox[128:192]
idx_1, idx_2, idx_3 = sbox[192], sbox[193], sbox[194] # 0 0 0
inp = bytearray(b"XzD+6/D+6/D+6/D+6/D+6/D+6/D+6/D+6/D+6/D+6/D=\x00")
print(len(inp))
out = bytearray([0] * 45)
for i in range(45):
idx = Maps.find(inp[i])
if idx == -1:
idx = 0
v12 = (idx_2 + box1[(idx_1 + idx) & 0x3f]) & 0x3f
v14 = box3[(idx_3 + box2[v12]) & 0x3f]
out[i] = Maps[v14]
idx_1 = (idx_1 + 1) & 0x3F
print(idx_1)
print(out)
逆向回去
Maps = bytearray(b'XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb=')
sbox = [0x33, 0x34, 0x2C, 0x36, 0x1D, 0x12, 0x1E, 0x0C, 0x1A, 0x3C, 0x29, 0x10, 0x20, 0x14, 0x3D, 0x3B, 0x19, 0x08, 0x0E, 0x1F, 0x30, 0x05, 0x38, 0x03, 0x11, 0x1B, 0x17, 0x21, 0x2E, 0x04, 0x18, 0x23, 0x2B, 0x02, 0x27, 0x37, 0x1C, 0x24, 0x39, 0x3F, 0x35, 0x2D, 0x26, 0x13, 0x2A, 0x0A, 0x00, 0x07,
0x3E, 0x01, 0x28, 0x2F, 0x32, 0x22, 0x0D, 0x06, 0x25, 0x3A, 0x09, 0x0F, 0x16, 0x0B, 0x15, 0x31, 0x0C, 0x2C, 0x0D, 0x21, 0x22, 0x09, 0x02, 0x39, 0x31, 0x17, 0x1A, 0x33, 0x06, 0x24, 0x10, 0x04, 0x1B, 0x0B, 0x34, 0x12, 0x38, 0x27, 0x0E, 0x20, 0x2B, 0x2E, 0x00, 0x13, 0x3E, 0x3A, 0x05, 0x1E,
0x36, 0x08, 0x32, 0x29, 0x19, 0x23, 0x3D, 0x3B, 0x3C, 0x3F, 0x37, 0x30, 0x18, 0x16, 0x35, 0x25, 0x0A, 0x2D, 0x28, 0x26, 0x15, 0x11, 0x07, 0x1D, 0x2A, 0x0F, 0x1F, 0x14, 0x01, 0x1C, 0x03, 0x2F, 0x13, 0x0D, 0x35, 0x31, 0x07, 0x11, 0x1B, 0x23, 0x0B, 0x0C, 0x10, 0x25, 0x2B, 0x21, 0x33, 0x18,
0x27, 0x29, 0x02, 0x2F, 0x28, 0x30, 0x0E, 0x19, 0x3C, 0x08, 0x34, 0x20, 0x3D, 0x2E, 0x05, 0x15, 0x2C, 0x1C, 0x36, 0x22, 0x1E, 0x24, 0x38, 0x0A, 0x3F, 0x1A, 0x04, 0x26, 0x16, 0x2A, 0x3A, 0x1F, 0x2D, 0x32, 0x06, 0x37, 0x03, 0x3B, 0x00, 0x17, 0x1D, 0x12, 0x09, 0x01, 0x3E, 0x39, 0x0F, 0x14,
0x00, 0x00, 0x00, 0x3F, 0xFB, 0x7F, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0xFB, 0x7F, 0x00, 0x00, 0x6B, 0x73, 0x50, 0x68, 0x53, 0x2F, 0x33, 0x34, 0x4D, 0x58, 0x69, 0x66, 0x6A, 0x2B, 0x49, 0x62, 0x74, 0x6A, 0x75, 0x64, 0x32, 0x54, 0x69, 0x6B, 0x6A, 0x35, 0x48, 0x6B, 0x41, 0x37, 0x69, 0x54,
0x70, 0x62, 0x61, 0x4E, 0x45, 0x4C, 0x42, 0x65, 0x62, 0x4F, 0x61, 0x49, 0x6D, 0x00, 0x00, 0x00]
box1 = sbox[0:64]
box2 = sbox[64:128]
box3 = sbox[128:192]
inp = bytearray(b"ksPhS/34MXifj+Ibtjud2Tikj5HkA7iTpbaNELBebOaIm")
# inp = bytearray(b'yl3bWT94MekETq0yejDlqVN/jmtXV+iWmbHM+4vTbEpIm')
print(len(inp))
out = bytearray([0] * 45)
for index in range(44, -1 , -1):
v14 = Maps.find(inp[index])
v12 = box2.index(box3.index(v14))
idx = (box1.index(v12) - index) & 0x3f
out[index] = Maps[idx]
print(out)
换表解码:
# base64 自定义变化码表
import base64
cipher = 'cAJ7BzX+6zHrHwnTc/i7Bz6f6t6EBQDvc/xfHt9d6S9=='
my_base64chars = "XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb"
STD_BASE64CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
cipher = cipher.translate(str.maketrans(my_base64chars, STD_BASE64CHARS))
data = base64.b64decode(cipher)
print(data)
# 8cdd01062b7e90dd372c3ea9977be53e
baby_re
jadx打开
onCreate里有
setContentView(inflate.getRoot());
((Button) _$_findCachedViewById(R.id.btn)).setOnClickListener(new MainActivity$$ExternalSyntheticLambda0(this,
new int[]{119, 9, 40, 44, 106, 83, 126, 123, 33, 87, 113, 123, 112, 93, 125, 127, 41, 82, 44, 127, 39, 3, 126, 125, 119, 87, 47, 125, 33, 6, 44, 127, 112, 0, 126, 123, 115, 24}));
}
/* renamed from: onCreate$lambda-0 reason: not valid java name */
public static final void m20onCreate$lambda0(MainActivity this$0, int[] $c, View it) {
Intrinsics.checkNotNullParameter(this$0, "this$0");
Intrinsics.checkNotNullParameter($c, "$c");
int[] array = ((EditText) this$0._$_findCachedViewById(R.id.input)).getText().toString().chars().toArray();
Intrinsics.checkNotNullExpressionValue(array, "flag.toArray()");
if (Arrays.equals(this$0.baby_xor(array), $c)) { // 关键比较
Toast.makeText(this$0, "Success", 1).show();
} else {
Toast.makeText(this$0, "Failed", 0).show();
}
}
public final native int[] baby_xor(int[] iArr); // native在so中
解压用ida打开so文件
__int64 __fastcall Java_com_example_createso_MainActivity_baby_1xor(__int64 a1, __int64 a2, __int64 a3)
{
int i; // [rsp+14h] [rbp-2Ch]
__int64 IntArrayElements; // [rsp+18h] [rbp-28h]
unsigned int ArrayLength; // [rsp+24h] [rbp-1Ch]
ArrayLength = _JNIEnv::GetArrayLength(a1, a3);
IntArrayElements = _JNIEnv::GetIntArrayElements(a1, a3, 0LL);
for ( i = 0; i < (int)ArrayLength; ++i )
*(_DWORD *)(IntArrayElements + 4LL * i) ^= key[i % 4];
_JNIEnv::SetIntArrayRegion(a1, a3, 0LL, ArrayLength, IntArrayElements);
return a3;
}
双击看key [56h, 57h ,58h, 59h]
解密。没解出来。翻了一下so里有个hidekey的函数。按x定位。它在init_array中。初始化时执行了。
_DWORD *hide_key(void)
{
_DWORD *result; // rax
result = key;
key[0] ^= 0x47u;
key[1] ^= 0x32u;
key[2] ^= 0x11u;
key[3] ^= 0x12u;
return result;
}
解密
enc =[ 0x77,0x9,0x28,0x2c,0x6a,0x53,0x7e,0x7b,0x21,0x57,0x71,0x7b,0x70,0x5d,0x7d,0x7f,0x29,0x52,0x2c,0x7f,0x27,0x3,0x7e,0x7d,0x77,0x57,0x2f,0x7d,0x21,0x6,0x2c,0x7f,0x70,0x0,0x7e,0x7b,0x73,0x18]
key = [0x56, 0x57, 0x58, 0x59]
key[0] ^= 0x47
key[1] ^= 0x32
key[2] ^= 0x11
key[3] ^= 0x12
print(len(enc))
lst = []
for i, c in enumerate(enc):
print(chr(c ^ key[i % 4]), end='')
# flag{6700280a84487e46f76f2f60ce4ae70b}
Maze
__int64 sub_40500A()
{
_QWORD *v0; // rbp
char v2; // [rsp+Fh] [rbp-29h] BYREF
_QWORD *v3; // [rsp+10h] [rbp-28h] BYREF
unsigned __int64 v4; // [rsp+18h] [rbp-20h]
v4 = __readfsqword(0x28u);
sub_404CD9();
v0 = *(_QWORD **)(*(_QWORD *)(*(_QWORD *)(qword_5D3680 + 8) + 8LL) + 8LL);
v3 = *(_QWORD **)(*(_QWORD *)(*(_QWORD *)(*(_QWORD *)(qword_5D36A0 + 8) + 8LL) + 8LL) + 8LL);
*((_BYTE *)v3 + 27) = 1;
print2(qword_5D45C0, "Welcome to Hexagonal maze\nplz enter the foot print\n");
v2 = 0;
do
{
printf(qword_5D45C0, (__int64)"> ", 2LL);
scanf(qword_5D46E0, &v2);
check_cur(&v3, v2); // 检查每一步
}
while ( v3 != v0 ); // 要v3要走到v0的位置才算结束
printf(qword_5D45C0, (__int64)"flag is md5 your input", 22LL);
sub_46D7E0(qword_5D45C0);
if ( __readfsqword(0x28u) != v4 )
sub_52CB40();
return 0LL;
}
_QWORD *__fastcall check_cur(_QWORD **av3, char a2)
{
_QWORD *v2; // rax
_QWORD *v3; // rax
_QWORD *result; // rax
_QWORD *v5; // rax
switch ( a2 )
{
case 'l':
if ( *((_BYTE *)*av3 + 24) || (v3 = (_QWORD *)**av3) == 0LL ) // qword av3_addr+24=1时退出, 然后将av3的地址给av3作为新指针
exit(0);
*av3 = v3;
break;
case 'r':
if ( *((_BYTE *)*av3 + 25) || (v5 = (_QWORD *)(*av3)[1]) == 0LL ) // qword av3_addr+25=1时退出, 然后将av3 + 8(qword长度为8)地址给av3作为新指针
exit(0);
*av3 = v5;
break;
case 't':
if ( *((_BYTE *)*av3 + 26) || (v2 = (_QWORD *)(*av3)[2]) == 0LL ) // qword av3_addr+25=1时退出, 然后将av3 + 16(qword长度为8)地址给av3作为新指针
exit(0);
*av3 = v2;
break;
default:
exit(0);
}
result = *av3;
if ( *((_BYTE *)*av3 + 27) )
exit(0);
*((_BYTE *)result + 27) = 1;
return result;
}
类似地下城选关卡的效果 。
Misc
Misc_water
题目提示:water -- 水印
文件名 ʍɐʇǝɹ‾dıɔʇnɹǝ
也提示是了这是water_picture倒过来的。
中间的一个文件就是16进制倒序。
png用010提取出3个文件。中间的文件16进制反序重组。
图2使用傅利叶变换得到密码(脚本或52pojie的水印工具)
ZC4#QaWbW
crc32恢复png。得到flag
PCL{f0b31d6f9abc59f34815678c31d79178}
简单取证
cmdscan提取到密码。
filescan恢复secret文件。是倒序的压缩包。逆序恢复。解压。
解压后用gnuplot画坐标。
#flag{a6b93e36-f097-11ec-a9b2-5254002d2b31}
babybit
用Misc_Windows Registry Recovery找到SYSTEM文件。再找ROOT\ControlSet001\Control\FVEStats下面的OsvEncryptInit和OsvEncryptComplete
按格式填写一下。
PCL{2022/6/13_15:17:39_2022/6/13_15:23:46}
what_is_log
1.sudo sysdig -r file.scap > 2.log
2. 看了一会儿,过滤出mysql, write, 长字符,搜索 mysql.*write.*\w{18,}
找到flag
# 1555a651a13ec074ce725383214fd7cc