0

我遇到了一种情况,我需要找到我在一段 VB 代码中使用的字符串的内存地址。我尝试使用各种调试器并使用简单的 procexplorer 来显示内存中可打印字符串的列表。但它没有显示任何让我困惑的东西。VB(.net framework 4)是否使用某种编码机制来存储字符串,使其不会以可打印格式出现?

这是我试图在内存中定位的变量:“spoilt”

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
4

2 回答 2

1

这些是托管字符串。我不确定您使用的工具是否知道如何从内存中读取托管字符串。

.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 的全部内容。

  1. 首先打开 WinDbg 并选择打开进程并打开您的 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
    

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

  4. !eeversion我们可以通过运行获取 Execution Enging 版本来测试 SOS 是否正确加载。对我来说,这给出了“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. 然后我们可以进入 Showwith t

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

    004ee820 5c22839c System.Windows.Forms.MessageBox.Show(System.String)
    PARAMETERS:
    text (<CLR reg>) = 0x022a1058
    
  10. 所以现在我们知道字符串的地址是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
    
于 2012-08-13T17:40:45.657 回答
0

回答我自己关于编码的问题:是的,Unicode 编码用于存储所有字符串。@vcsjones 的上述回答详细解释了如何找到这些字符串的内存位置。

为了寻找有关如何找到此地址的答案的人们的利益,有一种更简单的方法。mona.py (http://redmine.corelan.be/projects/mona) 是一个免疫调试器插件来完成这项工作。我用它来查找内存位置。我无法找到所需内容的唯一原因是 unicode 格式。但是,使用 mona.py 也可以选择搜索 unicode 字符串。

于 2012-08-15T14:03:50.440 回答