Skip to content

Commit

Permalink
fixed yet another race condition
Browse files Browse the repository at this point in the history
  • Loading branch information
forentfraps committed Aug 16, 2024
1 parent 4462208 commit c04cc64
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 152 deletions.
8 changes: 6 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ fn main() {
"cargo:rustc-link-search=native={}",
out_dir.to_str().unwrap()
);
Command::new("c_aes/make.bat").status().unwrap();
Command::new("c_verification/make.bat").status().unwrap();
Command::new("c_aes/make_microsoft_no_crt.bat")
.status()
.unwrap();
Command::new("c_verification/make_microsoft_no_crt.bat")
.status()
.unwrap();
/* embed_resource::compile("c_aes/res1.rc");
embed_resource::compile("c_verification/res2.rc"); */
println!("cargo:rustc-link-lib=static=tricks");
Expand Down
17 changes: 14 additions & 3 deletions c_aes/aes_dll.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@

extern void stub();

int __declspec(noinline)
EventLoop(unsigned char *keyArray, ULONGLONG volatile *status,
PVOID *workAddress) {
HANDLE console = NULL;

int __declspec(noinline) EventLoop(unsigned char *keyArray,
ULONGLONG volatile *status,
PVOID *workAddress) {
DWORD trash = 0;

while (1) {
if (*status != 0) {
if (*status == 2) {

// WriteConsole(console, "[C] STOPPED ENCRYPT\n", 22, &trash, NULL);
return 0;
}

// WriteConsole(console, "[C] DECRYPTED BLOCK\n", 22, &trash, NULL);
Decrypt(*workAddress, keyArray);
*status = 0;
}
Expand All @@ -35,6 +43,8 @@ DWORD WINAPI Initialise() {
while (*status != 0) {
}
*workAddress = (PVOID)1;
DWORD trash = 0;
// WriteConsole(console, "[C] INIT COMPLETE\n", 18, &trash, NULL);

EventLoop(keyArray, status, workAddress);
return 0;
Expand All @@ -43,6 +53,7 @@ DWORD WINAPI Initialise() {
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
console = GetStdHandle(STD_OUTPUT_HANDLE);
CreateThread(NULL, 0, Initialise, NULL, 0, NULL);
break;

Expand Down
4 changes: 2 additions & 2 deletions c_aes/make_microsoft_no_crt.bat
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
@echo off

REM Compile C files with Microsoft cl
cl /c /W4 /MD /GS- aes_dll.c /Fo:aes_dll.obj /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared" /I"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.39.33519\include" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt"
cl /c /W4 /MD /GS- aes_lib/aes.c /Fo:aes.obj /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared" /I"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.39.33519\include" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt"
cl /c /W4 /MT /GS- aes_dll.c /Fo:aes_dll.obj /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared" /I"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.39.33519\include" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt"
cl /c /W4 /MT /GS- aes_lib/aes.c /Fo:aes.obj /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared" /I"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.39.33519\include" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt"
nasm -fwin64 -o stub.obj stub.asm
REM Assemble the assembly file with nasm
nasm -f win64 aes_lib/fast.asm -o fast.obj
Expand Down
Binary file modified c_aes/stub.obj
Binary file not shown.
2 changes: 1 addition & 1 deletion c_verification/make_microsoft_nocrt.bat
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
nasm -fwin64 -o hook.obj hook.asm
cl /c /O2 /MD /W4 /GS- verification.c /Fo:verification.obj /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared" /I"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.39.33519\include" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt"
cl /c /O2 /MT /W4 /GS- verification.c /Fo:verification.obj /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared" /I"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.39.33519\include" /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt"
link /DLL /ENTRY:DllMain /NODEFAULTLIB /OUT:mod2_nocrt.dll verification.obj hook.obj /SUBSYSTEM:CONSOLE /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\um\x64" /LIBPATH:"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\lib\x64" /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\ucrt\x64" Kernel32.lib User32.lib
del verification.obj hook.obj
python .\encrypter.py
Binary file modified c_verification/mod2.dll.enc
Binary file not shown.
1 change: 1 addition & 0 deletions key.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{7h3_h4nd_0f_90d_h0v321n9_480v3}
173 changes: 42 additions & 131 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
//{7h3_h4nd_0f_90d_h0v321n9_480v3}

mod asm_macros;
mod warden;
mod winapi_cs;

use std::arch::asm;
Expand Down Expand Up @@ -27,123 +30,14 @@ use winapi_cs::core::*;

use crate::winapi_cs::reflective_dll::*;

#[repr(C)]
struct warden_args {
f: *const fn(),
status: *mut Arc<(Mutex<StatusEnum>, Condvar)>,
_workAddress: *mut Arc<(Mutex<u64>, Condvar)>,
}

extern "C" {

pub fn wardenCallback(arg: *mut u8);
}

#[derive(Debug)]
enum StatusEnum {
Idle,
Work,
Phase2,
}

static DECOY: AtomicUsize = AtomicUsize::new(0);
unsafe extern "stdcall" fn warden_spawner(args: *mut warden_args) {
if DECOY.fetch_and(1, Ordering::SeqCst) == 1 {
let status: u64 = transmute_copy(&((*args).status));
let workAddress: u64 = transmute_copy(&((*args)._workAddress));
thread::spawn(move || warden(status, workAddress));
}
}

unsafe fn warden(_status: u64, _workAddress: u64) {
let status: *mut Arc<(Mutex<StatusEnum>, Condvar)> = transmute(_status);
let workAddress: *mut Arc<(Mutex<*mut *mut u8>, Condvar)> = transmute(_workAddress);
let (_ntStr, pntStr) = string_to_lpcwstr(String::from("C:\\Windows\\System32\\ntdll.dll"));
let (_ker32strw, pker32strw) =
string_to_lpcwstr(String::from("C:\\Windows\\System32\\kernel32.dll"));
let (_virtProtStr, pvirtProtStr) = string_to_lpcstr(String::from("VirtualProtect"));
let ntdll = GetModuleHandle(pntStr).unwrap();
let (_DBreakStr, pDBreakStr) = string_to_lpcstr(String::from("DbgBreakPoint"));
let (_DRemoteStr, pDRemoteStr) = string_to_lpcstr(String::from("RtlUserThreadStart"));
let _kernel32: HMODULE = GetModuleHandle(pker32strw).unwrap();
let VirtualProtect: pVirtualProtect = GetProcAddress_(_kernel32, pvirtProtStr).unwrap();
let Cstatus: *mut u64 = GetProcAddress_(ntdll, pDBreakStr).unwrap();
let CworkAddress: *mut *const u8 = GetProcAddress_(ntdll, pDRemoteStr).unwrap();
let mut _oldProtect: DWORD = 0;
VirtualProtect(
Cstatus as PVOID,
8,
PAGE_EXECUTE_READWRITE,
&mut _oldProtect as *mut u32,
);
VirtualProtect(
CworkAddress as PVOID,
8,
PAGE_EXECUTE_READWRITE,
&mut _oldProtect as *mut u32,
);
*Cstatus = 0;
while *CworkAddress != 1 as *const u8 {
decoy(&mut (*CworkAddress as u64));
}
'mainloop: loop {
let (status_lock, cvar) = &**status;
{
let mut status = status_lock.lock().unwrap();

loop {
status = match *status {
StatusEnum::Idle => cvar.wait(status).unwrap(),
StatusEnum::Work => {
break;
}
StatusEnum::Phase2 => {
break 'mainloop;
}
};
}

let (data_lock, _) = &**workAddress;
let work_address = data_lock.lock().unwrap();

*CworkAddress = **work_address as *const u8;
*Cstatus = 1;
*status = StatusEnum::Idle;
}
while *Cstatus == 1 {
decoy(&mut (Cstatus as u64));
}

cvar.notify_one();
}
let (status_lock, cvar) = &**status;

let (data_lock, _) = &**workAddress;
{
let work_address = data_lock.lock().unwrap();
let mut status = status_lock.lock().unwrap();
*status = StatusEnum::Idle;
*CworkAddress = **work_address;
}
*Cstatus = 2;

cvar.notify_one();
}

fn decoy(data: &mut u64) {
unsafe {
let temp = core::ptr::read_volatile(data);
core::ptr::write_volatile(data, temp);
}
}
static mut stWA: u64 = 0;
unsafe extern "system" fn exception_handler(_exception_info: *mut EXCEPTION_POINTERS) -> i32 {
// Return EXCEPTION_CONTINUE_SEARCH to allow other handlers to process this exception,
// or EXCEPTION_EXECUTE_HANDLER to execute the exception handler.
match (*((*_exception_info).ExceptionRecord)).ExceptionCode {
0xC0000095 => (),
_ => {
println!("Uh oh...");
println!("You have reached a race condition!!!");
return EXCEPTION_CONTINUE_SEARCH;
}
}
Expand All @@ -160,7 +54,7 @@ unsafe extern "system" fn exception_handler(_exception_info: *mut EXCEPTION_POIN
let wa: PVOID = transmute(stWA);
TpAllocWork(
&mut workReturn as *mut PTP_WORK,
transmute(wardenCallback as *const ()),
transmute(warden::wardenCallback as *const ()),
wa,
null_mut(),
);
Expand All @@ -182,7 +76,6 @@ typedef VOID (NTAPI* TPPOSTWORK)(PTP_WORK);
typedef VOID (NTAPI* TPRELEASEWORK)(PTP_WORK);*/

fn main() {
//{7h3_h4nd_0f_90d_h0v321n9_480v3}
fake_exit!();
let (_ker32strw, pker32strw) =
string_to_lpcwstr(String::from("C:\\Windows\\System32\\kernel32.dll"));
Expand All @@ -198,8 +91,9 @@ fn main() {
let WriteConsole: pWriteConsole = GetProcAddress_(_kernel32, pWriteConsStr).unwrap();
let verif_data_sec = include_bytes!("../c_verification/mod2.dll.enc");
let mut _oldProtect: DWORD = 0;
let data = Arc::new((Mutex::new(0 as u64), Condvar::new()));
let status = Arc::new((Mutex::new(StatusEnum::Idle), Condvar::new()));
let condvar = Condvar::new();
let data = Arc::new((Mutex::new(0 as u64), condvar));
let status = Arc::new((Mutex::new(warden::StatusEnum::Idle), Condvar::new()));
VirtualProtect(
verif_data_sec.as_ptr() as PVOID,
verif_data_sec.len() * 2,
Expand All @@ -217,60 +111,77 @@ fn main() {
let mut data_th2 = data.clone();
let mut status_th2 = status.clone();
fake_exit!();
let mut wa = warden_args {
f: warden as *const fn(),
status: &mut status_th2 as *mut Arc<(Mutex<StatusEnum>, Condvar)>,
let mut wa = warden::warden_args {
f: warden::warden as *const fn(),
status: &mut status_th2 as *mut Arc<(Mutex<warden::StatusEnum>, Condvar)>,
_workAddress: &mut data_th2 as *mut Arc<(Mutex<u64>, Condvar)>,
};
stWA = (&mut wa as *mut warden_args) as u64;
stWA = (&mut wa as *mut warden::warden_args) as u64;
let _handle = AddVectoredExceptionHandler(1, Some(exception_handler));
asm!(".2byte 0x04cd");

let (_userStr, puserStr) = string_to_lpcstr(user_input);
asm!(".2byte 0x04cd");
ReflectiveLoadDll(aes_ptr.as_ptr() as *mut u8, false);
let (data_lock, _) = &*data;
let console = GetStdHandle(STD_OUTPUT_HANDLE);

let (data_lock, _) = &*data;
let (status_lock, cvar) = &*status;
{
// Waiting for C to initialise its code
cvar.wait(status_lock.lock().unwrap());
}

for i in 0..(verif_data_sec.len() / 16) {
let (_ds, pds) = string_to_lpcstr(String::from(format!("{i}")));
let mut cnt: DWORD = 0;
/*
let (_ds, pds) = string_to_lpcstr(String::from(format!("{i}")));
let mut cnt: DWORD = 0;
WriteConsole(console, pds, 0, &mut cnt as *mut u32, null_mut());
*/
// The lines above exist so that this loop is not optimised away
fake_exit!();
WriteConsole(console, pds, 0, &mut cnt as *mut u32, null_mut());
let data_ptr = verif_data_sec.as_ptr().offset(i as isize * 16) as *const u8;
{
let mut mut_work_mutex = data_lock.lock().unwrap();

*mut_work_mutex = transmute::<*const *const u8, u64>(&data_ptr as *const *const u8);
//Writing to the shared pointer and then locking so the warden can pass it further
}
{
let mut status_mutex = status_lock.lock().unwrap();
*status_mutex = StatusEnum::Work;
*status_mutex = warden::StatusEnum::Work;
//Setting the mutex to status WORK, that is so that warden knows what to do
}
//Sending to notification to condvar connected to status, that it could be unlocked
cvar.notify_one();
{
hide!();
let mut status_mutex = status_lock.lock().unwrap();
status_mutex = match *status_mutex {
StatusEnum::Work => cvar.wait(status_mutex).unwrap(),
_ => break,
};

// Waiting while the warden is wokring
loop {
let mut status_mutex = status_lock.lock().unwrap();
status_mutex = match *status_mutex {
warden::StatusEnum::Work => cvar.wait(status_mutex).unwrap(),
_ => break,
};
}
}
}

//Writing the user string for c_verification unit to verify
let data_ptr = puserStr as *const u8;
{
let mut work_mutex = data_lock.lock().unwrap();
*work_mutex = transmute::<*const *const u8, u64>(&data_ptr as *const *const u8);
}
{
let mut status_mutex = status_lock.lock().unwrap();
*status_mutex = StatusEnum::Phase2;
*status_mutex = warden::StatusEnum::Phase2;
}
cvar.notify_one();
{
let mut status_mutex = status_lock.lock().unwrap();
status_mutex = match *status_mutex {
StatusEnum::Phase2 => cvar.wait(status_mutex).unwrap(),
warden::StatusEnum::Phase2 => cvar.wait(status_mutex).unwrap(),
_ => status_mutex,
};
}
Expand Down
Loading

0 comments on commit c04cc64

Please sign in to comment.