Skip to content

Instantly share code, notes, and snippets.

@fuckup1337
Created December 20, 2021 00:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fuckup1337/98ceab297f58bb7544dd0f7f39ef63a0 to your computer and use it in GitHub Desktop.
Save fuckup1337/98ceab297f58bb7544dd0f7f39ef63a0 to your computer and use it in GitHub Desktop.
Find hooked API's using C#
using System;
using System.Runtime.InteropServices;
/* References
* 1. https://www.ired.team/offensive-security/defense-evasion/detecting-hooked-syscall-functions
* 2. https://github.com/Mr-Un1k0d3r/EDRs
*/
namespace SharpHookCheck
{
class Program
{
static void dump_exports(IntPtr dll_base)
{
//Get base address of the module in which our exported function of interest resides (kernel32 in the case of OpenProcess)
IntPtr handle = dll_base;
Console.WriteLine("[+] Library Base Address: 0x{0:X}", handle.ToString("X"));
//Obtain value of e_lfanew
STRUCTS.IMAGE_DOS_HEADER dosheader = (STRUCTS.IMAGE_DOS_HEADER)Marshal.PtrToStructure(handle, typeof(STRUCTS.IMAGE_DOS_HEADER));
//Obtain signature
IntPtr sgn = IntPtr.Add(handle, (int)dosheader.e_lfanew);
STRUCTS.SIGNATURE sign = (STRUCTS.SIGNATURE)Marshal.PtrToStructure(sgn, typeof(STRUCTS.SIGNATURE));
//Obtain PE file header
int si = 4 * sizeof(byte);
IntPtr file_head = IntPtr.Add(sgn, si);
STRUCTS.IMAGE_FILE_HEADER fileheader = (STRUCTS.IMAGE_FILE_HEADER)Marshal.PtrToStructure(file_head, typeof(STRUCTS.IMAGE_FILE_HEADER));
//Obtain address of optional header
IntPtr opt_head = IntPtr.Add(file_head, 0x14);
//Console.WriteLine("[+] Address of optional header: 0x{0:X}", opt_head.ToString("X"));
STRUCTS.IMAGE_OPTIONAL_HEADER64 optheader = (STRUCTS.IMAGE_OPTIONAL_HEADER64)Marshal.PtrToStructure(opt_head, typeof(STRUCTS.IMAGE_OPTIONAL_HEADER64));
IntPtr export_directory = IntPtr.Add(handle, (int)optheader.ExportTable.VirtualAddress);
//Console.WriteLine("[+] Export table Address: 0x{0:X}", export_directory.ToString("X"));
//Obtain address of export directory
STRUCTS.IMAGE_EXPORT_DIRECTORY export_header = (STRUCTS.IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(export_directory, typeof(STRUCTS.IMAGE_EXPORT_DIRECTORY));
//Console.WriteLine("[+] RVA of Functions: 0x{0:X}", export_header.AddressOfFunctions);
//Console.WriteLine("[+] RVA of Names: 0x{0:X}", export_header.AddressOfNames);
//Console.WriteLine("[+] RVA of NameOrdinals: 0x{0:X}", export_header.AddressOfNameOrdinals);
int no_of_names = (int)export_header.NumberOfNames;
int no_of_functions = (int)export_header.NumberOfFunctions;
Console.WriteLine("[+] No of Functions: 0x{0:X}", no_of_functions.ToString("X"));
//int base_val = (int)export_header.Base;
IntPtr address_functions = IntPtr.Add(handle, (int)export_header.AddressOfFunctions);
IntPtr address_names = IntPtr.Add(handle, (int)export_header.AddressOfNames);
//IntPtr address_nameordinals = IntPtr.Add(handle, (int)export_header.AddressOfNameOrdinals);
IntPtr func_exact_address = IntPtr.Zero;
string functionname = "";
int ctr = 0;
//Enumerating exported functions from the module
for (int i = 0; i < no_of_names; i++)
{
IntPtr func_name_address = IntPtr.Add(address_names, (sizeof(int)) * i);
int function_name_rva = Marshal.ReadInt32(func_name_address);
IntPtr func_name_string = IntPtr.Add(handle, function_name_rva);
functionname = Marshal.PtrToStringAnsi(func_name_string);
IntPtr func_address = IntPtr.Add(address_functions, (sizeof(int)) * i);
int func_address_rva = Marshal.ReadInt32(func_address);
func_exact_address = IntPtr.Add(handle, func_address_rva);
ctr += getbytes(func_exact_address, functionname);
//unhooked = B8D18B4C
//hooked = 14FE0BE9
//Console.WriteLine("[+] Function Name: {0} | Function Address: {1}", functionname,func_exact_address.ToString("X"));
}
Console.WriteLine("[+] Total no of functions hooked: " + ctr);
}
static int getbytes(IntPtr func_exact_address, string func_name)
{
int elementSize = 1;
string str = "";
for (int i = 0; i < 4; i++)
{
str += Marshal.ReadByte(func_exact_address, i * elementSize).ToString("X");
}
if (string.Compare(func_name.Substring(0, 2), "Nt") == 0 || string.Compare(func_name.Substring(0, 2), "Zw") == 0)
{
//Console.WriteLine("[+] Function name: " + func_name + " | opcode val: " + str + "\n");
if (string.Compare(str, "4C8BD1B8") != 0 && string.Compare(str.Substring(0,2),"E9") == 0)
{
Console.WriteLine(func_name + " is hooked!");
return 1;
}
}
return 0;
}
static void Main(string[] args)
{
string dllPath;
dllPath = "C:\\Windows\\System32\\ntdll.dll";
IntPtr hExe;
hExe = Pinvoke.GetModuleHandle(dllPath);
if (hExe == IntPtr.Zero)
{
throw new System.ComponentModel.Win32Exception("Cannot load " + dllPath);
}
else
{
dump_exports(hExe);
}
}
}
public class Pinvoke {
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
}
public class STRUCTS
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[Flags]
public enum ProcessCreationFlags : uint
{
ZERO_FLAG = 0x00000000,
CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
CREATE_DEFAULT_ERROR_MODE = 0x04000000,
CREATE_NEW_CONSOLE = 0x00000010,
CREATE_NEW_PROCESS_GROUP = 0x00000200,
CREATE_NO_WINDOW = 0x08000000,
CREATE_PROTECTED_PROCESS = 0x00040000,
CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
CREATE_SEPARATE_WOW_VDM = 0x00001000,
CREATE_SHARED_WOW_VDM = 0x00001000,
CREATE_SUSPENDED = 0x00000004,
CREATE_UNICODE_ENVIRONMENT = 0x00000400,
DEBUG_ONLY_THIS_PROCESS = 0x00000002,
DEBUG_PROCESS = 0x00000001,
DETACHED_PROCESS = 0x00000008,
EXTENDED_STARTUPINFO_PRESENT = 0x00080000,
INHERIT_PARENT_AFFINITY = 0x00010000
}
public struct IMAGE_DOS_HEADER
{ // DOS .EXE header
public UInt16 e_magic; // Magic number
public UInt16 e_cblp; // Bytes on last page of file
public UInt16 e_cp; // Pages in file
public UInt16 e_crlc; // Relocations
public UInt16 e_cparhdr; // Size of header in paragraphs
public UInt16 e_minalloc; // Minimum extra paragraphs needed
public UInt16 e_maxalloc; // Maximum extra paragraphs needed
public UInt16 e_ss; // Initial (relative) SS value
public UInt16 e_sp; // Initial SP value
public UInt16 e_csum; // Checksum
public UInt16 e_ip; // Initial IP value
public UInt16 e_cs; // Initial (relative) CS value
public UInt16 e_lfarlc; // File address of relocation table
public UInt16 e_ovno; // Overlay number
public UInt16 e_res_0; // Reserved words
public UInt16 e_res_1; // Reserved words
public UInt16 e_res_2; // Reserved words
public UInt16 e_res_3; // Reserved words
public UInt16 e_oemid; // OEM identifier (for e_oeminfo)
public UInt16 e_oeminfo; // OEM information; e_oemid specific
public UInt16 e_res2_0; // Reserved words
public UInt16 e_res2_1; // Reserved words
public UInt16 e_res2_2; // Reserved words
public UInt16 e_res2_3; // Reserved words
public UInt16 e_res2_4; // Reserved words
public UInt16 e_res2_5; // Reserved words
public UInt16 e_res2_6; // Reserved words
public UInt16 e_res2_7; // Reserved words
public UInt16 e_res2_8; // Reserved words
public UInt16 e_res2_9; // Reserved words
public UInt32 e_lfanew; // File address of new exe header
}
public struct SIGNATURE
{
public UInt32 signature;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct IMAGE_FILE_HEADER
{
public UInt16 Machine;
public UInt16 NumberOfSections;
public UInt32 TimeDateStamp;
public UInt32 PointerToSymbolTable;
public UInt32 NumberOfSymbols;
public UInt16 SizeOfOptionalHeader;
public UInt16 Characteristics;
}
public struct IMAGE_OPTIONAL_HEADER64
{
public UInt16 Magic;
public Byte MajorLinkerVersion;
public Byte MinorLinkerVersion;
public UInt32 SizeOfCode;
public UInt32 SizeOfInitializedData;
public UInt32 SizeOfUninitializedData;
public UInt32 AddressOfEntryPoint;
public UInt32 BaseOfCode;
public UInt64 ImageBase;
public UInt32 SectionAlignment;
public UInt32 FileAlignment;
public UInt16 MajorOperatingSystemVersion;
public UInt16 MinorOperatingSystemVersion;
public UInt16 MajorImageVersion;
public UInt16 MinorImageVersion;
public UInt16 MajorSubsystemVersion;
public UInt16 MinorSubsystemVersion;
public UInt32 Win32VersionValue;
public UInt32 SizeOfImage;
public UInt32 SizeOfHeaders;
public UInt32 CheckSum;
public UInt16 Subsystem;
public UInt16 DllCharacteristics;
public UInt64 SizeOfStackReserve;
public UInt64 SizeOfStackCommit;
public UInt64 SizeOfHeapReserve;
public UInt64 SizeOfHeapCommit;
public UInt32 LoaderFlags;
public UInt32 NumberOfRvaAndSizes;
public IMAGE_DATA_DIRECTORY ExportTable;
public IMAGE_DATA_DIRECTORY ImportTable;
public IMAGE_DATA_DIRECTORY ResourceTable;
public IMAGE_DATA_DIRECTORY ExceptionTable;
public IMAGE_DATA_DIRECTORY CertificateTable;
public IMAGE_DATA_DIRECTORY BaseRelocationTable;
public IMAGE_DATA_DIRECTORY Debug;
public IMAGE_DATA_DIRECTORY Architecture;
public IMAGE_DATA_DIRECTORY GlobalPtr;
public IMAGE_DATA_DIRECTORY TLSTable;
public IMAGE_DATA_DIRECTORY LoadConfigTable;
public IMAGE_DATA_DIRECTORY BoundImport;
public IMAGE_DATA_DIRECTORY IAT;
public IMAGE_DATA_DIRECTORY DelayImportDescriptor;
public IMAGE_DATA_DIRECTORY CLRRuntimeHeader;
public IMAGE_DATA_DIRECTORY Reserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_DATA_DIRECTORY
{
public UInt32 VirtualAddress;
public UInt32 Size;
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_EXPORT_DIRECTORY
{
public UInt32 Characteristics;
public UInt32 TimeDateStamp;
public UInt16 MajorVersion;
public UInt16 MinorVersion;
public UInt32 Name;
public UInt32 Base;
public UInt32 NumberOfFunctions;
public UInt32 NumberOfNames;
public UInt32 AddressOfFunctions; // RVA from base of image
public UInt32 AddressOfNames; // RVA from base of image
public UInt32 AddressOfNameOrdinals; // RVA from base of image
}
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError = true)]
public delegate Boolean CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, STRUCTS.ProcessCreationFlags dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STRUCTS.STARTUPINFO lpStartupInfo, out STRUCTS.PROCESS_INFORMATION lpProcessInformation);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment