kudaes / dinvoke_rs Goto Github PK
View Code? Open in Web Editor NEWDynamically invoke arbitrary unmanaged code
License: MIT License
Dynamically invoke arbitrary unmanaged code
License: MIT License
Hello !
Thank you for the repo :)
Could you provide more examples of using the repo ? Especially how to add other API type in the data folder, that would be amazing :)
You can add me on Discord nariod#4621
Cheers !
Not supporting win7?
Hi Kudaes,
thank you for this amazing project. I played around with HW breakpoints and tried to create a simple poc with the APIs you have already implemented. This is my code:
use std::{ffi::c_void, ptr};
use data::{THREAD_ALL_ACCESS, PVOID, PAGE_EXECUTE_READWRITE, MEM_COMMIT, MEM_RESERVE, PAGE_READWRITE, PAGE_EXECUTE_READ, PS_ATTRIBUTE_LIST};
use bindings::Windows::Win32::Foundation::HANDLE;
static X64: [u8; 106] = [0x53, 0x56, 0x57, 0x55, 0x54, 0x58, 0x66, 0x83, 0xE4, 0xF0, 0x50, 0x6A, 0x60, 0x5A, 0x68, 0x63, 0x61, 0x6C, 0x63, 0x54, 0x59, 0x48, 0x29, 0xD4, 0x65, 0x48, 0x8B, 0x32, 0x48, 0x8B, 0x76, 0x18, 0x48, 0x8B, 0x76, 0x10, 0x48, 0xAD, 0x48, 0x8B, 0x30, 0x48, 0x8B, 0x7E, 0x30, 0x03, 0x57, 0x3C, 0x8B, 0x5C, 0x17, 0x28, 0x8B, 0x74, 0x1F, 0x20, 0x48, 0x01, 0xFE, 0x8B, 0x54, 0x1F, 0x24, 0x0F, 0xB7, 0x2C, 0x17, 0x8D, 0x52, 0x02, 0xAD, 0x81, 0x3C, 0x07, 0x57, 0x69, 0x6E, 0x45, 0x75, 0xEF, 0x8B, 0x74, 0x1F, 0x1C, 0x48, 0x01, 0xFE, 0x8B, 0x34, 0xAE, 0x48, 0x01, 0xF7, 0x99, 0xFF, 0xD7, 0x48, 0x83, 0xC4, 0x68, 0x5C, 0x5D, 0x5F, 0x5E, 0x5B, 0xC3];
fn main() {
let process_id = get_process_id_by_name("notepad.exe");
unsafe {
//open handle
//----------------------------------------------------------------------------------------------
// We active the use of hardware breakpoints to spoof syscall parameters
dinvoke::use_hardware_breakpoints(true);
// We get the memory address of our function and set it as the
// top-level exception handler.
let handler = dinvoke::breakpoint_handler as usize;
dinvoke::set_unhandled_exception_filter(handler);
let h = HANDLE {0: -1};
let handle: *mut HANDLE = std::mem::transmute(&h);
//let mut handle_ptr: *mut HANDLE = Box::into_raw(Box::new(h));
let access = THREAD_ALL_ACCESS;
let attributes: *mut bindings::Windows::Win32::System::WindowsProgramming::OBJECT_ATTRIBUTES = std::mem::transmute(&bindings::Windows::Win32::System::WindowsProgramming::OBJECT_ATTRIBUTES::default());
// We set the PID of the remote process
let remote_pid = process_id as isize;
let c: data::CLIENT_ID = data::CLIENT_ID {unique_process: bindings::Windows::Win32::Foundation::HANDLE {0: remote_pid}, unique_thread: bindings::Windows::Win32::Foundation::HANDLE::default()};
let client_id: *mut data::CLIENT_ID = std::mem::transmute(&c);
// A call to NtOpenProcess is performed through Dinvoke. The parameters will be
// automatically spoofed by the function and restored to the original values
// before executing the syscall.
let ret1 = dinvoke::nt_open_process(handle, access, attributes, client_id);
if ret1 != 0 {
panic!("NTSTATUS openprocess hwb: {:x}", ret1);
}
println!("NTSTATUS openprocess hwb: {:x}\n", ret1);
//alloc
//----------------------------------------------------------------------------------------------
let base_address: *mut PVOID = std::mem::transmute(&usize::default());
let nsize: usize = X64.len() as usize;
let size: *mut usize = std::mem::transmute(&(nsize));
let ret2 = dinvoke::nt_allocate_virtual_memory(*(handle), base_address, 0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if ret2 != 0 {
panic!("NTSTATUS alloc hwb: {:x}", ret2);
}
println!("NTSTATUS alloc hwb: {:x}\nAt Address: 0x{:x}\n", ret2, *(base_address) as usize);
//write
//----------------------------------------------------------------------------------------------
let buffer: *mut c_void = std::mem::transmute(X64.as_ptr());
let bytes_written: *mut usize = std::mem::transmute(&usize::default());
let ret3 = dinvoke::nt_write_virtual_memory(*(handle), *base_address, buffer, nsize, bytes_written);
if ret3 != 0 {
panic!("NTSTATUS write hwb: {:x}", ret3);
}
println!("NTSTATUS write hwb: {:x}\nSupplied size: {}\nBytes written: {}\n", ret3, nsize, *bytes_written);
//protek
//----------------------------------------------------------------------------------------------
let old_protection: *mut u32 = std::mem::transmute(&u32::default());
let ret4 = dinvoke::nt_protect_virtual_memory(*handle, base_address, size, PAGE_EXECUTE_READ, old_protection);
if ret4 != 0 {
panic!("NTSTATUS write hwb: {:x}", ret4);
}
println!("NTSTATUS protek hwb: {:x}\nBytes reprotek: {}\nOld protek: 0x{:x}", ret4, *size, *old_protection);
//resume thread / exec
//----------------------------------------------------------------------------------------------
let thread_h = HANDLE {0: -1};
let thread_handle: *mut HANDLE = std::mem::transmute(&thread_h);
let lpStartAddress: PVOID = std::mem::transmute(base_address);
let lpParameter: PVOID = ptr::null_mut();
let mut attribut_list: PS_ATTRIBUTE_LIST = PS_ATTRIBUTE_LIST { size: 0, unk1: 0, unk2: 0, unk3: ptr::null_mut(), unk4: 0, unk5: 0, unk6: 0, unk7: ptr::null_mut(), unk8: 0 };
let attribut_list_ptr: *mut PS_ATTRIBUTE_LIST = std::mem::transmute(&attribut_list);
/*let ret5 = dinvoke::nt_create_thread_ex(thread_handle, THREAD_ALL_ACCESS, attributes, *handle, lpStartAddress, lpParameter, 4, 0, 0, 0, attribut_list_ptr);
if ret5 != 0 {
panic!("NTSTATUS write hwb: {:x}", ret5);
}
println!("NTSTATUS resume hwb: {:x}", ret5);*/
//close handle
//----------------------------------------------------------------------------------------------
if !dinvoke::close_handle(*handle) {
println!("Success");
};
}
}
However, when I compile it, it works exactely once. On the second run, I get the error c0000018 (STATUS_CONFLICTING_ADDRESSES) from nt_allocate_virtual_memory. Please see an exemplary output below:
C:\Users\...\target\release>dinvoketest.exe
NTSTATUS openprocess hwb: 0
NTSTATUS alloc hwb: 0
At Address: 0x7ff625640000
NTSTATUS write hwb: 0
Supplied size: 28672
Bytes written: 28672
NTSTATUS protek hwb: 0
Bytes reprotek: 28672
Old protek: 0x4
C:\Users\...\target\release>dinvoketest.exe
NTSTATUS openprocess hwb: 0
thread 'main' panicked at 'NTSTATUS alloc hwb: c0000018', src\main.rs:79:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
When I call dinvoke::nt_open_process
and then dinvoke::nt_allocate_virtual_memory
one by one without any other code the execution also works multiple times. As soon as I add more code, the c0000018 catches me again. What am I doing wrong here?
Also, could you please provide an example of calling dinvoke::nt_create_thread_ex
?
It would be very much appreciated
I try this.
let ret: Option<i32>;
let func_ptr: unsafe extern "system" fn () -> i32;
let ntdll = dinvoke::get_module_base_address("ntdll.dll");
dinvoke::dynamic_invoke!(ntdll,"NtTestAlert",func_ptr,ret);
But the complier reports an error
error: unexpected end of macro invocation
--> src\main.rs:39:66
|
39 | dinvoke::dynamic_invoke!(ntdll,"NtTestAlert",func_ptr,ret);
| ^ missing tokens in macro arguments
|
note: while trying to match `,`
--> D:\DevDir\Rust\dinvoke_nta\dinvoke\src\lib.rs:1391:40
|
1391 | ($a:expr, $b:expr, $c:expr, $d:expr, $($e:tt)*) => {
| ^
let cmd: String = String::from("Echo dynamically loaded");
let func_ptr: unsafe extern "Rust" fn (*const c_char) -> *const c_char; // Function header
let ret: Option<i32>; // The value that the called function will return
unsafe {
let parameter1 = cmd.as_ptr() as *const c_char;
dinvoke::dynamic_invoke!(overload.1, "command", func_ptr, ret, parameter1);
}
It throws
|
86 | dinvoke::dynamic_invoke!(overload.1, "command", func_ptr, ret, parameter1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found *-ptr
|
= note: expected type `i32`
found raw pointer `*const i8
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.