学破解第215天,《动态调试&Log插桩》失败学习

查看 92|回复 9
作者:小菜鸟一枚   
前言:
  坛友们,年轻就是资本,和我一起逆天改命吧,我的学习过程全部记录及学习资源:https://www.52pojie.cn/thread-2006536-1-1.html
立帖为证!--------记录学习的点点滴滴
0x1 动态调试&Log插桩(假)
  1.Log插桩指的是反编译APK文件时,在对应的smali文件里,添加相应的smali代码,将程序中的关键信息,以log日志的形式进行输出。
invoke-static {对应寄存器}, Lcom/mtools/LogUtils;->v(Ljava/lang/Object;)V
  2.算法助手获取获取日志时有延迟,需要退出重新启动才能看到日志。
  3.教程开始跟不上了,直接看这一关作业,点进来发现需要输入一个用户名和16位的注册码,直接点击注册后提示:无效用户名或注册码。


1.png (43.78 KB, 下载次数: 0)
下载附件
2025-2-20 20:41 上传

  4.用np管理器提取安装包,查看dex文件,搜索错误提示,发现搜索不到。
onCreate()一个Activity启动后第一个被调用的函数,常用来在此方法中进行Activity的一些初始化操作。例如创建View,绑定数据,注册监听,加载参数等。

  5.使用adb命令,adb shell,dumpsys activity top,显示顶层活动窗口,可以看到是com.droider.crackme0201/.MainActivity。
Debug logs:
TASK com.droider.crackme0201 id=3 userId=0
  ACTIVITY com.droider.crackme0201/.MainActivity a1c65dc pid=2979
    Local Activity 2ee3f73 State:
      mResumed=true mStopped=false mFinished=false
      mChangingConfigurations=false
      mCurrentConfig={1.0 460mcc65535mnc [zh_CN] ldltr sw360dp w360dp h616dp 480
dpi nrml long port finger qwerty/v/v -nav/h winConfig={ mBounds=Rect(0, 0 - 1080
, 1920) mAppBounds=Rect(0, 0 - 1080, 1920) mWindowingMode=fullscreen mActivityTy
pe=standard} s.7}
  6.再去np管理器打开dex文件,搜索这个类com.droider.crackme0201.MainActivity(去掉前面的下划线搜),onCreate函数前面说过了,启动的时候调用,setOnClickListener函数注册了一个单击事件,单击注册按钮触发onClick函数,这个函数里面有两个case分支,一个执行checkSNfalse函数,一个执行checkSN函数,可以看到如果不执行第二个case,或者第二个case里面的if不满足都会执行2131034123这个show。
    public void onClick(View view) {
        switch (view.getId()) {
            case 2131230723:
                checkSNfalse(this.edit_userName.getText().toString().trim(), this.edit_sn.getText().toString().trim());
                return;
            case 2131230724:
                if (checkSN(this.edit_userName.getText().toString().trim(), this.edit_sn.getText().toString().trim())) {
                    Toast.makeText(this, 2131034124, 0).show();
                    this.btn_register.setEnabled(false);
                    setTitle(2131034122);
                    return;
                }
                Toast.makeText(this, 2131034123, 0).show();
                return;
            default:
                return;
        }
    }
    private boolean checkSN(String str, String str2) {
        if (str == null) {
            return false;
        }
        try {
            if (str.length() == 0 || str2 == null || str2.length() != 16) {
                return false;
            }
            MessageDigest instance = MessageDigest.getInstance("MD5");
            instance.reset();
            instance.update(str.getBytes());
            String toHexString = toHexString(instance.digest(), "");
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i
  7.前面学习过了show就是弹窗,我们打开arsc资源编辑搜索这个id,看到原来这个弹窗内容就是无效用户名或注册码,再看另外一个show的id:2131034124,搜索一下,弹窗内容是恭喜您!注册成功,到这里就很清楚了,关键在于checkSN函数。


2.png (47.68 KB, 下载次数: 0)
下载附件
2025-2-20 20:41 上传

  Crackme0201
  Settings
  Crackme0201
  Android程序破解演示实例
  用户名:
  注册码:
  注 册
  请输入用户名
  请输入16位的注册码
  程序未注册
  程序已注册
  无效用户名或注册码
  恭喜您!注册成功
  8.checkSN函数可以看到传入了userName和sn,这是我们输入的,进来后执行了一个if三个长度判断,接着就是将userName进行MD5处理,再就是一个for循环,自增2,也就是取md5后字符串的奇数位,再通过注册码16位,可以猜测就是生成32位字符串,那么只要在动态调试中找到这个字符串就能得到正确的注册码。
  9.安卓里面很多都是java代码写的,所以我们有一个更快的办法,那就是去掉这些if判断,把两个函数单独拿出来,随便设置一个初始化字符串“xcn”作为用户名,跑一遍,flag就出来了。
public class Test {
        private static String toHexString(byte[] bArr, String str) {
            StringBuilder hexString = new StringBuilder();
            for (byte b : bArr) {
                String hex = Integer.toHexString(b & 255);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex).append(str);
            }
            return hexString.toString();
        }
        public static void main(String[] args) throws NoSuchAlgorithmException {
                String str= "xcn";//这个是用户名
                MessageDigest instance = MessageDigest.getInstance("MD5");
        instance.reset();
        instance.update(str.getBytes());
        String toHexString = toHexString(instance.digest(), "");
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i
  10.当然了,我们目标是练习动态插桩,前面的偏题了,接下来正文。
0x2 动态调试&Log插桩(真)
  1.打开jeb,找到关键代码,在0000004A这个地方打上断点,跑起来
0000004A  invoke-direct       MainActivity->checkSN(String, String)Z, p0, v0, v1
00000050  move-result         v0
00000052  if-nez              v0, :6C
:56
00000056  const               v0, 0x7F05000B        # string:unsuccessed "无效用户名或注册码"
0000005C  invoke-static       Toast->makeText(Context, I, I)Toast, p0, v0, v2
00000062  move-result-object  v0
00000064  invoke-virtual      Toast->show()V, v0
0000006A  goto                :10
:6C
0000006C  const               v0, 0x7F05000C        # string:successed "恭喜您!注册成功"
  2.输入xcn和16个1,点击注册按钮断了下来,进入函数内部,可以看到先是v3那里出现了我们前面的猜测的md5了,但是v6这里似乎看不到内容,返回值不应该是在v6里面吗?


3.png (84.43 KB, 下载次数: 0)
下载附件
2025-2-20 20:41 上传

  3.那就去看v6前面的v5,可以看到一串字节数组,这个就是我们前面的正确注册码了。


4.png (20.81 KB, 下载次数: 0)
下载附件
2025-2-20 20:41 上传

  4.使用np管理器提取安装包,打开dex文件,将日志插装.dex文件插入这个安装包,改名为classes2.dex,然后去代码中添加代码。
  invoke-virtual {v6, p2}, Ljava/lang/String;->equalsIgnoreCase(Ljava/lang/String;)Z
    invoke-static {v6}, Lcom/mtools/LogUtils;->v(Ljava/lang/Object;)V
    move-result v8
  5.重新安装后运行,程序崩溃了,太难了,才学了一点点就跟不上了前辈的节奏。┭┮﹏┭┮
0x3 参考文档
  1.《安卓逆向这档事》五、1000-7=?&动态调试&Log插桩

注册码, 函数

shenxinfu2024   

吾爱是一个有爱的地方,虽然我才疏学浅,看不懂。但是我还是觉得逆很厉害。
xiabo   

坚持,不要放弃。加油!
rayzju   

佩服楼主,向你学习!
xfwww   

感谢分享经验,我也在学习,刚开始。
haiyangw   

你加油,我还没开始
orangewinnie   

不看学习成果 光看215天就已经很牛了
wuliwl   

坚持!正因为有你,所以我把业务代码都搬到服务端了。
leger1210   

加油,我当时看到log插装,也没有成功。。。
qlh520   

虽然学着吃力,但一起坚持
您需要登录后才可以回帖 登录 | 立即注册

返回顶部