Visual Basic如何在内存中存储字符串?

时间:2012-08-13 17:08:30

标签: vb.net string memory-management .net-4.0 reverse-engineering

我遇到了一个需要找到我在一段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

3 个答案:

答案 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


现在,如果你想在运行时找到字符串的地址......

我将使用WinDbgSOS extensions选择的工具。以下是如何在内存中找到该字符串。

这完全适用于x86 .NET Framework 4。

  1. 首先打开WinDbg并选择Open Process并打开您的EXE。它会立即打破,让你有机会进行设置,比如断点。
  2. 加载CLR JIT时设置异常停止。这是加载SOS调试器扩展的正确时间。

    sxe ld:clrjit
    

    然后继续执行g

  3. 此时我们应该在clrjit的modload上找到一个断点。

    ModLoad: 57910000 57970000   C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll
    

    从那里我们可以使用.loadby sos clr加载SOS调试扩展。

  4. 我们可以通过运行!eeversion来测试正确加载SOS以获取Execution Enging版本。对我来说,这给了“4.0.30319.269零售”。

  5. 现在找到那个字符串。让我们从加载System.Windows.Forms.dll模块时开始。

     sxe ld:System.Windows.Forms
    

    并使用g继续执行。我们应该在加载模块时中断。继续并跳过它,以便模块实际上加载p

  6. 现在我们可以像MessageBox.Show那样打破:

    !bpmd System.Windows.Forms.dll System.Windows.Forms.MessageBox.Show
    
  7. 现在继续g。您的应用程序应该立即运行。继续并单击按钮,我们的断点应该被击中。

  8. 然后我们可以使用Show加入 t

  9. 从那里我们可以使用!clrstack -p来显示带参数的堆栈跟踪。在堆栈的顶部将是对MessageBox.Show的调用。

    004ee820 5c22839c System.Windows.Forms.MessageBox.Show(System.String)
    PARAMETERS:
    text (<CLR reg>) = 0x022a1058
    
  10. 现在我们知道字符串的地址是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字符串。