JNI, NDK, so, IDA

JNI, NDK, so, IDA

实验准备

在settings-System Settings-Android SDK-SDK Tools中安装NDK 和 CMake
在这里插入图片描述

在AndroidStudio中新建C++项目
在这里插入图片描述
选择语言为java
在这里插入图片描述
等待 Build,项目运行正常。
在Project Structure中配置ndk路径,然后可以在local.properties中查看配置
在这里插入图片描述
在这里插入图片描述
并且项目会生成cpp文件夹
在这里插入图片描述
查看 CMakeLists.txt 的内容
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在构建脚本中指定“native-lib”作为共享库的名称,CMake 就会创建一个名为
libnative-lib.so 的文件

  • add_library 用来设置编译生成的本地库的名字为 native-lib,SHARED 表示
    编译生成的是动态链接库,native-lib.cpp 表示参与编译的文件。
  • find_library 是用来添加一些我们在编译我们的本地库的时候需要依赖的一些
    库,由于 cmake 已经知道系统库的路径,所以这里只是指定使用 log 库,然
    后给 log 库起别名为 log-lib 便于后面引用,此处的 log 库是后面调试时需要
    用来打 log 日志的库,是 NDK 提供的。
  • target_link_libraries 是为了关联自己的库和一些第三方库或者系统库,这里把
    自己的库 native-lib 库和 log 库关联起来。

实验过程

一、编写登录程序

在MainActivity里声明
public native boolean checkNameAndPwd(String name, String pwd);
并且alt+enter自动create在对应cpp中生成代码
在这里插入图片描述
在这里插入图片描述
编写实现方法

extern "C"
JNIEXPORT jboolean JNICALL
/**
* C 语言检查用户名密码
* @param name 用户名
* @param pwd 密码
* @return name == pwd
*/
Java_com_exampie_hellojni_MainActivity_checkNameAndPwd(JNIEnv *env, jobject thiz, jstring name,
                                                       jstring pwd) {
    // TODO: implement checkNameAndPwd()
    // 获取 nameC 和 pwdC
    const char *nameC = (char *)(env->GetStringUTFChars(name, JNI_FALSE));
    const char *pwdC = (char *)(env->GetStringUTFChars(pwd, JNI_FALSE));
    env->ReleaseStringUTFChars(name, nameC);
    env->ReleaseStringUTFChars(pwd, pwdC);
    return (jboolean)(strncmp(nameC, pwdC, strlen(pwdC)+1) == 0);
}

在MainActivity里编写监听代码

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                TextView tv = findViewById(R.id.checkResult);
                EditText editTextName = findViewById(R.id.name);
                EditText editTextPwd = findViewById(R.id.pwd);
                String result = checkNameAndPwd(editTextName.getText().toString(), editTextPwd.getText().toString()) ? "Welcome" : "Sorry";
                tv.setText(result);
            }
        });
    }

layout页面
在这里插入图片描述
尝试运行,运行成功
在这里插入图片描述

二、学习so文件

在 src-main 文件夹中,新建一个文件夹 jnilibs,然后将 build 出来的 so 文件拷贝进去
在这里插入图片描述

在这里插入图片描述
接着,删除 cpp 文件夹里的 cpp 文件
在这里插入图片描述

事实上,此时 AS 也会提醒该文件被正引用着,所以很显然,删除完之后,还需要删除对应的引用。
这里是 CMakeLists.txt 文件:
注释 add_library 部分:
在这里插入图片描述
再注释 target_link_libraries 部分:
在这里插入图片描述
此时,MainActivity 之前声明的方法都报红,因为 cpp 文件已经被删除,它并不知
道其如何实现:
在这里插入图片描述
删除 build 文件夹,重新打包。这时会发现,build 不再有 cmake 文件夹。
在这里插入图片描述
重新安装程序,发现运行正常。
在这里插入图片描述
在 Android Studio 中,如果将 so 文件放在 libs 目录里,是不会被打包到 apk 中
的,只有 jniLibs 目录里的 so 文件会被打包到 apk 中。当然这个目录指定的文件夹
可以更改,但是默认就是 \src\main\jniLibs
更改目录的方法是,在 app 内的 gradle 文件里面的 android{…},添加一个:

sourceSets {
 main {
 jniLibs.srcDirs = ['src/main/jni']
 }
}

此时,src/main/jni 下的 so 文件也会被打包,是的,之前的 jniLibs 仍然可用
流程类似于手动编译,但是安全性大大提高

so文件调试

打开 CMD,作为电脑端,在 IDA 的 dbgsrv 目录下,将 android_server 文件
上传到手机端(路径可以自定义):

adb push android_server /data/local/tmp/android_server

在这里插入图片描述
再打开一个 CMD,作为手机端,进入其终端:
adb shell
进入刚才上传的文件夹,可以看到文件上传成功:

在这里插入图片描述
赋予文件可执行权限,并执行:

  • 赋予权限
    chmod 777 android_server
  • 查看
    ls -l android_server
  • 执行文件
    ./android_server
    在这里插入图片描述
    端口转发,电脑端 CMD 输入命令:
    adb forward tcp:23946 tcp:23946
    在这里插入图片描述
    打开 IDA(注意无需打开 so 文件),选择 Debugger -> Attach-> Remote
    ARMLinux/Android debugger,设置对应 IP 及端口,这里即默认的 23946
    在这里插入图片描述
    点击 OK,会弹框如下,选择对应的 apk 包名
    在这里插入图片描述
    然后再modules中选择对应的函数,双击查看代码
    在这里插入图片描述
    在这里插入图片描述
    F2 下断点,然后 F9 ,此时 APP 可以输入用户名密码:
    在这里插入图片描述

输入后点击提交,程序停在断点处:

在这里插入图片描述
接下来尝试静态调试

使用ak逆向,打开MainActivity查看汇编代码,但是看不到native-lib实现
在这里插入图片描述
在这里插入图片描述
但是多了lib文件夹,里面有so文件
在这里插入图片描述
使用ida打开so文件,找到MainActivity
在这里插入图片描述
F5查看伪代码
在这里插入图片描述

分析代码,v20和v19分别存储a3用户名和a4密码,即传入的参数,接着根据v8用户名的长度 malloc一个v7,将当前值赋为ascii63(为‘?’),总长度减一然后strncat一个字符串he110
在这里插入图片描述
成功

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值