目录
2.2 使用IDA进行启动调试,原理是在应用程序执行初始化函数之前挂载进入应用
1.从方便性来看,肯定是第2种方法更好,这里采用第2种修改全局系统属性方法
2.启动ddms(在android_studio界面下载SDK或者网上搜索单独下载SDK文件)
一、系统环境
OS: Windows_NT x64 10.0.19045
JADX:1.5.0
IDA:7.7.220118
python:3.8.10
Node.js: 18.17.1
frida :14.2.14
objection:1.11.0
vscode: 1.87.2
device:nexus 5x-8.1.2
二、详细分析
前言:
典型的 Crake me 应用,废话不多说,开整
正文:
1.静态分析
使用 Jadx 打开后可以看到 Java层 MainActivity 逻辑很简单,真正对输入密码进行校验的位置在加载的 libwolf.so 中
public class MainActivity extends AppCompatActivity {
private EditText editText = null;
static {
System.loadLibrary("wolf");
}
/* JADX INFO: Access modifiers changed from: protected */
@Override // android.support.v7.app.AppCompatActivity, android.support.v4.app.FragmentActivity, android.support.v4.app.BaseFragmentActivityDonut, android.app.Activity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(C0225R.layout.activity_main);
setTitle("Hey Man! Crack me!");
this.editText = (EditText) findViewById(C0225R.id.editText);
}
public void click(View v) {
if (this.editText.getText().toString().equals("")) {
Toast.makeText(this, "Please Enter Your PassWord!", 0).show();
} else {
C0224NI.greywolf(this, this.editText.getText().toString());
}
}
/* renamed from: s1 */
public String m13s1() {
return "s1";
}
/* renamed from: s2 */
public String m14s2() {
return "s2";
}
}
public class C0224NI {
public static native void greywolf(Context context, String str);
}
上 IDA 对 libwolf.so 进行分析
先看看 greywolf 这个函数是不是静态注册,以 java 为关键字在函数窗口搜索没有找到,说明是动态注册
函数窗口搜索找到 JNI_OnLoad分析
伪代码虽然可以基本看到大概,但还是看着不太舒服,尝试将代码还原得更贴近源码,JNI_OnLoad动态注册得流程是固定的,直接搜索 JNI_Onload动态注册源码实现(百度的ai智能回答还可以)
比对源码对变量类型和名字重命名后发现除了 AD() 这个函数外,其他都是动态注册的正常内容
进入 AD() 函数内部通过字符串可以分析出这个函数的作用应该是反调试
通过上面这些字符串可以分析出至少存在两种反调试方法:双进程反调试 和 调试端口检测,后面动态调试时需要处理
目前先重点看RegisterNatives函数,dword_55058就是 函数指针数组的地址
点击 dword_55058之后发现这个数组在 .bss 段
.bss段的作用
.bss段的主要作用是存放程序中未初始化的全局变量和静态变量。这些变量在编译时没有明确赋初值,因此在程序加载到内存时,系统会自动将.bss段的内存空间清零,以保证变量在使用前具备确定的初值。
也就是说 dword_55058 这个数组在应用运行的时候才能确定值,那么这个赋值操作是在哪里进行的呢?
点击 dword_55058,按下 X 键查找引用
可以看到在 sub_13C4C 这个函数中被引用,进入sub_13C4C 后再次查找引用
最终来到 .init_array 段
关于为什么可以在 .init_array段中进行初始化,这涉及到 so 的加载原理,如果感兴趣可以看看下面几篇文章