安卓逆向 IDA和frida调试回忆

admin 2025年6月20日20:44:03评论17 views字数 14063阅读46分52秒阅读模式

0x1 基础准备

  1.先去攻防世界:下载目标easy-so题目的文件https://adworld.xctf.org.cn/media/file/task/456c1dab04b24036ba1d6e32a08dc882.apk

  2.工具:雷电模拟器、NP管理器、IDA、frida、deepseek。

  3.本文目的,每次小菜鸟隔好久再来弄就忘记怎么操作,这个干脆把常用的工具步骤记得详详细细的,温故而知新。

  4.向deepseek提问,从简洁到复杂,我要干什么?-》我在干什么?遇到什么问题?,如果解决方式不是自己想要的,告诉它以XX的方式干这个事情。

  5.注意事项:

1)、雷电模拟器要开启root、硬盘可写入、开发者模式,最好不要有第三方root程序,防止因为未知原因干扰root权限调用

2)、ida和frida调试程序时要上传对应版本的服务端,连接不上模拟器可以通过端口转发,ip的方式进行连接。

  6.逆向思维:

1)、字符串a经过过程1、2、3变成b,现在已知最终b要等于xxx,如果反推a?倒着看从3个步骤开始,如果前面是加,那我推回去就是减,如果前面是第一个字符交换,我推回去就是第二个字符与第一个字符交换,这里会发现这个过程正推逆推都一样,所以可以直接复用这个算法,异或和这个类似,两次异或就还原了。

2)、还有一种情况a经过n多种算法变成b,直接推回去很难,但是字符串比较短,例如只有4位是变化的,那么可以尝试爆破法,复用程序中的算法,穷举的方式比较判断得到输入的值。

0x2 分析java层代码

  1.使用np管理器的安装包提取功能,提取安装包。

安卓逆向  IDA和frida调试回忆

  2.然后定位到apk文件,点查看

安卓逆向  IDA和frida调试回忆

  3.打开apk,可以看到有一个输入框,有一个check按钮,随便输入123,点击check按钮提示验证失败。

安卓逆向  IDA和frida调试回忆

  4.回到np管理器,发起新搜索,搜索“验证失败”字符串

安卓逆向  IDA和frida调试回忆

1)、定位到如下的smali代码

 复制代码 隐藏代码
    .line 28
 :cond_26
 iget-object v2, p0, Lcom/testjava/jack/pingan2/MainActivity$1;->this$0:Lcom/testjava/jack/pingan2/MainActivity;

 const-string v3, "验证失败!"

 invoke-static {v2, v3, v4}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

 move-result-object v2

 invoke-virtual {v2}, Landroid/widget/Toast;->show()V

2)、向上翻可以看到关键跳前面的函数CheckString

 复制代码 隐藏代码
    .line 22
    .local v1, "strIn":Ljava/lang/String;
 invoke-static {v1}, Lcom/testjava/jack/pingan2/cyberpeace;->CheckString(Ljava/lang/String;)I

 move-result v2

 if-ne v2, v4, :cond_26

3)、再往上翻是onclick函数,也就说我们输入内容,单击check按钮后会进入这个函数,然后通过CheckString校验我们输入的字符串是否正确。

 复制代码 隐藏代码
# virtual methods
.method public onClick(Landroid/view/View;)V

  5.选择这个函数,点三个点的地方就能跳转到函数声明处,然后看到了native关键字,说明要去so层才能看到代码。

安卓逆向  IDA和frida调试回忆
 复制代码 隐藏代码
# classes.dex
.class publicLcom/testjava/jack/pingan2/cyberpeace;
.superLjava/lang/Object;
.source"cyberpeace.java"

# direct methods
.method static constructor <clinit>()V
    .registers 1

    .prologue
    .line 9
 const-string v0, "cyberpeace"

 invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

    .line 10
 return-void
.end method

.method public constructor <init>()V
    .registers 1

    .prologue
    .line 7
 invoke-direct {p0}, Ljava/lang/Object;-><init>()V

 return-void
.end method

.method public static native CheckString(Ljava/lang/String;)I
.end method

  6.点np管理器右上角的三个点可以将smali代码转换为java代码,因为这里java层代码没什么可分析的,所以java层的分析到此为止了。

安卓逆向  IDA和frida调试回忆
 复制代码 隐藏代码
//
// Decompiled by Jadx (from NP Manager)
//
package com.testjava.jack.pingan2;

import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.Toast;

classMainActivity$1 implementsOnClickListener {
final/* synthetic */ MainActivity this$0;

public void onClick(View view) {
if (cyberpeace.CheckString(((EditText) this.this$0.findViewById(2131165233)).getText().toString()) == 1) {
            Toast.makeText(this.this$0"验证通过!"1).show();
        } else {
            Toast.makeText(this.this$0"验证失败!"1).show();
        }
    }

    MainActivity$1(MainActivity mainActivity) {
this.this$0 = mainActivity;
    }
}

0x3 so函数分析

  1.回到np管理器,找到apk文件这次还是点查,进入到lib目录(存放so文件),因为这里用的是雷电模拟器64位,所以选择x86_64位的so文件。ida安装在我们的win系统上,所以选左边文件,长按可以添加到右边,长按右边可以添加到左边,右边的目录实际映射到本机的。

安卓逆向  IDA和frida调试回忆

  2.使用雷电模拟器自带的文件夹共享功能,打开电脑文件夹就能找到那个so文件了。

安卓逆向  IDA和frida调试回忆

  3.使用64位 ida加载so文件,找到CheckString函数,按F5就会出现伪代码

安卓逆向  IDA和frida调试回忆
 复制代码 隐藏代码
_BOOL8 __fastcall Java_com_testjava_jack_pingan2_cyberpeace_CheckString(__int64 a1, __int64 a2, __int64 a3)
{
 const char *v3; // r14
  size_t v4; // rax
 int v5; // r15d
  unsigned __int64 v6; // r12
  char *v7; // rax
  char *v8; // r13
  bool v9; // cc
  size_t v10; // r12
  size_t v11; // rbx
  char v12; // al
  char v13; // al
  size_t v14; // rbx
  char v15; // al

  v3 = (const char *)(*(__int64 (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)a1 + 1352LL))(a1, a3, 0LL);
  v4 = strlen(v3);
  v5 = v4;
  v6 = (__int64)((v4 << 32) + 0x100000000LL) >> 32;
  v7 = (char *)malloc(v6);
  v8 = v7;
  v9 = v6 <= v5;
  v10 = v6 - v5;
 if ( v9 )
    v10 = 0LL;
  memset(&v7[v5], 0, v10);
  memcpy(v8, v3, v5);
 if ( strlen(v8) >= 2 )
  {
    v11 = 0LL;
    do
    {
      v12 = v8[v11];
      v8[v11] = v8[v11 + 16];
      v8[v11++ + 16] = v12;
    }
    while ( strlen(v8) >> 1 > v11 );
  }
  v13 = *v8;
 if ( *v8 )
  {
    *v8 = v8[1];
    v8[1] = v13;
 if ( strlen(v8) >= 3 )
    {
      v14 = 2LL;
      do
      {
        v15 = v8[v14];
        v8[v14] = v8[v14 + 1];
        v8[v14 + 1] = v15;
        v14 += 2LL;
      }
      while ( strlen(v8) > v14 );
    }
  }
 return strcmp(v8, "f72c5a36569418a20907b55be5bf95ad") == 0;
}

  4.可以看到大概就是v8经过一系列运算,最后和f72c5a36569418a20907b55be5bf95ad比较,相等就是验证通过,如果是原来我需要一行行阅读代码,现在借助deepseek吧,试了试分析的结果,我拿去输入验证失败。

 复制代码 隐藏代码
一、变换流程分析
函数对输入字符串 v3 进行两次变换:

1. 第一阶段变换(位置交换)
操作:交换 v8[i] 和 v8[i+16]0 ≤ i < len/2)。

效果:将字符串的前16个字符与后16个字符交换位置。

示例:
输入字符串 ABCDEFGHIJKLMNOPQRSTUVWXYZ123456(32字符)
交换后变为 QRSTUVWXYZ123456ABCDEFGHIJKLMNOP。

2. 第二阶段变换(字符对交换)
操作:

交换 v8[0] 和 v8[1]

从索引2开始,每两个字符交换一次(swap(v8[2]↔v8[3], v8[4]↔v8[5], ...)。

效果:将字符串的字符对顺序打乱。

示例:
输入字符串 123456
交换后变为 214365

最终正确输入
59da5efbb55b70902a81496563a5c27f

  5.deepseek的分析看起来很专业,为什么不对呢?先记下deepseek的分析,手动模拟一下变换过程。

1)、将字符串的前16个字符与后16个字符交换位置

 复制代码 隐藏代码
f72c5a36569418a20907b55be5bf95ad

f72c5a36569418a2
0907b55be5bf95ad

0907b55be5bf95adf72c5a36569418a2

2)、第二阶段变换:字符对交换,每两个字符交换一次

 复制代码 隐藏代码
09
07
b5
5b
e5
bf
95
ad
f7
2c
5a
36
56
94
18
a2

90705bb55efb59da7fc2a5636549812a

3)、最终得到flag:90705bb55efb59da7fc2a5636549812a,拿去验证通过。

4)、这里说明一下,是输入按照这个步骤变换成输出,为什么我输出作输入可以模拟直接这样换,因为第一排和第二排交换,再次一次交换就换回了,第一个字符和第二个字符交换,再次一次也是换回了,算法都一样。

  6.我以为deepseek在手就能通杀简单的CTF,万万没想到ai逻辑分析正确,代码和输出结果不对,但凡我会写代码都不会吃这样的亏,流下来不会算法的泪水,还好算法不复杂,靠大脑就能手动计算出来。

安卓逆向  IDA和frida调试回忆

0x4 使用IDA调试so文件

  1.打开cmd窗口,adb devices,adb push android_x64_server /sbin,然后报错了,权限不足,这种问题真烦人,使用批量多开器,新建一个模拟器(为了重置模拟器环境排除干扰),打开root和磁盘可读写功能。

安卓逆向  IDA和frida调试回忆

  2.然后问问deepseek怎么解决。

 复制代码 隐藏代码
adb root          # 获取 Root 权限
adb remount       # 自动重新挂载 /system 为可写
adb push android_x64_server /system/bin/
adb shell chmod +x /system/bin/android_x64_server
 复制代码 隐藏代码
实际执行结果
C:MySofewareIDA_Pro_7.7dbgsrv>adb root
restarting adbd as root

C:MySofewareIDA_Pro_7.7dbgsrv>adb remount
remount succeeded

C:MySofewareIDA_Pro_7.7dbgsrv>adb push android_x64_server /system/bin/
android_x64_server:1 file pushed, 0 s...d. 54.8 MB/s (1230968 bytes in0.021s)

C:MySofewareIDA_Pro_7.7dbgsrv>adb shell chmod +x /system/bin/android_x64_server

  3.启动android server,然后输入adb forward tcp:23946 tcp:23946命令,将手机上的23946窗口,转发到我们电脑本地的23946端口,adb shell am start -n com.testjava.jack.pingan2/.MainActivity。

 复制代码 隐藏代码
adb shell /system/bin/android_x64_server &  //& 表示后台运行。

C:MySofewareIDA_Pro_7.7dbgsrv>adb shell /system/bin/android_x64_server &
IDA Android x86 64-bit remote debug server(ST) v7.7.27. Hex-Rays (c) 2004-2022
Listening on 0.0.0.0:23946...

C:UsersLENOVODesktop>adb shell am start -n com.testjava.jack.pingan2/.MainActivity
Starting: Intent { cmp=com.testjava.jack.pingan2/.MainActivity }

  4.使用F2在IDA中下上断点,颜色会变红,然后点击菜单栏debugger->Attach to process...,找到对应报名就成功附加调试了。

安卓逆向  IDA和frida调试回忆

  5.F9运行,到app输入f72c5a36569418a20907b55be5bf95ad, 开始单步调试走,重点观察v8的变换过程。

1)、首先看第一个循环代码

 复制代码 隐藏代码
  memcpy(v8, v3, v5);//这一行v8开始将我输入的值复制过去了

      v12 = v8[v11];
      v8[v11] = v8[v11 + 16];
      v8[v11++ + 16] = v12;
do
    {
      v12 = v8[v11];
      v8[v11] = v8[v11 + 16];
      v8[v11++ + 16] = v12;
    }
    while ( strlen(v8) >> 1 > v11 );

        //一轮循环
          f72c5a36569418a20907b55be5bf95ad
          072c5a36569418a2f907b55be5bf95ad

        //二轮循环
          092c5a36569418a2f707b55be5bf95ad

        //最后一轮交换后
          0907b55be5bf95adf72c5a36569418a2

        //经过反复调试,可以看出这里就是交换前16位和后16位的字符,逐一交换

2)、在继续往下走

 复制代码 隐藏代码
  v13 = *v8;
    *v8 = v8[1];
    v8[1] = v13;

        //这里可以看出是将第一个字符和第二个字符交换,if语句都是干扰

        v14 = 2LL;
      do
      {
        v15 = v8[v14];
        v8[v14] = v8[v14 + 1];
        v8[v14 + 1] = v15;
        v14 += 2LL;
      }
      while ( strlen(v8) > v14 );
        //这里下标从2开始就是从第三个字符开始交换,+1可以看出是第三个字符和后一个字符交换,重复这个过程

        //结束循环时v8的值为:90705bb55efb59da7fc2a5636549812a

 return strcmp(v8, "f72c5a36569418a20907b55be5bf95ad") == 0;
        //最后这里就是判断是否相等了。

3)、这里说明一下,IDA调试命令和OD差不多,F2下断点,F8单步运行,F4运行到鼠标指定的行,鼠标放在v8上面就可以看到具体内容了。

安卓逆向  IDA和frida调试回忆

  6.告诉deepseek:使用java编写一段代码,计算“f72c5a36569418a20907b55be5bf95ad”每两位交换一次,最后将前16位与后16位交换后的值。

 复制代码 隐藏代码
package test;

publicclassTest {

publicstaticvoidmain(String[] args) {
String original = "f72c5a36569418a20907b55be5bf95ad";

// 第一步:每两位交换一次
String swapped = swapEveryTwoChars(original);
System.out.println("每两位交换后: " + swapped);

// 第二步:交换前16位和后16位
String result = swapFirstAndSecondHalf(swapped);
System.out.println("最终结果: " + result);
    }

// 每两位交换一次
publicstaticStringswapEveryTwoChars(String str) {
        char[] chars = str.toCharArray();
for (int i = 0; i < chars.length - 1; i += 2) {
            char temp = chars[i];
            chars[i] = chars[i + 1];
            chars[i + 1] = temp;
        }
returnnewString(chars);
    }

// 交换前16位和后16位
publicstaticStringswapFirstAndSecondHalf(String str) {
if (str.length() != 32) {
thrownewIllegalArgumentException("输入字符串长度必须为32位");
        }
String firstHalf = str.substring(016);
String secondHalf = str.substring(16);
return secondHalf + firstHalf;
    }
}

每两位交换后: 7fc2a5636549812a90705bb55efb59da
最终结果: 90705bb55efb59da7fc2a5636549812a

  7.我算是发现了,deepseek给的分析过程合情合理,代码也比较准确,但是给不了你正确的值,需要你自己动手跑一遍,deepseek会惩罚不想动手的人。

安卓逆向  IDA和frida调试回忆

0x5 使用frida hook so中的函数

  1.先看一下我系统里面frida的版本,然后下载对应版本的服务端去https://github.com/frida/frida/releases/tag/16.6.6:frida-server-16.6.6-android-x86_64.xz

 复制代码 隐藏代码
C:UsersLENOVO>frida --version
16.6.6

  2.将下载sever解压,重命名为frida-server(只是为了名称短点,改成别的都行),传到模拟器上运行,提示权限不足就加上su命令。

 复制代码 隐藏代码
adb push frida-server /data/local/tmp/
adb shell chmod +x /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server &

  3.我告诉deepseek你给我hook v8的返回值,一直提示找不到Java_com_testjava_jack_pingan2_cyberpeace_CheckString函数,自定义函数不能hook吗?最后选择去hook strcmp这个库函数。

 复制代码 隐藏代码
Java.perform(function() {
// 1. 查找strcmp函数
const strcmp = Module.findExportByName(null"strcmp");

if (!strcmp) {
console.log("[-] 找不到strcmp函数");
return;
    }

console.log("[+] strcmp函数地址: " + strcmp);

// 2. Hook strcmp函数
Interceptor.attach(strcmp, {
onEnterfunction(args) {
// 读取两个比较字符串
const str1 = args[0].readUtf8String();
const str2 = args[1].readUtf8String();

// 检查是否是我们要找的比较(与目标字符串比较)
const targetStr = "f72c5a36569418a20907b55be5bf95ad";
if (str2 === targetStr) {
console.log("n[+] 捕获到v8字符串比较:");
console.log("变换后的字符串(v8):", str1);
console.log("目标字符串:", str2);

// 保存到全局变量以便在onLeave中使用
this.isTargetComparison = true;
this.v8str = str1;
            }
        },
onLeavefunction(retval) {
if (this.isTargetComparison) {
console.log("比较结果:", retval.toInt32() === 0 ? "匹配" : "不匹配");
console.log("完整的v8字符串内容:"this.v8str);

// 如果你想强制返回匹配结果,可以取消下面注释
// retval.replace(0); // 0表示匹配
            }
        }
    });

console.log("[+] strcmp hook已安装,等待捕获v8字符串...");
});

  4.这里直接 -U一直显示等待连接,然后还是选择老办法adb转发端口,然后使用ip地址连接模拟器。

 复制代码 隐藏代码
C:UsersLENOVODesktop>frida -H 127.0.0.1:27042 -f com.testjava.jack.pingan2 -l
 hook.js
     ____
    / _  |   Frida 16.6.6 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
/_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to 127.0.0.1:27042 (id=socket@127.0.0.1:27042)
Spawned `com.testjava.jack.pingan2`. Resuming main thread!
[Remote::com.testjava.jack.pingan2 ]-> [+] strcmp函数地址: 0x7ffff6726020
[+] strcmp hook已安装,等待捕获v8字符串...

[+] 捕获到v8字符串比较:
变换后的字符串(v8): 90705bb55efb59da7fc2a5636549812a
目标字符串: f72c5a36569418a20907b55be5bf95ad
比较结果: 不匹配
完整的v8字符串内容: 90705bb55efb59da7fc2a5636549812a

  5.函数是静态注册的,并且从IDA中可以到已导出,为什么不能hook呢,deepseek说可能延迟加载了,所以我得这样问deepseek:使用Frida Hook监控V8值变化(处理SO延迟加载,函数已导出)

安卓逆向  IDA和frida调试回忆

  6.最终得到如下脚本,其中目标SO文件名、目标导出函数名要根据实际情况修改(so文件名就是apk解压出来的那个,不要改动,目标函数函数要写全,IDA里面一般识别到的java开头的那个就是)。

 复制代码 隐藏代码
Java.perform(function() {
// 配置参数
const config = {
targetSo"libcyberpeace.so",      // 目标SO文件名
targetFunction"Java_com_testjava_jack_pingan2_cyberpeace_CheckString",     // 目标导出函数名
targetString"f72c5a36569418a20907b55be5bf95ad"// 用于识别比较的目标字符串
maxRetries10,                    // 最大重试次数
retryInterval1000// 重试间隔(ms)
    };

console.log(`[+] 开始Hook目标函数: ${config.targetSo}!${config.targetFunction}`);

// 1. 等待SO加载并获取函数地址
let retryCount = 0;
let targetFuncAddress = null;

functionwaitAndHook() {
const mod = Process.findModuleByName(config.targetSo);

if (mod) {
console.log(`[+] 模块已加载: ${config.targetSo} @ ${mod.base}`);

// 获取导出函数地址
            targetFuncAddress = Module.getExportByName(config.targetSo, config.targetFunction);

if (targetFuncAddress) {
console.log(`[+] 找到导出函数 ${config.targetFunction} @ ${targetFuncAddress}`);
setupHooks();
            } else {
console.log(`[-] 在${config.targetSo}中未找到导出函数${config.targetFunction}`);
            }
        } elseif (retryCount < config.maxRetries) {
            retryCount++;
console.log(`[.] 等待模块加载 (${retryCount}/${config.maxRetries})...`);
setTimeout(waitAndHook, config.retryInterval);
        } else {
console.log("[-] 模块加载超时");
        }
    }

// 2. 设置Hook
functionsetupHooks() {
let v8Ptr = null;

// Hook目标函数
Interceptor.attach(targetFuncAddress, {
onEnterfunction(args) {
console.log("n=== 函数调用开始 ===");

// 保存v8指针到上下文
this.v8 = v8Ptr;
                v8Ptr = null;

// 获取输入字符串
try {
const inputStr = Java.vm.getEnv().getStringUtfChars(args[2], null).readCString();
console.log(`输入字符串: ${inputStr}`);

if (this.v8) {
console.log(`v8地址: ${this.v8}`);
// 读取初始值(可能尚未初始化)
// console.log(`v8初始值: ${this.v8.readCString()}`);
                    }
                } catch (e) {
console.log(`获取输入字符串错误: ${e}`);
                }
            },
onLeavefunction(retval) {
console.log("n=== 函数调用结束 ===");

if (this.v8) {
try {
const finalValue = this.v8.readCString();
console.log(`v8最终值: ${finalValue}`);
console.log(`返回值: ${retval}`);

// 可选:强制修改返回值
// if (finalValue === config.targetString) {
//     retval.replace(1);
// }
                    } catch (e) {
console.log(`读取v8值错误: ${e}`);
                    }
                }
            }
        });

// Hook strcmp获取最终比较
const strcmpFunc = Module.findExportByName(null"strcmp");
if (strcmpFunc) {
Interceptor.attach(strcmpFunc, {
onEnterfunction(args) {
try {
const compareStr = args[1].readCString();
if (compareStr === config.targetString) {
this.isTargetCompare = true;
console.log(`[strcmp] 比较值: ${args[0].readCString()}`);
                        }
                    } catch (e) {
console.log(`strcmp读取错误: ${e}`);
                    }
                },
onLeavefunction(retval) {
if (this.isTargetCompare) {
console.log(`[strcmp] 比较结果: ${retval}`);
                    }
                }
            });
        }

// Hook memcpy监控数据复制
const memcpyFunc = Module.findExportByName(null"memcpy");
if (memcpyFunc) {
Interceptor.attach(memcpyFunc, {
onEnterfunction(args) {
if (this.v8 && args[0].equals(this.v8)) {
try {
console.log(`[memcpy] 复制到v8: ${args[1].readCString()}`);
                        } catch (e) {
console.log(`memcpy读取错误: ${e}`);
                        }
                    }
                }
            });
        }

console.log("[+] Hook安装完成,等待函数调用...");
    }

// 开始执行
waitAndHook();
});

输出:
[.] 等待模块加载 (1/10)...             
[.] 等待模块加载 (2/10)...
[.] 等待模块加载 (3/10)...
[+] 模块已加载: libcyberpeace.so @ 0x7fff55510000
[+] 找到导出函数 Java_com_testjava_jack_pingan2_cyberpeace_CheckString @ 0x7fff5
5510800
[+] Hook安装完成,等待函数调用...ace.so!Java_com_testjava_jack_pingan2_cyberpeac
e_CheckString
=== 函数调用开始 ===
输入字符串: f72c5a36569418a20907b55be5bf95ad
[strcmp] 比较值: 90705bb55efb59da7fc2a5636549812a
[strcmp] 比较结果: 0xffffffd3

=== 函数调用结束 ===

  7.这里so文件加载好像必须是我点check按钮后才会加载。

0x6 总结

  还是得有点基础,用起deepseek才会得心应手,不然给我一个代码我都不知道怎么修改,怎么定制我要的功能。

原文始发于微信公众号(逆向有你):安卓逆向 -- IDA和frida调试回忆

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月20日20:44:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   安卓逆向 IDA和frida调试回忆https://cn-sec.com/archives/4185503.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息