【Android逆向】破解看雪test3.apk方案一

android,逆向,破解,test3,apk,方案 · 浏览次数 : 45

小编点评

**问题分析:** 在将 `test3.apk` 安装到 `手机2` 之间的过程中,发现代码逻辑与 `test2.apk` 基本一致,但加入了一些检查逻辑代码。这些代码在判断 `REAL` 与 `FAKE` 之间时,如果满足条件,将字符串 `REAL` 替换为 `FAKE` 并添加到字符串后面。 **解决方案:** 为了确保代码逻辑完整,可以采取以下步骤: 1. **明确代码逻辑:**明确代码在判断 `REAL` 与 `FAKE` 之间的条件以及字符串替换操作,以便在生成代码时对其进行正确处理。 2. **保持代码逻辑一致性:**确保所有使用到的逻辑代码在 `test3.apk` 中都有对应的实现。 3. **添加必要的排版:**使用 `sprintf` 或其他类似的函数进行字符串格式化,确保输出的代码逻辑清晰易懂。 4. **保留代码的可读性:**使用注释来说明代码逻辑,方便开发者理解和维护代码。 **示例代码:** ```java // 假设代码逻辑如下: String realStr = "REAL"; String fakeStr = "FAKE"; if (condition1 || condition2 || strstr(stringUTFChars, "aosp")) { // 将 REAL 替换为 FAKE string = fakeStr; } // 使用 sprintf 进行格式化 String formattedStr = String.format("my string: %s", realStr); ``` **注意:** * 代码示例仅供参考,实际代码可能会有所不同。 * 在将代码部署到不同的平台之前,请确保代码逻辑和功能与目标平台兼容。

正文

1. test3.apk 安装到手机

2. 发现其实际逻辑和之前的test2.apk基本一致,逆向so查看到加入了一些检查逻辑

代码:

jstring __fastcall fuck(JNIEnv *env, jclass jcls, jstring str_)
{
......

  if ( !str_ )
    return 0;
  src = (unsigned __int8 *)_JNIEnv::GetStringUTFChars(env, str_, 0);
  v20 = "REAL";
  clazz = _JNIEnv::FindClass(env, "android/os/Build");
  fieldID = _JNIEnv::GetStaticFieldID(env, clazz, "FINGERPRINT", "Ljava/lang/String;");
  StaticObjectField = (_jstring *)_JNIEnv::GetStaticObjectField(env, clazz, fieldID);
  if ( function_check_tracerPID()
    || system_getproperty_check()
    || (StringUTFChars = (char *)_JNIEnv::GetStringUTFChars(env, StaticObjectField, 0), strstr(StringUTFChars, "aosp")) )
  {
    v20 = "FAKE";
  }
  strcat((char *)src, v20);

  obj = (_jobject *)j_o0OoOOOO(env, src);
  Class = _JNIEnv::FindClass(env, "java/security/MessageDigest");
  methodID = _JNIEnv::GetStaticMethodID(env, Class, "getInstance", "(Ljava/lang/String;)Ljava/security/MessageDigest;");
  v4 = j_o0OoOOOO(env, "MD5");
  v14 = _JNIEnv::CallStaticObjectMethod(env, Class, methodID, v4);
  v13 = _JNIEnv::GetMethodID(env, Class, "digest", "([B)[B");
  v12 = _JNIEnv::FindClass(env, "java/lang/String");
  v11 = _JNIEnv::GetMethodID(env, v12, "getBytes", "()[B");
  v10 = _JNIEnv::CallObjectMethod(env, obj, v11);
  array = (_jbyteArray *)_JNIEnv::CallObjectMethod(env, v14, v13, v10);
  ByteArrayElements = _JNIEnv::GetByteArrayElements(env, array, 0);
  for ( i = 0; i <= 15; ++i )
    sprintf((char *)&v27[i], "%02x", (unsigned __int8)ByteArrayElements[i]);
  v26 = (char *)j_ll11l1l1ll(src);
  strcat(v26, (const char *)v27);
  v6 = j_o0OoOOOO(env, (const unsigned __int8 *)v26);
  _JNIEnv::ReleaseStringUTFChars(env, str_, src);
  free(v26);
  return v6;
}

从这里可以看到,增加了一个检查system_getproperty_checkstrstr(StringUTFChars, "aosp"),如果满足条件就会把 REAL 改为 FAKE,追加到字符串后面,那么就怎么都不会成功得到正确结果了

就不会进入到if块中;方案一是strcat的入参,让第二个参数传入时永远是REAL

方案一代码:

function main() {
    Java.perform(function () {
        hookCheck()
        var MainActivityHandler = Java.use('com.roysue.easyso1.MainActivity')

        for (var i = 87650; i <= 87700; i++) {
            var str = i + ""
            var ret = MainActivityHandler.Sign(str)
            if (i % 1000 == 0) {
                console.log("now is", str);
            }
            //console.log(ret)
            if (ret == "57fdeca2cac0509b2e9e5c52a5b573c1608a33ac1ffb9e8210d2e129557e7f1b") {
                console.log("find it : " + str)
                break
            }
        }
        
        console.log("end : ")
    })

}

function hookCheck() {
    var lib_hanlder = Process.findModuleByName("libroysue.so");
    console.log("lib_handler: " + lib_hanlder)
    
    if (lib_hanlder) {
        var addr_hook = lib_hanlder.base.add(0x00037226 + 0x1)
        
        Interceptor.attach(addr_hook,{
            onEnter: function(args) {
                console.log(" === hook before")
                console.log("=== r1:" + this.context.r1.readCString())
                Memory.protect(this.context.r1, 1024, 'rw-')
                this.context.r1.writeUtf8String("REAL")
                console.log("=== r1:" + this.context.r1.readCString())
            },
            onLeave:function(retVal) {
                console.log(" === hook after: ")
                //print_dump(retVal, 128)
                console.log("=== after r1:" + this.context.r1.readCString())

            }
        })
    }
}

setTimeout(main, 2000)

关键汇编代码

.text:00037220 24 91                         STR             R1, [SP,#0xD8+var_48]
.text:00037222 26 98                         LDR             R0, [SP,#0xD8+var_40]   ; char *
.text:00037224 24 99                         LDR             R1, [SP,#0xD8+var_48]   ; char *
.text:00037226 FC F7 00 ED                   BLX             strcat
这里的 0x00037226 就是 strcat 对应的偏移地址,其实也可以hook 0x00037224,结果是一样的(hook的这一行相当于是执行后进入onEnter)

日志:

 === hook before
=== r1:FAKE
=== r1:REAL
 === hook before
=== r1:REAL
=== r1:REAL
 === hook before                                                                           
=== r1:REAL
=== r1:REAL
 === hook before
=== r1:REAL
=== r1:REAL
 === hook before
=== r1:REAL
=== r1:REAL
find it : 87654
end : 

从日志上课 onLeave没执行,原因是这里不是一个标准的函数特征,所以没有入栈出栈逻辑,所以就onLeave没执行

与【Android逆向】破解看雪test3.apk方案一相似的内容:

【Android逆向】破解看雪test3.apk方案一

1. test3.apk 安装到手机 2. 发现其实际逻辑和之前的test2.apk基本一致,逆向so查看到加入了一些检查逻辑 代码: jstring __fastcall fuck(JNIEnv *env, jclass jcls, jstring str_) { ...... if ( !str

【Android逆向】破解看雪test3.apk方案二

方案二就是要hook那三个条件,不让追加字符串变成false v20 = "REAL"; clazz = _JNIEnv::FindClass(env, "android/os/Build"); fieldID = _JNIEnv::GetStaticFieldID(env, clazz, "FIN

【Android逆向】破解看雪 test1.apk

1. 获取apk,并安装至手机 apk 获取地址: https://www.kanxue.com/work-task_read-800624.htm adb install -t test1.apk # 这个apk必须加-t ,否则会报错 2. 只有一个输入框,随便输入内容,提示壮士继续加油 3.

【Android逆向】破解看雪9月算法破解第一题

1. 安装apk到手机 2. 随意输入账号和密码,点击register,报错crackme1:ERROR 3. 将apk拖入到jadx中进行观察 public native String register(String str); static { System.loadLibrary("nativ

【Android逆向】破解看雪9月算法破解第二题

1. apk安装到手机,一样的界面,随便输入一样的报错 2. apk拖入到jadx重看看 public native String sha1(String str); static { System.loadLibrary("native-lib"); } /* JADX INFO: Access

【Android逆向】破解看雪9月算法破解第三题

这题的目标是算法还原,并写出注册机 1. 9月份算法第一题.apk 安装到手机 2. 随意输入账号密码,提示错误 3. apk拖入到jadx中 public native boolean register(String str, String str2); static { System.loadL

【Android逆向】破解黑宝宝apk,绕过签名校验

这是52pojie的一道题,实现输入任何密码都可以登录成功 他知道你最近在学习Android逆向 他想在游戏上线前让你测试一下他新加的签名验证是否能防住别人的破解。 下面是李华编写的黑宝宝apk 链接:https://pan.baidu.com/s/1h6pX2ARE3qtiKiYbcnJ-3g 密

【Android逆向】frida 破解 jwxdxnx02.apk

apk 路径: https://pan.baidu.com/s/1cUInoi 密码:07p9 这题比较简单,主要是用于练习frida 1. 安装apk到手机 需要输入账号密码 2. 使用jdax 查看apk package hfdcxy.com.myapplication; import andr

[Android逆向]Exposed 破解 jwxdxnx02.apk

使用exposed 遇到了一些坑,这里记录一下 源码: package com.example.exposedlesson01; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.X

[Android 逆向]frida 破解 切水果大战原版.apk

1. 手机安装该apk,运行,点击右上角礼物 提示 支付失败,请稍后重试 2. apk拖入到jadx中,待加载完毕后,搜素失败,找到疑似目标类MymmPay的关键方法payResultFalse 4. adb logcat 或者androidstudio 查看该进程的日志,发现以下日志 com.mf