/// <summary> /// Finds the address for the given method inside the given module. /// The method requested must be exported to be found. /// This is equivalent to the GetProcAddress() Win64 API but takes into account ASLR by reading the export tables directly from the loaded modules within the debugged process. /// </summary> /// <param name="modName">Name of the DLL that contains the function (must include extension)</param> /// <param name="method">The method whose address is being requested.</param> /// <returns>The address of the method if it was found</returns> /// <exception cref="System.Exception">Target doesn't have module: + modName + loaded.</exception> public ulong FindProcAddress(String modName, String method) { Win64.MODULEENTRY32 module = getModule(modName); if (module.dwSize == 0) { Console.WriteLine("Failed to find module"); throw new Exception("Target doesn't have module: " + modName + " loaded."); } ulong modBase = (ulong)module.modBaseAddr; uint peAddress, exportTableAddress, exportTableSize; byte[] exportTable; ReadDWORD(modBase + 0x3c, out peAddress); ReadDWORD(modBase + peAddress + 0x88, out exportTableAddress); ReadDWORD(modBase + peAddress + 0x8C, out exportTableSize); ReadData(modBase + exportTableAddress, (int)exportTableSize, out exportTable); ulong exportEnd = modBase + exportTableAddress + exportTableSize; uint numberOfFunctions = BitConverter.ToUInt32(exportTable, 0x14); uint numberOfNames = BitConverter.ToUInt32(exportTable, 0x18); uint functionAddressBase = BitConverter.ToUInt32(exportTable, 0x1c); uint nameAddressBase = BitConverter.ToUInt32(exportTable, 0x20); uint ordinalAddressBase = BitConverter.ToUInt32(exportTable, 0x24); StringBuilder sb = new StringBuilder(); for (int x = 0; x < numberOfNames; x++) { sb.Clear(); uint namePtr = BitConverter.ToUInt32(exportTable, (int)(nameAddressBase - exportTableAddress) + (x * 4)) - exportTableAddress; while (exportTable[namePtr] != 0) { sb.Append((char)exportTable[namePtr]); namePtr++; } ushort funcOrdinal = BitConverter.ToUInt16(exportTable, (int)(ordinalAddressBase - exportTableAddress) + (x * 2)); ulong funcAddress = BitConverter.ToUInt32(exportTable, (int)(functionAddressBase - exportTableAddress) + (funcOrdinal * 4)); funcAddress += modBase; if (sb.ToString().Equals(method)) { return(funcAddress); } } return(0); }
private Win64.MODULEENTRY32 getModule(String modName) { IntPtr hSnap = Win64.CreateToolhelp32Snapshot(Win64.SnapshotFlags.NoHeaps | Win64.SnapshotFlags.Module, (uint)debuggedProcessInfo.dwProcessId); Win64.MODULEENTRY32 module = new Win64.MODULEENTRY32(); module.dwSize = (uint)Marshal.SizeOf(module); Win64.Module32First(hSnap, ref module); if (module.szModule.Equals(modName, StringComparison.CurrentCultureIgnoreCase)) { return(module); } while (Win64.Module32Next(hSnap, ref module)) { if (module.szModule.Equals(modName, StringComparison.CurrentCultureIgnoreCase)) { return(module); } } module = new Win64.MODULEENTRY32(); Win64.CloseHandle(hSnap); return(module); }