Lazy loaded image
Hook All In Unidbg(转)
字数 11771阅读时长 30 分钟
2022-1-6
2024-7-5
type
status
date
slug
summary
tags
category
icon
password
原文链接: https://blog.csdn.net/qq_38851536/category_11102404.html
更多Unidbg使用和算法还原的教程可见龙哥星球。
本文总结了Unidbg Hook and Call 的知识,部分Hook代码采用Frida 与 Unidbg 对照的方式,帮助熟悉Frida但不熟悉Unidbg的读者快速入门。样例前往百度云下载。

一、基础知识

1.获取SO基地址

Ⅰfrida 获取基地址

Ⅱ Unidbg 获取基地址

加载了多个SO的情况
如果只主动加载一个SO,其基址恒为0x40000000 ,这是一个检测Unidbg的点,可以在 com/github/unidbg/memory/Memory.java 中做修改

2.获取函数地址

Ⅰ Frida 获取导出函数地址

Ⅱ Unidbg 获取导出函数地址

Ⅲ Frida 获取非导出函数地址

Ⅳ Unidbg 获取非导出函数地址

Hook 非导出函数时,不管是Frida还是Unidbg都需要考虑thumb2下地址+1的问题。

3.Unidbg Hook 大盘点

Unidbg 在Android 上支持两大类Hook方案
  • Unidbg 内置的第三方Hook框架,包括xHook/Whale/HookZz
  • Unicorn Hook以及基于它封装的Console Debugger,主要就指Console Debugger。
第一类是Unidbg支持并内置的第三方Hook框架,有Dobby(前身HookZz)/Whale这样的Inline Hook框架,也有xHook这样的PLT Hook 框架,支持这些Hook框架的使用,证明了Unidbg确实相对完善。但支持Frida还有很远的路要走,Frida比Dobby或者xHook都复杂的多,使用到了多线程、信号处理等Unidbg尚不支持的机制。总体来说,Dobby + Whale + xHook 也绝对够用了,没有非Frida不可的需求。
第二类是Unicorn Hook,只有当Unidbg的底层引擎选择为Unicorn时(默认引擎),才能使用。Unicorn提供了各种级别和粒度的Hook,内存Hook/指令/基本块 Hook/异常Hook 等等,十分强大,Unidbg基于它封装了更便于使用的Console Debugger,Unidbg也支持IDA/GDB的联合调试,但仍处于实验性质,不建议尝试。
该选择哪一类Hook方案?这得看使用Unidbg的目的。如果用于模拟执行,那么建议使用第一类Hook,为什么?这得从Unidbg支持的汇编执行引擎说起。Unidbg支持多种底层引擎,最早也是默认的引擎是Unicorn,从名字也能看出,Unidbg和Unicorn有很大关系。但后续Unidbg又支持了数个引擎,丰富了Unidbg的底层生态。但我们知道,任何提高程序复杂度的行为,肯定都为了解决什么问题。
hypervisor 引擎用于搭载了 Apple Silicon 芯片的设备;
KVM 引擎用于树莓派;
Dynarmic 引擎是为了更快的模拟执行;
Unicorn 是最强大最完善的模拟执行引擎,但它相比Dynarmic太慢了,同场景下,Dynarmic比Unicorn模拟执行快数倍甚至十数倍。因此在生产环境中,采用 Dynarmic 引擎配上 unidbg-boot-server 实现高并发。
Dynarmic引擎使用
Unicorn 默认引擎
使用Unidbg的第二个场景是辅助算法还原,即模拟执行只作为算法还原的前奏,在模拟执行输出结果无误后,再使用Unidbg辅助算法还原。这种情况下对执行速度要求不高,那肯定使用更强大的Unicorn引擎。这时候两大类Hook方案都可以使用,选择哪类?我倾向于自始至终使用第二类方案,即基于Unicorn Hook的方案。
我个人认为有三点优势
  • HookZz或者xHook等方案,都可以基于其Hook实现原理进行检测,但Unicorn 原生Hook不容易被检测。
  • Unicorn Hook 没有局限,其他方案局限性较大。比如Inline Hook方案不能Hook短函数,或者两个相邻的地址;PLT Hook 不能 Hook Sub_xxx 子函数。
  • 两类方案混用时,一定几率触发bug,事实上,单使用Unicorn的某些Hook功能都有bug,因此统一用原生Hook可以少一些bug。
总结如下

Ⅰ 以模拟执行为目的

使用第三方Hook方案,arm32下HookZz的支持较好,arm64下Dobby的支持较好,HookZz/Dobby Hook不成功时,如果函数是导出函数就用xHook,否则使用 Whale。

Ⅱ 以算法还原为目的

使用Console Debugger 和 Unicorn Hook,不优先使用第三方Hook方案。

4.本篇的基础代码

即模拟执行demo的代码
运行时有一些日志输出,为正常逻辑。

二、Hook 函数

demo hookInunidbg中运行了数个函数,在本节中关注其中运行的base64_encode函数。
参数解释如下
char *out:一块buffer的首地址,用来存放转码后的内容。
char *in:原字符串的首地址,指向原字符串内容。
int inlen:原字符串长度。
返回值:正常情况下返回转换后字符串的实际长度。
本节的任务就是打印base64编码前的内容,以及编码后的内容。

1.Frida

2.Console Debugger

Console Debugger 是快速打击、快速验证的交互调试器,在call JNIOnLoad之前下断点。
需要重申和强调几个概念
  • 运行到对应地址时触发断点,类似于GDB调试或者IDA调试,时机为目标指令执行前
  • 断点不具有函数的种种概念,需要从汇编指令的角度去理解函数。
  • Console Debugger 用于辅助算法分析,快速分析、确认某个函数的功能。在Unicorn 引擎下才可以用。
针对第二条做补充
根据ARM ATPCS调用约定,当参数个数小于等于4个的时候,子程序间通过R0~R3来传递参数(即R0-R3代表参数1-参数4),如果参数个数大于4个,余下的参数通过sp所指向的数据栈进行参数传递。而函数的返回值总是通过R0传递回来。
以目标函数为例,函数调用前,调用方把三个参数依次放在R0-R2中。
notion image
 
立即数可以直接看,比如此处参数2是5。如果怀疑不是立即数而是指针,比如参数1和参数3,那么在交互调试中输入 mxx 查看其指向的内存,等价于Frida中的hexdump(xxx)。写法有两种,以此处r0为例,既可以 mr0 也可以 m0x400022e0 。
Unidbg 在数据展示上,相较于Frida Hexdump,有一些不同,体现在两方面
  • Frida hexdump时,左侧基地址从当前地址开始,而Unidbg从0开始。
  • Unidbg 给出了所打印数据块的md5值,方便对比两块数据块内容是否一致,而且还展示数据的Hex String,方便在大量日志中搜索。
Console Debugger 支持许多调试、分析的命令,如下:
在Frida代码中,用 console.log(hexdump(args[0],{length: args[1].toUInt32()}))来打印 参数1指向的内存块,长度为参数2的值 ,Unidbg中同样可以指定长度。
目前Console Debugger 还不支持 mr0 r1这样的语法。
至此实现了Frida OnEnter的功能,接下来要获取OnLeave即函数执行完的时机。在ARM编程中,LR寄存器存放了程序的返回地址,当函数跑到LR所指向的地址时,意味着函数结束跳转了出来。又因为断点是在目标地址执行前触发,所以在LR处的断点断下时,目标函数执行完且刚执行完,这就是Frida OnLeave 时机点的原理。在Console Debugger交互调试中,使用 blr 命令可以在 lr 处下一个临时断点,它只会触发一次。
整体逻辑如下
  • 在目标函数的地址处下断点
  • 运行到断点处,进入Console Debugger 交互调试
  • mxx 系列查看参数
  • blr 在函数返回处下断点
  • c 使程序继续运行,到返回值处断下
  • 查看此时的buffer
需要注意的是,在onLeave时机中通过mr2查看入参3是胡闹。R2只在程序入口处表示参数3,在函数运算的过程中,R2作为通用寄存器被用于存储、运算,它已经不是指向buffer的地址了。在Frida中也存在这个问题,所以我们在OnEnter里将args[2]即R2的值保存在this.buffer中,OnLeave中再取出来打印。而在Console Debugger交互调试中,办法更简单粗暴——鼠标往上拉一下,看看原来r2的值是什么,发现是0x401d2000,然后m0x401d2000即可。
这样我们就实现了Frida的等价功能。似乎有点麻烦,但熟练后你会发现Console Debugger 是最快最稳的Hook & Debug 工具。除此之外,当函数被调用了三五百次时,我们不希望它反复停下来,然后不停“c”来继续运行。Console Debugger 也可以做持久化的Hook,代码如下。

3.第三方Hook框架

如下目标函数均在JNIOnLoad前调用

ⅠxHook

xHook是爱奇艺开源的Android PLT hook框架,优点是挺稳定好用,缺点是不能Hook Sub_xxx 子函数。这是其原理所限。

Ⅱ HookZz

HookZz 也可以实现类似于单行断点的Hook,但在Unidbg 的Hook大环境下感觉用处不大,不建议使用。
HookZz是老名字,现在叫Dobby,Unidbg中HookZz和Dobby是两个独立的Hook库,因为Unidbg作者认为HookZz在arm32上支持较好,Dobby在arm64上支持较好。HookZz或者说Dobby采用的是inline hook方案,因此可以Hook Sub_xxx,缺点是短函数可能出bug,受限于其 inline Hook 原理。

Ⅲ Whale

Whale 是一个跨平台的Hook框架,在Andorid Native Hook 上也是inline Hook方案,具体情况我了解不多。

4.Unicorn Hook

如果想对某个函数进行集中的、高强度的、同时又灵活的调试,Unicorn CodeHook是一个好选择。比如我想查看目标函数第一条指令的r1,第二条指令的r2,第三条指令的r3,类似于这种需求。
hook_add_new 第一个参数是Hook回调,我们这里选择CodeHook,它是逐条指令Hook,参数2是起始地址,参数3是结束地址,参数4一般填null。这意味着从起始地址到终止地址这个执行范围内的每条指令,我们都可以在其执行前处理它。
找到目标函数的代码范围
notion image
 

三、Replace 参数和返回值

1.替换参数

需求:入参改为hello world,对应的入参长度也要改,正确结果是 aGVsbG8gd29ybGQ=,供验证效果。

ⅠFrida

Ⅱ Console Debugger

Console Debugger 如何实现这一目标?
①下断点,运行代码后进入debugger
②通过命令修改参数1和2,字符串得通过hexstring的形式传入
Console Debugger 支持下列写操作
但这其实并不方便,还是做持久化比较舒服。

Ⅲ 第三方Hook框架

原理和Unicorn Hook完全不同,但得益于良好的封装,代码是类似的。
① xHook
② HookZz
因为可以用HookZzArm32RegisterContext,相对来说代码简单一些。

2.修改返回值

修改返回值的逻辑和替换参数并没什么区别,但它可以引出第四节,所以还是仔细讲一下。
在demo 中,有一个verifyApkSign函数,它总是返回1,并导致APK校验失败,因此目标就是让它返回0。

ⅠFrida

Ⅱ Console Debugger

我们的Hook生效了,但 verifyApkSign 函数里的log 还是打印出来了。在一些情况中,我们并不希望函数执行本来的逻辑,这就引出了第四节,即需要彻底的函数替换——替换并使用自己的函数。

四、替换函数

1.Frida

Frida 这部分门道还挺多,但不是我们这里的重点。

2.第三方Hook框架

这里只演示xHook
xHook的版本很清晰易懂,我们做了两件事
  • R0 赋值为0
  • LR 赋值给 PC,这意味着函数一行不执行就返回了,又因为R0赋值0所以返回值为0。

3.Console Debugger

非常清晰易懂。

五、Call 函数

分析具体算法时,常需要对其进行主动调用,进行更灵活和细致的分析。举两个例子
1是主动调用base64_encode 函数
2是一个更复杂一些的函数。

1.Frida

2.Unidbg

六、Patch 与内存检索

1.Patch

Patch 就是直接对二进制文件进行修改,Patch本质上只有两种形式
  • patch 二进制文件
  • 在内存里 patch
Patch的应用场景很多,有时候比Hook更简单好用,所以要介绍它。Patch 二进制文件大家都很熟悉,在IDA中使用KeyPatch即可。但这里我们关注内存Patch。
notion image
 
0x8CA处调用了签名校验函数,第三四节中通过Replace返回值或函数的方式来处理它,但实际上,修改0x8CA处这条四字节指令也是好办法。
notion image
 
需要注意的是,本文只讨论了arm32,指令集只考虑最常见的thumb2,arm以及arm64可以自行测试。

ⅠFrida

①方法一
但这并不是最佳代码,Patch存在两个问题
  • 是否存在多个线程同时读写这块内存?是否有冲突
  • arm 的缓存刷新机制
所以Frida 提供了更安全可靠的API来修改内存中的字节
②方法二

Ⅱ Unidbg

Unidbg在修改内存上,既可以传机器码,也可以传汇编指令,方法一和方法二其实没区别。
①方法一
②方法二
③方法三

2.内存检索

假设SO存在碎片化,比如要分析某个SO的多个版本,需要Patch签名校验或者某处汇编,其地址在不同版本中不一样,而且不是导出函数。内存检索+Patch就是一个好办法,可以很好适应多版本、碎片化。
搜索特征片段,可能是搜索函数开头十字节,也可能是搜索目标地址上下字节或者其他特征。
 
notion image

ⅠFrida

Ⅱ Unidbg

值得一提的是,本节的内容也可用 LIEF Patch二进制文件实现。

七、Hook时机过晚问题

上文中,Hook代码都位于 SO加载后, 执行JNI_OnLoad之前,和如下Frida代码Spawn注入进程等价。
而Unidbg Hook代码位于JNI_OnLoad后时,和如下Frida代码Spawn注入进程等价
但如果**.init和.init_array段**存在代码逻辑(init→init_array→JNIOnLoad),我们想捕获这个时机,那么上述的时机点都太晚了,这种情况下就需要将Hook时机点提前到init执行前。在Frida中,为了实现这一点,通常做法是Hook Linker中的call_function或call_constructor函数。
以我们的demo hookInUnidbg为例,其中init段里就有如下逻辑,比较两个字符串的大小。
当前显示str1 大于 str2,我们的Hook目标是让其显示 str1 小于 str2。如果还想之前那样,在JNIOnLoad之前下断,是断不下来的,因为时机太晚了,Unidbg中可以使用下面几个办法。

1.提前加载libc

提前加载libc,然后hook strcmp函数,修改其返回值为-1是一个办法。如下是完整代码,提供了Console Debugger 以及 HookZz 两个版本。
但如果想hook的目标函数不是libc里的函数,就没效果了。比如想在0x978下个断点。
 
notion image

2.固定地址下断点

这是最常用也最方便的方式,但只有Unicorn引擎下可以使用。
通过 vm.loadLibrary 加载的第一个用户SO,其基地址是0x40000000,因此可以在IDA中看函数偏移,通过绝对地址Console Debugger Hook。
 
notion image
如果加载了多个用户SO,可以先运行一遍代码,确认目标SO的基地址(Unidbg中不存在地址随机化,目标函数每次地址都固定。)然后在loadLibrary前Hook该地址,即可保证Hook不遗漏。

3.使用Unidbg提供的模块监听器

实现自己的模块监听器
通过memory.addModuleListener绑定。
每种方法都有对应使用场景,按需使用。除此之外也可以修改Unidbg源码,在 callInitFunction函数前添加自己的逻辑。

八、条件断点

在算法分析时,条件断点可以减少干扰信息。以strcmp为例,整个进程的所有模块都可能调用strcmp函数。

1.限定于某SO

ⅠFrida

Ⅱ Unidbg

在Unidbg中,“Hook限定于目标SO内”的使用场景可能不那么多,因为Unidbg虚拟进程里只有我们的目标SO在活跃,但Android系统中,目标进程里可能有数十个模块。当我们想hook strlen 来窥探目标SO里的字符串操作时,如果不加筛选,会被其他模块的大量调用干扰。或者我们想替换pthread_create函数,观察或者阻止子线程创建的时候,也会发现libart等模块也在创建子线程,除此之外替换时间等操作也都要注意这个问题。

2.限定于某函数

比如某个函数在SO中被大量使用,现在只想分析这个函数在函数A中的使用。

ⅠFrida

Ⅱ Unidbg

3.限定于某处

notion image
 
比如上图,只关注0xA00 处发生的strcmp。一个办法是hook strcmp函数,只在lr寄存器=module.base + 0xA00 + 4 + 1时打印输出。
另一个办法是Console Debugger ,也很方便。
一定要掌握这些知识,并做到灵活变通。在实际使用中,诸如“A hook生效后再打印B函数的输出“这样的需求是很常见的,否则每个函数都打印成百上千行会迷人眼,干扰对关键信息的寻找。

九、系统调用拦截——以时间为例

这里说的系统调用拦截,并不是要对系统调用进行Hook,比如 frida - syscall - intercceptor 这样,系统调用全部是Unidbg自己实现的,日志一开就能看,显然也没有Hook的必要。Unidbg的系统调用拦截是为了替换系统调用,修改Unidbg中系统调用的实现。
有两个问题需要解释
  • 为什么要修改系统调用?
    • Unidbg中部分系统调用没实现或者没实现好,以及有时候想要固定其输出,比如获取时间的系统调用,这些需求需要我们修复或修改Unidbg中系统调用的实现。
  • 为什么不直接修改Unidbg源码
    • 1是灵活性较差,2是我们的实现或修改并不是完美的,直接改Unidbg源码是对运行环境的污染,影响其他项目。
在分析算法时,输入不变的前提下,如果输出在不停变化,会干扰算法分析,这种情况的一大来源是时间戳参与了运算。在Frida中,为了控制这种干扰因素,常常会Hook libc的gettimeodfay这个时间获取函数。

1.Frida

hook time
hook gettimeofday
但Frida做这件事并不容易做圆满,单是libc.so,就有time、gettimeodfay、clock_gettime、clock 这四个库函数可以获取时间戳,而且样本可以通过内联汇编使用系统调用,获取时间戳。

2.Unidbg

Unidbg中可以更方便、更大范围的固定时间,不必像Frida那般。time和gettimeodfay库函数基于gettimeodfay这个系统调用,clock_gettime和clock基于clock_gettime系统调用。所以只要在Unidbg中固定gettimeodfay和clock_gettime这两个系统调用获取的时间戳,就可以一劳永逸。
首先实现时间相关的系统调用处理器,其中的*System.currentTimeMillis()System.nanoTime()*改成定数。
在自己的模拟器上使用它,原先模拟器创建是这么一句
修改如下

十、Hook 检测

Anti Unidbg的方法浩如烟海,但事实上几乎没有主动Anti Unidbg的样本,有两方面原因
  • Unidbg 自身的多个重大弱点没有解决,比如多线程和信号机制尚未实现。
  • Unidbg 普及率和推广度还不高。
所以本节专注于Hook 检测。

1.检测第三方Hook框架

基于其Hook实现原理,可以对应检测。

ⅠInline Hook

以我熟悉的inline Hook 检测为例,inline Hook 需要修改Hook处的前几个字节,跳转到自己的地方实现逻辑,最后再跳转回来。那么就有两类思路实现检测,首先开辟一个检测线程,对关键函数做如下二选一循环操作
  • 函数开头前几个字节是否被篡改
  • 函数体是否完整未被修改,常使用crc32校验,为什么不用md5或其他哈希函数?因为crc32极快,性能影响小,碰撞率又在可接受的范围内
相关项目:check_fish_inline_hook

Ⅱ Got Hook

2.检测Unicorn Based Hook

Unicorn Hook 似乎不可检测,但Unicorn也是可检测的。在星球的Anti-Unidbg系列,就提到过一种检测方式。在Android系统中,只支持对四字节对齐的内存地址做读写操作,所以通过内联汇编尝试向SP+1的位置做读写,在真机上会导致App崩溃,而Unidbg模拟执行不会出任何问题。当然,我们并不希望App崩溃,所以需要在代码中实现自己的信号处理函数,当此处发生异常时,信号处理函数接收信号并做出某种处理,因为Unidbg中程序不会异常,所以也不会走到信号处理函数,这里面可以设计形成差异。
除此之外,Unicorn下断点调试或者做指令追踪时,必然会导致函数运行时间超出常理,基于运行时间的反调试策略也可行。

十一、Unidbg Trace 五件套

基于Frida 存在许多trace 方案,比如用于 trace JNI函数的 [JNItrace],用于trace Java调用的 [ZenTrace]、[r0tracer],又或者是官方的多功能 trace 工具 [frida-trace],用于指令级 trace 的 [Frida Stalker],又或者是trace SO中所有函数的 trace_natives ,以及Linux上著名的strace 或者 基于Frida 的 [frida-syscall-interceptor],用于 trace 系统调用。
在Unidbg 上,上述的大部分trace,只需要调整日志等级就能实现。我们这里所讲的trace,聚焦于如何让使用者对代码执行流有更强的掌控。

1.Instruction tracing

令追踪包括两部分
  • 记录每条指令的执行,打印地址、机器码、汇编等信息
  • 打印每条指令相关的寄存器值
Unidbg 基于 Unicorn CodeHook 封装了指令追踪,方法和效果如下
 
notion image
Unidbg的指令追踪,在第一部分的工作做得很好,采用 模块名+相对偏移+机器码+绝对地址+汇编 的展示形式,但美中不足的是,它并没有做第二部分的工作,可以使用如下的脚本在Unidbg中实现完善的指令追踪,其原理也是实现了一个自己的codehook。

2.Function Tracing

指令Trace是最细粒度的Trace,优点是细,缺点是动辄数百上千万行,让人迷失其中。函数粒度的trace则不然,粗糙但容易理解全貌,在算法还原的一些场景中会起到帮助。在IDA Debug中,即可选择函数追踪来记录函数调用,包括了有符号函数以及IDA识别并命名为Sub_addr的子函数。
notion image
 
在Frida上,可以使用 trace_natives 对 一个SO中的全部函数进行Trace,并形成如下调用图。
notion image
 
Unidbg中可以做到这一点吗?不妨看一下 Frida trace_natives 脚本,其中有三个关注点。
  • 如何获得一个SO的全部函数列表,就像IDA一样
  • 如何Hook函数
  • 如何获得调用层级关系,形成树结构
关于问题1,trace_natives怎么解决的?直接编写IDA脚本获取IDA的函数列表
脚本获取了函数以及对应函数名列表,同时通过minLength过滤较短的函数,至少包含10条汇编指令的函数才会被计入。这么做有两个原因
  • 过短的函数可能导致Frida Hook失败(inline hook 原理所致)
  • 过短的函数可能是工具函数,调用次数多,但价值不大,让调用图变得臃肿不堪
完整的IDA插件 getFunctions 代码如下
关于问题2:使用Frida Native Hook
关于问题3:Frida的frida-trace自带调用层级关系,所以trace_Natives脚本依赖Frida-trace,展示出了树结构的调用图。分析源码发现,frida-trace 使用了Frida在 Interceptor.attach 环境中的depth 如下代码中的this.depth),depth表示了调用深度。那深度的值哪来的呢?其最终依赖于Frida的栈回溯。
这三个问题能在Unidbg中解决吗?如果能解决,那就有了Unidbg 版的Function Tracing。
首先问题一,只是一个获取函数列表的插件,与使用Frida还是Unidbg无关,构不成问题。我们还可以更进一步思考,trace_Natives 依赖IDA实现对SO 函数的识别,但与此同时也增加了使用的复杂度,而且加壳的SO无法直接识别函数,必须得先dump+fix SO,其实还挺折腾人,不如不依赖IDA,换个办法识别函数。ARM中,函数序言常常以 push 指令开始,这可以代表绝大多数函数。配合Unidbg的BlockHook 或者 CodeHook,就可以解析并 Hook 这些函数,问题二也顺带解决了。少部分函数会遗漏,但也无关痛痒。BlockHook 还会提供当前基本块的大小,我们设置对较小的块不予理睬。
接下来就是问题三,栈回溯这块,Unidbg也实现了arm unwind栈回溯,一些情况下有Bug,但总体应该能用。但Unidbg没有提供打印深度的函数,在Unwinder类中添加一个它。
src/main/java/com/github/unidbg/unwind/Unwinder.java
接下来三步骤合一,组装代码
可以发现代码非常的简洁优雅,效果也不错
notion image
 
它还有三个明显的缺陷
1是时机过晚,init或者init_arrayz里的内容无法Hook到,可以结合第七节的方法进行完善。
2是有符号的函数也以sub_xxx 显示
3是导入表中的函数无法包括在内,因为原理上讲,只扫描so内push开头的函数。

3.Memory Search

4.Unidbg-FindKey

这是我写的小工具,具体原理见星球,目前支持查找AES-128/AES-256的密钥,理论上还可以将更多的加密算法包括进去,只需要算法满足以下三点:
1.程序的预处理(最典型的场景即密钥编排)会产生某个结构
2.这个结构是可分辨的
3.这个结构可以解码出原始Key
AES完美符合这三点,SM4也很适用,过往的研究表明,DES、RSA、TwoFish、Separnt等加密算法都满足或者部分满足上述三条件。

5.Unidbg-Findcrypt

Findcrypt是老牌经典工具,Unidbg版的Findcrypt是要做啥?解决什么痛点?有三个主要原因
  • Findcrypt 处理不了加壳SO
  • Findcrypt 中说存在某种加密,但SO中并不一定用,我们的目标函数更不一定用。
  • 从Findcrypt提示的常数不一定能找到对应函数,静态交叉分析有局限
// TODO

十二、固定随机数

// TODO

十三、杂项

无需Hook,Unidbg中通过其他方式实现
// TODO
上一篇
Frida主动调用函数
下一篇
Tampermonkey油猴脚本安装及入门

评论
Loading...