This commit is contained in:
b1
2021-02-05 17:36:28 +08:00
parent 9d18d77bd5
commit 071fbad9d8
5 changed files with 108 additions and 215 deletions
+7 -2
View File
@@ -15,8 +15,13 @@ rustflags = [
#"-C", "link-arg=/OPT:REF,ICF",
"-C", "link-arg=/MERGE:.edata=.rdata",
"-C", "link-arg=/MERGE:.rustc=.data",
"-C", "link-arg=/MERGE:.rdata=.text",
"-C", "link-arg=/MERGE:.pdata=.text",
#"-C", "link-arg=/INTEGRITYCHECK"
"-C", "link-arg=/DEBUG:NONE",
"-C", "link-arg=/EMITPOGOPHASEINFO",
"-C", "target-feature=-mmx,-sse,+soft-float"
"-C", "target-feature=-mmx,-sse,+soft-float"
]
]
+4 -1
View File
@@ -12,4 +12,7 @@ https://github.com/johnthagen/min-sized-rust
edit
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4acc288a658ce23cb2c3da66aa818b8d
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4acc288a658ce23cb2c3da66aa818b8d
https://stackoverflow.com/questions/46134477/how-can-i-call-a-raw-address-from-rust
+2
View File
@@ -1,5 +1,6 @@
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(dead_code)]
pub enum c_void {}
pub type BOOLEAN = u8;
@@ -28,6 +29,7 @@ pub struct PEB_LDR_DATA {
// ...
}
pub type PLDR_DATA_TABLE_ENTRY = *const LDR_DATA_TABLE_ENTRY;
#[repr(C)]
pub struct LDR_DATA_TABLE_ENTRY {
pub InLoadOrderModuleList: LIST_ENTRY,
+76 -203
View File
@@ -1,263 +1,136 @@
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![allow(overflowing_literals)]
#![no_std]
#![no_main]
#![feature(asm)]
#![feature(link_args)]
use core::{ptr::null_mut, slice, usize};
use core::ptr::null_mut;
mod binds;
mod utils;
use arrayvec::ArrayString;
use binds::*;
use utils::*;
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
loop {}
}
// use winapi::um::libloaderapi::LoadLibraryA;
// pub type LLA = extern "stdcall" LoadLibraryA;
// const KERNEL32_DLL: &str = concat!("KERNEL32.DLL", "\0");
const USER32_DLL: &str = concat!("user32.dll", "\0");
const OutputDebugStringA_: &str = concat!("OutputDebugStringA", "\0");
const LoadLibraryA_: &str = concat!("LoadLibraryA", "\0");
const GetProcAddress_: &str = concat!("GetProcAddress", "\0");
const MessageBoxA_: &str = concat!("MessageBoxA", "\0");
pub type LoadLibraryAFn = extern "system" fn(lpFileName: LPCSTR) -> PVOID;
pub type GetProcAddressFn = extern "system" fn(hmodule: PVOID, name: LPCSTR) -> PVOID;
pub type MessageBoxAFn = extern "system" fn(h: PVOID, text: LPCSTR, cation: LPCSTR, t: u32) -> u32;
pub type OutputDebugStringAFn = extern "C" fn(*const i8);
pub type DbgPrintFn = extern "C" fn(Format: *const u8, ...) -> NTSTATUS;
#[no_mangle]
// #[link_section = ".text.prologue"]
pub extern "C" fn main() -> ! {
// "KERNEL32.DLL"
unsafe {
// clean argc and argv
asm!("mov rcx, 0", "mov rdx, 0",);
}
let KERNEL32_STR: [u16; 13] = [75, 69, 82, 78, 69, 76, 51, 50, 46, 68, 76, 76, 0];
// let KERNEL32_STR = "KERNEL32.DLL";
// username: Username::try_from_str("user")?,
// let KERNEL32_STR = KK20::try_from_str("KERNEL32.DLL");
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());
let kernel32_ptr = get_module_by_name(KERNEL32_STR.as_ptr());
let dbg_addr = get_func_by_name(kernel32_ptr, OutputDebugStringA_.as_ptr());
let load_library_ptr = get_func_by_name(kernel32_ptr, LoadLibraryA_.as_ptr());
let get_proc = get_func_by_name(kernel32_ptr, GetProcAddress_.as_ptr());
let LoadLibraryA: LoadLibraryAFn = unsafe { core::mem::transmute(load_library_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 LoadLibraryA_ :LoadLibraryA = 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");
// make stack align
unsafe { asm!("push rax") };
let u32_dll = LoadLibraryA(USER32_DLL.as_ptr() as *const i8);
let GetProcAddress: GetProcAddressFn = unsafe { core::mem::transmute(get_proc) };
let message_box_ptr = GetProcAddress(u32_dll, MessageBoxA_.as_ptr() as *const i8);
let MessageBoxA: MessageBoxAFn = unsafe { core::mem::transmute(message_box_ptr) };
MessageBoxA(
null_mut(),
MessageBoxA_.as_ptr() as *const i8,
MessageBoxA_.as_ptr() as _,
0x30,
);
let OutputDebugStringA: OutputDebugStringAFn = unsafe { core::mem::transmute(dbg_addr) };
#[macro_export]
macro_rules! debug_print {
($msg:expr) => {
OutputDebugStringA(concat!($msg, "\0").as_ptr() as _)
};
}
let u32_dll = LoadLibraryA(c_world);
// 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 c_world1 = b"xxx";
let c_world1 = "title\0";
// let c_world1 = aa + "123";
// c_world1.to_uppercase();
// let mut u = ArrayString::from_byte_string(b"hello world").unwrap();
// u.push_str("abc");
let message_box_ptr = GetProcAddress(u32_dll, c_world);
// 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, c_world1.as_ptr() as _, 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);
// let msg = b"mmmmsg";
// let msg: &[u8] = [b'a', b'b'];
//let a = "abc";
// OutputDebugStringA(msg.as_ptr() as _);
debug_print!("we made it! see me in DebugView or Debugger");
loop {}
}
fn get_module_by_name(module_name: *const u16) -> PVOID {
let peb: *mut PEB;
unsafe {
let peb: *mut PEB;
asm!(
"mov {}, gs:[0x60]",
out(reg) peb,
);
let ldr = (*peb).Ldr;
let mut list = &((*ldr).InLoadOrderModuleList);
let mut curr_module: *mut LDR_DATA_TABLE_ENTRY = &mut list as *mut _ as *mut _;
let list_entry = &((*ldr).InLoadOrderModuleList);
let mut cur_module: *const LDR_DATA_TABLE_ENTRY = &list_entry as *const _ as *const _;
loop {
// println!("loop start");
if curr_module.is_null() || (*curr_module).BaseAddress.is_null() {
// println!(
// "gg, {}, {}",
// curr_module.is_null(),
// (*curr_module).BaseAddress.is_null()
// );
// break;
if cur_module.is_null() || (*cur_module).BaseAddress.is_null() {
// TODO: when to break
}
let mut curr_name = (*curr_module).BaseDllName.Buffer;
if curr_name.is_null() {
// continue;
}
// curr_name = curr_name.offset(1)
// // println!("1");
let mut i: isize = 0;
// // println!("2");
// // println!("curr_name: {:?}", curr_name);
if curr_name.is_null() {
} else {
// let name = u16_ptr_to_string(curr_name);
// let name = "";
// // // println!("name===: {} {:?}", name.len(), name);
// if name_len == module_name.len() {
if compare_raw_str(module_name, curr_name) {
// println!("base: {:?}", (*curr_module).BaseAddress);
// break;
return (*curr_module).BaseAddress;
let cur_name = (*cur_module).BaseDllName.Buffer;
if !cur_name.is_null() {
if compare_raw_str(module_name, cur_name) {
return (*cur_module).BaseAddress;
}
}
// for
// break;
let flink = (*curr_module).InLoadOrderModuleList.Flink;
curr_module = flink as *mut LDR_DATA_TABLE_ENTRY;
let flink = (*cur_module).InLoadOrderModuleList.Flink;
cur_module = flink as *const LDR_DATA_TABLE_ENTRY;
}
// // // println!("")
}
}
// type LoadLibraryA
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");
} else {
return null_mut();
}
let e_lfanew = (*idh).e_lfanew;
// dbg!(e_lfanew);
let nt_headers: *const IMAGE_NT_HEADERS =
(module as *const u8).offset(e_lfanew as isize) as *const _;
let op_header = &(*nt_headers).OptionalHeader;
let exp_dir = &op_header.DataDirectory[0];
let virtual_addr = (&op_header.DataDirectory[0]).VirtualAddress;
let export_dir: *const IMAGE_EXPORT_DIRECTORY =
(module as *const u8).offset(virtual_addr as _) as _;
let number_of_names = (*export_dir).NumberOfNames;
let addr_of_funcs = (*export_dir).AddressOfFunctions;
let addr_of_names = (*export_dir).AddressOfNames;
let addr_of_ords = (*export_dir).AddressOfNameOrdinals;
for i in 0..number_of_names {
let name_rva_p: *const DWORD =
(module as *const u8).offset((addr_of_names + i * 4) as isize) as *const _;
let name_index_p: *const WORD =
(module as *const u8).offset((addr_of_ords + i * 2) as isize) as *const _;
let name_index = name_index_p.as_ref().unwrap();
let mut off: u32 = (4 * name_index) as u32;
off = off + addr_of_funcs;
let func_rva: *const DWORD = (module as *const u8).offset(off as _) as *const _;
let exp_addr = exp_dir.VirtualAddress;
if exp_addr == 0 {
// // println!("virtualaddr error");
} else {
// // 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?
let names_count = (*exp).NumberOfNames;
let funcs_rva = (*exp).AddressOfFunctions;
let func_names_rva = (*exp).AddressOfNames;
let names_ords_rva = (*exp).AddressOfNameOrdinals;
// // println!("names_count: {}", names_count);
for i in 0..names_count {
// // // 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 =
(module as *const u8).offset((names_ords_rva + i * 2) as isize) as *const _;
let name_i = name_index.as_ref().unwrap();
let mut off1: u32 = (4 * name_i) as u32;
off1 = off1 + funcs_rva;
let func_rva: *const DWORD = (module as *const u8).offset(off1 as isize) as *const _;
let mut rav_i = name_rva.as_ref().unwrap();
let curr_name = (module as *const u8).offset(*rav_i as isize);
let name_rva = name_rva_p.as_ref().unwrap();
let curr_name = (module as *const u8).offset(*name_rva as isize);
if *curr_name == 0 {
continue;
// let bla= CString::from_raw(curr_name as _);
}
// 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);
// OutputDebugStringA
// if slice[0] == 'O' as u8 && slice[6] == 'D' as u8 {
if compare_raw_str(func_name, curr_name) {
// for i in slice {
//print!("{}", *i as char);
// }
// // println!("");
// break;
let mo = (module as *const u8).offset(*func_rva as isize);
// return 0;
return mo as _;
let res = (module as *const u8).offset(*func_rva as isize);
return res as _;
}
// let c_string = CString::new("LoadLibraryA").expect("CString::new failed");
// let load_library = c_string.as_bytes();
// for i in 0..load_library.len() {
// if load_library[i] == slice[i] {
// continue
// } else {
// // // println!("{} => {}", i, load_library.len());
// if load_library.len() - i < 2 {
// // // println!("got it: {:?}", slice);
// }
// break;
// }
// }
// i
}
}
return 0 as _;
return null_mut();
}
// pub unsafe extern "system" fn LoadLibraryA(lp_lib_file_name: *const i8) -> isize;
// pub unsafe extern "system" fn OutputDebugStringA(lpOutputString: LPCSTR)
#[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.
extern "C" {
// /// `DbgPrint` routine sends a message to the kernel debugger.
// pub fn DbgPrint(Format: *const u8, ...) -> NTSTATUS;
// /// The `DbgPrintEx` routine sends a string to the kernel debugger if certain conditions are met.
// pub fn DbgPrintEx(ComponentId: u32, Level: u32, Format: *const u8, ...) -> NTSTATUS;
}
// #[macro_export]
// macro_rules! KdPrint {
// ($msg:expr $(, $arg:expr)*) => { unsafe { DbgPrint( concat!($msg, "\0").as_ptr() $(, $arg )* )} };
// }
// #[allow(unused_attributes)]
// #[cfg(target_env = "msvc")]
// #[link_args = "/GS- /MERGE:.rdata=.text /MERGE:.pdata=.text /NODEFAULTLIB /EMITPOGOPHASEINFO /DEBUG:NONE"]
// extern "C" {}
+19 -9
View File
@@ -1,3 +1,6 @@
#![allow(dead_code)]
unsafe fn u16_ptr_len(ptr: *const u16) -> usize {
let len = (0..).take_while(|&i| *ptr.offset(i) != 0).count();
return len;
@@ -21,7 +24,22 @@ fn compare_str_u16(s: &str, u: *const u16) -> bool {
}
}
use core::cmp::PartialEq;
// TODO: use alloc
pub fn str_to_u16_ptr(s: &str, buf: &mut [u16]) {
let s_len = s.len();
let s_bytes = s.as_bytes();
// for i in 0..255 {
// }
// let buf = vec![0u16;s_len+1];
for i in 0..s_len {
buf[i] = s_bytes[i] as _;
}
buf[s_len] = 0;
// buf.as_ptr()
}
use num_traits::Num;
pub fn compare_raw_str<T>(s: *const T, u: *const T) -> bool
@@ -68,11 +86,3 @@ fn compare_str_u8(s: &str, u: *const u8) -> bool {
fn str_to_i8(s: &str) -> *const i8 {
s.as_bytes().as_ptr() as *const i8
}
// 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();
// let slice = std::slice::from_raw_parts(ptr, len);
// OsString::from_wide(slice)
// }