Personal commit
This commit is contained in:
parent
ba567d1bba
commit
bdaa48defd
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.idea/
|
||||||
|
target/
|
||||||
|
Cargo.lock
|
27
Cargo.toml
Normal file
27
Cargo.toml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
[workspace]
|
||||||
|
resolver = "2"
|
||||||
|
members = [
|
||||||
|
"app",
|
||||||
|
"shellcode",
|
||||||
|
"codeloader",
|
||||||
|
"shellcode-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
region = "3.0.2"
|
||||||
|
utf16_lit = "2.0.2"
|
||||||
|
|
||||||
|
[workspace.dependencies.windows-sys]
|
||||||
|
version = "0.59.0"
|
||||||
|
features = [
|
||||||
|
"Win32",
|
||||||
|
"Win32_Foundation",
|
||||||
|
"Win32_System",
|
||||||
|
"Win32_System_Diagnostics",
|
||||||
|
"Win32_System_Diagnostics_Debug",
|
||||||
|
"Win32_System_Kernel",
|
||||||
|
"Win32_System_SystemInformation",
|
||||||
|
"Win32_System_SystemServices",
|
||||||
|
"Win32_System_Threading",
|
||||||
|
"Win32_System_WindowsProgramming"
|
||||||
|
]
|
9
app/Cargo.toml
Normal file
9
app/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "app"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
shellcode-util = { path = "../shellcode-util" }
|
||||||
|
utf16_lit = { workspace = true }
|
||||||
|
windows-sys = { workspace = true }
|
57
app/src/main.rs
Normal file
57
app/src/main.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
extern crate core;
|
||||||
|
|
||||||
|
use core::{ffi::c_void, mem, ptr};
|
||||||
|
use shellcode_util::{get_module_handle_from_peb, get_procedure_from_edt};
|
||||||
|
use utf16_lit::utf16;
|
||||||
|
use windows_sys::{
|
||||||
|
core::PCSTR,
|
||||||
|
Win32::Foundation::{BOOL, HANDLE, HMODULE, HWND},
|
||||||
|
};
|
||||||
|
|
||||||
|
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
unsafe { shellcode() }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn shellcode() {
|
||||||
|
// Initial Imports
|
||||||
|
let kernel32 = get_module_handle_from_peb(&utf16!("KERNEL32.DLL")).unwrap();
|
||||||
|
let LoadLibraryA: extern "system" fn(PCSTR) -> HMODULE =
|
||||||
|
get_procedure_from_edt(kernel32, "LoadLibraryA\0").unwrap();
|
||||||
|
let GetProcAddress: extern "system" fn(HMODULE, PCSTR) -> *const () =
|
||||||
|
get_procedure_from_edt(kernel32, "GetProcAddress\0").unwrap();
|
||||||
|
|
||||||
|
// Console output
|
||||||
|
let GetStdHandle: extern "system" fn(u32) -> HANDLE =
|
||||||
|
mem::transmute(GetProcAddress(kernel32, "GetStdHandle\0".as_ptr()));
|
||||||
|
let output_handle = GetStdHandle(u32::MAX - 11);
|
||||||
|
let WriteConsoleA: extern "system" fn(HANDLE, PCSTR, u32, *mut u32, *mut c_void) -> BOOL =
|
||||||
|
mem::transmute(GetProcAddress(kernel32, "WriteConsoleA\0".as_ptr()));
|
||||||
|
|
||||||
|
let text = "Hello from Console!\n\0";
|
||||||
|
WriteConsoleA(
|
||||||
|
output_handle,
|
||||||
|
text.as_ptr(),
|
||||||
|
text.len() as u32,
|
||||||
|
ptr::null_mut(),
|
||||||
|
ptr::null_mut(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Messagebox
|
||||||
|
let user32 = LoadLibraryA("user32.dll\0".as_ptr());
|
||||||
|
let MessageBoxA: extern "system" fn(HWND, PCSTR, PCSTR, u32) -> i32 =
|
||||||
|
mem::transmute(GetProcAddress(user32, "MessageBoxA\0".as_ptr()));
|
||||||
|
|
||||||
|
let text = "Hello World!\0";
|
||||||
|
MessageBoxA(ptr::null_mut(), text.as_ptr(), text.as_ptr(), 0);
|
||||||
|
|
||||||
|
let text = "Bye World\0";
|
||||||
|
MessageBoxA(ptr::null_mut(), text.as_ptr(), text.as_ptr(), 0);
|
||||||
|
|
||||||
|
// Exit
|
||||||
|
let ExitProcess: extern "system" fn(u32) =
|
||||||
|
mem::transmute(GetProcAddress(kernel32, "ExitProcess\0".as_ptr()));
|
||||||
|
ExitProcess(5);
|
||||||
|
}
|
5
codeloader/.cargo/config.toml
Normal file
5
codeloader/.cargo/config.toml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[build]
|
||||||
|
target = "i686-pc-windows-msvc"
|
||||||
|
|
||||||
|
[alias]
|
||||||
|
runcode = "run -- ../target/i686-unknown-none/release/code.bin"
|
7
codeloader/Cargo.toml
Normal file
7
codeloader/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "codeloader"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
region = { workspace = true }
|
20
codeloader/src/main.rs
Normal file
20
codeloader/src/main.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + 'static>>;
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let file = std::env::args().nth(1).unwrap_or("code.bin".to_string());
|
||||||
|
|
||||||
|
let code = std::fs::read(file)?;
|
||||||
|
|
||||||
|
let code: extern "C" fn() = unsafe {
|
||||||
|
region::protect(
|
||||||
|
code.as_ptr(),
|
||||||
|
code.len(),
|
||||||
|
region::Protection::READ_WRITE_EXECUTE,
|
||||||
|
)?;
|
||||||
|
std::mem::transmute(code.as_ptr())
|
||||||
|
};
|
||||||
|
|
||||||
|
code();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
8
shellcode-util/Cargo.toml
Normal file
8
shellcode-util/Cargo.toml
Normal 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
shellcode-util/src/lib.rs
Normal file
128
shellcode-util/src/lib.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
29
shellcode.ld
Normal file
29
shellcode.ld
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* has a header still? objcopy -O binary output is accurate */
|
||||||
|
/* OUTPUT_FORMAT("binary") */
|
||||||
|
|
||||||
|
ENTRY(_start);
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = SIZEOF_HEADERS;
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text._start)
|
||||||
|
*(.text .text.*)
|
||||||
|
*(.rodata .rodata.*)
|
||||||
|
|
||||||
|
}
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.got .got.*)
|
||||||
|
*(.data .data.*)
|
||||||
|
*(.bss .bss.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
/DISCARD/ :
|
||||||
|
{
|
||||||
|
*(.comment)
|
||||||
|
*(.debug_frame)
|
||||||
|
*(.interp)
|
||||||
|
*(.note .note.*)
|
||||||
|
}
|
||||||
|
}
|
22
shellcode/.cargo/config.toml
Normal file
22
shellcode/.cargo/config.toml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[build]
|
||||||
|
target = "i686-unknown-none.json"
|
||||||
|
rustflags = [
|
||||||
|
"-Z", "no-unique-section-names=yes",
|
||||||
|
"-C", "link-args=--script=shellcode.ld --build-id=none"
|
||||||
|
]
|
||||||
|
|
||||||
|
[unstable]
|
||||||
|
build-std-features = ["compiler-builtins-mem"]
|
||||||
|
build-std = ["core", "compiler_builtins", "alloc"]
|
||||||
|
trim-paths = true
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = false
|
||||||
|
debug-assertions = false
|
||||||
|
overflow-checks = false
|
||||||
|
strip = true
|
||||||
|
lto = "fat"
|
||||||
|
opt-level = "z"
|
||||||
|
panic = "abort"
|
||||||
|
trim-paths = "all"
|
||||||
|
|
15
shellcode/Cargo.toml
Normal file
15
shellcode/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
cargo-features = ["different-binary-name"]
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "code"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "code"
|
||||||
|
filename = "code.bin"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
shellcode-util = { path = "../shellcode-util" }
|
||||||
|
utf16_lit = { workspace = true }
|
||||||
|
windows-sys = { workspace = true }
|
32
shellcode/i686-unknown-none.json
Normal file
32
shellcode/i686-unknown-none.json
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"arch": "x86",
|
||||||
|
"code-model": "kernel",
|
||||||
|
"cpu": "i686",
|
||||||
|
"crt-objects-fallback": "false",
|
||||||
|
"data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128",
|
||||||
|
"disable-redzone": true,
|
||||||
|
"features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float",
|
||||||
|
"linker": "rust-lld",
|
||||||
|
"linker-flavor": "gnu-lld",
|
||||||
|
"llvm-target": "i686-unknown-none-elf",
|
||||||
|
"max-atomic-width": 32,
|
||||||
|
"metadata": {
|
||||||
|
"description": "Freestanding/bare-metal i686 softfloat",
|
||||||
|
"host_tools": false,
|
||||||
|
"std": false,
|
||||||
|
"tier": 2
|
||||||
|
},
|
||||||
|
"panic-strategy": "abort",
|
||||||
|
"plt-by-default": false,
|
||||||
|
"position-independent-executables": true,
|
||||||
|
"relro-level": "full",
|
||||||
|
"stack-probes": {
|
||||||
|
"kind": "inline"
|
||||||
|
},
|
||||||
|
"static-position-independent-executables": true,
|
||||||
|
"supported-sanitizers": [
|
||||||
|
"kcfi",
|
||||||
|
"kernel-address"
|
||||||
|
],
|
||||||
|
"target-pointer-width": "32"
|
||||||
|
}
|
62
shellcode/src/main.rs
Normal file
62
shellcode/src/main.rs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
extern crate core;
|
||||||
|
|
||||||
|
use core::{
|
||||||
|
arch::asm,
|
||||||
|
ffi::c_void,
|
||||||
|
mem,
|
||||||
|
ptr
|
||||||
|
};
|
||||||
|
use shellcode_util::{get_module_handle_from_peb, get_procedure_from_edt};
|
||||||
|
use utf16_lit::utf16;
|
||||||
|
use windows_sys::{
|
||||||
|
core::PCSTR,
|
||||||
|
Win32::Foundation::{BOOL, HANDLE, HMODULE, HWND},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
pub fn panic(_panic: &core::panic::PanicInfo) -> ! {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always ensure _start() is at beginning of .text, despite what the linker thinks it should do.
|
||||||
|
// Placed at top of .text section in shellcode.ld, may not be needed since wildcard matches alphabetically
|
||||||
|
#[no_mangle]
|
||||||
|
#[link_section = ".text._start"]
|
||||||
|
unsafe extern "C" fn _start() {
|
||||||
|
let kernel32 = get_module_handle_from_peb(&utf16!("KERNEL32.DLL")).unwrap();
|
||||||
|
let LoadLibraryA: extern "system" fn(PCSTR) -> HMODULE =
|
||||||
|
get_procedure_from_edt(kernel32, "LoadLibraryA\0").unwrap();
|
||||||
|
let GetProcAddress: extern "system" fn(HMODULE, PCSTR) -> *const () =
|
||||||
|
get_procedure_from_edt(kernel32, "GetProcAddress\0").unwrap();
|
||||||
|
|
||||||
|
let user32 = LoadLibraryA("user32.dll\0".as_ptr());
|
||||||
|
let MessageBoxA: extern "system" fn(HWND, PCSTR, PCSTR, u32) -> i32 =
|
||||||
|
mem::transmute(GetProcAddress(user32, "MessageBoxA\0".as_ptr()));
|
||||||
|
|
||||||
|
let GetStdHandle: extern "system" fn(u32) -> HANDLE =
|
||||||
|
mem::transmute(GetProcAddress(kernel32, "GetStdHandle\0".as_ptr()));
|
||||||
|
let output_handle = GetStdHandle(u32::MAX - 11);
|
||||||
|
let WriteConsoleA: extern "system" fn(HANDLE, PCSTR, u32, *mut u32, *mut c_void) -> BOOL =
|
||||||
|
mem::transmute(GetProcAddress(kernel32, "WriteConsoleA\0".as_ptr()));
|
||||||
|
|
||||||
|
let text = "Hello from Console!\n\0";
|
||||||
|
WriteConsoleA(
|
||||||
|
output_handle,
|
||||||
|
text.as_ptr(),
|
||||||
|
text.len() as u32,
|
||||||
|
ptr::null_mut(),
|
||||||
|
ptr::null_mut(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let text1 = "Hello World!\0";
|
||||||
|
MessageBoxA(ptr::null_mut(), text1.as_ptr(), text1.as_ptr(), 0);
|
||||||
|
|
||||||
|
let text2 = "Bye World\0";
|
||||||
|
MessageBoxA(ptr::null_mut(), text2.as_ptr(), text2.as_ptr(), 0);
|
||||||
|
|
||||||
|
let ExitProcess: extern "system" fn(u32) =
|
||||||
|
mem::transmute(GetProcAddress(kernel32, "ExitProcess\0".as_ptr()));
|
||||||
|
ExitProcess(4);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user