shellcode run success(messagebox, outdebugstring), but need stack align hack

This commit is contained in:
b1
2021-02-03 17:57:29 +08:00
parent 7ab18c2251
commit b7446b4d7f
2 changed files with 149 additions and 72 deletions
+5 -5
View File
@@ -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"
+144 -67
View File
@@ -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;