How to execute shellcodes from memory in Rust

Executing code from memory in Rust is very dependant of the platform as all modern Operating Systems implement security measures to avoid it. The following applies to Linux.

There are at least 3 ways to execute raw instructions from memory:

By embed…

Executing code from memory in Rust is very dependant of the platform as all modern Operating Systems implement security measures to avoid it. The following applies to Linux.

There are at least 3 ways to execute raw instructions from memory:

  • By embedding the shellcode in the .text section of our program by using a special attribute.
  • By using the mmap crate and setting a memory-mapped area as executable.
  • A third alternative not covered in this post is to use Linux’s mprotect function.

This post is an excerpt from my book Black Hat Rust

Our shellcode

We will use the following shellcode:

488d35140000006a01586a0c5a4889c70f056a3c5831ff0f05ebfe68656c6c6f20776f726c640a

Which is a basic hello-world for x86_64.

We can use the following command to write it to a binary file:

$ echo '488d35140000006a01586a0c5a4889c70f056a3c5831ff0f05ebfe68656c6c6f20776f726c640a' | xxd -r -p > shellcode.bin
$ objdump -D -b binary -mi386 -Mx86-64 -Mintel shellcode.bin

shellcode.bin:     file format binary


Disassembly of section .data:

00000000 <.data>:
   0:   48 8d 35 14 00 00 00    lea    rsi,[rip+0x14]        # 0x1b
   7:   6a 01                   push   0x1
   9:   58                      pop    rax
   a:   6a 0c                   push   0xc
   c:   5a                      pop    rdx
   d:   48 89 c7                mov    rdi,rax
  10:   0f 05                   syscall           // <- write(1, "hello world\n", 12)
  12:   6a 3c                   push   0x3c
  14:   58                      pop    rax
  15:   31 ff                   xor    edi,edi
  17:   0f 05                   syscall           // <- exit
  19:   eb fe                   jmp    0x19
  1b:   68 65 6c 6c 6f          push   0x6f6c6c65 // <- hello world\n
  20:   20 77 6f                and    BYTE PTR [rdi+0x6f],dh
  23:   72 6c                   jb     0x91
  25:   64                      fs
  26:   0a                      .byte 0xa

Embedding a shellcode in the .text section

Embedding a shellcode in our program is easy thanks to the include_bytes! macro, but adding it to the .text section is a little bit tricky as by default only the reference to the buffer will be added to the .text section, and not the buffer itself.

It can be achieved as follow:

main.rs

use std::mem;

// we do this trick because otherwise only the reference of the buffer is in the .text section
// and not the buffer itself
const SHELLCODE_BYTES: &[u8] = include_bytes!("../shellcode.bin");
const SHELLCODE_LENGTH: usize = SHELLCODE_BYTES.len();

#[no_mangle]
#[link_section = ".text"]
static SHELLCODE: [u8; SHELLCODE_LENGTH] = *include_bytes!("../shellcode.bin");

fn main() {
    let exec_shellcode: extern "C" fn() -> ! =
        unsafe { mem::transmute(&SHELLCODE as *const _ as *const ()) };
    exec_shellcode();
}
$ cargo run
hello world

Setting a memory-mapped area as executable

Cargo.toml

[dependencies]
mmap = "0.1"

main.rs

use mmap::{
    MapOption::{MapExecutable, MapReadable, MapWritable},
    MemoryMap,
};
use std::mem;

// as the shellcode is not in the `.text` section, we can't execute it as it
const SHELLCODE: &[u8] = include_bytes!("../shellcode.bin");

fn main() {
    let map = MemoryMap::new(SHELLCODE.len(), &[MapReadable, MapWritable, MapExecutable]).unwrap();

    unsafe {
        // copy the shellcode to the memory map
        std::ptr::copy(SHELLCODE.as_ptr(), map.data(), SHELLCODE.len());
        let exec_shellcode: extern "C" fn() -> ! = mem::transmute(map.data());
        exec_shellcode();
    }
}

The code is on GitHub

As usual, you can find the code on GitHub: github.com/skerkour/kerkour.com (please don’t forget to star the repo 🙏).

Want to learn more Rust, Offensive Security and Applied Cryptography? Take a look at my book Black Hat Rust where among other things you will learn to craft simple and advanced shellcodes with Rust.


Print Share Comment Cite Upload Translate Updates
APA

Sylvain Kerkour | Sciencx (2022-12-08T14:00:00+00:00) How to execute shellcodes from memory in Rust. Retrieved from https://www.scien.cx/2022/12/08/how-to-execute-shellcodes-from-memory-in-rust/

MLA
" » How to execute shellcodes from memory in Rust." Sylvain Kerkour | Sciencx - Thursday December 8, 2022, https://www.scien.cx/2022/12/08/how-to-execute-shellcodes-from-memory-in-rust/
HARVARD
Sylvain Kerkour | Sciencx Thursday December 8, 2022 » How to execute shellcodes from memory in Rust., viewed ,<https://www.scien.cx/2022/12/08/how-to-execute-shellcodes-from-memory-in-rust/>
VANCOUVER
Sylvain Kerkour | Sciencx - » How to execute shellcodes from memory in Rust. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/12/08/how-to-execute-shellcodes-from-memory-in-rust/
CHICAGO
" » How to execute shellcodes from memory in Rust." Sylvain Kerkour | Sciencx - Accessed . https://www.scien.cx/2022/12/08/how-to-execute-shellcodes-from-memory-in-rust/
IEEE
" » How to execute shellcodes from memory in Rust." Sylvain Kerkour | Sciencx [Online]. Available: https://www.scien.cx/2022/12/08/how-to-execute-shellcodes-from-memory-in-rust/. [Accessed: ]
rf:citation
» How to execute shellcodes from memory in Rust | Sylvain Kerkour | Sciencx | https://www.scien.cx/2022/12/08/how-to-execute-shellcodes-from-memory-in-rust/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.