常见加解密算法03 - RC4逆向认识

各位聪明绝顶,才高八斗的读者们你们好!今天我们主要讨论编译之后的RC4算法识别。

题外话,之前看到一个蛋疼的小知识,说“势”这个字最好不好查词典释义。我是很好奇的,果然后来无法直视势不可挡这个成语。

言归正传,我们将上一篇的Java与C的代码都编译一下,分别反编译看看。

Java版

Java版的就很好识别,几乎与源码没啥区别。

C版

这里我们先给出RC4加密算法在逆向分析过程中的快速识别经验:

  1. 首先判断明文和密文长度是否相等,等长则代表是序列密码。

  2. 接下来判断是否是RC4。RC4算法中的初始化算法(KSA)中有两轮非常显著的长度为256的循环体,用于根据给定的key生成s盒。伪随机子密码生成算法(PRGA)会根据上一步得到的扰乱的s盒,进一步生成子密钥流,最终和给定的明文进行逐字节的异或。

由于 so 是可以加 ollvm 的,而且还可以做字符混淆,所以逆向起来不会像Java那么容易,在我们找到一个怀疑对象函数之后,就可以通过编写frida脚本或xposed插件完成对相应函数的主动调用,判断当输入明文为任意长度时的密文长度。

关于 ndk 的混淆是有很多文章的,自己可以尝试一下控制流混淆与字符串混淆。

我们看一个混淆之后的例子:

  sub_F658(&unk_38008, dest);

unk_38008实际上是一个字符串,不过这个字符串被混淆了,在 init 阶段后才会被解密。

看里面的逻辑:

  sub_F0AC((__int64)v7, (__int64)a1, v4);
  v2 = strlen(a2);
  return sub_F3C4(v7, a2, v2);

有2个函数比较可疑,先看 sub_F0AC

先看1处,有一个很明显的交换数组元素的逻辑。

再看2处,只有当 v7 = 915845509 的时候才会交换逻辑,循环次数是 256 次,这些都与  RC4 的 init 阶段是一样。

当然这里也只是大胆猜测,而且混淆级别开的没那么高,所以还能看清楚一定的逻辑。实际上这里就已经很难看出来第一个给 S 盒赋值的循环在哪里了,只能根据 result 的位置来看。

后面我们可以使用hook来验证我们的想法。

再看 sub_F3C4 函数:

看 1,2处,发现循环会执行的次数与第3个参数一样,看前面的逻辑:

这就是说,循环次数是第二个字符串的长度。配合第3处的异或,也可以合理怀疑这里就是加密函数。

Hook验证

 sub_F0AC((__int64)v7, (__int64)a1, v4);

通过上面的分析,第一个参数是返回值,第二个参数是密钥,第三个参数是密钥长度。所以返回的是一个密钥流。

sub_F3C4(v7, a2, v2);

第一个参数是密钥流,第二个参数是明文,第三个参数是明文的长度。返回值(第一个参数)是加密后的结果。

sub_F658()

所以,这个函数就是一个 RC4 算法,我们 hook 这些函数,观察参数与结果。

export function invoke_sub_F658(arg1: string, arg2: string) {
    var offset = 0xF658;
    var module = Process.getModuleByName("libnative-lib.so");
    var sub_address = module.base.add(offset);

    var arg1_address = Memory.alloc(10);
    let arg2_address = Memory.alloc(10);
    arg1_address.writeUtf8String(arg1);
    arg2_address.writeUtf8String(arg2);

    var hooked_sub_f658 = new NativeFunction(sub_address, 'pointer', ['pointer', 'pointer']);
    var result = hooked_sub_f658(arg1_address, arg2_address);
    console.log("result:", hexdump(result));
}

function hook_libnativelib() {
    var nativelibmodule = Process.getModuleByName("libnative-lib.so");
    var subf0ac = nativelibmodule.base.add(0xf0ac);
    var subf3c4 = nativelibmodule.base.add(0xf3c4);
    Interceptor.attach(subf0ac, {
        onEnter: function (args) {
            console.log("secret key: ", hexdump(args[1]), '\n length:', args[2]);
        }, onLeave: function () {
        }
    });
    Interceptor.attach(subf3c4, {
        onEnter: function (args) {
            this.arg1 = args[1];
            console.log("input: ", hexdump(args[1]), args[2]);
        }, onLeave: function () {
            console.log("output: ", hexdump(this.arg1));
        }
    });

}

function main() {
    if (Java.available) {
        Java.perform(function () {
            console.log("go into main");
            var RuntimeClass = Java.use('java.lang.Runtime');
            RuntimeClass.loadLibrary0.implementation = function (arg0: object, arg1: string) {
                var result = this.loadLibrary0(arg0, arg1);
                console.log("Runtime.loadLibrary0:", arg1);
                if (arg1.indexOf('native-lib') != -1) {
                    hook_libnativelib();
                }

                return result;
            }
        })
    }
}

rpc.exports = {
    invokesubf658: invoke_sub_F658
};

setImmediate(main);

注意,我们hook so 的加载选择的是 Runtime 类,这是因为直接hook System 类会导致 Reflection.getCallerClass() 的值出问题。还有就是我的手机系统换到了 Android 10,注意自行查看源码区别。

hook 逻辑也很简单,就不细说了,看一下就明白。

注入脚本,看一下输出:

┌──(root㉿kali)-[~/workspace/frida-agent-example]
└─# frida -U -f com.kanxue.rc4 --no-pause -l _agent.js 
secret key:
              0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
724f339008  72 63 34 74 65 73 74 00 31 32 33 34 35 36 37 38  rc4test.12345678

可以看到,secret key 是 rc4test

input:
              0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
7fe568aa10  31 32 33 34 35 36 37 38 00 00 00 00 00 00 00 00  12345678........

加密的明文是 12345678

加密后的结果是:

output:
              0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
7fe568aa10  a6 df 7a 5d dd ea 97 47 00 00 00 00 00 00 00 00  ..z]...G........

从 a6 到 47 这8个字节。

我们也可以主动调用函数,反复确认输入与输出是否一样长。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/623991.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络安全之OSPF进阶

该文针对OSPF进行一个全面的认识。建议了解OSPF的基础后进行本文的一个阅读能较好理解本文。 OSPF基础的内容请查看:网络安全之动态路由OSPF基础-CSDN博客 OSPF中更新方式中的触发更新30分钟的链路状态刷新。是因为其算法决定的,距离矢量型协议是边算边…

【微信小程序开发】深入探索事件绑定、事件冒泡、页面跳转的逻辑实现

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

Windows Qt中支持heic 图片显示

安装vcpkg: git clone https://github.com/microsoft/vcpkg 执行脚本: .\vcpkg\bootstrap-vcpkg.bat 在安装之前如果需要指定vs的编译器, 在如下文件中做更改, 我指定的是用vs2019编译的: D:\vcpkg\vcpkg\triplets 增…

安科瑞AIM-D100-ES光伏储能系统直流绝缘监测仪

概述 AIM-D100-ES 型直流绝缘监测仪主要用于在线监测直流不接地系统正负极对地绝缘电阻,当绝缘电阻低于设定值时,能发出预警和报警信号。 产品可测 100-1500V 的直流系统,可应用于储能直流系统、电动汽车充电装置、UPS 供电系统、光伏直流系…

联合四川博物院跨界,探索五粮液700余年“活窖之美”

执笔 | 尼 奥 编辑 | 扬 灵 “川酒甲天下,精华在宜宾。”千百年来,宜宾得天独厚的自然风土,传承巴蜀大地的臻臻韵味,酝酿出“美酒哉”的和美五粮液,奠定大国浓香的品牌基石。 5月10日,“中国品牌日”如…

「Python绘图」绘制同心圆

python 绘制同心圆 一、预期结果 二、核心代码 import turtle print("开始绘制同心圆") # 创建Turtle对象 pen turtle.Turtle() pen.shape("turtle") # 移动画笔到居中位置 pen.pensize(2) #设置外花边的大小 # 设置填充颜色 pen.fillcolor("green&…

JSP相关题目练习

一、前置知识 【eclipse/IDEA】如何在IDE里创建一个Java Web项目? 1. 实现Bean类的User实例 以一个实现Bean类User的实例。在Eclipse里调用Tomcat服务器运行。 Javabean是一种Java类, 通过封装属性和方法成为具有某种功能或者处理某个业务的对象&…

ai电销机器人智能系统的应用场景包括什么?

随着科技的不断进步,传统的销售方式已经无法满足现代企业的需求,电销机器人智能系统可以在各种场景中发挥作用,其中一些主要的应用场景包括: 客户服务与支持:通过语音识别和自然语言处理技术,电销机器人可以…

812寸硅片为什么没有平边(flat)?

知识星球(星球名:芯片制造与封测社区,星球号:63559049)里的学员问:上期种说2,4,6寸硅片都有平边,那为什么8&12寸硅片只有一个notch?为什么不能像小尺寸晶…

汇编语言程序设计-2-访问寄存器和内存

2. 访问寄存器和内存 文章目录 2. 访问寄存器和内存2.0 导学2.1 寄存器及数据存储2.2 mov和add指令2.3 确定物理地址的方法2.4 内存的分段表示法2.5 Debug的使用2.6 【代码段】CS、IP与代码段2.7 【代码段】jmp指令2.8 【数据段】内存中字的存储2.9 【数据段】用DS和[address]实…

Transformers中加载预训练模型的过程剖析(一)

使用HuggingFace的Transformers库加载预训练模型来处理下游深度学习任务很是方便,然而加载预训练模型的方法多种多样且过程比较隐蔽,这在一定程度上会给人带来困惑。因此,本篇文章主要讲一下使用不同方法加载本地预训练模型的区别、加载预训练模型及其配置的过程,藉此做个记…

ARM64汇编09 - 分支指令与模式切换

本文主要讨论两部分内容: 分支指令,B、BL 等 v7中的模式切换,arm切thumb,thumb切arm。理解了模式切换就会明白为什么在做 inline hook 时,有些地址需要加上1,加上 1 的作用是什么。 B B指令是无条件跳转…

linux phpstudy 重启命令

[rootLinuxWeb phpstudy]# ./system/phpstudyctl restart 查看命令 1) phpstudy -start 启动小皮面板 2) phpstudy -stop 停止小皮面板 3) phpstudy -restart 重启小皮面板 4) phpstudy -status 查询面板状态 5) phpstudy -in…

中北大学软件学院javaweb实验三JSP+JDBC综合实训(一)__数据库记录的增加、查询

目录 1.实验名称2.实验目的3.实验内容4.实验原理或流程图5.实验过程或源代码(一)编程实现用户的登录与注册功能【步骤1】建立数据库db_news2024和用户表(笔者使用的数据库软件是navicat)【步骤2】实现用户注册登录功能(与上一实验报告不同的是&#xff0…

windows下redis配置为服务自启动

1. 准备安装包 2. 解压该zip到文件夹 3. 配置环境变量 4. 配置自启动 4.1 检查redis.windows.conf和 redis.windows-service.conf 文件,将bind注释掉 4.2 [cmd]窗口运行redis 输入 redis-server.exe 或者 redis-server.exe redis.windows.conf 4.3 验证redis是否…

外卖订餐总后台系统原型

页面数量:共 210 页 源文件格式:rp格式,兼容 Axure RP 9/10 应用领域:O2O领域、网上订餐、外卖行业 文章展示不够全面,如有兴趣请联系作者 该原型作品为外卖订餐总后台管理系统,定位偏向美团外卖与饿了么一…

力扣HOT100 - 45. 跳跃游戏 II

解题思路&#xff1a; 贪心 class Solution {public int jump(int[] nums) {int end 0;int maxPosition 0;int steps 0;for (int i 0; i < nums.length - 1; i) {maxPosition Math.max(maxPosition, i nums[i]);if (i end) {end maxPosition;steps;}}return steps;…

[FlareOn1]Bob Doge

[FlareOn1]Bob Doge Hint:本题解出相应字符串后请用flag{}包裹&#xff0c;形如&#xff1a;flag{123456flare-on.com} 得到的 flag 请包上 flag{} 提交。 密码&#xff1a;malware 没什么思路&#xff0c;原exe文件运行又install了一个challenge1.exe文件 c#写的&#xff…

MySQL————创建存储过程函数 有参数传递

存储过程使用大纲 有参数传递 delimiter $$ 声明一个名称为get_student_introduce CREATE PROCEDURE gei_student_introduce(in p_name VARCHAR(20)) 开始操作 BEGIN 撰写真正在操作DMLDQL都行 select introduce 简介 from student WHERE userNamep_name; end $$ delimite…

地下车库导航地图怎么做?停车场地图绘制软件哪个好?

上海懒图科技以先进技术和丰富的行业服务经验为用户提供停车场景下的全流程服务平台&#xff0c;用户基于平台可自主快速绘制酷炫的停车场地图&#xff0c;通过提供完善的停车场应用功能集和扩展API服务包&#xff0c;可以方便地实现电子地图服务于您的各类停车场应用中&#x…