这个题目我有两种解法:第一种是分析核心代码,理清它的逻辑,然后写python代码得到答案。第二种是利用objection直接让app跳到相应的activity(因为activity的exported没有设置成true,所以用objection跳,当然也可以把exported改成true,然后重新打包app),然后写Frida hook native 函数(当然直接hook java代码也行),第二种方法比第一种省时省力。因为第二种方法忘了截图,就不介绍了。现在只介绍第一种方法:
在IsThisTheRealOne类中(在其他两个类中有类似的),注意到这行代码,它调用了so中的函数。
String s = this.getClass().getName();
intent.putExtra("msg", IsThisTheRealOne.this.perhapsThis("TRytfrgooq|F{i-JovFBungFk\\VlphgQbwvj~HuDgaeTzuSt.@Lex^~", "ZGFkNGIwYzIWYjEzMTUWNjVjNTVlNjZhOGJkNhYtODIyOGEaMTMWNmQaOTVjZjkhMzRjYmUzZGE?\n", Utilities.doBoth(s.substring(0, s.length() - 2))));
该函数的参数有三个,首先要求出这三个参数的值,前两个参数是可见的,第三个参数是调用了另一个类的函数获得的。为了方便,直接复制然后修改该类的代码如下:
import java.util.Base64;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
class HelloWorld {
public static void main(String[] args) {
String s = "com.example.application.IsThisTheRealOne";
String result = doBoth(s);
System.out.println(result);
}
public static String customEncodeValue(String input) {
String output = "";
byte[] arr_b = input.getBytes();
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-224");
}
catch(NoSuchAlgorithmException noSuchAlgorithmException0) {
}
md.update(arr_b, 0, arr_b.length);
byte[] arr_b1 = md.digest();
for(int i = 0; i < arr_b1.length; ++i) {
output = output + String.format("%02x", ((byte)arr_b1[i]));
}
return Base64.getEncoder().encodeToString(output.getBytes());
}
public static String translate(String input) {
char[] arr_c = input.replace('=', '?').toCharArray();
HashMap table = new HashMap();
for(int i = 0; i < 10; ++i) {
table.put(Integer.valueOf(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}[i]), Character.valueOf(new char[]{'W', 'h', 'a', 't', 'i', 's', 'd', 'o', 'n', 'e'}[i]));
}
for(int i = 0; i < arr_c.length; ++i) {
int charcode = arr_c[i];
if(charcode > 0x2F && charcode < 58) {
arr_c[i] = ((Character)table.get(Integer.valueOf(charcode - 0x30))).charValue();
}
}
return new String(arr_c);
}
// String Decryptor: 1 succeeded, 0 failed
public static String doBoth(String input) {
return translate(customEncodeValue(input));
}
}
以下是so中的关键代码:
int __fastcall Java_com_example_application_IsThisTheRealOne_perhapsThis(int a1, int a2, int a3, int a4, int a5)
{
char *v7; // r4
const char *v8; // r8
const char *v9; // r10
int v10; // r4
int v11; // r1
char v13[80]; // [sp+4h] [bp-16Ch] BYREF
char v14[80]; // [sp+54h] [bp-11Ch] BYREF
char v15[80]; // [sp+A4h] [bp-CCh] BYREF
char v16[80]; // [sp+F4h] [bp-7Ch] BYREF
v7 = (char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0);
v8 = (const char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a4, 0);
v9 = (const char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a5, 0);
strcat(v7, aWnwgrabOutbh);
strncpy(v15, v7, 0x4Cu);
v10 = 0;
strncpy(v13, v8, 0x4Cu);
strncpy(v14, v9, 0x4Cu);
v15[76] = 0;
v14[76] = 0;
v13[76] = 0;
do
{
v11 = (unsigned __int8)v14[v10] ^ (unsigned __int8)v13[v10] ^ (unsigned __int8)v15[v10];
v16[v10++] = v11;
printf("%c\n", v11);
}
while ( v10 != 76 );
v16[76] = 0;
printf("Here is your Reply: %s", v16);
return (*(int (__fastcall **)(int, char *))(*(_DWORD *)a1 + 668))(a1, v16);
}
为了方便,我用python重写了关键部分,得到答案
v7 = "TRytfrgooq|F{i-JovFBungFk\\VlphgQbwvj~HuDgaeTzuSt.@Lex^~wnwGrab{Outbh"
sub = "rCtfqm}"
v8 = "ZGFkNGIwYzIWYjEzMTUWNjVjNTVlNjZhOGJkNhYtODIyOGEaMTMWNmQaOTVjZjkhMzRjYmUzZGE?"
v9 = "MzQxZTZmZjAxMmIiMWUzNjUxMmRiYjIxNDUwYTUxMWItZGQzNWUtMzkyOWYyMmQeYjZmMzEaNDQ?"
v15 = []
for i in range(len(v7)):
v15.append(ord(v7[i]))
v15.append(0x7f)
for i in range(len(sub)):
v15.append(ord(sub[i]))
print(v15)
print(len(v15))
v13 = []
for i in range(len(v8)):
v13.append(ord(v8[i]))
print(v13)
print(len(v13))
v14 = []
for i in range(len(v9)):
v14.append(ord(v9[i]))
print(v14)
print(len(v14))
v10 = 0
v16 = []
while v10 != 75:
v10 = v10 + 1
v16.append(v14[v10] ^ v13[v10] ^ v15[v10])
print(v16)
for i in range(len(v16)):
print(chr(v16[i]),end="")