IDA : 反编译.so文件
AndroIDKiller: 反编译apk文件及再次编译为apk
jd-gui : 将.jar文件反编译为java代码
dex2jar: 反编译.dex文件
apktool: 能够反编译及回编译apk
夜神模拟器: 运行apk文件
例题 1 [easy-so]下载
来源:攻防世界
使用夜神模拟器运行该apk文件, 发现需要输入flag
zip解压apk文件, 用 dex2jar反编译 classes.dex文件得到classes-dex2jar.jar,
d2j-dex2jar.bat classes.dex
再用jd-gui打开classes-dex2jar.jar反编译为java代码.
public class MainActivity extends AppCompatActivity { protected voID onCreate(Bundle paramBundle) { super.onCreate(paramBundle); setContentVIEw(2131296283); ((button)findVIEwByID(2131165218)).setonClickListener(new VIEw.OnClickListener() { public voID onClick(VIEw param1VIEw) { if (cyberpeace.CheckString(((EditText)MainActivity.this.findVIEwByID(2131165233)).getText().toString()) == 1) { Toast.makeText((Context)MainActivity.this, ", 1).show(); return; } Toast.makeText((Context)MainActivity.this, ", 1).show(); } }); }}
在这里可以发现, cyberpeace加载了'cyberpeace'动态库, CheckString函数是native层的, 这个函数的实现就在libcyberpeace.so文件中
package com.testjava.jack.Pingan2;public class cyberpeace { static { System.loadlibrary("cyberpeace"); } public static native int CheckString(String paramString);}
使用IDa打开lib/x86/libcyberpeace.so文件, 找到 _BOol4 __cdecl Java_com_testjava_jack_Pingan2_cyberpeace_CheckString(int a1, int a2, int a3)函数, 该函数实现如下:
_BOol4 __cdecl Java_com_testjava_jack_Pingan2_cyberpeace_CheckString(int a1, int a2, int a3){ const char *get_str; // ST1C_4 size_t len; // edi char *str; // esi size_t i; // edi char v7; // al char v8; // al size_t v9; // edi char v10; // al get_str = (const char *)(*(int (__cdecl **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0); // 从java层获取所输入的字符串 len = strlen(get_str); str = (char *)malloc(len + 1); memset(&str[len], 0, len != -1); memcpy(str, get_str, len); if ( strlen(str) >= 2 ) // 加密1 { i = 0; do { v7 = str[i]; str[i] = str[i + 16]; str[i++ + 16] = v7; } while ( i < strlen(str) >> 1 ); } // 加密2 v8 = *str; if ( *str ) { *str = str[1]; str[1] = v8; if ( strlen(str) >= 3 ) { v9 = 2; do { v10 = str[v9]; str[v9] = str[v9 + 1]; str[v9 + 1] = v10; v9 += 2; } while ( v9 < strlen(str) ); } } return strcmp(str, "f72c5a36569418a20907b55be5bf95ad") == 0; // 与字符串作比较}
从以上发现, 对我们所输入的字符串进行了加密, 然后再与f72c5a36569418a20907b55be5bf95ad进行比较. 现在只需逆一下以上代码即可得到flag, exp代码如下
#include <stdio.h>#include <string.h>int main(voID) { char str[] = "f72c5a36569418a20907b55be5bf95ad"; int i, v7, v8, v9, v10; v8 = *str; if ( *str ) { *str = str[1]; str[1] = v8; if ( strlen(str) >= 3 ) { v9 = 2; do { v10 = str[v9]; str[v9] = str[v9 + 1]; str[v9 + 1] = v10; v9 += 2; } while ( v9 < strlen(str) ); } } // 交换 if ( strlen(str) >= 2 ) { i = 0; do { v7 = str[i]; str[i] = str[i + 16]; str[i++ + 16] = v7; } while ( i < strlen(str) >> 1 ); } printf("%s", str); return 0;}
运行以上代码即可获取flag
例题 2 [app2]下载
来源:攻防世界
对输入的账号和密码在SecondActivity类中进行加密判断, 而加密调用了native层的加密函数
protected voID onCreate(Bundle paramBundle) { super.onCreate(paramBundle); setContentVIEw(2130903041); Intent intent = getIntent(); String str1 = intent.getStringExtra("ili"); String str2 = intent.getStringExtra("lil"); if (Encryto.doRawData(this, str1 + str2).equals("VEIzd/V2UPYNdn/bxH3Xig==")) { intent.setAction("androID.test.action.MoniterInstallService"); intent.setClass((Context)this, MoniterInstallService.class); intent.putExtra("company", "tencent"); intent.putExtra("name", "Hacker"); intent.putExtra("age", 18); startActivity(intent); startService(intent); } SharedPreferences.Editor editor = getSharedPreferences("test", 0).edit(); editor.putString("ilil", str1); editor.putString("lili", str2); editor.commit(); }
IDA反编译doRawData函数, 因为a为对象, 选择a按下y 键 然后输入 jnienv*就可以显示对象的函数调用, 如下
int __cdecl doRawData(jnienv *a1, int a2, int a3, int a4){ char *v4; // esi const char *v5; // ST10_4 int result; // eax char *v7; // esi Jstring (*v8)(jnienv *, const jchar *, Jsize); // ST10_4 size_t v9; // eax int v10; // [esp+4h] [ebp-28h] int v11; // [esp+8h] [ebp-24h] int v12; // [esp+Ch] [ebp-20h] int v13; // [esp+10h] [ebp-1Ch] char v14; // [esp+14h] [ebp-18h] unsigned int v15; // [esp+18h] [ebp-14h] v15 = __readgsDWord(0x14u); if ( checkSignature((int)a1, a2, a3) == 1 ) { v14 = 0; v13 = 0x3D3D7965; v12 = 0x6B747365; v11 = 0x74617369; v10 = 0x73696874; v4 = (char *)(*a1)->GetStringUTFChars(a1, (Jstring)a4, 0); v5 = (const char *)AES_128_ECB_PKCS5padding_Encrypt(v4, (int)&v10); (*a1)->ReleaseStringUTFChars(a1, (Jstring)a4, v4); result = (int)(*a1)->NewStringUTF(a1, v5); } else { v7 = UNSIGNATURE[0]; v8 = (*a1)->NewString; v9 = strlen(UNSIGNATURE[0]); result = (int)v8(a1, (const jchar *)v7, v9); } return result;}
可以发现, 加密方式为aes加密, key 为 v10中的内容.为thisisatestkey==
对VEIzd/V2UPYNdn/bxH3Xig== 解密为aimagetencent, 发现提交flag错误, 重新找另一个字符串,在fileDataActivity类中找到如下.
public class fileDataActivity extends a { private TextVIEw c; protected voID onCreate(Bundle paramBundle) { super.onCreate(paramBundle); setContentVIEw(2130903042); this.c = (TextVIEw)findVIEwByID(2131165184); this.c.setText(Encryto.decode(this, "9YuQ2dk8CSaCe7DTAmaqAA==")); }}
调用了decode函数, 而decode函数与doRawData实现一样, 直接与之前一样的AES ecb解密, 得到flag
总结以上是内存溢出为你收集整理的Android 逆向入门全部内容,希望文章能够帮你解决Android 逆向入门所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)