调用博主最近登录时间
生活中的HYGGE
第四篇Android逆向:动态调试&Log插桩

第四篇Android逆向:动态调试&Log插桩

hygge
2023-07-26 / 0 评论 / 228 阅读 / 正在检测是否收录...

一、基本概念

1.1 动态调试

动态调试是指自带的调试器跟踪自己软件的运行,可以在调试的过程中知道参数或者局部变量的值记忆捋清代码运行的先后顺序。

多用于爆破注册码(CTF必备技能)

1.2 Log插桩

Log插桩是指在反编译APK文件时,在对应的smali文件里,添加相应的smali代码,将程序的关键信息,以log日志的形式进行输出。

二、动态调试

2.1 修改debug权限

方法一:在AndroidManifest.xml里添加可调试权限

android:debuggable="true"

方法二:XappDebug模块hook对应的app

项目地址

XappDebug

https://github.com/Palatis/XAppDebug

方法三:Magisk命令(重启失效)

1. adb shell # adb进入命令行模式
2. su # 切换至超级用户
3. magisk resetprop ro.debuggable 1
4. stop;start; # 一定要通过该方式重启

方法四:刷入MagiskHide Props Config模块(永久有效)

一般来说,在4选项中如果有ro.debuggable那就直接修改

没有的话就选5

lkjnuqgh.png

修改ro.debuggable的值为1

2.2 端口转发以及开启adb权限

版本后点击七次开启开发者模式并开启adb调试权限

夜神模拟器: adb connect 127.0.0.1:62001

2.3 下端点

Jeb里使用ctrl + b下断点

2.4 debug模式启动

adb shell am start -D -n com.zj.wuaipojie/.ui.MainActivity 
  • adb shell am start -D -n 包名/类名
  • am start -n 表示启动一个activity
  • am start -D 表示将应用设置为可调试模式

2.5 Jeb附加调试进程

快捷键作用
F6进入方法
F7从方法中跳出来
F8
R运行到光标处

三、修改debug权限实操

3.1 修改AndroidManifest

lkjnv1r8.png

3.2 XAppDebug模块

lkjnwr83.png

lkjnwwhd.png

3.3 Magisk命令

上文

3.4 MigiskHide Props Config

安装模块

lkjny9k6.png

打开Mt管理器终端模拟器

输入props进入模块

lkjnyft9.png

然后按照上文操作即可

四、追码练习

lkjnyo8m.png

4.1 开发者选项开启USB调试,目标App要开启Debug调试

lkjnyu4c.png

4.2 apk拖入JEB,搜索关键字密钥错误

lkjnzutl.png

发现关键点是

if(this.check(((EditText)this.findViewById(0x7F0800AC)).getText().toString())) {  // id:edit_check
    Context context0 = (Context)this;
    Toast.makeText(context0, "恭喜你,密钥正确!", 1).show();
    SPUtils.INSTANCE.saveInt(context0, "level", 3);
    return;
}

Toast.makeText(((Context)this), "密钥错误哦,再想想!", 1).show();

4.3 继续追check方法,双击方法名进入

public final boolean check(String s) {
    int v = 0;
    Integer integer0 = null;
    if(!StringsKt.startsWith$default(s, "flag{", false, 2, null)) {
        return false;
    }

    if(!StringsKt.endsWith$default(s, "}", false, 2, null)) {
        return false;
    }

    String s1 = s.substring(5, s.length() - 1);
    Intrinsics.checkNotNullExpressionValue(s1, "this as java.lang.String…ing(startIndex, endIndex)");
    String s2 = SPUtils.INSTANCE.getString(((Context)this), "id", "");
    if(s2 != null) {
        integer0 = (int)s2.length();
    }

    int v1 = 1000;
    Intrinsics.checkNotNull(integer0);
    int v2 = (int)integer0;
    if(v2 >= 0) {
        while(true) {
            v1 += -7;
            if(v == v2) {
                break;
            }

            ++v;
        }
    }

    byte[] arr_b = Encode.encode(s2 + v1).getBytes(Charsets.UTF_8);
    Intrinsics.checkNotNullExpressionValue(arr_b, "this as java.lang.String).getBytes(charset)");
    return Intrinsics.areEqual(s1, Base64Utils.INSTANCE.encodeToString(arr_b));
}

首先密钥必须以flag{开头,以}结尾

然后回取出除开头和结尾中间的内容和一个base64加密的字符串进行比对

base64加密的数据是由s2(打开软件注册的用户名) + v1(整数常量组成),当s2固定时base64加密的结果也就固定了。

下一步就需要对加密结果打断点

lkjo08mm.png

4.4 app开启调试

lkjo0fok.png

4.5 Jeb附加调试进程

lkjo0l7q.png

然后再去应用模拟验证一下

lkjo0s8y.png

已经成功断点了,右边的寄存器也能看到局部变量

lkjo0x8g.png

此时已拿到密钥:5YaF57OkDAUM

lkjo12gh.png

五、Log插桩

5.1 日志插桩dex注入

lkjo1740.png

5.2 代码关键处添加输出

invoke-static {对应寄存器}, Lcom/mtools/LogUtils;->v(Ljava/lang/Object;)V

lkjo1cvk.png

5.3 使用算法助手查看日志

lkjo1iei.png

然后启动 去触发一下关键点

lkjo1ndu.png

拿到密钥

实战

lkjo1ruf.png

反编译发现程序逻辑如下:

lkjo1vsj.png

可以直接通过程序跑出来结果:

let str = 'e10adc3949ba59abbe56e057f20f883e'; // 对 123456 进行md5 再转 十六进制的结果
let sb = ''
for(let i = 0;true;i+=2){
    if(i >= str.length){
        console.log(sb);
        return sb == '123';
    }
    // 将 str i位置上的字符追加到sb中
    sb += str.charAt(i);
}

lkjo20mz.png

引用

1.《安卓逆向这档事》五、1000-7=?&动态调试&Log插桩:https://www.52pojie.cn/thread-1714727-1-1.html

2.吾爱破解安卓逆向入门教程《安卓逆向这档事》五、1000-7? & 动态调试&Log插桩:https://www.bilibili.com/video/BV1hg411q7dj/

3.JEB动态调试Smali-真机/模拟器(详细,新手必看):https://www.52pojie.cn/thread-1598242-1-1.html

4.Log简易打印工具,超简单的调用方法:https://www.52pojie.cn/thread-411454-1-1.html

5.Android修改ro.debuggable 的四种方法:https://blog.csdn.net/jinmie0193/article/details/111355867

0

评论 (0)

取消