这些是托管字符串。我不确定您使用的工具是否知道如何从内存中读取托管字符串。
.NET 字符串文字存储在可移植可执行文件的元数据部分。除非该工具了解如何从 .NET 的元数据部分中读取它,否则它不会找到它。您可以使用ildasm之类的工具查看字符串。在“查看”和“元信息”下,单击“显示!”。新窗口中的某处将是“用户字符串”部分。这是我的示例应用程序。
User Strings
-------------------------------------------------------
70000001 : (35) L"Property can only be set to Nothing"
70000049 : (28) L"WinForms_RecursiveFormCreate"
70000083 : (26) L"WinForms_SeeInnerException"
700000b9 : ( 7) L"Button1"
700000c9 : ( 6) L"Label1"
700000d7 : ( 8) L"TextBox1"
700000e9 : ( 5) L"Form1"
700000f5 : (29) L"WindowsApplication1.Resources"
在这里我们可以看到字符串(在我的例子中)的 MetaData Token 是700000b9
.
现在,如果您想在运行时查找字符串的地址...
我将用来执行此操作的首选工具是带有SOS 扩展的WinDbg。以下是如何在内存中找到该字符串。
这就是 x86 .NET Framework 4 的全部内容。
- 首先打开 WinDbg 并选择打开进程并打开您的 EXE。它会立即中断,让您有机会进行设置,例如断点。
加载 CLR JIT 时设置异常停止。这将是加载 SOS 调试器扩展的正确时机。
sxe ld:clrjit
然后继续执行g
.
在这一点上,我们应该在 clrjit 的 modload 上打断点。
ModLoad: 57910000 57970000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll
从那里我们可以加载 SOS 调试扩展.loadby sos clr
。
!eeversion
我们可以通过运行获取 Execution Enging 版本来测试 SOS 是否正确加载。对我来说,这给出了“4.0.30319.269 零售”。
现在找到那个字符串。System.Windows.Forms.dll
让我们从加载模块时中断开始。
sxe ld:System.Windows.Forms
并用于g
继续执行。我们应该在模块加载时中断。继续并跨过它,以便模块实际加载p
.
现在我们可以MessageBox.Show
像这样中断:
!bpmd System.Windows.Forms.dll System.Windows.Forms.MessageBox.Show
现在继续前进g
。您的应用程序现在应该正在运行。继续并单击按钮,我们的断点应该被命中。
然后我们可以进入 Show
with t
。
从那里我们可以使用!clrstack -p
参数显示堆栈跟踪。在堆栈的顶部将调用MessageBox.Show
.
004ee820 5c22839c System.Windows.Forms.MessageBox.Show(System.String)
PARAMETERS:
text (<CLR reg>) = 0x022a1058
所以现在我们知道字符串的地址是0x022a1058
. 这对你来说当然会有所不同。如果我们执行 a!do 0x022a1058
它会给我们字符串:
Name: System.String
MethodTable: 638afb08
EEClass: 635e8bb0
Size: 28(0x1c) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: Button1