Skip to content

Instantly share code, notes, and snippets.

@etra0
Last active December 27, 2020 19:44
Show Gist options
  • Save etra0/bd2e498a370bb44a2582c78eb15d2af3 to your computer and use it in GitHub Desktop.
Save etra0/bd2e498a370bb44a2582c78eb15d2af3 to your computer and use it in GitHub Desktop.

I did this exercise in order to learn about internal hacking using DLL injection and interfacing ASM with Rust.

This code will not compile by itself, you need to create the rust structure which should look something like this

dll
├── Cargo.toml
├── build.rs
└── src
    ├── interceptor.asm
    └── lib.rs

In the Cargo.toml you have to specify this

[lib]
crate-type = ["cdylib"]

in order to create an injectable DLL because symbols 'n stuff.

The build script is just as simple as

fn main() {
    cc::Build::new()
        .file("src/interceptor.asm")
        .compile("interceptor");
    println!("cargo:rerun-if-changed=interceptor.asm");
}
EXTERN array_start: qword
EXTERN _end: qword
EXTERN new_value: qword
EXTERN my_arr: qword
PUBLIC get_values
.code
get_values PROC
pushf
cmp [array_start],rcx
ja @f
mov [array_start],rcx
@@:
; original code
popf
lea rax,[my_arr]
mov rax,[rax + rdx*8 + 08]
mov [rcx + rdx*8 + 08],rax
jmp [_end]
get_values ENDP
END
use std::ffi::{CStr, CString};
use std::io;
use std::os::raw::c_char;
use std::ptr;
use winapi;
use winapi::shared::minwindef::{BOOL, DWORD, HINSTANCE, LPVOID};
use winapi::um::consoleapi::AllocConsole;
macro_rules! export_var {
($($name:ident: $v:ty = $val:expr),*) => {
$(#[no_mangle] pub static mut $name: $v = $val;)*
}
}
/// Export variables for interfacing with the ASM code using the macro of above.
/// (basically I wanted a no_mangle scoped)
export_var!{
array_start: usize = std::usize::MIN,
_end: usize = 0,
new_value: f64 = 0.,
my_arr: [f64; 120] = [0f64; 120]
}
extern "C" {
static get_values: u8;
}
/// Replaces an array of bytes for a jmp f
/// in order to hook our own code.
fn hook_fun(dest: usize, f: *const u8, len: usize) {
let nops = vec![0x90; len];
let mut _t: DWORD = 0;
unsafe {
let result = winapi::um::memoryapi::VirtualProtect(
dest as LPVOID,
len,
winapi::um::winnt::PAGE_EXECUTE_READWRITE,
&mut _t
);
}
println!("{:?}", std::io::Error::last_os_error());
let mut ptr = dest as *mut u8;
// nop the stuff
unsafe {
for n in nops {
*ptr = n;
}
}
let _f: isize = (f as isize);
let _dest: isize = dest as isize;
let r_addr: DWORD = (_f - _dest) as DWORD - 5;
let mut ptr = dest as *mut u8;
unsafe {
*ptr = 0xE9; // jmp opcode
let ptr = (dest + 1) as *mut DWORD; // target address
*ptr = r_addr;
}
}
#[no_mangle]
pub unsafe extern "system" fn intercept_input(_: LPVOID) -> DWORD {
use winapi::um;
// AllocConsole();
let _name = CString::new("CHARTV.dll").unwrap();
let mba = um::libloaderapi::GetModuleHandleA(_name.as_ptr()) as usize;
// specific offset which may not work for every taskmgr.exe
let target_addr = mba + 0x312E;
let mut _b = String::new();
unsafe {
// _end is used by the asm injection to jmp back from our
// injection to their own code.
_end = target_addr + 5;
hook_fun(target_addr, &get_values as *const u8, 5);
}
let _t = CString::new("Enjoy the waves!").unwrap();
winapi::um::winuser::MessageBoxA(std::ptr::null_mut(), _t.as_ptr(), _t.as_ptr(), 0);
println!("Enjoy the waves!");
// dirty math to create sinusoidal chart
let mut t = 0f64;
loop {
for i in 0..my_arr.len() {
let _i = (i as f64)/10f64;
my_arr[i] = 50f64*(1f64 + (t + _i).sin())
}
t += 1e-5;
if t > 2.*3.14 {
t = 0f64;
}
}
// winapi::um::wincon::FreeConsole();
return 1;
}
#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn DllMain(_: HINSTANCE, reason: DWORD, _: LPVOID) -> BOOL {
unsafe {
match reason {
winapi::um::winnt::DLL_PROCESS_ATTACH => {
winapi::um::processthreadsapi::CreateThread(
ptr::null_mut(),
0,
Some(intercept_input),
ptr::null_mut(),
0,
ptr::null_mut(),
);
}
_ => (),
};
}
return true as BOOL;
}
@GreenMine
Copy link

Hello. Can you check instagram direct message?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment