Skip to content

Instantly share code, notes, and snippets.

@Wra7h
Created April 2, 2022 07:02
Show Gist options
  • Save Wra7h/7b6c2ad5d4970891195c167013373cc4 to your computer and use it in GitHub Desktop.
Save Wra7h/7b6c2ad5d4970891195c167013373cc4 to your computer and use it in GitHub Desktop.
Scan processes for any Application Recovery Callbacks
// Scan for any Application Recovery Callbacks on your system. Each Process ID/Callback address combination should only be displayed once.
// Also, it's a continuous loop so it shouldn't die until you're done with it.
// Full PoC here: https://github.com/Wra7h/ARCInject
// Compile: C:\windows\Microsoft.NET\Framework64\v3.5\csc.exe .\ARC_Scan.cs
// Execute: .\ARC_Scan.exe
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
namespace ARC_Scan
{
class Program
{
static void Main(string[] args)
{
List<KeyValuePair<int, IntPtr>> prevDetected = new List<KeyValuePair<int, IntPtr>>();
Console.WriteLine("\t\t\t+----------------------+");
Console.WriteLine("\t\t\t| ARC SCAN |");
Console.WriteLine("\t\t\t+----------------------+\n");
while (true)
{
FindRegisteredCallbacks(ref prevDetected);
}
}
static void FindRegisteredCallbacks(ref List<KeyValuePair<int, IntPtr>> prevDetected)
{
Process[] processList = Process.GetProcesses();
IntPtr pRC = IntPtr.Zero; // A pointer to the recovery callback function.
IntPtr ppvParam = IntPtr.Zero; // A pointer to the callback parameter.
uint pdwPI = 0; // The recovery ping interval, in 100-nanosecond intervals.
uint reserved = 0; // Reserved for future use.
foreach (Process proc in processList)
{
try
{
uint ret = GetApplicationRecoveryCallback(proc.Handle, out pRC, out ppvParam, out pdwPI, out reserved);
if (ret == 0 && pRC != IntPtr.Zero)
{
if (prevDetected.Where(kv => kv.Key == proc.Id).Count() == 0)
{
Console.WriteLine("[+] Process Name: {0} | PID: {1} | Address: 0x{2:X}", proc.MainModule.ModuleName, proc.Id, pRC.ToInt64());
prevDetected.Add(new KeyValuePair<int, IntPtr>(proc.Id, pRC));
}
else if ((prevDetected.Where(kv => kv.Key == proc.Id).Count() > 0) && (prevDetected.Where(kv => kv.Value == pRC).Count() == 0))
{
Console.WriteLine("[+] Process Name: {0} | PID: {1} | Address: 0x{2:X}", proc.MainModule.ModuleName, proc.Id, pRC.ToInt64());
prevDetected.Add(new KeyValuePair<int, IntPtr>(proc.Id, pRC));
}
}
}
catch
{
continue; //Keep looping through the other processes that have been identified
}
}
}
// GetApplicationRecoveryCallback: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getapplicationrecoverycallback
[DllImport("kernel32.dll")]
static extern uint GetApplicationRecoveryCallback(IntPtr hProcess, out IntPtr pRecoveryCallback, out IntPtr ppvParameter, out uint pdwPingInterval, out uint pdwFlags);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment