|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Just_Ero How do I cheat? Reputation: 0
Joined: 09 Feb 2020 Posts: 7
|
Posted: Sat Dec 04, 2021 3:58 pm Post subject: How does Cheat Engine load debug symbols from a PDB? |
|
|
Hi,
I'm trying to create some helper functions in C# that allow me to load and enumerate a module's symbols via a provided PDB file. Particularly, I want to get some specific symbols of a Unity game's UnityPlayer.dll, the PDB of which I download from Unity's symbol server.
Looking through the source (which is incredibly difficult, because Pascal feels like complete gibberish) I found that CE makes use of the normal symbol funcitons from WinAPI's `dbghelp.dll` in the `symbolhandler.pas` file:
I believe the PDB loading is handled in `procedure TSymbolloaderthread.processThreadEvents` (though I may be wrong. This leads me to believe that the function used to retrieve the symbol info from a PDB is SymSearch (line 2226).
I have attempted to implement this in C# (.NET 6.0) in the following way:
Code: |
[DbgHelp.cs]
public delegate bool PSYM_ENUMERATESYMBOLS_CALLBACK([In] ref SYMBOL_INFO pSymInfo, [In] uint SymbolSize, [In, Optional] IntPtr UserContext);
[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymInitialize([In] IntPtr hProcess, [In, Optional] string UserSearchPath, [In] bool fInvadeProcess);
[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.U8)]
public static extern ulong SymLoadModuleEx([In] IntPtr hProcess, [In] IntPtr hFile, [In] string ImageName, [In] string ModuleName, [In, MarshalAs(UnmanagedType.U8)] ulong BaseOfDll, [In] uint DllSize, [In] IntPtr Data, [In] uint Flags);
[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymSearch([In] IntPtr hProcess, [In] ulong BaseOfDll, [In, Optional] uint Index, [In, Optional, MarshalAs(UnmanagedType.U4)] SymTag SymTag, [In, Optional] string Mask, [In, Optional] ulong Address, [In] PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, [In, Optional] IntPtr UserContext, [In, MarshalAs(UnmanagedType.U4)] SymSearchOptions Options);
[DllImport("dbghelp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymCleanup([In] IntPtr hProcess);
|
Code: |
[ProcessUtils.cs]
public static SYMBOL_INFO[] AllSymbols(this Process process, ProcessModule module, string symbol = "*")
{
var procHandle = process.Handle;
if (!DbgHelp.SymInitialize(procHandle, null, false))
throw new Exception("Failed to initialize symbols.");
var symbols = new List<SYMBOL_INFO>();
try
{
if (DbgHelp.SymLoadModuleEx(procHandle, IntPtr.Zero, module.ModuleName, null, (ulong)(module.BaseAddress), (uint)(module.ModuleMemorySize), IntPtr.Zero, 0) == 0)
throw new Exception("Failed to load module's symbols.");
DbgHelp.PSYM_ENUMERATESYMBOLS_CALLBACK callback = new(enumSyms);
if (!DbgHelp.SymSearch(procHandle, (ulong)(module.BaseAddress), 0, SymTag.Function, symbol, 0, callback, IntPtr.Zero, SymSearchOptions.SYMSEARCH_ALLITEMS))
throw new Exception("Failed to enumerate over PDB symbols.");
}
finally
{
DbgHelp.SymCleanup(procHandle);
}
return symbols.ToArray();
bool enumSyms(ref SYMBOL_INFO pSymInfo, uint SymbolSizem, IntPtr UserContext)
{
symbols.Add(pSymInfo);
return true;
}
}
|
SymTag.Function translates to the same dword(SymTagFunction) used in L2226 and SymSearchOptions.SYMSEARCH_ALLITEMS also translates to 8 at the end of L2226.
Am I missing something?
|
|
Back to top |
|
|
Csimbi I post too much Reputation: 94
Joined: 14 Jul 2007 Posts: 3108
|
Posted: Sat Dec 04, 2021 6:23 pm Post subject: |
|
|
You know that CE is open source, right?
You can just read the code and adapt it.
|
|
Back to top |
|
|
Just_Ero How do I cheat? Reputation: 0
Joined: 09 Feb 2020 Posts: 7
|
Posted: Sun Dec 05, 2021 6:15 am Post subject: |
|
|
Uh, yes? Why do you think I said I looked through the code and that Pascal is unreadable to me? There's no such thing as "just read the code and adapt it" when the code is 22 years old.
|
|
Back to top |
|
|
Csimbi I post too much Reputation: 94
Joined: 14 Jul 2007 Posts: 3108
|
Posted: Sun Dec 05, 2021 6:53 am Post subject: |
|
|
Just_Ero wrote: | Uh, yes? Why do you think I said I looked through the code and that Pascal is unreadable to me? There's no such thing as "just read the code and adapt it" when the code is 22 years old. |
It might be 22 years old, but it still runs today.
That means it's very good code.
I'd suggest you learn Pascal a bit so you can actually understand what's going on.
|
|
Back to top |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25287 Location: The netherlands
|
Posted: Sun Dec 05, 2021 11:23 am Post subject: |
|
|
what part doesn't work ?
Have you tried with invasive on ?
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
|
Just_Ero How do I cheat? Reputation: 0
Joined: 09 Feb 2020 Posts: 7
|
Posted: Sun Dec 05, 2021 1:28 pm Post subject: |
|
|
Well, I'm only finding embedded symbols with the method I'm using. Is Cheat Engine parsing the PDB file somehow? I'm not finding any code that's doing that.
|
|
Back to top |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25287 Location: The netherlands
|
Posted: Sun Dec 05, 2021 1:35 pm Post subject: |
|
|
just the windows symbol api
also, there's another part where symbols are enumerated
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
|
Just_Ero How do I cheat? Reputation: 0
Joined: 09 Feb 2020 Posts: 7
|
Posted: Sun Dec 05, 2021 1:39 pm Post subject: |
|
|
Hm, do you know or recall which parts are doing what?
It's difficult finding the correct methods, since I don't know all that much about CE's internal workings. In C#, I have access to all of the windows symbol API, which sounds like great news, but I seem to be missing something.
It's only the PDB-specific symbols I'm missing. I can see them fine in CE, just not in my code...
|
|
Back to top |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25287 Location: The netherlands
|
Posted: Sun Dec 05, 2021 2:18 pm Post subject: |
|
|
look at symEnumSymbols
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
|
Just_Ero How do I cheat? Reputation: 0
Joined: 09 Feb 2020 Posts: 7
|
Posted: Sun Dec 05, 2021 2:59 pm Post subject: |
|
|
I've done that using the following code:
Code: |
WinAPI.SymEnumSymbols(procHandle, (ulong)(module.BaseAddress), symbol, callback, IntPtr.Zero);
|
Code: |
bool enumSyms(ref SYMBOL_INFO pSymInfo, uint SymbolSizem, IntPtr UserContext)
{
symbols.Add(pSymInfo);
return true;
}
|
"procHandle" is a HANDLE to the current process,
"(ulong)(module.BaseAddress)" is the BaseOfDll value of the module to check the symbols from as a ULONG64,
"symbol" is a PCSTR with the symbol name/mask,
"callback" is "enumSyms", which is a PSYM_ENUMERATESYMBOLS_CALLBACK (symbols is just a list of SYMBOL_INFO structs),
"IntPtr.Zero" is a null PVOID object for the UserContext variable.
Is the issue that my UserContext is NULL?
|
|
Back to top |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25287 Location: The netherlands
|
Posted: Sun Dec 05, 2021 3:11 pm Post subject: |
|
|
perhaps you havn't set the path to where to find the pdb in syminitialize or SymSetSearchPath
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
|
Just_Ero How do I cheat? Reputation: 0
Joined: 09 Feb 2020 Posts: 7
|
Posted: Sun Dec 05, 2021 3:56 pm Post subject: |
|
|
Cool, thank you! Using
Code: |
WinAPI.SymInitialize(procHandle, Path.GetDirectoryName(module.FileName), false);
|
I can now get all symbols (of course, as long as the PDB is in the same directory as the DLL).
Thank you!
|
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|