Skip to content

Commit 507f1d8

Browse files
tyranidtyranid
authored andcommitted
Added symbol enumerator and code to query a symbol's machine type.
1 parent 53b6587 commit 507f1d8

9 files changed

+659
-7
lines changed

NtApiDotNet/NtApiDotNet.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,9 +530,12 @@
530530
<Compile Include="Win32\ConsoleSession.cs" />
531531
<Compile Include="Win32\Debugger\DbgHelpCallbackActionCode.cs" />
532532
<Compile Include="Win32\Debugger\DbgHelpDebugCallbackHandler.cs" />
533+
<Compile Include="Win32\Debugger\IDiaSession.cs" />
534+
<Compile Include="Win32\Debugger\IDiaSymbol.cs" />
533535
<Compile Include="Win32\Debugger\IMAGEHLP_CBA_EVENTW.cs" />
534536
<Compile Include="Win32\Debugger\IMAGEHLP_DEFERRED_SYMBOL_LOADW.cs" />
535537
<Compile Include="Win32\Debugger\IMAGEHLP_STACK_FRAME.cs" />
538+
<Compile Include="Win32\Debugger\ISymbolEnumerator.cs" />
536539
<Compile Include="Win32\DirectoryService\DirectoryServiceBinding.cs" />
537540
<Compile Include="Win32\DirectoryService\DirectoryServiceNameError.cs" />
538541
<Compile Include="Win32\DirectoryService\DirectoryServiceNameFlags.cs" />

NtApiDotNet/NtSectionNative.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ public enum DllMachineType : ushort
181181
SH5 = 0x1A8,
182182
THUMB = 0x1C2,
183183
WCEMIPSV2 = 0x169,
184+
ARM64EC = 0xA641,
184185
ARM64 = 0xAA64,
185186
}
186187

NtApiDotNet/Win32/Debugger/DataSymbolInformation.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,17 @@ public class DataSymbolInformation : SymbolInformation
2323
/// Address of the symbol.
2424
/// </summary>
2525
public long Address { get; }
26+
/// <summary>
27+
/// The machine type of the symbol.
28+
/// </summary>
29+
public DllMachineType MachineType { get; }
2630

2731
internal DataSymbolInformation(SymTagEnum tag, int size, int type_index,
28-
long address, SymbolLoadedModule module, string name)
32+
long address, SymbolLoadedModule module, string name, DllMachineType machine_type)
2933
: base(tag, size, type_index, module, name)
3034
{
3135
Address = address;
36+
MachineType = machine_type;
3237
}
3338
}
3439
}

NtApiDotNet/Win32/Debugger/DbgHelpSymbolResolver.cs

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
namespace NtApiDotNet.Win32.Debugger
3232
{
33-
internal sealed partial class DbgHelpSymbolResolver : ISymbolResolver, ISymbolTypeResolver, IDisposable
33+
internal sealed partial class DbgHelpSymbolResolver : ISymbolResolver, ISymbolTypeResolver, ISymbolEnumerator, IDisposable
3434
{
3535
public static string DEFAULT_SYMSRV = "https://msdl.microsoft.com/download/symbols";
3636

@@ -215,6 +215,13 @@ delegate bool SymGetHomeDirectoryW(
215215
HomeDirectoryType type,
216216
[In, Out] StringBuilder dir,
217217
IntPtr size
218+
);
219+
220+
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
221+
delegate bool SymGetDiaSession(
222+
SafeKernelObjectHandle hProcess,
223+
long BaseOfDll,
224+
[MarshalAs(UnmanagedType.Interface)] out IDiaSession DiaSession
218225
);
219226

220227
private readonly SafeLoadLibraryHandle _dbghelp_lib;
@@ -239,6 +246,7 @@ IntPtr size
239246
private readonly SymSetContext _sym_set_context;
240247
private readonly SymEnumSymbolsW _sym_enum_symbols;
241248
private readonly SymGetHomeDirectoryW _sym_get_home_directory;
249+
private readonly SymGetDiaSession _sym_get_dia_session;
242250
private IEnumerable<SymbolLoadedModule> _loaded_modules;
243251
private readonly TextWriter _trace_writer;
244252
private readonly bool _trace_symbol_loading;
@@ -250,6 +258,11 @@ IntPtr size
250258
private void GetFunc<T>(ref T f) where T : Delegate
251259
{
252260
f = _dbghelp_lib.GetFunctionPointer<T>();
261+
}
262+
263+
private void GetFuncNoThrow<T>(ref T f) where T : Delegate
264+
{
265+
f = _dbghelp_lib.GetFunctionPointer<T>(false);
253266
}
254267

255268
private void GetFunc<T>(ref T f, string name) where T : Delegate
@@ -267,6 +280,29 @@ private static string GetNameFromSymbolInfo(SafeStructureInOutBuffer<SYMBOL_INFO
267280
return buffer.Data.ReadNulTerminatedUnicodeString();
268281
}
269282

283+
private DllMachineType GetSymbolMachineType(SYMBOL_INFO sym_info)
284+
{
285+
IDiaSession session = null;
286+
IDiaSymbol symbol = null;
287+
try
288+
{
289+
if (_sym_get_dia_session == null || !_sym_get_dia_session(Handle, sym_info.ModBase, out session))
290+
return DllMachineType.UNKNOWN;
291+
292+
if (session.findSymbolByVA(sym_info.Address, sym_info.Tag, out symbol) != 0)
293+
return DllMachineType.UNKNOWN;
294+
295+
return (DllMachineType)symbol.machineType;
296+
}
297+
finally
298+
{
299+
if (symbol != null)
300+
Marshal.ReleaseComObject(symbol);
301+
if (session != null)
302+
Marshal.ReleaseComObject(session);
303+
}
304+
}
305+
270306
private static SafeStructureInOutBuffer<SYMBOL_INFO> MapSymbolInfo(IntPtr symbol_info)
271307
{
272308
int base_size = Marshal.SizeOf(typeof(SYMBOL_INFO));
@@ -707,7 +743,8 @@ private DataSymbolInformation GetSymbolInfoForAddress(IntPtr address)
707743
var result = sym_info.Result;
708744

709745
return new DataSymbolInformation(result.Tag, result.Size, result.TypeIndex,
710-
result.Address, GetModuleForAddress(new IntPtr(result.ModBase)), GetNameFromSymbolInfo(sym_info));
746+
result.Address, GetModuleForAddress(new IntPtr(result.ModBase)),
747+
GetNameFromSymbolInfo(sym_info), GetSymbolMachineType(result));
711748
}
712749

713750
return null;
@@ -724,7 +761,8 @@ private DataSymbolInformation GetSymbolInfoForName(string name)
724761
}
725762
var result = sym_info.Result;
726763
return new DataSymbolInformation(result.Tag, result.Size, result.TypeIndex,
727-
result.Address, GetModuleForAddress(new IntPtr(result.ModBase)), GetNameFromSymbolInfo(sym_info));
764+
result.Address, GetModuleForAddress(new IntPtr(result.ModBase)),
765+
GetNameFromSymbolInfo(sym_info), GetSymbolMachineType(result));
728766
}
729767
}
730768

@@ -850,8 +888,20 @@ private Tuple<string, Uri> GetFallbackSymbolPaths(string symbol_path)
850888
}
851889
}
852890
return Tuple.Create(cache_path, server_path);
891+
}
892+
893+
private bool GetSymbolInfo(List<SymbolInformation> symbols, IntPtr symbol_info, Dictionary<long, SymbolLoadedModule> modules)
894+
{
895+
using (var sym_info = MapSymbolInfo(symbol_info))
896+
{
897+
var result = sym_info.Result;
898+
var symbol = new DataSymbolInformation(result.Tag, result.Size, result.TypeIndex,
899+
result.Address, GetModuleForAddress(new IntPtr(result.ModBase)),
900+
GetNameFromSymbolInfo(sym_info), GetSymbolMachineType(result));
901+
symbols.Add(symbol);
902+
return true;
903+
}
853904
}
854-
855905
#endregion
856906

857907
#region Public Methods
@@ -1058,6 +1108,23 @@ public TypeInformation GetTypeForSymbolByAddress(IntPtr address)
10581108
var ret = CreateType(type_cache, symbol.Tag, symbol.Module.BaseAddress.ToInt64(), symbol.TypeIndex, symbol.Size, symbol.Module, symbol.Name, symbol.Address);
10591109
type_cache.FixupPointerTypes();
10601110
return ret;
1111+
}
1112+
1113+
public IEnumerable<SymbolInformation> EnumerateSymbols(IntPtr base_address, string mask)
1114+
{
1115+
if (string.IsNullOrWhiteSpace(mask))
1116+
{
1117+
throw new ArgumentException($"'{nameof(mask)}' cannot be null or whitespace.", nameof(mask));
1118+
}
1119+
1120+
List<SymbolInformation> symbols = new List<SymbolInformation>();
1121+
Dictionary<long, SymbolLoadedModule> modules = GetLoadedModules().ToDictionary(m => m.BaseAddress.ToInt64());
1122+
if (!_sym_enum_symbols(Handle, base_address.ToInt64(),
1123+
mask, (s, z, x) => GetSymbolInfo(symbols, s, modules), IntPtr.Zero))
1124+
{
1125+
Win32Utils.GetLastWin32Error().ToNtException();
1126+
}
1127+
return symbols.AsReadOnly();
10611128
}
10621129

10631130
#endregion
@@ -1091,6 +1158,7 @@ internal DbgHelpSymbolResolver(NtProcess process, string dbghelp_path, string sy
10911158
GetFunc(ref _sym_enum_symbols);
10921159
GetFunc(ref _sym_set_context);
10931160
GetFunc(ref _sym_get_home_directory);
1161+
GetFuncNoThrow(ref _sym_get_dia_session);
10941162

10951163
_trace_writer = trace_writer ?? new TraceTextWriter();
10961164
SymOptions options = SymOptions.INCLUDE_32BIT_MODULES | SymOptions.UNDNAME | SymOptions.DEFERRED_LOADS;
@@ -1178,8 +1246,8 @@ void IDisposable.Dispose()
11781246
{
11791247
Dispose(true);
11801248
GC.SuppressFinalize(this);
1181-
}
1182-
1249+
}
1250+
11831251
#endregion
11841252
}
11851253
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright 2018 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// NOTE: This file is a modified version of SymbolResolver.cs from OleViewDotNet
16+
// https://github.com/tyranid/oleviewdotnet. It's been relicensed from GPLv3 by
17+
// the original author James Forshaw to be used under the Apache License for this
18+
// project.
19+
20+
using System.Runtime.InteropServices;
21+
22+
namespace NtApiDotNet.Win32.Debugger
23+
{
24+
[ComImport]
25+
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
26+
[Guid("2F609EE1-D1C8-4E24-8288-3326BADCD211")]
27+
internal interface IDiaSession
28+
{
29+
[DispId(1)]
30+
ulong loadAddress
31+
{
32+
get;
33+
[param: In]
34+
set;
35+
}
36+
37+
[DispId(2)]
38+
IDiaSymbol globalScope
39+
{
40+
[return: MarshalAs(UnmanagedType.Interface)]
41+
get;
42+
}
43+
void getEnumTables();
44+
void getSymbolsByAddr();
45+
void findChildren();
46+
void findChildrenEx();
47+
void findChildrenExByAddr();
48+
void findChildrenExByVA();
49+
void findChildrenExByRVA();
50+
void findSymbolByAddr();
51+
void findSymbolByRVA();
52+
[PreserveSig]
53+
int findSymbolByVA([In] long va, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol);
54+
}
55+
}

0 commit comments

Comments
 (0)