从下面的代码知道,它调用了cyberspace的CheckString方法,而这个CheckString调用了so里的函数。
public class MainActivity extends AppCompatActivity {
@Override // android.support.v7.app.AppCompatActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(0x7F09001B); // layout:activity_main
((Button)this.findViewById(0x7F070022)).setOnClickListener(new View.OnClickListener() { // id:button
@Override // android.view.View$OnClickListener
public void onClick(View v) {
if(cyberpeace.CheckString(((EditText)MainActivity.this.findViewById(0x7F070031)).getText().toString()) == 1) { // id:editText
Toast.makeText(MainActivity.this, "验证通过!", 1).show();
return;
}
Toast.makeText(MainActivity.this, "验证失败!", 1).show();
}
});
}
}
CheckString方法里J_TestDec方法,用于对传入的字符串做处理
int __fastcall Java_com_testjava_jack_pingan2_cyberpeace_CheckString(int a1, int a2, int a3)
{
int v3; // r8
const char *v4; // r9
size_t len; // r6
char *v6; // r5
v3 = 0;
v4 = (const char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0);
len = strlen(v4);
v6 = (char *)malloc(len + 1);
memset(&v6[len], 0, len != -1);
qmemcpy(v6, v4, len);
j_TestDec((int)v6);
if ( !strcmp(v6, "f72c5a36569418a20907b55be5bf95ad") )
v3 = 1;
return v3;
}
size_t __fastcall TestDec(char *a1)
{
size_t i; // r5
unsigned __int8 *v3; // r1
unsigned __int8 v4; // r0
size_t result; // r0
int v6; // r5
unsigned __int8 *v7; // r0
unsigned __int8 v8; // r1
size_t v9; // r1
if ( strlen(a1) >= 2 )
{
i = 0;
do
{
v3 = (unsigned __int8 *)&a1[i];
v4 = a1[i];
a1[i] = a1[i + 16];
++i;
v3[16] = v4;
}
while ( i < strlen(a1) >> 1 );
}
result = (unsigned __int8)*a1;
if ( *a1 )
{
*a1 = a1[1];
a1[1] = result;
result = strlen(a1);
if ( result >= 3 )
{
v6 = 0;
do
{
v7 = (unsigned __int8 *)&a1[v6];
v8 = a1[v6 + 2];
v7[2] = a1[v6 + 3];
v7[3] = v8;
result = strlen(a1);
v9 = v6 + 4;
v6 += 2;
}
while ( v9 < result );
}
}
return result;
}
上面的c++代码有点乱,为了方便理解,我用python代码重写了
def TestDec(a1):
# 将字符串转换为字符列表
a1 = list(a1)
length = len(a1)
i = 0
while length - i >= 17:
tmp = a1[i]
a1[i] = a1[i + 16]
a1[i + 16] = tmp
i += 1
result = ord(a1[0])
if result > 0:
a1[0] = a1[1]
a1[1] = chr(result)
result = len(a1) # 这里result变成了列表的长度
v9 = 2 # 从2开始,因为我们已经处理了前两个字符
if result >= 3:
v6 = 0
while v6 < result - 2: # 确保不会越界
tmp = a1[v6 + 2]
a1[v6 + 2] = a1[v6 + 3]
a1[v6 + 3] = tmp
v6 += 2
这样就很容易理解,它主要是用于交换输入字符串的字符。下面是它的逆向,输出就是flag
def reverse_test_dec(result):
a1 = bytearray(result, 'utf-8')
# 逆向第二个交换操作
length = len(a1)
v6 = 0
v9 = 0
if length >= 3:
while v9 < length:
tmp = a1[v6 + 2]
a1[v6 + 2] = a1[v6 + 3]
a1[v6 + 3] = tmp
v6 += 2
v9 = v6 + 2 # 更新v9以匹配原始while循环的条件
# 逆向第一个交换操作和字符交换
if a1[0] > 0: # 这里应该检查字符是否为空,但在Python中应使用if a1[0] != 0 or a1[0] != ord(''):
tmp = a1[0]
a1[0] = a1[1]
a1[1] = tmp
# 逆向主要的字符交换操作
i = 0
while length - i >= 17:
tmp = a1[i]
a1[i] = a1[i + 16]
a1[i + 16] = tmp
i += 1
# 将字节数组转换回字符串并返回
return a1.decode('utf-8') # 注意:这里假设原始字符串是UTF-8编码的
result_str = "f72c5a36569418a20907b55be5bf95ad"
original_str = reverse_test_dec(result_str)
print(original_str)