diff --git a/.cargo/config b/.cargo/config index d96d520..f66f8e3 100644 --- a/.cargo/config +++ b/.cargo/config @@ -6,15 +6,15 @@ rustflags = [ # Pre Link Args #"-Z", "pre-link-arg=/NOLOGO", #"-Z", "pre-link-arg=/NXCOMPAT", - # "-Z", "pre-link-arg=/NODEFAULTLIB", + "-Z", "pre-link-arg=/NODEFAULTLIB", #"-Z", "pre-link-arg=/DYNAMICBASE", #"-Z", "pre-link-arg=/MANIFEST:NO", - + "--emit", "asm", # Post Link Args - #"-C", "link-arg=/ENTRY:main", + "-C", "link-arg=/ENTRY:main", #"-C", "link-arg=/OPT:REF,ICF", - #"-C", "link-arg=/MERGE:.edata=.rdata", - #"-C", "link-arg=/MERGE:.rustc=.data", + "-C", "link-arg=/MERGE:.edata=.rdata", + "-C", "link-arg=/MERGE:.rustc=.data", #"-C", "link-arg=/INTEGRITYCHECK" "-C", "target-feature=-mmx,-sse,+soft-float" diff --git a/src/main.rs b/src/main.rs index 2d59e40..a991647 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,19 +1,81 @@ #![allow(non_camel_case_types)] #![allow(overflowing_literals)] -// #![no_std] +#![no_std] #![no_main] #![feature(asm)] #![feature(link_args)] use core::{ptr::null_mut, slice, usize}; // use std::{ffi::OsString, str::FromStr}; // use std::os::windows::prelude::*; -use std::ffi::CString; -use std::os::raw::c_char; +// use std::ffi::CString; +// use std::os::raw::c_char; // use ntapi::winapi_local::um::winnt::__readgsqword; -// #[panic_handler] -// fn panic(_: &core::panic::PanicInfo) -> ! { -// loop {} -// } +#[panic_handler] +fn panic(_: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[no_mangle] +// #[link_section = ".text.prologue"] +pub extern "C" fn main() -> ! { + // "KERNEL32.DLL" + let KERNEL32_STR:[u16;13]= [75, 69, 82, 78, 69, 76, 51, 50, 46, 68, 76, 76, 0]; + let kk = get_module_by_name(KERNEL32_STR.as_ptr()); + // println!("kernel32: {:p}", kk); + // let kk = get_module_by_name(12); + let OutputDebugStringA_STR:[u8;19] = [79, 117, 116, 112, 117, 116, 68, 101, 98, 117, 103, 83, 116, 114, 105, 110, 103, 65, 0]; + let dbg_addr = get_func_by_name(kk, OutputDebugStringA_STR.as_ptr()); + // "LoadLibraryA" + let LoadLibraryA_STR:[u8;13] = [76, 111, 97, 100, 76, 105, 98, 114, 97, 114, 121, 65, 0]; + let load_library = get_func_by_name(kk, LoadLibraryA_STR.as_ptr()); + + // "GetProcAddress" + let GetProcAddress_STR:[u8;15] = [71, 101, 116, 80, 114, 111, 99, 65, 100, 100, 114, 101, 115, 115, 0]; + let get_proc = get_func_by_name(kk, GetProcAddress_STR.as_ptr()); + // println!("dbg_addr: {:p}", dbg_addr); + // println!("load_library: {:p}", load_library); + + let LoadLibraryA: extern "system" fn(lpFileName: LPCSTR) -> PVOID = + unsafe { core::mem::transmute(load_library) }; + // let a = "user32.dll"; + // let c_str = CString::new("user32.dll").unwrap(); + // let c_world: *const c_char = c_str.as_ptr() as *const c_char; + // let c_world = b"user32.dll\0".as_ptr() as *const i8; + let c_world:[i8;11] =[117, 115, 101, 114, 51, 50, 46, 100, 108, 108, 0]; + unsafe{asm!("push rax");} + let u32_dll = LoadLibraryA(c_world.as_ptr()); + // println!("u32_dll: {:p}", u32_dll); + + // pub unsafe extern "system" fn GetProcAddress( + // hModule: HMODULE, + // lpProcName: LPCSTR + // ) -> FARPROC + + let GetProcAddress: extern "system" fn(hmodule: PVOID, name: LPCSTR) -> PVOID = unsafe {core::mem::transmute(get_proc)} ; + + // let c_str = CString::new("MessageBoxA").unwrap(); + // let c_world: *const c_char = c_str.as_ptr() as *const c_char; + // let c_world = b"MessageBoxA\0".as_ptr() as *const i8; + let c_world:[i8;12] = [77, 101, 115, 115, 97, 103, 101, 66, 111, 120, 65, 0]; + let message_box_ptr = GetProcAddress(u32_dll, c_world.as_ptr()); + + // println!("message_box_ptr: {:p}", message_box_ptr); + + let MessageBoxA: extern "system" fn(h: PVOID, text: LPCSTR, cation: LPCSTR, t:u32) -> u32 = unsafe {core::mem::transmute(message_box_ptr)}; + + MessageBoxA(null_mut(), c_world.as_ptr(), c_world.as_ptr(), 0x30); + // https://stackoverflow.com/questions/46134477/how-can-i-call-a-raw-address-from-rust + let OutputDebugStringA: extern "C" fn(*const i8) = unsafe { core::mem::transmute(dbg_addr) }; + // let c_str = CString::new("helloxx").unwrap(); + // let c_world: *const c_char = c_str.as_ptr() as *const c_char; + // let c_str = "helloxxx123"; + // let c_str:[u8;3] = [0x41,0x42,0x0]; + // let c_world = c_str.as_ptr(); + // // // // println!("1: {:?}", c_world); + OutputDebugStringA(c_world.as_ptr()); + loop {} +} + // https://stackoverflow.com/questions/48586816/converting-raw-pointer-to-16-bit-unicode-character-to-file-path-in-rust // unsafe fn u16_ptr_to_string(ptr: *const u16) -> OsString { // let len = (0..).take_while(|&i| *ptr.offset(i) != 0).count(); @@ -61,6 +123,46 @@ fn compare_str_u16(s: &str, u: *const u16) -> bool { return true; } } +// #[inline(always)] +fn compare_u16_u16(s: *const u16, u: *const u16) -> bool { + unsafe { + let u_len = (0..).take_while(|&i| *u.offset(i) != 0).count(); + let u_slice = core::slice::from_raw_parts(u, u_len); + + let s_len = (0..).take_while(|&i| *s.offset(i) != 0).count(); + let s_slice = core::slice::from_raw_parts(s, s_len); + + if s_len != u_len { + return false; + } + for i in 0..s_len { + if s_slice[i] != u_slice[i] { + return false; + } + } + return true; + } +} +// #[inline(always)] +fn compare_u8_u8(s: *const u8, u: *const u8) -> bool { + unsafe { + let u_len = (0..).take_while(|&i| *u.offset(i) != 0).count(); + let u_slice = core::slice::from_raw_parts(u, u_len); + + let s_len = (0..).take_while(|&i| *s.offset(i) != 0).count(); + let s_slice = core::slice::from_raw_parts(s, s_len); + + if s_len != u_len { + return false; + } + for i in 0..s_len { + if s_slice[i] != u_slice[i] { + return false; + } + } + return true; + } +} fn compare_str_u8(s: &str, u: *const u8) -> bool { unsafe { let len = (0..).take_while(|&i| *u.offset(i) != 0).count(); @@ -78,7 +180,12 @@ fn compare_str_u8(s: &str, u: *const u8) -> bool { return true; } } -fn get_module_by_name(module_name: &str) -> PVOID { + +fn str_to_i8(s: &str) -> *const i8 { + s.as_bytes().as_ptr() as *const i8 +} +// #[inline(always)] +fn get_module_by_name(module_name:*const u16) -> PVOID { unsafe { let peb: *mut PEB; asm!( @@ -89,13 +196,13 @@ fn get_module_by_name(module_name: &str) -> PVOID { let mut list = &((*ldr).InLoadOrderModuleList); let mut curr_module: *mut LDR_DATA_TABLE_ENTRY = &mut list as *mut _ as *mut _; loop { - println!("loop start"); + // println!("loop start"); if curr_module.is_null() || (*curr_module).BaseAddress.is_null() { - println!( - "gg, {}, {}", - curr_module.is_null(), - (*curr_module).BaseAddress.is_null() - ); + // println!( + // "gg, {}, {}", + // curr_module.is_null(), + // (*curr_module).BaseAddress.is_null() + // ); // break; } let mut curr_name = (*curr_module).BaseDllName.Buffer; @@ -103,20 +210,20 @@ fn get_module_by_name(module_name: &str) -> PVOID { // continue; } // curr_name = curr_name.offset(1) - // println!("1"); + // // println!("1"); let mut i: isize = 0; - // println!("2"); - // println!("curr_name: {:?}", curr_name); + // // println!("2"); + // // println!("curr_name: {:?}", curr_name); if curr_name.is_null() { } else { // let name = u16_ptr_to_string(curr_name); let name_len = u16_ptr_len(curr_name); // let name = ""; - // // println!("name===: {} {:?}", name.len(), name); + // // // println!("name===: {} {:?}", name.len(), name); // if name_len == module_name.len() { - if compare_str_u16(module_name, curr_name) { - println!("base: {:?}", (*curr_module).BaseAddress); + if compare_u16_u16(module_name, curr_name) { + // println!("base: {:?}", (*curr_module).BaseAddress); // break; return (*curr_module).BaseAddress; } @@ -126,16 +233,17 @@ fn get_module_by_name(module_name: &str) -> PVOID { let flink = (*curr_module).InLoadOrderModuleList.Flink; curr_module = flink as *mut LDR_DATA_TABLE_ENTRY; } - // // println!("") + // // // println!("") } } // fn get_func_by_name(module: PVOID) -> PVOID{ -fn get_func_by_name(module: PVOID, func_name: &str) -> PVOID { +// #[inline(always)] +fn get_func_by_name(module: PVOID, func_name: *const u8) -> PVOID { let idh: *const IMAGE_DOS_HEADER = module as *const _; unsafe { if (*idh).e_magic != IMAGE_DOS_SIGNATURE { - // println!("e_magic eror"); + // // println!("e_magic eror"); } else { } let e_lfanew = (*idh).e_lfanew; @@ -147,9 +255,9 @@ fn get_func_by_name(module: PVOID, func_name: &str) -> PVOID { let exp_addr = exp_dir.VirtualAddress; if exp_addr == 0 { - // println!("virtualaddr error"); + // // println!("virtualaddr error"); } else { - // println!("virtualAddr: 0x{:x} {}", exp_addr, exp_addr); + // // println!("virtualAddr: 0x{:x} {}", exp_addr, exp_addr); } // let exp_dir_raw = exp_dir as *const _ as *const u8; let exp: *const IMAGE_EXPORT_DIRECTORY = (module as *const u8).offset(exp_addr as _) as _; // this case error? @@ -158,9 +266,9 @@ fn get_func_by_name(module: PVOID, func_name: &str) -> PVOID { let func_names_rva = (*exp).AddressOfNames; let names_ords_rva = (*exp).AddressOfNameOrdinals; - // println!("names_count: {}", names_count); + // // println!("names_count: {}", names_count); for i in 0..names_count { - // // println!("=== {} ===", i); + // // // println!("=== {} ===", i); let name_rva: *const DWORD = (module as *const u8).offset((func_names_rva + i * 4) as isize) as *const _; let name_index: *const WORD = @@ -179,14 +287,14 @@ fn get_func_by_name(module: PVOID, func_name: &str) -> PVOID { } // let len = (0..).take_while(|&i| *curr_name.offset(i) != 0).count(); // let slice = core::slice::from_raw_parts(curr_name, len); - // // println!("cur_name: {:?}",slice); + // // // println!("cur_name: {:?}",slice); // OutputDebugStringA // if slice[0] == 'O' as u8 && slice[6] == 'D' as u8 { - if compare_str_u8(func_name, curr_name) { + if compare_u8_u8(func_name, curr_name) { // for i in slice { //print!("{}", *i as char); // } - // println!(""); + // // println!(""); // break; let mo = (module as *const u8).offset(*func_rva as isize); // return 0; @@ -199,9 +307,9 @@ fn get_func_by_name(module: PVOID, func_name: &str) -> PVOID { // if load_library[i] == slice[i] { // continue // } else { - // // println!("{} => {}", i, load_library.len()); + // // // println!("{} => {}", i, load_library.len()); // if load_library.len() - i < 2 { - // // println!("got it: {:?}", slice); + // // // println!("got it: {:?}", slice); // } // break; @@ -217,37 +325,6 @@ fn get_func_by_name(module: PVOID, func_name: &str) -> PVOID { type LPCSTR = *const i8; // pub unsafe extern "system" fn LoadLibraryA(lp_lib_file_name: *const i8) -> isize; // pub unsafe extern "system" fn OutputDebugStringA(lpOutputString: LPCSTR) -#[no_mangle] -// #[link_section = ".text.prologue"] -pub extern "C" fn main() -> ! { - let kk = get_module_by_name("KERNEL32.DLL"); - println!("kernel32: {:p}", kk); - // let kk = get_module_by_name(12); - let dbg_addr = get_func_by_name(kk, "OutputDebugStringA"); - let load_library = get_func_by_name(kk, "LoadLibraryA"); - let get_proc = get_func_by_name(kk, "GetProcAddress"); - println!("dbg_addr: {:p}", dbg_addr); - println!("load_library: {:p}", load_library); - - let LoadLibraryA: extern "system" fn(lpFileName: LPCSTR) -> PVOID = - unsafe { core::mem::transmute(load_library) }; - // let a = "user32.dll"; - let c_str = CString::new("user32.dll").unwrap(); - let c_world: *const c_char = c_str.as_ptr() as *const c_char; - let u32_dll = LoadLibraryA(c_world); - println!("u32_dll: {:p}", u32_dll); - - // https://stackoverflow.com/questions/46134477/how-can-i-call-a-raw-address-from-rust - // let OutputDebugStringA: extern "C" fn(*const i8) = unsafe { core::mem::transmute(dbg_addr) }; - // let c_str = CString::new("helloxx").unwrap(); - // let c_world: *const c_char = c_str.as_ptr() as *const c_char; - // let c_str = "helloxxx123"; - // let c_str:[u8;3] = [0x41,0x42,0x0]; - // let c_world = c_str.as_ptr(); - // // // println!("1: {:?}", c_world); - // OutputDebugStringA(c_world as _); - loop {} -} #[cfg(test)] mod tests { @@ -260,10 +337,10 @@ mod tests { } } -// #[allow(unused_attributes)] -// #[cfg(target_env = "msvc")] -// #[link_args = "/GS- /MERGE:.rdata=.text /MERGE:.pdata=.text /NODEFAULTLIB /EMITPOGOPHASEINFO /DEBUG:NONE"] -// extern "C" {} +#[allow(unused_attributes)] +#[cfg(target_env = "msvc")] +#[link_args = "/GS- /MERGE:.rdata=.text /MERGE:.pdata=.text /NODEFAULTLIB /EMITPOGOPHASEINFO /DEBUG:NONE"] +extern "C" {} /// NT Status type. pub type NTSTATUS = Status; type HMODULE = HINSTANCE;