jeb反编译apk
输入字符串传入到native方法CheckString进行判断。
核心逻辑都在so里面的CheckString函数。
ida反编译so
直接反编译看伪代码,代码比较简单直接手撕即可,循环走一两遍就可以知道整个逻辑了。
整理逻辑流程就是输入字符串前16位与后16位互换。
然后单双位互换,0,1互换,2,3互换,4,5互换。。。
最后与指定字符串比较。
bool __fastcall Java_com_testjava_jack_pingan2_cyberpeace_CheckString(JNIEnv *a1, jobject a2, jstring a3)
{
const char *v3; // x20
__int64 v4; // x0
signed int v5; // w21
unsigned __int64 v6; // x22
_BYTE *v7; // x0
_BYTE *v8; // x19
size_t v9; // w2
unsigned __int64 v10; // x20
_BYTE *v11; // x8
char v12; // w9
char v13; // w10
char v14; // w9
__int64 v15; // x20
_BYTE *v16; // x8
char v17; // w10
unsigned __int64 v18; // x0
unsigned __int64 v19; // x8
v3 = (*a1)->GetStringUTFChars(a1, a3, 0LL); // 输入字符串
v4 = strlen(v3); // 字符串长度
v5 = v4;
v6 = ((v4 << 32) + 0x100000000LL) >> 32; // v6 = v4 +1
v7 = malloc(((v4 << 32) + 0x100000000LL) >> 32);
v8 = v7;
if ( v6 > v5 )
v9 = v6 - v5; // v9 = 1
else
v9 = 0;
memset(&v7[v5], 0, v9);
memcpy(v8, v3, v5); // 输入字符复制到v8
if ( strlen(v8) >= 2uLL )
{
v10 = 0LL;
do
{
v11 = &v8[v10]; // v11 = &v8[0]--循环1--v10=1, v11 = v8[1]
v12 = v8[v10 + 16]; // v12 = v8[16]--循环1--v12 = v8[17]
v13 = v8[v10++]; // v13 = v8[0],v10=1--循环1--v13 = v8[1],v10 =2
*v11 = v12; // v11 = v8[16] --循环1--v11 = v8[17]
v11[16] = v13; // v11[16] = v8[0] --循环1-- v8[17] = v8[1]
} // v8[0]与v8[16]互换,循环1--v8[1]与v8[17]互换。。。
// 这段循环的逻辑就是前16位与后16位互换
while ( strlen(v8) >> 1 > v10 ); // v8的长度/2 > v10 , 就是循环v8的长度/2
}
if ( *v8 )
{
v14 = v8[1]; // v14 = v8[1]
v8[1] = *v8; // v8[1] = v8[0]
*v8 = v14; // v8[0] = v8[1]
// 这段逻辑就是v8[0]与v8[1]互换
if ( strlen(v8) >= 3uLL )
{
v15 = 0LL;
do
{
v16 = &v8[v15]; // v16 = &v8[0]
v17 = v8[v15 + 2]; // v17 = v8[2]
v16[2] = v8[v15 + 3]; // v8[2] = v8[3]
v16[3] = v17; // v8[3] = v8[2]
v18 = strlen(v8);
v19 = v15 + 4; // v19 = 4
v15 += 2LL; // v15 = 2
} // 这一段循环的逻辑就是单双位互换,0,1互换,2,3互换,4,5互换。。。
while ( v18 > v19 ); // v18是v8的长度,v19 = v15 + 4, v15是自加2,那v19也是自加2,也就是循环是自加2循环
}
}
return strcmp(v8, "f72c5a36569418a20907b55be5bf95ad") == 0;// 最后v8与指定字符串比较
}
算法还原
还原过程就是指定的字符串“f72c5a36569418a20907b55be5bf95ad”先单双位互换得到“7fc2a5636549812a90705bb55efb59da”
然后前16位与后16位互换得到
flag{90705bb55efb59da7fc2a5636549812a}
public static void main(String[] args) {
String string = "f72c5a36569418a20907b55be5bf95ad";
char[] chars = new char[string.length()];
for (int i = 0; i < string.length(); i+=2) {
chars[i] = string.charAt(i+1);
chars[i+1] = string.charAt(i);
}
char[] ch2 = new char[chars.length];
for (int i = 0; i < 16; i++) {
ch2[i] = chars[i+16];
ch2[i+16] = chars[i];
}
System.out.println(ch2);
}