【Rust编程】如何用Rust构建Shellcode

news/2024/12/25 9:00:16/文章来源:https://www.cnblogs.com/o-O-oO/p/18629200

Shellcode是一段可以直接执行的机器码,通常用于漏洞利用或攻击中。它们通常是极小的程序,能直接在目标内存中运行。Rust作为一种系统编程语言,可以用来编写高效、安全的Shellcode。以下是如何用Rust构建Shellcode的详细步骤。

1. 什么是Shellcode?

Shellcode是一种直接执行的二进制代码,通常通过漏洞注入到目标系统中。它的名字来源于其常见用途,即启动一个shell(命令行)以供攻击者控制。

例如,以下是一个简单的Shellcode,它打印“hello world”:

echo '488d35140000006a01586a0c5a4889c70f056a3c5831ff0f05ebfe68656c6c6f20776f726c640a' | xxd -r -p > shellcode.bin

通过反汇编可以看出,它包含了一个write系统调用来输出“hello world”字符串。

2. 可执行文件的结构

所有的可执行文件都分为多个部分(section),如.text(存储代码)、.data(存储数据)等。Rust编译器会自动生成这些部分,但我们需要了解它们的作用以便更好地控制Shellcode的生成。

3. Rust的编译过程

Rust的编译过程分为以下几个阶段:

1. 解析和宏展开:将源码解析为抽象语法树(AST)。
2. 分析:包括类型检查、借用检查等,生成中间表示(MIR)。
3. 优化与代码生成:通过LLVM生成目标机器码。
4. 链接:将生成的对象文件链接为最终的可执行文件。

4. 使用#![no_std]

默认情况下,Rust依赖标准库(std),但Shellcode通常运行在没有操作系统支持的环境中,因此我们需要使用#![no_std]来禁用标准库。

以下是一个最小的#![no_std]程序:

#![no_std]
#![no_main]
#![feature(start)]#[start]
fnstart(_argc: isize, _argv: *const *constu8) ->isize {0
}#[panic_handler]
fnpanic(_: &core::panic::PanicInfo) -> ! {loop {}
}

需要在.cargo/config.toml中配置编译参数:

[build]
rustflags = ["-C", "link-arg=-nostdlib", "-C", "link-arg=-static"]

5.在Rust中使用汇编

Rust支持内联汇编(asm!),可以直接嵌入机器码。以下是一个简单的例子,使用syscall系统调用打印“hello world”:

#![feature(asm)]const SYS_WRITE: usize = 1;
const STDOUT: usize = 1;
static MESSAGE: &str = "hello world\n";unsafefnsyscall3(scnum: usize, arg1: usize, arg2: usize, arg3: usize) ->usize {letret: usize;asm!("syscall",in("rax") scnum,in("rdi") arg1,in("rsi") arg2,in("rdx") arg3,lateout("rax") ret,options(nostack),);ret
}fnmain() {unsafe {syscall3(SYS_WRITE, STDOUT, MESSAGE.as_ptr() asusize, MESSAGE.len());}
}

6. 使用Never类型

Rust中的“Never”类型(!)表示永远不会返回的函数。对于Shellcode,这非常有用,因为Shellcode通常不会返回任何值。例如:

#[no_mangle]
fn _start() -> ! {loop {}
}

7.执行Shellcode

在Linux上,可以通过以下两种方式执行Shellcode:

嵌入到.text段 通过#[link_section = ".text"]将Shellcode嵌入到.text段:

#[link_section = ".text"]
static SHELLCODE: [u8; 16] = *include_bytes!("shellcode.bin");fn main() {let exec_shellcode: extern "C" fn() -> ! =unsafe { std::mem::transmute(&SHELLCODE as *const _ as *const ()) };exec_shellcode();
}

8. 使用mmap设置可执行内存

使用mmap将内存标记为可执行:


use mmap::{MapOption::*, MemoryMap};
use std::mem;static SHELLCODE: &[u8] = include_bytes!("shellcode.bin");fnmain() {letmap = MemoryMap::new(SHELLCODE.len(), &[MapReadable, MapWritable, MapExecutable]).unwrap();unsafe {std::ptr::copy(SHELLCODE.as_ptr(), map.data(), SHELLCODE.len());letexec_shellcode: extern"C"fn() -> ! = mem::transmute(map.data());exec_shellcode();}
}

9. Hello World Shellcode

以下是一个完整的Hello World Shellcode示例:


#![no_std]
#![no_main]
#![feature(asm)]const SYS_WRITE: usize = 1;
const SYS_EXIT: usize = 60;
const STDOUT: usize = 1;
static MESSAGE: &str = "hello world\n";#[no_mangle]
fn_start() -> ! {unsafe {syscall3(SYS_WRITE, STDOUT, MESSAGE.as_ptr() asusize, MESSAGE.len());syscall1(SYS_EXIT, 0);}loop {}
}unsafefnsyscall1(scnum: usize, arg1: usize) ->usize {letret: usize;asm!("syscall",in("rax") scnum,in("rdi") arg1,lateout("rax") ret,options(nostack),);ret
}unsafefnsyscall3(scnum: usize, arg1: usize, arg2: usize, arg3: usize) ->usize {letret: usize;asm!("syscall",in("rax") scnum,in("rdi") arg1,in("rsi") arg2,in("rdx") arg3,lateout("rax") ret,options(nostack),);ret
}

10. 生成反向TCP Shellcode

以下是一个更复杂的Shellcode示例,用于建立反向TCP连接并启动一个shell:

const SYS_SOCKET: usize = 41;
const SYS_CONNECT: usize = 42;
const SYS_DUP2: usize = 33;
const SYS_EXECVE: usize = 59;#[no_mangle]
fn _start() -> ! {// 创建socket、连接服务器、重定向输入输出、启动shellloop {}
}

通过这些示例,我们可以看到Rust在构建Shellcode时的强大能力,同时也能更好地理解Shellcode的工作原理。如果有任何疑问,可以随时提问!

原创 梦兽编程

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何解决域名转移过程中授权码错误的问题?

您在域名转移过程中遇到了授权码错误的问题。域名转移是一个相对复杂的过程,涉及到多个环节的验证和配置。为了帮助您顺利解决授权码错误的问题,以下是详细的排查步骤和解决方案。 1. 确认授权码格式 首先,确保您输入的授权码格式正确。授权码通常由字母和数字组成,长度固定…

manim边学边做--同伦变换

在Manim中,移动一个元素除了之前介绍的方法之外,还可以通过同伦运算来移动一个元素。 与普通的移动元素方式相比,使用同伦运算移动一个元素时,实际上是在考虑整个空间的连续变形过程中元素的相应变化。 这种移动不是孤立地看待元素的位置改变,而是将元素置于空间的整体结构…

破解多区域协作难题,打造无缝连接新生态,让企业效率倍增!

跨国公司在全球范围内拥有多个分支机构、生产基地和供应链,为了实现高效的运营和多区域协作,跨国公司需要建立稳定、安全的网络连接,确保不同地区之间的数据传输顺畅。例如,苹果、微软、可口可乐等全球知名企业均在全球范围内进行商品和服务的国际贸易、资本投资以及资产配…

网站迁移处理-云服务器问题

关于您提到的网站迁移过程中遇到的问题,包括数据丢失、文件丢失以及迁移前后不一致的情况,我们将为您提供详细的解决方案。确保在迁移过程中不会出现数据丢失和文件丢失,并且迁移后的网站与原网站保持一致是至关重要的。以下是具体的排查和解决步骤:备份与恢复: 在进行任何…

域名解析很久始终无法访问

关于您提到的域名解析很长时间但始终无法访问的问题,这可能是由于DNS传播延迟、服务器配置错误或解析设置不当引起的。为了帮助您顺利解决问题,建议您从以下几个方面进行排查和调整:DNS传播延迟: 域名解析通常需要一定的时间才能在全球范围内传播。DNS传播时间可能从几分钟…

无法访问网站-虚拟主机/数据库问题

关于您提到的无法访问网站的问题,可能是由多种原因引起的,包括DNS解析错误、服务器配置问题、数据库连接失败等。为了帮助您顺利解决问题,建议您从以下几个方面进行排查和调整:域名解析检查: 首先,请确认域名解析是否正常。DNS传播可能需要一定时间才能在全球范围内生效。…

Fortify:静态代码分析器

Fortify静态代码分析器,‌是一款强大的静态代码分析工具,主要用于检测源代码中的安全漏洞和缺陷。它支持多种编程语言,包括Java、C#、C、C++、Swift、PHP等,能够发现并修复潜在的代码泄露风险点‌。 兼容系统: Windows/MacOS/Linux安装步骤 一、解压补丁压缩包,把fortify…

【安全就业】2024年网络安全技术技能人才职业能力图谱+工控安全

工控安全,是指针对工业控制系统进行网络安全保障的相关工作。由于工控系统与一般的民用办公系统、Web系统等都有很大不同,因此想要做好工控安全工作,需要掌握很多工业控制领域的专业知识和能力,具体包括资产识别、工控协议、工业安全检测(漏洞挖掘)、工业自动化、主机安全…

跟着 8.6k Star 的开源数据库,搞 RAG!

过去 9 年里,HelloGitHub 月刊累计收录了 3000 多个开源项目。然而,随着项目数量的增加,不少用户反馈:“搜索功能不好用,找不到想要的项目!” 这让我意识到,仅仅收录项目是不够的,还需要通过更智能的方式,帮助用户找到心仪的开源项目。于是,我开始探索如何通过 RAG 技…

【内网】内网远程桌面密码获取

一、远程桌面历史IP获取 1.1 mstsc查看历史登录IP 1.2 注册表地址获取历史登录IP地址 1.3 ListRDPConnections 二、获取 RDP 远程桌面连接凭据 2.1 在凭据管理器中查看 Windows 凭据 2.2 使用 Mimikatz 导出远程桌面连接凭据 2.3 从 svchost 中获取 RDP 连…

直击心灵:别让‘在吗’成为沟通障碍

在聊天过程中,我特别反感收到“在吗”的询问或是“微笑”表情。 当需要请求他人协助时,相较于冷冰冰又显敷衍的“在吗?”或是让人感觉虚伪的“微笑”表情,我更倾向于在“在吗”前加上对方的名字或昵称,随后直接切入主题。这样的沟通方式更为亲切且高效,也更容易得到对方的…

【半解决】开启代理后无法连接github仓库,开启tun模式后无法连接github仓库

背景 如图所示。问题 无法连接github仓库,代理可以正常访问外网。 PS C:\Users\acer\bin\ps> ssh -Tv git@github.com OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2 debug1: Reading configuration data C:\\Users\\acer/.ssh/config debug1: C:\\Users\\acer/.ssh/config l…