惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
V
V2EX
博客园 - 【当耐特】
WordPress大学
WordPress大学
爱范儿
爱范儿
美团技术团队
宝玉的分享
宝玉的分享
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
小众软件
小众软件
量子位
Hugging Face - Blog
Hugging Face - Blog
B
Blog RSS Feed
Recorded Future
Recorded Future
Engineering at Meta
Engineering at Meta
雷峰网
雷峰网
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
H
Hackread – Cybersecurity News, Data Breaches, AI and More
腾讯CDC
大猫的无限游戏
大猫的无限游戏
Jina AI
Jina AI
博客园 - 叶小钗
GbyAI
GbyAI
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
F
Full Disclosure
G
Google Developers Blog
D
Docker
T
Tailwind CSS Blog
C
Check Point Blog
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
T
The Blog of Author Tim Ferriss
B
Blog
博客园 - 三生石上(FineUI控件)
博客园 - Franky
H
Help Net Security
MyScale Blog
MyScale Blog
U
Unit 42
D
DataBreaches.Net
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
I
InfoQ
阮一峰的网络日志
阮一峰的网络日志
The GitHub Blog
The GitHub Blog
L
LangChain Blog
有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
Microsoft Security Blog
Microsoft Security Blog

博客园 - GKLBB

软件研发 --- AI模型 之 图片转xlsx 软件神器 --- ctf靶场 之 pwn.college 术语俗话 --- 什么是加密狗 软件神器 --- 自动电脑锁屏软件 软件研发 --- 网络安全 之 putty生成无密码登录密钥 软件神器 --- 视频剪辑 之 Avidemux MP4Joiner Shotcut 软件神器 --- 视频格式转化 之 handbrake 软件研发 --- 经验之谈 这个是什么图标,经常看到 软件研发 --- 术语俗话 之 多模态 术语俗话 --- 什么是大数据开发 软件研发 --- 术语俗话 之 什么是边缘计算 软件研发 --- 应知应会 之 什么是云计算开发 应知应会 --- 如何不装软件查看网速 常见问题解决 --- 360拦截接触 常见问题解决 --- 加入会议摄像头无法打开 网络安全 --- CTF打靶 之 ZIP伪加密 → Robot36慢扫电视 → 二维码补齐 → DeepSound隐写 → GPG解密 → Base64图片 → SilentEye隐写 软件研发 --- 应知应会 之 无错误的闪退如何解决 软件研发 --- 应知应会 之 为什么别人的软件如此复杂我的如此简单 网络安全 --- 应知应会 之 什么是旁站 应知应会 --- 如何查询备案 软件神器 --- 格式转化 之 jpg 2 svg 网络安全 --- CTF打靶 之 flag搜索 软件神器 --- 互联网测速 之 软件神器 --- 局域网测速 之 iperf 常见问题解决 --- 模拟器USG6000打开后,启动设备失败,错误40 软件研发 --- AI网络 之 ensp配置生成 软件研发 --- AI编程 之 极简流程 软件研发 --- AI生图产品比较 常见问题解答 --- 为什么我的服务一直被人DDOS 软件研发 --- 开发万能格式转化工具 网站神器 --- 在线格式转化 之 文档转md 术语俗话 --- 什么是云电脑 常见问题解决 --- 如何在没有安装杀毒软件的情况下知道这个文件是不是牧马 常见问题解决 --- Win10下VMware 17安装VMware Tools选项灰色/失效解决办法 常见问题解决 --- 云电脑报错 :PAGE FAULT IN NONPAGED AREA 记一次牧马的发现 人生感悟 --- 为什么我们生活中同一件事有多个品牌,他们到底有什么区别 软件运维 --- 云电脑安装打印机 常见问题解决 --- 网络打印默认端口 常见问题解决 --- 京瓷打印云电脑无法设置双面打印 软件研发 --- 网络安全 之 brupsuite如何设置上游袋里 术语俗话 --- 什么是同步和异步 我的目标 软件研发 --- dify配置 之 markword转word带有简单样式的方法 软件研发 --- 接口文档格式 常见问题 --- dify 的 deepseek是旧模型版本 OWASP 非营利性开源社区 计算机标准化组织 术语俗话 --- POSIX 就是 Unix 世界的"普通话",大家说同一种语言就能互相理解。 我的数字生活唯一选择 软件开发 --- 安卓开发 之 命名空间隔离 术语俗话 --- 页面对齐、 跨页 计算机的哪些人 --- 社交之王 马克·扎克伯格 计算机的哪些人 --- 重新定义新能源 之 埃隆·马斯克 软件研发 --- AI生成ppt word excel pdf的开发关键 软件研发 --- AI应用开发 之 AI生成Word 人生感悟 --- 致可悲的人 软件研发 --- pdf 表格图片 转 excel 常见问题解决 --- 装有系统的固态硬盘错误 人生感悟 --- 什么是行业黑话 术语俗话 --- Kubernetes 术语俗话 --- 什么是DBI,和hook什么区别 答疑解惑 --- 为什么苹果手机电池不允许拆卸 代码可视化技术 术语俗话 --- Wrap 函数 人生感悟 --- 逆向工程为什么十分枯燥且无聊 --- 这里引用一句逆向工程核心原理的话 人生感悟 --- 为什么干活时不见同事,活干完了就来了 软件研发 --- AI应用研发 之 提炼提示词 软件研发 --- AI应用开发 之 AI生成PPT最佳方案 基于屏幕-摄像头的单向数据传输方案设计 俗语俗话 --- 纯虚函数 硬件研发 --- 产品介绍 之 AX6 硬件研发 --- 产品大全 之 SUMAVISION CM50X 应知应会 --- 为什么U盘不识别但是还是可以数据恢复回来 应知应会 --- 为什么我删除了一个文件但是还是可以恢复回来 软件研发 --- AI UI设计 之 PC端效果比对 常见问题修复 --- chrome浏览器白屏 应用安全 --- 逆向工程 之 C++类的本质 软件研发 --- AI提示词开发 之 代码注释提示词 dobby反编译 https://www.cnblogs.com/Un1corn/p/18615567 应知应会 --- 手机作为热点,windows电脑临时作为网关,给其他电脑上网 应知应会 --- 大量小文件如何快速迁移 常见问题解决 --- apk安装过程中闪退 应用安全 --- 安卓逆向 之 dobby框架 在线生成 APK 图标工具推荐 一个开源库 术语俗话 --- 什么是软件即服务 软件神器 --- 常用谷歌插件 应用安全 --- 逆向技巧 之 识别未知函数 人生感悟 --- 为什么两句话可以说明白的事情要500字说明 软件研发 --- Dify 生成 PPT 方案分析 应用安全 --- 逆向技巧 之 IDA未知函数如何识别 https://yuuki.cool/ 应用安全 --- 逆向技巧 之 ELF节(Section) 与 段(Segment) 硬件研发 --- 接口 人生感悟 --- 为什么ld一直爱开会 应用安全 --- 逆向技巧 之 ida反编译yahfa的so和源码的差异化比对
应用安全 --- 逆向技巧 之 IDA和claude反编译缺陷
GKLBB · 2026-04-05 · via 博客园 - GKLBB

主要缺点

1.我认为最大的缺陷是常量值错误,比如打印hello world,但是代没有展示字符串,只有引用的地址,导致反编译失真,解决方法是提前将字符串定义在函数开头的位置,或者直接写入目标引用

比如

// 反编译还原(错误)
static uint32_t dword_4BF8 = 0;           // 未初始化!
// 真实源码(正确)
static uint32_t dword_4BF8 = 0x0100;
实际上它是有默认值的

.data:0000000000004BF8 dword_4BF8 DCD 0x200000 ; DATA XREF: LOAD:00000000000000F8↑o
.data:0000000000004BF8              ; Java_lab_galaxy_yahfa_HookMain_init:loc_153C↑o ...

 这里的解决方法就是将这里的全局变量提前引入方法前定义

 2. AI识别命名相反,解决方法就是引入常量定义并对照源码

// 反编译还原(错误方向)
if (SDKVersion >= 29)
    cur &= ~g_kAccNative;           // ❌ 错误:SDK29+清除kAccNative
if (SDKVersion <= 29)
    cur |=  g_kAccFastInterpreterToInterpreterInvoke; // ❌ 错误

// 真实源码(正确逻辑)
if (SDKVersion >= __ANDROID_API_Q__) {  // SDK29
    access_flags &= ~kAccFastInterpreterToInterpreterInvoke; // 清除fast标志
}
if (SDKVersion <= __ANDROID_API_Q__) {  // SDK<=29
    access_flags |= kAccNative;          // 设置native标志
}
// SDK30+: 不设置kAccNative(会导致查找真实native指针而非entry_point)

3.claude的 jni.h的函数名称识别错误

// 反编译还原(错误)
env->DeleteLocalRef(hookMethod);   // ❌ 删除局部引用   (*(void (__fastcall **)(__int64, __int64))(*(_QWORD *)a1 + 168LL))(a1, a4);
if (backupMethod)
    env->DeleteLocalRef(backupMethod);

// 真实源码(正确)
(*env)->NewGlobalRef(env, hook);   // ✅ 创建全局引用,防止GC回收
if(backup) (*env)->NewGlobalRef(env, backup);

4.内联汇编实现无法识别,只是汇编代码

// 反编译还原(不完整)
__int64 Java_lab_galaxy_xjhook_HookMain_00024Utils_getThread() {
    __int64 v0; // x19  ← 仅注释提示
    return v0;
}

// 真实源码(裸函数+内联汇编)
jlong __attribute__((naked))
Java_lab_galaxy_yahfa_HookMain_00024Utils_getThread(...) {
#if defined(__aarch64__)
    __asm__("mov x0, x19\n" "ret\n");  // x19存储ART Thread*
#elif defined(__arm__)
    __asm__("mov r0, r9\n" "bx lr\n");
#endif
}

影响:反编译工具无法还原裸函数的汇编语义,仅识别出寄存器 x19,但丢失了多架构实现。

5.条件编译丢失,这个不能是缺陷但是也是问题

// 反编译还原(不完整)
bool sub_24C8() {
    return SDKVersion >= 30;  // 仅考虑SDK版本
}

// 真实源码(还考虑架构)
static int shouldVisiblyInit() {
#if defined(__i386__) || defined(__x86_64__)
    return 0;  // x86/x86_64 不需要
#else
    return SDKVersion >= __ANDROID_API_R__;
#endif
}

影响:x86架构下应始终返回0,反编译丢失了架构条件编译信息。

宏条件丢失

// 真实源码:仅 aarch64 需要
#if defined(__aarch64__)
#define NEED_CLASS_VISIBLY_INITIALIZED
#endif

// 反编译还原:无此条件,始终启用
// (因为反编译的二进制本身就是 aarch64,条件编译已展开)

还有全局数组被识别为单个字节,正确的识别特征是

1. 类型信息丢失(最核心缺陷)

C

// 原始代码
struct User {
    char name[32];
    int age;
    float salary;
};

// IDA 反编译后(类型信息严重退化)
int sub_401000(int a1) {
    *(_DWORD *)(a1 + 32) = 0;      // age 变成了偏移计算
    *(float *)(a1 + 36) = 0.0;     // 结构体完全丢失语义
}

2. 变量识别错误

C

// 原始代码
int a = 10;
int b = 20;
int c = a + b;

// IDA 可能合并为
int v1 = 30;  // 常量折叠后变量被合并,语义丢失

常见问题:

  • 局部变量被错误合并
  • 同一内存地址在不同上下文被复用(变量生命周期分析失败)
  • 寄存器变量难以准确还原

3. 间接调用 / 函数指针识别困难

C

// 原始代码
void (*func_ptr)(int) = get_handler();
func_ptr(42);

// IDA 反编译后
((void(__cdecl *)(int))some_var)(42);  // 无法确定实际调用目标
// 甚至可能显示为
CALL dword ptr [eax]  // 直接放弃反编译

4. 控制流还原失真

C

// 原始 switch 语句
switch(x) {
    case 1: do_a(); break;
    case 2: do_b(); break;
    case 3: do_c(); break;
}

// IDA 可能还原为跳转表形式(难以辨认)
if ((unsigned)(x - 1) <= 2)
    (jpt_table[x - 1])();
// 或者变成一堆 goto

5. 字符串与数据类型混淆

C

// 原始代码
const char *msg = "Hello";

// IDA 可能识别为
int v1 = 0x6C6C6548;  // 把字符串当整数处理
int v2 = 0x006F;

6. 编译器优化导致代码变形

内联展开 函数边界消失,代码膨胀 循环展开 循环结构无法还原 SIMD 指令 intrinsics 难以识别 尾调用优化 函数调用变成 JMP 死代码消除 逻辑不完整
优化手段反编译后的问题

C

// 原始循环
for(int i = 0; i < 4; i++)
    sum += arr[i];

// 编译器展开后,IDA 反编译
v1 = arr[0] + arr[1];
v2 = v1 + arr[2];
result = v2 + arr[3];  // 完全看不出是循环

7. 调用约定识别错误

C

// 原始代码(__fastcall)
int __fastcall calc(int a, int b) { return a + b; }

// IDA 误识别为 __cdecl
int calc(int a1) {           // 参数数量错误
    return a1 + some_global; // 把寄存器参数当全局变量
}

8. 面向对象代码还原困难

C

// 原始 C++ 代码
obj->method(arg);

// IDA 反编译(虚表调用变得极其晦涩)
(*(void (__thiscall **)(_DWORD, int))(*(DWORD*)obj + 0xC))(obj, arg);
//  ↑ vtable偏移0xC处的函数,语义完全丢失

9. 全局变量与局部变量混淆

C

// IDA 经常将栈上变量识别为
int v1;                    // 实际上可能是数组或结构体
*(DWORD*)(v1 + 4) = 0;   // 只能看到偏移访问

10. 异常处理(SEH/C++异常)

C

// 原始代码
try {
    risky_operation();
} catch(Exception& e) {
    handle(e);
}

// IDA 反编译后充满编译器运行时调用
__CxxFrameHandler3(...);  // 晦涩难懂的异常框架代码

总结对比

text

原始代码清晰度    ████████████  100%
IDA反编译结果     ████░░░░░░░░   40%~70%(视情况而定)

影响因素:
- 有调试符号(PDB)  → 质量大幅提升
- 开启高优化(O2/O3)→ 质量大幅下降
- 有混淆保护       → 几乎无法阅读

最根本的原因:编译是单向有损压缩过程,语义信息在汇编层面无法完整保留。

一、符号信息丢失类

1.1 函数名丢失 静态函数名完全丢失,以地址命名 setNonCompilable → sub_1B04 1.2 全局变量名丢失 有意义的常量名变为地址标签 kAccCompileDontBother → dword_4BFC 1.3 结构体字段名丢失 偏移量取代字段名 OFFSET_access_flags_in_ArtMethod → dword_4C54 1.4 数组名丢失 数组退化为全局地址 trampoline[9] → byte_4C11 1.5 宏定义丢失 宏展开后无法还原 roundUpToPtrSize(...) → (v5+7) & 0xFFFFFFFFFFFFFFF8 1.6 枚举/常量语义丢失 具名常量变为数字字面量 PROT_READ|PROT_WRITE|PROT_EXEC → 7 1.7 包名/类名变更无法感知 混淆或改名后无从区分 yahfa → xjhook 仅从字符串可见 1.8 注释完全丢失 所有开发者注释消失 // keep a global ref so that hook method would not be GCed → 无
#缺陷类型简要说明本项目实例

二、类型信息丢失类

2.1 返回类型误判 void函数被判为有返回值 void setFlags() → __int64 sub_1DB8() 2.2 参数类型退化 具名JNI类型退化为整数 JNIEnv *env, jobject hook → __int64 a1, __int64 a4 2.3 函数指针类型丢失 typedef的函数指针类型消失 InitClassFunc → __int64(__fastcall*)(_QWORD,_QWORD,_QWORD) 2.4 bool/int混淆 布尔语义丢失 int shouldVisiblyInit() → bool sub_24C8() (反而多了信息) 2.5 有符号/无符号混淆 符号性推断错误 uint32_t access_flags → int v4 / unsigned int v5 拆分 2.6 指针const属性丢失 const修饰符消失 const void *targetMethod → __int64 a1 2.7 数组退化为指针 数组类型信息丢失 unsigned char trampoline[24] → byte_4C08 起始的若干字节 2.8 size_t语义丢失 大小类型退化 size_t trampolineSize → __int64 v2
#缺陷类型简要说明本项目实例

三、控制流失真类

3.1 条件取反 if条件被编译器优化后取反 if (!doBackupAndHook()) → if (sub_1978()) 逻辑反转 3.2 条件合并 多层if被合并为单一复合条件 if(!a||!b){if(f()!=0){err}} → if(a&&b || !f()){ok}else{err} 3.3 fall-through语义丢失 switch的贯穿逻辑变为goto case 27: kAcc=0x2000000; //fall-through → case 27: dword=0x2000000; goto LABEL_8 3.4 goto引入 反编译器用goto还原复杂跳转 源码无goto → 反编译出现 goto LABEL_3/4/8 3.5 提前返回丢失 early return被重构为条件嵌套 if(SDK<24) return; 逻辑被合并进大if块 3.6 循环变量类型变化 循环控制变量类型改变 int i → unsigned int i (影响负数判断)
#缺陷类型简要说明本项目实例

四、函数调用失真类

4.1 JNI调用变为vtable偏移 JNI函数名消失,变为数字偏移 (*env)->GetMethodID(env,...) → (*(_QWORD*)a1+264LL)(a1,...) 4.2 系统调用包装替换 编译器替换为安全版本 memcpy(...) → __memcpy_chk(..., -1) 4.3 宏函数展开 宏调用变为内联表达式 open(...) → __open_2(...) 4.4 errno访问方式变化 全局宏展开为函数调用 strerror(errno) → v0=__errno(); strerror(*v0) 4.5 log返回值被当函数返回值 void函数末尾log的返回值被误用 LOGI(...); //void return → return __android_log_print(...) 4.6 可变参数信息丢失 变参函数原型退化 __android_log_print(int,char*,char*,...) → 参数直接展开
#缺陷类型简要说明本项目实例

五、内存操作失真类

5.1 指针运算语义丢失 有意义的偏移计算变为数字 (char*)method + OFFSET_access_flags → *(a1 + dword_4C54) 5.2 读写宏展开 readAddr/writeAddr宏变为指针解引用 writeAddr(from+OFFSET, val) → *(_QWORD*)&a1[dword_4C58]=v6 5.3 数组下标语义丢失 有意义的下标变为偏移量 trampoline[9] |= offset<<4 → byte_4C11 |= 16*result 5.4 结构体访问退化 结构体字段访问变为原始偏移 method->entry_point → *(a1+48) 5.5 局部变量被合并 两个变量共用同一栈地址 v6/v7 共用 [xsp+8h] 但语义不同
#缺陷类型简要说明本项目实例

六、架构特性丢失类

6.1 naked函数属性丢失 无栈帧函数被误加函数框架 __attribute__((naked)) → 普通函数形式 6.2 内联汇编完全丢失 asm块语义只能部分还原 __asm__("mov x0, x19\nret\n") → __int64 v0; //x19 return v0 6.3 寄存器语义丢失 特殊寄存器用途无法表达 x19=ART线程寄存器 → 仅标注//x19 6.4 栈canary artifact 栈保护代码产生多余伪调用 多出 _ReadStatusReg(TPIDR_EL0) 调用 6.5 SIMD/特殊指令丢失 向量指令无法正确反编译 (本项目未涉及,常见于加密/媒体代码) 6.6 调用约定推断错误 fastcall/thiscall等推断失误 部分函数被标为__fastcall但实际为其他约定
#缺陷类型简要说明本项目实例

七、语义等价但信息损失类

7.1 位运算等价替换 移位被替换为乘除 offset << 4 → 16 * result 7.2 常量折叠 编译期计算结果替代表达式 roundUpToPtrSize(4*4+2*2)+pointer_size*2 → 40 7.3 变量拆分 一个变量被拆为多个 int res → int v4 + unsigned int v5 7.4 中间变量消除 有意义的临时变量被优化掉 void *originEntrypoint = readAddr(...) → 直接作为参数 7.5 参数传递方式改变 值传递/引用传递语义改变 &toMethod 传指针 → v8数组 包装后传递 7.6 运算顺序改变 编译器重排指令顺序 多处变量赋值顺序与源码不同
#缺陷类型简要说明本项目实例

八、完全无法反编译类

8.1 PLT/GOT表项无法反编译 动态链接跳转表 _android_log_print_00004C98 → // 反编译失败 8.2 thunk函数语义退化 跳转桩函数自引用 close(fd) → return close(fd) 自调用形式 8.3 数据段代码混合 代码被识别为数据或反之 trampoline字节数组被执行时IDA可能识别为数据 8.4 间接跳转无法追踪 计算跳转目标丢失 sub_2850: JUMPOUT(0) 完全无法分析 8.5 动态生成代码 运行时写入的代码不可见 genTrampoline生成的代码在IDA静态视图中不存在
#缺陷类型简要说明本项目实例

缺陷影响程度速查

text

严重程度: ████ 极高  ███ 高  ██ 中  █ 低

符号丢失  ████  → 需要大量上下文推断才能还原
类型失真  ███   → 影响指针运算和边界判断的正确性  
控制流失真 ███  → 可能误判程序逻辑分支
调用失真  ██    → 函数语义可还原但需查vtable
架构特性  ████  → naked/asm几乎完全丢失,无法还原
完全失败  ████  → PLT条目/动态代码静态分析无效

免责声明 本文档所有内容仅供安全研究、学术交流与技术学习使用,严禁用于任何未经授权的逆向破解、网络攻击、隐私窃取、恶意软件开发及其他违反《中华人民共和国网络安全法》《数据安全法》等法律法规的行为,使用者应确保已获得目标软件权利人的合法授权并自行承担因使用本文档内容所产生的一切法律责任与后果,作者不对任何直接或间接损害承担任何责任,继续阅读即视为您已知悉并同意上述全部条款。