今までどうしても出来ず,半年以上戦ってきたJNIに,ついに勝利したので,記念にあげとく。
アンパックルーチン
xorした後,zp(inputStream, null)を呼んでる。
/* renamed from: a */
private void m6a(OutputStream outputStream, byte[] bArr, InputStream inputStream) {
InputStream inputStream2 = (InputStream) C0031qi.m800zp(inputStream, null);
while (true) {
int read = inputStream2.read(bArr);
if (read == -1) {
inputStream2.close();
return;
}
outputStream.write(bArr, 0, read);
}
}
zpは,引数1にobjを受け取り,objを返す,native関数
/* renamed from: zp */
public static native Object m800zp(Object obj, Object obj2);
Ghidraでデコンパイル
void Java_aw_qi_zp(int *param_1,undefined4 param_2,undefined4 param_3)
{
_jmethodID *p_Var1;
undefined4 uVar2;
p_Var1 = (_jmethodID *)(**(code **)(*param_1 + 0x18))(param_1,"java/util/zip/InflaterInputStream")
;
uVar2 = (**(code **)(*param_1 + 0x84))(param_1,p_Var1,&UNK_00012ef1,"(Ljava/io/InputStream;)V");
_JNIEnv::NewObject((_jclass *)param_1,p_Var1,uVar2,param_3);
return;
}
JNIのネイティブメソッド名前解決を使用した動的リンクとなっており,関数名は,Java_aw_qi_zp
となっている。
よくわからない部分もあるが,コードが少なく,InflaterInputStream
から,zlib
だけやってると確信できる。
が,戻り値がvoidになっているし,引数の型があっていない。
戻り値voidをint *に
第1引数の型をJNIEnvに
第2引数は使われていないので名前をunusedに変更
int * Java_aw_qi_zp(JNIEnv *param_1,undefined4 unused,undefined4 param_3)
{
int *piVar1;
jclass clazz;
jmethodID p_Var2;
clazz = (*(*param_1)->FindClass)(param_1,"java/util/zip/InflaterInputStream");
p_Var2 = (*(*param_1)->GetMethodID)(param_1,clazz,"<init>","(Ljava/io/InputStream;)V");
piVar1 = (int *)_JNIEnv::NewObject((_jclass *)param_1,(_jmethodID *)clazz,p_Var2,param_3);
return piVar1;
}
見やすくなった。
別の検体
/* renamed from: b */
private void m14b() {
Runtime.getRuntime().load(((PathClassLoader) getClassLoader()).findLibrary("jv"));
new ByteArrayOutputStream();
File c = m13c();
m15a((byte[]) C0004oi.m4ez(this, "xzghh"), c.getPath());
String absolutePath = c.getAbsolutePath();
Class cls = (Class) C0004oi.oqs(C0004oi.dvg(1), C0004oi.vqz(absolutePath, getFilesDir().getAbsolutePath() + "/xzghh"), new Object(), 0);
this.f1b = cls;
this.f0a = C0004oi.m0yk(cls);
}
/* renamed from: a */
private static void m15a(byte[] bArr, String str) {
m12d(str, bArr);
}
C0004oi.m4ez(this, "xzghh")
は,バイトアレイを返す関数
/* renamed from: ez */
public static native Object m4ez(Object obj, String str);
アンパックルーチンが全部native関数の中
undefined4 Java_j_oi_ez(int *param_1,undefined4 param_2,_jmethodID *param_3,undefined4 param_4)
{
undefined4 uVar1;
_jmethodID *p_Var2;
undefined4 uVar3;
char *pcVar4;
size_t sVar5;
undefined4 uVar6;
int iVar7;
int iVar8;
_jobject *p_Var9;
undefined4 uVar10;
int iVar11;
undefined8 uVar12;
byte *local_c0;
byte *local_bc;
byte *local_b8;
byte local_a9;
undefined2 auStack168 [64];
int local_28;
local_28 = __stack_chk_guard;
uVar1 = (**(code **)(*param_1 + 0x7c))(param_1,param_3);
uVar1 = (**(code **)(*param_1 + 0x84))
(param_1,uVar1,"getAssets","()Landroid/content/res/AssetManager;");
p_Var2 = (_jmethodID *)_JNIEnv::CallObjectMethod((_jobject *)param_1,param_3,uVar1);
uVar1 = (**(code **)(*param_1 + 0x18))(param_1,"android/content/res/AssetManager");
uVar3 = (**(code **)(*param_1 + 0x84))
(param_1,uVar1,&UNK_00025c01,"(Ljava/lang/String;)[Ljava/lang/String;");
uVar1 = (**(code **)(*param_1 + 0x84))
(param_1,uVar1,&UNK_00025c2e,"(Ljava/lang/String;)Ljava/io/InputStream;");
uVar3 = _JNIEnv::CallObjectMethod((_jobject *)param_1,p_Var2,uVar3,param_4);
uVar3 = (**(code **)(*param_1 + 0x2b4))(param_1,uVar3,0);
__aeabi_memclr8(auStack168,0x80);
pcVar4 = (char *)(**(code **)(*param_1 + 0x2a4))(param_1,param_4,0);
strcat((char *)auStack168,pcVar4);
(**(code **)(*param_1 + 0x2a8))(param_1,param_4,pcVar4);
sVar5 = strlen((char *)auStack168);
*(undefined2 *)((int)auStack168 + sVar5) = 0x2f;
pcVar4 = (char *)(**(code **)(*param_1 + 0x2a4))(param_1,uVar3,0);
strcat((char *)auStack168,pcVar4);
(**(code **)(*param_1 + 0x2a8))(param_1,uVar3,pcVar4);
uVar3 = (**(code **)(*param_1 + 0x29c))(param_1,auStack168);
p_Var2 = (_jmethodID *)_JNIEnv::CallObjectMethod((_jobject *)param_1,p_Var2,uVar1,uVar3);
uVar1 = (**(code **)(*param_1 + 0x18))(param_1,"java/io/InputStream");
uVar3 = (**(code **)(*param_1 + 0x84))(param_1,uVar1,&UNK_00025c71,&UNK_00025c76);
uVar1 = (**(code **)(*param_1 + 0x84))(param_1,uVar1,"close",&UNK_00025c82);
uVar6 = (**(code **)(*param_1 + 0x2c0))(param_1,0xc);
_JNIEnv::CallIntMethod((_jobject *)param_1,p_Var2,uVar3,uVar6);
(**(code **)(*param_1 + 800))(param_1,uVar6,0,0xc);
uVar6 = (**(code **)(*param_1 + 0x2c0))(param_1,0x200);
local_c0 = (byte *)0x0;
local_bc = (byte *)0x0;
local_b8 = (byte *)0x0;
while (iVar7 = _JNIEnv::CallIntMethod((_jobject *)param_1,p_Var2,uVar3,uVar6), -1 < iVar7) {
iVar8 = (**(code **)(*param_1 + 0x2e0))(param_1,uVar6,0);
iVar11 = 0;
while (iVar11 < iVar7) {
if (local_bc < local_b8) {
*local_bc = *(byte *)(iVar8 + iVar11) ^ local_a9;
local_bc = local_bc + 1;
}
else {
std::__ndk1::vector<signed_char,std::__ndk1::allocator<signed_char>>::
__push_back_slow_path<signed_char>((signed *)&local_c0);
}
iVar11 = iVar11 + 1;
}
(**(code **)(*param_1 + 0x300))(param_1,uVar6,iVar8,0);
}
_JNIEnv::CallVoidMethod((_jobject *)param_1,p_Var2,uVar1);
p_Var9 = (_jobject *)(**(code **)(*param_1 + 0x2c0))(param_1,local_bc + -(int)local_c0);
(**(code **)(*param_1 + 0x340))(param_1,p_Var9,0,local_bc + -(int)local_c0);
p_Var2 = (_jmethodID *)(**(code **)(*param_1 + 0x18))(param_1,"java/io/ByteArrayInputStream");
uVar10 = (**(code **)(*param_1 + 0x84))(param_1,p_Var2,&UNK_00025a94,&UNK_00025ca3);
uVar12 = _JNIEnv::NewObject((_jclass *)param_1,p_Var2,uVar10);
p_Var2 = (_jmethodID *)
createInflateStream((_JNIEnv *)param_1,(_jclass *)((ulonglong)uVar12 >> 0x20),
(_jobject *)uVar12,p_Var9);
local_bc = local_c0;
while (iVar7 = _JNIEnv::CallIntMethod((_jobject *)param_1,p_Var2,uVar3,uVar6), -1 < iVar7) {
iVar8 = (**(code **)(*param_1 + 0x2e0))(param_1,uVar6,0);
iVar11 = 0;
while (iVar11 < iVar7) {
if (local_bc == local_b8) {
std::__ndk1::vector<signed_char,std::__ndk1::allocator<signed_char>>::
__push_back_slow_path<signed_char_const&>((signed *)&local_c0);
}
else {
*local_bc = *(byte *)(iVar8 + iVar11);
local_bc = local_bc + 1;
}
iVar11 = iVar11 + 1;
}
(**(code **)(*param_1 + 0x300))(param_1,uVar6,iVar8,0);
}
_JNIEnv::CallVoidMethod((_jobject *)param_1,p_Var2,uVar1);
uVar1 = (**(code **)(*param_1 + 0x2c0))(param_1,local_bc + -(int)local_c0);
(**(code **)(*param_1 + 0x340))(param_1,uVar1,0,local_bc + -(int)local_c0);
std::__ndk1::__vector_base<signed_char,std::__ndk1::allocator<signed_char>>::~__vector_base
((__vector_base<signed_char,std::__ndk1::allocator<signed_char>> *)&local_c0);
if (__stack_chk_guard != local_28) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return uVar1;
}
*local_bc = *(byte *)(iVar8 + iVar11) ^ local_a9;
と
createInflateStream((_JNIEnv *)param_1,(_jclass *)((ulonglong)uVar12 >> 0x20),
からアンパックルーチンに見える。
ただlocal_a9
に代入が無いなど,デコンパイルできているとは言いがたい。
戻り値void
をint *
に
第1引数の型をJNIEnv
に
第2引数は使われていないので名前をunused
に変更
int * Java_j_oi_ez(JNIEnv *param_1,undefined4 unused,_jmethodID *param_3,jstring param_4)
{
jclass p_Var1;
jmethodID p_Var2;
_jmethodID *p_Var3;
jmethodID p_Var4;
jobjectArray array;
jobject str;
char *pcVar5;
size_t sVar6;
jstring p_Var7;
jbyteArray p_Var8;
int iVar9;
jbyte *pjVar10;
jbyteArray array_00;
jmethodID p_Var11;
int *array_01;
int iVar12;
undefined8 uVar13;
byte *local_c0;
byte *local_bc;
byte *local_b8;
jbyte ajStack180 [11];
byte local_a9;
undefined2 auStack168 [64];
int local_28;
local_28 = __stack_chk_guard;
p_Var1 = (*(*param_1)->GetObjectClass)(param_1,(jobject)param_3);
p_Var2 = (*(*param_1)->GetMethodID)
(param_1,p_Var1,"getAssets","()Landroid/content/res/AssetManager;");
p_Var3 = (_jmethodID *)_JNIEnv::CallObjectMethod((_jobject *)param_1,param_3,p_Var2);
p_Var1 = (*(*param_1)->FindClass)(param_1,"android/content/res/AssetManager");
p_Var2 = (*(*param_1)->GetMethodID)
(param_1,p_Var1,"list","(Ljava/lang/String;)[Ljava/lang/String;");
p_Var4 = (*(*param_1)->GetMethodID)
(param_1,p_Var1,"open","(Ljava/lang/String;)Ljava/io/InputStream;");
array = (jobjectArray)_JNIEnv::CallObjectMethod((_jobject *)param_1,p_Var3,p_Var2,param_4);
str = (*(*param_1)->GetObjectArrayElement)(param_1,array,0);
__aeabi_memclr8(auStack168,0x80);
pcVar5 = (*(*param_1)->GetStringUTFChars)(param_1,param_4,(jboolean *)0x0);
strcat((char *)auStack168,pcVar5);
(*(*param_1)->ReleaseStringUTFChars)(param_1,param_4,pcVar5);
sVar6 = strlen((char *)auStack168);
*(undefined2 *)((int)auStack168 + sVar6) = 0x2f;
pcVar5 = (*(*param_1)->GetStringUTFChars)(param_1,(jstring)str,(jboolean *)0x0);
strcat((char *)auStack168,pcVar5);
(*(*param_1)->ReleaseStringUTFChars)(param_1,(jstring)str,pcVar5);
p_Var7 = (*(*param_1)->NewStringUTF)(param_1,(char *)auStack168);
p_Var3 = (_jmethodID *)_JNIEnv::CallObjectMethod((_jobject *)param_1,p_Var3,p_Var4,p_Var7);
p_Var1 = (*(*param_1)->FindClass)(param_1,"java/io/InputStream");
p_Var2 = (*(*param_1)->GetMethodID)(param_1,p_Var1,"read","([B)I");
p_Var4 = (*(*param_1)->GetMethodID)(param_1,p_Var1,"close","()V");
p_Var8 = (*(*param_1)->NewByteArray)(param_1,0xc);
_JNIEnv::CallIntMethod((_jobject *)param_1,p_Var3,p_Var2,p_Var8);
(*(*param_1)->GetByteArrayRegion)(param_1,p_Var8,0,0xc,ajStack180);
p_Var8 = (*(*param_1)->NewByteArray)(param_1,0x200);
local_c0 = (byte *)0x0;
local_bc = (byte *)0x0;
local_b8 = (byte *)0x0;
while (iVar9 = _JNIEnv::CallIntMethod((_jobject *)param_1,p_Var3,p_Var2,p_Var8), -1 < iVar9) {
pjVar10 = (*(*param_1)->GetByteArrayElements)(param_1,p_Var8,(jboolean *)0x0);
iVar12 = 0;
while (iVar12 < iVar9) {
if (local_bc < local_b8) {
*local_bc = pjVar10[iVar12] ^ local_a9;
local_bc = local_bc + 1;
}
else {
std::__ndk1::vector<signed_char,std::__ndk1::allocator<signed_char>>::
__push_back_slow_path<signed_char>((signed *)&local_c0);
}
iVar12 = iVar12 + 1;
}
(*(*param_1)->ReleaseByteArrayElements)(param_1,p_Var8,pjVar10,0);
}
_JNIEnv::CallVoidMethod((_jobject *)param_1,p_Var3,p_Var4);
array_00 = (*(*param_1)->NewByteArray)(param_1,(jsize)(local_bc + -(int)local_c0));
(*(*param_1)->SetByteArrayRegion)
(param_1,array_00,0,(jsize)(local_bc + -(int)local_c0),(jbyte *)local_c0);
p_Var1 = (*(*param_1)->FindClass)(param_1,"java/io/ByteArrayInputStream");
p_Var11 = (*(*param_1)->GetMethodID)(param_1,p_Var1,"<init>","([B)V");
uVar13 = _JNIEnv::NewObject((_jclass *)param_1,(_jmethodID *)p_Var1,p_Var11);
p_Var3 = (_jmethodID *)
createInflateStream((_JNIEnv *)param_1,(_jclass *)((ulonglong)uVar13 >> 0x20),
(_jobject *)uVar13,(_jobject *)array_00);
local_bc = local_c0;
while (iVar9 = _JNIEnv::CallIntMethod((_jobject *)param_1,p_Var3,p_Var2,p_Var8), -1 < iVar9) {
pjVar10 = (*(*param_1)->GetByteArrayElements)(param_1,p_Var8,(jboolean *)0x0);
iVar12 = 0;
while (iVar12 < iVar9) {
if (local_bc == local_b8) {
std::__ndk1::vector<signed_char,std::__ndk1::allocator<signed_char>>::
__push_back_slow_path<signed_char_const&>((signed *)&local_c0);
}
else {
*local_bc = pjVar10[iVar12];
local_bc = local_bc + 1;
}
iVar12 = iVar12 + 1;
}
(*(*param_1)->ReleaseByteArrayElements)(param_1,p_Var8,pjVar10,0);
}
_JNIEnv::CallVoidMethod((_jobject *)param_1,p_Var3,p_Var4);
array_01 = (int *)(*(*param_1)->NewByteArray)(param_1,(jsize)(local_bc + -(int)local_c0));
(*(*param_1)->SetByteArrayRegion)
(param_1,(jbyteArray)array_01,0,(jsize)(local_bc + -(int)local_c0),(jbyte *)local_c0);
std::__ndk1::__vector_base<signed_char,std::__ndk1::allocator<signed_char>>::~__vector_base
((__vector_base<signed_char,std::__ndk1::allocator<signed_char>> *)&local_c0);
if (__stack_chk_guard != local_28) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return array_01;
}
第4引数の型が,自動的にjstring
に変わった。
read
の文字や12バイトを意味する0xc
などが見える。
11バイトread(スキップ)
1バイトread(xor鍵として使用)と関係ありそう?
p_Var1 = (*(*param_1)->FindClass)(param_1,"java/io/InputStream");
p_Var2 = (*(*param_1)->GetMethodID)(param_1,p_Var1,"read","([B)I");
p_Var8 = (*(*param_1)->NewByteArray)(param_1,0xc);
_JNIEnv::CallIntMethod((_jobject *)param_1,p_Var3,p_Var2,p_Var8);
(*(*param_1)->GetByteArrayRegion)(param_1,p_Var8,0,0xc,ajStack180);
12バイト読んでるのに jbyte ajStack180 [11];
と 11バイトしか定義されていない?
を byte[12]に変更してみる。
その結果
int * Java_j_oi_ez(JNIEnv *param_1,undefined4 unused,_jmethodID *param_3,jstring param_4)
{
jclass p_Var1;
jmethodID p_Var2;
_jmethodID *p_Var3;
jmethodID p_Var4;
jobjectArray array;
jobject str;
char *pcVar5;
size_t sVar6;
jstring p_Var7;
jbyteArray p_Var8;
int iVar9;
jbyte *pjVar10;
jbyteArray array_00;
jmethodID p_Var11;
int *array_01;
int iVar12;
undefined8 uVar13;
byte *local_c0;
byte *local_bc;
byte *local_b8;
jbyte ajStack180 [12];
undefined2 auStack168 [64];
int local_28;
local_28 = __stack_chk_guard;
p_Var1 = (*(*param_1)->GetObjectClass)(param_1,(jobject)param_3);
p_Var2 = (*(*param_1)->GetMethodID)
(param_1,p_Var1,"getAssets","()Landroid/content/res/AssetManager;");
p_Var3 = (_jmethodID *)_JNIEnv::CallObjectMethod((_jobject *)param_1,param_3,p_Var2);
p_Var1 = (*(*param_1)->FindClass)(param_1,"android/content/res/AssetManager");
p_Var2 = (*(*param_1)->GetMethodID)
(param_1,p_Var1,"list","(Ljava/lang/String;)[Ljava/lang/String;");
p_Var4 = (*(*param_1)->GetMethodID)
(param_1,p_Var1,"open","(Ljava/lang/String;)Ljava/io/InputStream;");
array = (jobjectArray)_JNIEnv::CallObjectMethod((_jobject *)param_1,p_Var3,p_Var2,param_4);
str = (*(*param_1)->GetObjectArrayElement)(param_1,array,0);
__aeabi_memclr8(auStack168,0x80);
pcVar5 = (*(*param_1)->GetStringUTFChars)(param_1,param_4,(jboolean *)0x0);
strcat((char *)auStack168,pcVar5);
(*(*param_1)->ReleaseStringUTFChars)(param_1,param_4,pcVar5);
sVar6 = strlen((char *)auStack168);
*(undefined2 *)((int)auStack168 + sVar6) = 0x2f;
pcVar5 = (*(*param_1)->GetStringUTFChars)(param_1,(jstring)str,(jboolean *)0x0);
strcat((char *)auStack168,pcVar5);
(*(*param_1)->ReleaseStringUTFChars)(param_1,(jstring)str,pcVar5);
p_Var7 = (*(*param_1)->NewStringUTF)(param_1,(char *)auStack168);
p_Var3 = (_jmethodID *)_JNIEnv::CallObjectMethod((_jobject *)param_1,p_Var3,p_Var4,p_Var7);
p_Var1 = (*(*param_1)->FindClass)(param_1,"java/io/InputStream");
p_Var2 = (*(*param_1)->GetMethodID)(param_1,p_Var1,"read","([B)I");
p_Var4 = (*(*param_1)->GetMethodID)(param_1,p_Var1,"close","()V");
p_Var8 = (*(*param_1)->NewByteArray)(param_1,0xc);
_JNIEnv::CallIntMethod((_jobject *)param_1,p_Var3,p_Var2,p_Var8);
(*(*param_1)->GetByteArrayRegion)(param_1,p_Var8,0,0xc,ajStack180);
p_Var8 = (*(*param_1)->NewByteArray)(param_1,0x200);
local_c0 = (byte *)0x0;
local_bc = (byte *)0x0;
local_b8 = (byte *)0x0;
while (iVar9 = _JNIEnv::CallIntMethod((_jobject *)param_1,p_Var3,p_Var2,p_Var8), -1 < iVar9) {
pjVar10 = (*(*param_1)->GetByteArrayElements)(param_1,p_Var8,(jboolean *)0x0);
iVar12 = 0;
while (iVar12 < iVar9) {
if (local_bc < local_b8) {
*local_bc = pjVar10[iVar12] ^ ajStack180[11];
local_bc = local_bc + 1;
}
else {
std::__ndk1::vector<signed_char,std::__ndk1::allocator<signed_char>>::
__push_back_slow_path<signed_char>((signed *)&local_c0);
}
iVar12 = iVar12 + 1;
}
(*(*param_1)->ReleaseByteArrayElements)(param_1,p_Var8,pjVar10,0);
}
_JNIEnv::CallVoidMethod((_jobject *)param_1,p_Var3,p_Var4);
array_00 = (*(*param_1)->NewByteArray)(param_1,(jsize)(local_bc + -(int)local_c0));
(*(*param_1)->SetByteArrayRegion)
(param_1,array_00,0,(jsize)(local_bc + -(int)local_c0),(jbyte *)local_c0);
p_Var1 = (*(*param_1)->FindClass)(param_1,"java/io/ByteArrayInputStream");
p_Var11 = (*(*param_1)->GetMethodID)(param_1,p_Var1,"<init>","([B)V");
uVar13 = _JNIEnv::NewObject((_jclass *)param_1,(_jmethodID *)p_Var1,p_Var11);
p_Var3 = (_jmethodID *)
createInflateStream((_JNIEnv *)param_1,(_jclass *)((ulonglong)uVar13 >> 0x20),
(_jobject *)uVar13,(_jobject *)array_00);
local_bc = local_c0;
while (iVar9 = _JNIEnv::CallIntMethod((_jobject *)param_1,p_Var3,p_Var2,p_Var8), -1 < iVar9) {
pjVar10 = (*(*param_1)->GetByteArrayElements)(param_1,p_Var8,(jboolean *)0x0);
iVar12 = 0;
while (iVar12 < iVar9) {
if (local_bc == local_b8) {
std::__ndk1::vector<signed_char,std::__ndk1::allocator<signed_char>>::
__push_back_slow_path<signed_char_const&>((signed *)&local_c0);
}
else {
*local_bc = pjVar10[iVar12];
local_bc = local_bc + 1;
}
iVar12 = iVar12 + 1;
}
(*(*param_1)->ReleaseByteArrayElements)(param_1,p_Var8,pjVar10,0);
}
_JNIEnv::CallVoidMethod((_jobject *)param_1,p_Var3,p_Var4);
array_01 = (int *)(*(*param_1)->NewByteArray)(param_1,(jsize)(local_bc + -(int)local_c0));
(*(*param_1)->SetByteArrayRegion)
(param_1,(jbyteArray)array_01,0,(jsize)(local_bc + -(int)local_c0),(jbyte *)local_c0);
std::__ndk1::__vector_base<signed_char,std::__ndk1::allocator<signed_char>>::~__vector_base
((__vector_base<signed_char,std::__ndk1::allocator<signed_char>> *)&local_c0);
if (__stack_chk_guard != local_28) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return array_01;
}
xorしてるところが*local_bc = pjVar10[iVar12] ^ ajStack180[11];
に変わった。
12バイト目をxor鍵にしてる。
やったぜ!