Personal commit

This commit is contained in:
2024-08-21 19:01:00 -07:00
parent ba567d1bba
commit bdaa48defd
14 changed files with 424 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
[package]
name = "shellcode-util"
version = "0.1.0"
edition = "2021"
[dependencies]
utf16_lit = { workspace = true }
windows-sys = {workspace = true }
+128
View File
@@ -0,0 +1,128 @@
#![no_std]
#![feature(core_intrinsics)]
#![allow(internal_features)]
#![allow(unused_imports)]
use core::{arch::asm, ffi::CStr, intrinsics, slice};
use windows_sys::{
core::PCSTR,
Win32::{
Foundation::{HMODULE, UNICODE_STRING},
System::{
Diagnostics::Debug::{
IMAGE_DIRECTORY_ENTRY_EXPORT, IMAGE_NT_HEADERS32, IMAGE_NT_HEADERS64,
},
SystemServices::{IMAGE_DOS_HEADER, IMAGE_EXPORT_DIRECTORY},
Threading::TEB,
WindowsProgramming::LDR_DATA_TABLE_ENTRY,
},
},
};
pub unsafe fn get_module_handle_from_peb(module_name: &[u16]) -> Option<HMODULE> {
// Start at the top boys
let mut teb: *mut TEB;
#[cfg(target_arch = "x86")]
asm!(
"mov {}, fs:[0x18]",
out(reg) teb
);
#[cfg(target_arch = "x86_64")]
asm!(
"mov {}, gs:[0x30]",
out(reg) teb
);
// I will dereference every pointer
let teb = *teb;
let peb = *(teb.ProcessEnvironmentBlock);
let ldr_data = *(peb.Ldr);
// Hidden fields of PEB_LDR_DATA and LDR_DATA_TABLE_ENTRY abound
// Reserved2[0] = SsHandle, Reserved[1] = InLoadOrderLinks.Flink, Reserved[2] = InLoadOrderLinks.Blink
let mut module_list = *(ldr_data.Reserved2[1] as *mut LDR_DATA_TABLE_ENTRY);
while !module_list.DllBase.is_null() {
// BaseDllName
let base_dll_name = *(module_list.Reserved4.as_ptr() as *mut UNICODE_STRING);
let base_dll_name = slice::from_raw_parts(
base_dll_name.Buffer,
base_dll_name.Length as usize / size_of::<u16>(),
);
if module_name == base_dll_name {
return Some(module_list.DllBase as HMODULE);
}
// Reserved1[0] = InLoadOrderLinks.Flink, Reserved1[1] = InLoadOrderLinks.Blink
module_list = *(module_list.Reserved1[0] as *mut LDR_DATA_TABLE_ENTRY);
}
None
}
pub unsafe fn get_procedure_from_edt<F>(module: HMODULE, proc_name: &str) -> Option<F> {
let module = module as usize;
let proc_name = CStr::from_ptr(proc_name.as_ptr() as *const _);
let dos_headers = *(module as *const IMAGE_DOS_HEADER);
#[cfg(target_arch = "x86")]
let nt_headers = *((module + dos_headers.e_lfanew as usize) as *const IMAGE_NT_HEADERS32);
#[cfg(target_arch = "x86_64")]
let nt_headers = *((module + dos_headers.e_lfanew as usize) as *const IMAGE_NT_HEADERS64);
let export_directory = *((module
+ nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT as usize]
.VirtualAddress as usize)
as *const IMAGE_EXPORT_DIRECTORY);
let functions_table_ptr =
(module + export_directory.AddressOfFunctions as usize) as *const usize;
let names_table_ptr = (module + export_directory.AddressOfNames as usize) as *const usize;
let ordinals_table_ptr =
(module + export_directory.AddressOfNameOrdinals as usize) as *const u16;
let functions_table = slice::from_raw_parts(
functions_table_ptr,
export_directory.NumberOfFunctions as usize,
);
let names_table =
slice::from_raw_parts(names_table_ptr, export_directory.NumberOfNames as usize);
let ordinals_table =
slice::from_raw_parts(ordinals_table_ptr, export_directory.NumberOfNames as usize);
for i in 0..names_table.len() {
let name = CStr::from_ptr((module + names_table[i]) as *const _);
let ordinal = ordinals_table[i];
let address = functions_table[ordinal as usize];
if name == proc_name {
return Some(intrinsics::transmute_unchecked(module + address));
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
use utf16_lit::utf16;
fn get_module_test() {
let module = unsafe { get_module_handle_from_peb(&utf16!("KERNEL32.DLL")) };
assert!(!module.is_some());
}
fn get_procedure_test() {
let module = unsafe { get_module_handle_from_peb(&utf16!("KERNEL32.DLL")) };
assert!(module.is_some());
let procedure = unsafe {
get_procedure_from_edt::<extern "system" fn() -> u32>(module.unwrap(), "GetProcessId\0")
};
assert!(procedure.is_some());
let procedure = procedure.unwrap();
assert_ne!(procedure(), 0)
}
}