news 2026/5/27 1:36:31

逆向之常用算法识别二

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
逆向之常用算法识别二

在数据保护和数据转换算法中,rc4和base64是使用频率最高的算法;rc4用于数据加密,base64用于数据转换。

本篇文章介绍的识别算法和上一篇稍有不同,本篇讲述的算法识别方法我把它称之为“结构和特征识别”的识别方法;该方法适用于算法简单,算法结构逻辑清晰,并且算法中包含或者算法输出包含明显的特征,把这些明显的固定的特征抽取加以整理就构成了识别这些算法的关键。

base64识别

介绍识别方法之前我们先看一下base64原理。

Base64 的核心点:

1. 每 3 个字节 → 转成 4 个字符

一个字节是 8 位(bit),3 个字节是 3 x 8 = 24 位

把这 24 位分成 4 组,每组 6 位(因为 6 x 4 = 24)

每个 6 位的值范围是 0 ~ 63,所以可以查一个“64个字符的表”,得到 4 个可打印字符

2. Base64 使用的 64 个字符是:

A–Z(26个) a–z(26个) 0–9(10个) + 和 /(2个)

所以一共有 64 个字符,叫做 “Base64”。

3.补位(padding)

如果不是刚好 3 个字节,比如你只给了 "Ma"(2 个字符 = 16 位)怎么办?

→ Base64 会补零到 24 位,然后结果里加一个 = 做标志。

规则:

如果最后只有 1 个字节(8位),补 4 个 0,末尾加 ==

如果最后有 2 个字节(16位),补 2 个 0,末尾加 =

其他略

结构特征描述

1. 把三个字节变成四个字符(后面我们着重讲一下)

2. Base64依赖一个64个字符的表

"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

3. 输出可能会出现“=”作为补位,如”Hello, world!”的base64为SGVsbG8sIHdvcmxkIQ==

把三个字节变成四个字符

举个例子(超简单)

假设我们要编码文本:

"Man"

它的 ASCII 是:

M: 77 → 二进制 01001101

a: 97 → 二进制 01100001

n: 110 → 二进制 01101110

拼在一起:

01001101 01100001 01101110 → 共24位

把这 24 位切成 4 组,每组 6 位:

010011 010110 000101 101110

从上面base64原理举例中我们抽取核心特征是三个字节变成四个字符,一个字节8位,共24位,在把24位切成4组,每组6位;这不是妥妥的位运算嘛,位运算就涉及左右移位、或与操作。

算法特征抽取

由以上分析得,base64算法具备如下直观的特征:

1、 取三个字符组成24位二进制数,在此基础上进行移位或与操作后得到每组6位的二进制数共4组

2、 有一个固定的字符表是(参与算法索引字符):

"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

3、 输出字符串中可能包含”=”

对特征1有很多种实现,我贴图出来参考一下;

实现一:

实现二:

实现三(这种实现不多见, 它不把三个字节对应的二进制数组合成24位,而是独立看待每个字节的二进制数,组合拼接形成每组6位的4组二进制数):

我们需要从前两种(第三种结合原理去分析)不同的实现中抽取相同的特征作为识别算法的特征,从输入字符(这里不是很准确,应该是任意二进制字节,有些二进制数不是可显示字符)序列连续取三个字节,左移8、16位或操作后形成一个24位的二进制数,先移位后与(右移6、12、18位,然后都与0x3f(十进制数63)); 先与后移位(分别与0xfc0(十进制数4032),0x3f00(十进制数258048), 0xfc000(十进制数16515072),在对应移位18、12、6。

最终我们得到快速定位base64算法的特征如下:

1、看输出结果是否包含”=”,算法中是否包含一个固定64个字符的表

"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

2、由抽取实现方式简化得到;看左移8、16位,右移6、12、18位,&四个常数0xfc0、0x3f00、0xfc000、0x3f

示例

我先以一段arm v7汇编举例,示例中通过base64固定的字符串替换表(64个)交叉引用找到了算法位置,然后通过base64原理看移位等推断它是base64算法。

定位字符串:

交叉引用:

定位函数:

伪代码(base64后两位可能涉及补码=的情况,这里忽略,不给出演示):

伪代码和我们上面介绍的实现三比较接近,我们来分析一下,v9是计数器从0开始,v4是输入的原始数据,(v4 + v9) >> 2等价于byte1 >> 2,整行是把计算的值直接作为base64表的索引查找出了替换的值即结果;v11是 (v4 + v9)即byte1, 16 * v11即v11(byte1) << 4 & 0x30 等价于(v11 & 3) << 4,作为第二个字符的高2位,v10是原始输入数据序列的下一个字节byte2,右移4位同刚刚计算得出的高2位与操作即第二个替换后的字符的索引即((byte1 << 4) & 0x30) | (byte2 >> 4),其他代码逻辑类似,这里就不在做分析了。

上面识别方法是通过特征base64固定的替换表,和简单的base64核心逻辑特征确定了上面算法是base64;基于算法的实现存在差异(逻辑相同),其他算法可能包含实现1和实现2的移位操作和特殊的常量数字(0x3f, 0x3f00,……),这些都是我们识别base64算法的核心;base64算法如此的简单以至于它太容易被识别,因此出现了vmp化的base64,被vmp化后我们无法直观识别,但当我们动态分析时,它的特征就会一一暴漏,这样我们就能快速识别它了,另外如果某个算法最终输出是一段长长的字符串且末尾中最多包含两个”=”,那我们首先假设它就是base64算法。

rc4识别

有了识别base64的基础识别rc4就更容易了,虽说这两个算法毫无关系,但因为rc4算法简单,因此结构和特征识别方式同样适用于rc4。同样我们看一下rc4的核心逻辑:

rc4核心点:

用密钥生成一个“伪随机序列”,然后和明文按位异或(XOR)得到密文。

你只要记住这句话,RC4的原理你已经掌握了一半。

RC4 工作流程分两步:

KSA(Key-Scheduling Algorithm) 用密钥打乱一个 0~255 的数组(称为 S-box)

PRGA(Pseudo-Random Generation Algorithm) 生成一个伪随机字节流(keystream) 明文和这个流逐字节 XOR,就得到了密文

KSA

初始化 S 盒(S-box)

准备一个数组 S,包含从 0 到 255 的整数(共 256 个数):

S = [0, 1, 2, ..., 255]

再准备一个密钥数组 K,用密钥循环填充:

key = "key" → ASCII:[107, 101, 121]

K = [107, 101, 121, 107, 101, 121, ..., 共 256 个]

KSA(Key-Scheduling Algorithm)

我们开始打乱 S 数组:

j = 0

for i = 0 to 255:

j = (j + S[i] + K[i]) % 256

swap(S[i], S[j])

这个过程的目的就是用密钥来打乱初始数组 S,从而产生一个独一无二的 S-box。

KSA结构性描述

1、 一个可有可无的大小为256的数组S,数组中元素值即为索引值(可能通过循环获得)

2、 一个循环(256次),对大小为256的数组K不停的重复填充输入密钥,如密钥是“ABC”,则数组K为[A,B,C,A,B,C……](可能在循环中通过索引直接获取密钥对应数据)

3、 又一个循环(256次),计算某个索引(几个数的和),数据交换(S数组元素交换)

PRGA

PRGA(生成伪随机序列)

初始化:

i = 0 j = 0

开始生成密钥流(每生成 1 字节加密 1 字节):

循环每个字节:

i = (i + 1) % 256

j = (j + S[i]) % 256

交换 S[i] 和 S[j]

t = (S[i] + S[j]) % 256

keystream_byte = S[t]

这个 keystream_byte 就是你用来和明文 XOR 的密钥流。

加密(XOR)

每个明文字节和密钥流字节异或:

cipher_byte = plaintext_byte ⊕ keystream_byte

对每个字符都这样做,最终得到加密后的字节序列。

PRGA结构性描述

1、 又一次循环(最后一次),循环次数是输入数据的长度(流式加密顺序的逐个的)

2、 又一次数据交换,得到一个异或因子

3、 取输入数据(按顺序一个字节)和异或因子异或得到加密后的值即输出结果

rc4算法特征抽取

由以上对rc4的原理详细分析,我们可有抽取一些直观的特征:

1、 包含多次循环,循环次数均循环256次,256是一个常数(除最后一次循环)

2、 无论是否由循环得到,总有一个大小为256的数组,并且数组元素值即为索引值(初始S-box)

3、 某个循环(256次)计算了很多数据的和,同时用该值作为数组项交换的索引

4、 最后一次循环次数等于输入数据长度,该循环包含数组数据交换,同时存在异或操作

看一下源代码(c实现)

从源码中我们能看到存在三个大循环,除最后一个都是循环256次,存在多个循环256次的循环需要被注意;很多和的计算,很多数组的交换,同时在最后一个循环中存在异或操作。

示例

KSA(两个循环,次数均为256)

伪代码(重命名修改过):

PRGA

伪代码(重命名过):

以上两个部分合在一起就构成了完整的rc4,总结rc4算法的识别最简单的特征就是算法包含多次循环,并且多数循环的循环次数是256,算法中数字256出现的频率特别多,算法之初会构造(或者默认提供)一个256大小的数组,并且数组元素值为其索引;另外算法中包含异或操作,并且异或后的值作为最终结果存储,基本就可有断定它是rc4了;如果你还想十分肯定它确实是那就依据rc4算法其他特征来做最终的判定。

rc4是比较经典的流式加密算法,做产品一般不会对算法进行修改,但也会存在个别人或者企业偷偷对算法进行一点点的修改(每个加密算法都有很深的数学和密码学原理,胡乱修改会导致算法失效或者加密强度、性能降低等),它仍被认为是rc4算法。

rc4算法比较简单,因此很多vmp化rc4很常见,但它的原理结构和执行流程不变,当我们动态分析一个算法时,如果遇到算法出现多次循环(循环次数256),很多数组都是256大小,甚至256作为变量出现很多次,同时在某个循环体内存在异或操作,那基本就可有肯定它是rc4了。

好,本篇文章到此就结束了,它和上篇文章有相似之处,都是在找固定的东西,就像病毒查杀一样,把它们收集起来作为识别的指纹,简单算法一样,其实复杂算法也一样,也可以固定特征用于识别它们,只不过需要做到效率折中,希望这两篇文章能帮助刚刚入门不久或者经验不多的工程师们。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/27 17:58:48

基于YOLOv12农作物检测系统1:农作物检测数据集说明(含下载链接)

一. 前言 本篇博客是《基于YOLOv12农作物检测系统》系列文章之《农作物检测数据集说明(含下载链接)》&#xff0c;网上有很多农作物检测数据集的数据&#xff0c;百度一下&#xff0c;一搜一大堆&#xff0c;但质量参差不齐&#xff0c;很多不能用&#xff0c;即使一个一个的看…

作者头像 李华
网站建设 2026/5/27 2:05:09

pip遇到依赖冲突警告时候的排查办法

使用pip安装的时候遇到了以下的依赖冲突问题&#xff0c;解决流程记录一下&#xff0c;相似的过程可以进行排查: (hello-agent) tipriestUranus:~/Documents/hello-agents/code/chapter15/Helloagents-AI-Town/backend (main*) $ pip install -r requirements.txt Collecting …

作者头像 李华
网站建设 2026/5/25 21:51:20

Linux 线程(1)

1.线程概念线程是进程内的最小执行单元&#xff0c;一个进程可以包含多个线程&#xff0c;所有线程共享进程的资源&#xff08;内存、文件句柄等&#xff09;&#xff0c;但有自己独立的执行栈和程序计数器。结合进程的核心区别可以这样理解&#xff1a;进程是资源分配的基本单…

作者头像 李华
网站建设 2026/5/27 17:06:20

医疗AI辅助诊断小程序:藏在便捷背后的技术底气

不用跑医院排队&#xff0c;打开手机小程序&#xff0c;上传症状描述或检查影像&#xff0c;几秒就能拿到AI辅助诊断建议——如今这样的医疗体验越来越常见。很多人觉得“好用”就够了&#xff0c;却不知道这些便捷背后&#xff0c;藏着好几项关键技术的支撑。作为深耕医疗数字…

作者头像 李华
网站建设 2026/5/26 4:34:41

mac 安装brew实战应用案例分享

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个mac 安装brew实战项目&#xff0c;包含完整的功能实现和部署方案。点击项目生成按钮&#xff0c;等待项目生成完整后预览效果 作为一名长期使用Mac进行开发的程序员&#x…

作者头像 李华