2024年HF赛前练-CTF Reverse
迷宫
逆天题目,答案直接给你了。
FindTheKey
.so的JNI_OnLoad中,最后调用了sub_B004(前面都是frida检测),疑似是某个加固软件的,见了很多次。
int __fastcall sub_B004(JNIEnv *a1)
{
jobject v2; // [sp+38h] [bp-E8h]
jobject v3; // [sp+3Ch] [bp-E4h]
jsize j; // [sp+40h] [bp-E0h]
jobject ObjectArrayElement; // [sp+44h] [bp-DCh]
jsize i; // [sp+48h] [bp-D8h]
jobject v7; // [sp+4Ch] [bp-D4h]
struct _jmethodID *v8; // [sp+50h] [bp-D0h]
struct _jmethodID *v9; // [sp+54h] [bp-CCh]
struct _jmethodID *v10; // [sp+58h] [bp-C8h]
jclass v11; // [sp+5Ch] [bp-C4h]
jobject v12; // [sp+60h] [bp-C0h]
jobject v13; // [sp+64h] [bp-BCh]
jobject v14; // [sp+68h] [bp-B8h]
jobject v15; // [sp+6Ch] [bp-B4h]
jobject v16; // [sp+70h] [bp-B0h]
struct _jmethodID *v17; // [sp+74h] [bp-ACh]
jclass v18; // [sp+78h] [bp-A8h]
struct _jfieldID *v19; // [sp+7Ch] [bp-A4h]
jclass v20; // [sp+80h] [bp-A0h]
struct _jfieldID *v21; // [sp+84h] [bp-9Ch]
jclass v22; // [sp+88h] [bp-98h]
jobject clazz_loader; // [sp+8Ch] [bp-94h]
struct _jmethodID *v24; // [sp+90h] [bp-90h]
jclass v25; // [sp+94h] [bp-8Ch]
jclass main_activity; // [sp+98h] [bp-88h]
struct _jmethodID *v27; // [sp+9Ch] [bp-84h]
struct _jmethodID *v28; // [sp+A0h] [bp-80h]
void *v29; // [sp+A4h] [bp-7Ch]
jmethodID StaticMethodID; // [sp+A8h] [bp-78h]
jclass v31; // [sp+ACh] [bp-74h]
void *ptr; // [sp+B4h] [bp-6Ch]
void *v33; // [sp+B8h] [bp-68h]
jint v34; // [sp+BCh] [bp-64h]
struct _jmethodID *read__; // [sp+C0h] [bp-60h]
jclass v36; // [sp+C4h] [bp-5Ch]
jbyteArray _array_; // [sp+C8h] [bp-58h]
jobject v38; // [sp+CCh] [bp-54h]
struct _jmethodID *v39; // [sp+D0h] [bp-50h]
size_t size; // [sp+D4h] [bp-4Ch]
struct _jmethodID *v41; // [sp+D8h] [bp-48h]
jclass v42; // [sp+DCh] [bp-44h]
jobject v43; // [sp+E0h] [bp-40h]
jstring v44; // [sp+E4h] [bp-3Ch]
struct _jmethodID *v45; // [sp+ECh] [bp-34h]
jclass v46; // [sp+F0h] [bp-30h]
jobject v47; // [sp+F4h] [bp-2Ch]
struct _jmethodID *MethodID; // [sp+F8h] [bp-28h]
jclass v49; // [sp+FCh] [bp-24h]
jobject ObjectField; // [sp+100h] [bp-20h]
jobject StaticObjectField; // [sp+104h] [bp-1Ch]
struct _jfieldID *FieldID; // [sp+108h] [bp-18h]
struct _jfieldID *StaticFieldID; // [sp+10Ch] [bp-14h]
jclass Class; // [sp+110h] [bp-10h]
Class = FindClass(a1, asc_1F0A0); // android/app/ActivityThread
StaticFieldID = GetStaticFieldID(a1, Class, aWgqvvajpegpmrm, aDiflzgalIxxIkA);
FieldID = GetFieldID(a1, Class, byte_1F280, byte_1F2A0);
StaticObjectField = GetStaticObjectField(a1, Class, StaticFieldID);
ObjectField = GetObjectField(a1, StaticObjectField, FieldID);
v49 = FindClass(a1, aTHus5Jj5JjvsyN); // android/app/Application
MethodID = GetMethodID(a1, v49, byte_1F2D8, byte_1F2F0);
v47 = CallObjectMethodV(a1, ObjectField, MethodID);
v46 = FindClass(a1, byte_1F320); // android/content/res/AssetManager
v45 = GetMethodID(a1, v46, byte_1F341, byte_1F350);
v44 = NewStringUTF(a1, aOKzLg); // asset.bin
v43 = CallObjectMethodV(a1, v47, v45, v44);
v42 = FindClass(a1, aFicuhncDhisbis); // android/content/res/AssetFileDescriptor
v41 = GetMethodID(a1, v42, byte_1F3C8, byte_1F3D2);// getLength
size = CallLongMethodV(a1, v43, v41);
v39 = GetMethodID(a1, v46, "7(=6X", byte_1F3E0);// open
v38 = CallObjectMethodV(a1, v47, v39, v44);
_array_ = NewByteArray(a1, size);
v36 = FindClass(a1, byte_1F410); // java/io/InputStream
read__ = GetMethodID(a1, v36, aRead, byte_1F429);// read ([BII)I
v34 = CallIntMethodV(a1, v38, read__, _array_, 0, size);
v33 = malloc(size);
if ( v34 >= 1 )
GetByteArrayRegion(a1, (int)_array_, 0, size, (int)v33);
ptr = malloc(size);
sub_AC38(unk_1F431, v33, size, ptr); // RC4(goodluck)
SetByteArrayRegion(a1, (int)_array_, 0, size, (int)ptr);
if ( ptr )
free(ptr);
if ( v33 )
free(v33);
v31 = FindClass(a1, byte_1F440);
StaticMethodID = GetStaticMethodID(a1, v31, byte_1F454, byte_1F460);
v29 = (void *)sub_A234(a1, v31, StaticMethodID, size);
v28 = GetMethodID(a1, v31, byte_1F479, byte_1F480);// put ([B)Ljava/nio/ByteBuffer;
v27 = GetMethodID(a1, v31, byte_1F49A, byte_1F4B0);// position (I)Ljava/nio/Buffer;
CallObjectMethodV(a1, v29, v28, _array_);
CallObjectMethodV(a1, v29, v27, 0);
main_activity = FindClass(a1, byte_1F4D0); // com/ctf/findthekey/MainActivity
v25 = FindClass(a1, a388v587V); // java/lang/Class
//
v24 = GetMethodID(a1, v25, byte_1F500, byte_1F510);// getClassLoader
clazz_loader = CallObjectMethodV(a1, main_activity, v24);
v22 = FindClass(a1, byte_1F530);
v21 = GetFieldID(a1, v22, byte_1F54E, aVVlsq5icin);// pathList Ldalvik/system/DexPathList;
v20 = FindClass(a1, byte_1F580); // dalvik/system/DexPathList
v19 = GetFieldID(a1, v20, ":;&\x1B2;3;0*-^", byte_1F5B0);// dexElements [Ldalvik/system/DexPathList$Element;
v18 = FindClass(a1, byte_1F5E0); // dalvik/system/InMemoryDexClassLoader
v17 = GetMethodID(a1, v18, "k>9>#iW", byte_1F610);
v16 = NewObjectV(a1, v18, v17, v29, clazz_loader);
v15 = GetObjectField(a1, v16, v21);
v14 = GetObjectField(a1, v15, v19);
v13 = GetObjectField(a1, clazz_loader, v21);
v12 = GetObjectField(a1, v13, v19);
v11 = FindClass(a1, byte_1F640); // java/util/ArrayList
v10 = GetMethodID(a1, v11, aJoo, byte_1F660);
v9 = GetMethodID(a1, v11, aCxveevn7, byte_1F680);
v8 = GetMethodID(a1, v11, "k>9>#iW", byte_1F696);
v7 = NewObjectV(a1, v11, v8);
for ( i = 0; i < GetArrayLength(a1, v14); ++i )
{
ObjectArrayElement = GetObjectArrayElement(a1, v14, i);
CallBooleanMethodV(a1, v7, v10, ObjectArrayElement);
}
for ( j = 0; j < GetArrayLength(a1, v12); ++j )
{
v3 = GetObjectArrayElement(a1, v12, j);
CallBooleanMethodV(a1, v7, v10, v3);
}
v2 = CallObjectMethodV(a1, v7, v9);
return SetObjectField(a1, (int)v13, (int)v19, (int)v2);
}
显然是读取了Assets的asset.bin,然后走rc4解密
int __fastcall sub_AC38(const char *k, char *key, unsigned int len, char *buf)
{
char S[256]; // [sp+34h] [bp-114h] BYREF
rc4_init(k, S);
rc4_crypt(S, key, buf, len);
return 0;
}
int __fastcall rc4_init(const char *k, const char *S)
{
int j; // [sp+18h] [bp-20h]
int i; // [sp+1Ch] [bp-1Ch]
int v5; // [sp+20h] [bp-18h]
signed int v6; // [sp+24h] [bp-14h]
v6 = strlen(k);
v5 = 0;
for ( i = 0; i <= 255; ++i )
S[i] = i;
for ( j = 0; j <= 255; ++j )
{
v5 = ((unsigned __int8)k[j % v6] + v5 + (unsigned __int8)S[j]) % 256;
swap(&S[j], &S[v5]);
}
return 0;
}
int __fastcall rc4_crypt(char *S, char *a2, char *dest, unsigned int len)
{
unsigned int i; // [sp+1Ch] [bp-24h]
int v6; // [sp+20h] [bp-20h]
int v7; // [sp+24h] [bp-1Ch]
v7 = 0;
v6 = 0;
for ( i = 0; i < len; ++i )
{
v7 = (v7 + 1) % 256;
v6 = (v6 + (unsigned __int8)S[v7]) % 256;
swap(&S[v7], &S[v6]);
dest[i] = S[(unsigned __int8)(S[v7] + S[v6])] ^ a2[i];
}
return 0;
}
int __fastcall swap(_BYTE *a1, _BYTE *a2)
{
int result; // r0
int v3; // [sp+8h] [bp-Ch]
v3 = (unsigned __int8)*a1;
*a1 = *a2;
result = v3;
*a2 = v3;
return result;
}
然后解密了asset.bin就可以直接拖入jadx了
覆盖Util.java,换表base64+rc4,就可以CyberChef解了。