我遇到了一个需要找到我在一段VB代码中使用的String的内存地址的情况。我尝试使用各种调试器,并使用简单的procexplorer在内存中显示可打印字符串列表。但它没有显示任何困扰我的东西。 VB(.net框架4)是否使用某种编码机制来存储字符串,使其不以可打印格式显示?
这是我试图在内存中找到的变量:“被宠坏了”
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
MessageBox.Show("Button1")
Dim spoilt As String
spoilt = TextBox1.Text
Label1.Text = spoilt
End Sub
答案 0 :(得分:1)
这些是托管的字符串。我不确定你使用的工具是否知道如何读取内存中的托管字符串。
.NET字符串文字存储在可移植可执行文件的元数据部分中。除非该工具了解如何从.NET的元数据部分中读取它,否则它将无法找到它。您可以使用ildasm之类的工具查看字符串。在“查看”和“MetaInfo”下,单击“显示!”。新窗口中的某个位置将是“用户字符串”部分。这是我的示例应用程序。
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令牌(在我的例子中)是700000b9
。
现在,如果你想在运行时找到字符串的地址......
我将使用WinDbg和SOS extensions选择的工具。以下是如何在内存中找到该字符串。
这完全适用于x86 .NET Framework 4。
加载CLR JIT时设置异常停止。这是加载SOS调试器扩展的正确时间。
sxe ld:clrjit
然后继续执行g
。
此时我们应该在clrjit的modload上找到一个断点。
ModLoad: 57910000 57970000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll
从那里我们可以使用.loadby sos clr
加载SOS调试扩展。
我们可以通过运行!eeversion
来测试正确加载SOS以获取Execution Enging版本。对我来说,这给了“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
将加入 t
。
从那里我们可以使用!clrstack -p
来显示带参数的堆栈跟踪。在堆栈的顶部将是对MessageBox.Show
的调用。
004ee820 5c22839c System.Windows.Forms.MessageBox.Show(System.String)
PARAMETERS:
text (<CLR reg>) = 0x022a1058
现在我们知道字符串的地址是0x022a1058
。这当然会对你有所不同。如果我们执行!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
答案 1 :(得分:0)
见Jeffrey Hantin的回答here。他的代码是用C#编写的,但我相信你可以很容易地翻译成VB.NET语法。
答案 2 :(得分:0)
回答我自己关于编码的问题:是的,Unicode编码用于存储所有字符串。 @vcsjones的上述答案提供了如何查找这些字符串的内存位置的详细说明。
为了寻找如何找到这个地址的答案的人的利益,有一种更简单的方法。 mona.py (http://redmine.corelan.be/projects/mona)是一个免疫调试器的插件来完成这项工作。我用它来查找内存位置。我无法找到我要找的东西的唯一原因是因为unicode格式。但是,使用mona.py还可以选择搜索unicode字符串。