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

news2025/1/19 14:36:54

各位聪明绝顶,才高八斗的读者们你们好!今天我们主要讨论编译之后的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个字节。

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python tensor向量维度转换,不同维度的向量转化为相同的维度,经过全连接层MLP的维度转换,代码实战

问题:在机器学习特征工程中,假如每类特征需要转化为相同的维度进行拼接,那该怎么办呢?接一个全连接层MLP就可以了。 例子:将(128,64) 维度的向量转化为(128,32)维。 impo…

安装ps提示找不到msvcp140.dll,无法继续执行此代码如何修复

MSVCP140.dll,作为Windows操作系统中的一个关键组件,扮演着不可或缺的角色,尤其对于基于C开发的应用程序而言。本文旨在深入探讨这一动态链接库文件的功能、重要性、常见问题及解决方案,为您提供全面的MSVCP140.dll指南。 一、MSV…

zookeeper集群部署以及zookeeper原理

文章目录 简介工作原理特性官网地址准备节点准备环境准备JAVA主机映射 部署 简介 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服…

触摸播放视频,并用iframe实现播放外站视频

效果&#xff1a; html: <div:style"{ height: homedivh }"class"rightOne_content_div_div"mouseenter"divSeenter(i)"mouseleave"divLeave(i)"click"ItemClick(i)"><!-- isUser是否是用户上传 --><divv-if…

react18【系列实用教程】组件 (2024最新版 | 含父子组件传值、兄弟组件传值、越层组件传值、“插槽“)

什么是组件&#xff1f; 一个组件就是用户界面的一部分&#xff0c;它可以有自己的逻辑和外观。 组件之间可以互相嵌套&#xff0c;也可以复用多次 为什么要用组件&#xff1f; 组件能让开发者像搭积木一样快速构建一个完整的庞大应用&#xff0c;大大提升了开发效率&#xff…

刚刚OpenAI发布ChatGPT-4o模型,免费使用GPT4o并免费提供更多功能

就在今日凌晨1点&#xff0c;OpenAI举行了春季发布会&#xff0c;发布了GPT-4o 并免费提供更多功能。 亲测GPT-4o已经可以免费试用&#xff0c;每个人都可以使用它并从中受益&#xff0c;GPT4终于不再是少部分人的玩物。 点击加入ChatGPT4交流群&#xff1a;https://www.aijour…

vue3专栏项目 -- 五、权限管理(上)

一、登录部分 1、第一部分&#xff1a;获取token 前面我们主要是在获取数据上下功夫&#xff0c;到目前为止我们已经能获取首页和详情页的数据了&#xff0c;现在我们将数据转移到权限管理上来&#xff0c;也就是说我们要处理用户登录、注册等一系列的行为&#xff0c;在这部…

JavaScript:正则表达式属于字符串吗-不属于/字符串转正则表达式的两种方法

一、需求描述 js 字符串转正则表达式 二、理解正则表达式属于字符串吗? 正则表达式不属于字符串&#xff0c;它是一种用于匹配、查找和操作文本的模式。正则表达式是一种特殊的语法&#xff0c;用于描述字符串的特征。通过使用正则表达式&#xff0c;可以检查一个字符串是否…

找不到vcomp140.dll多种修复方法分享,轻松解决dll报错问题

当你在尝试运行某款软件时&#xff0c;系统突然弹出一个错误提示&#xff0c;明确指出“vcomp140.dll文件丢失”&#xff0c;这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;我们需要采取一些修复措施。本文将详细介绍vcomp140.dll丢失的5种修复方法…

Java的VO,BO,PO,DO,DTO

写在前面 本文看下VO&#xff0c;BO&#xff0c;PO&#xff0c;DO&#xff0c;DTO&#xff0c;都是啥&#xff01; 1&#xff1a;正文 先看一张图&#xff0c;看了图就能知道个大概了&#xff1a; 1.1&#xff1a;PO 全称是persistent object&#xff0c;对应数据的表&am…

记录一次 vue2 前端项目整合过程

整合成功效果图 具体说明&#xff1a; 项目A是现在的vue2前端项目&#xff0c;项目B是一个开源的工作流前端&#xff0c;项目后端代码已经整合了&#xff0c;就不多提了。这里主要记录下前端整合的过程和思路。 1、开源工作流里面的功能&#xff0c;拷贝到自己对应的vue2项目里…

【Linux】解析键盘组合键产生信号的完整过程:从硬件中断到信号发送

前言 每一个了解Linux的都知道这样一个知识&#xff0c;CtrlC组合键能够终止一个进程。 个人了解进程相关知识之后知道&#xff0c;一个进程被终止只会有有三种情况&#xff1a; 代码运行完毕&#xff0c;结果正确代码运行完毕&#xff0c;结果不正确代码运行异常&#xff…

广东省网络安全竞赛部分web,misc wp

我的队伍只做了5题&#xff0c;还是太菜了&#xff0c;本来不想发的&#xff0c;但是写都写了&#xff0c;还是水一篇博客吧 这里是我们队的wp misc1 给了一个压缩包&#xff0c;解压需要密码&#xff0c;用纯数字密码没跑出来&#xff0c;感觉可能不是要强跑&#xff0c;看…

海外媒体宣发:新加坡.马来西亚如何在海外媒体投放新闻通稿-大舍传媒

导言 随着全球化的进程加速&#xff0c;海外市场对于企业的发展越来越重要。而在海外媒体上宣传企业的新闻通稿&#xff0c;成为了拓展海外市场和提升企业知名度的重要手段之一。本文将介绍大舍传媒对于如何在海外媒体上投放新闻通稿的经验和策略。 准备工作&#xff1a;了解…

Patch-Wise Graph Contrastive Learning for Image Translation

Patch-Wise Graph Contrastive Learning for Image Translation 图像翻译中的逐块图对比学习 Chanyong Jung1, Gihyun Kwon1, Jong Chul Ye1, 2 Chanyong Jung&#xff0c;Gihyun Kwon&#xff0c;Jong Chul Ye 1, 2 Abstract 摘要 Patch-Wise Graph Cont…

CSS实现渐变色

渐变色分为线性渐变和径向渐变。 线性渐变linear-gradient(方向, 颜色1, 颜色2, … ,颜色n)径向渐变radial-gradient(颜色1 覆盖区域大小, 颜色2 覆盖区域大小, … ) 线性渐变的方向可以为&#xff1a; ​ 1、一个方向值时&#xff1a; to bottom 表示从上边到下边渐变 ​ 2、…

SpringAMQP 发布订阅-DirectExchange

DirectExchange: 路由模式模型 代码实现 直接通过注解方式绑定交换机和队列&#xff0c;这里边加了key也就是BingdingKey绑定key&#xff0c;可以看作交换机的路由规则&#xff0c;交换机收到消息后读取消息中指定的Routingkey发送到存有相应BingdingKey的队列中。 RabbitLis…

【Power BI】DAX语言 VS Power Query M语言

DAX&#xff08;Data Analysis Expressions&#xff09;和Power Query M语言是Microsoft Power BI和Excel中的两种强大的数据处理和分析工具。尽管它们在许多方面都有重叠之处&#xff0c;特别是用于数据建模和数据转换&#xff0c;但它们在用途、语法和功能上有显著的区别。本…

联想移动硬盘数据不见了?别急,分享4种实用恢复方法

在数字化时代&#xff0c;硬盘作为数据存储的核心设备&#xff0c;承载着大量的重要信息和文件。然而&#xff0c;有时我们可能会遭遇硬盘数据丢失的困境&#xff0c;特别是当这个问题发生在联想硬盘上时&#xff0c;更是让人倍感焦虑。本文将深入探讨联想硬盘数据丢失的可能原…

【热门话题】Vue.js:现代前端开发的轻量级框架之旅

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 Vue.js&#xff1a;现代前端开发的轻量级框架之旅一、Vue.js概览1.1 Vue.js的诞…