【问题标题】:Windbg managed objects poi for arrays first element, second elementWindbg 托管对象 poi 用于数组第一个元素,第二个元素
【发布时间】:2020-04-29 05:50:54
【问题描述】:

我可以在windbg 脚本中使用poi 来遍历字段,然后打印我感兴趣的字段。 例如如果我有X 类型的所有对象,其中z 是一个数组,其中y 位于偏移量0x10z 位于偏移量0x8。我会写

.foreach ( dSM { !dumpheap -short -type X})
 { 
    .printf "%p\n", poi(poi(${dSM}+0x10)+0x8); 
    !dumparray poi(poi(${dSM}+0x10)+0x8)     
}

现在我想打印所有这些数组的第一个/第二个元素,我该怎么做?

使用!do poi(poi(poi(${dSM}+0x10)+0x8)) 不起作用。

0:045> !DumpArray /d 000001d3b96787a8
Name:        ABC[]
MethodTable: 00007ffc951e76e0
EEClass:     00007ffcf22f4480
Size:        56(0x38) bytes
Array:       Rank 1, Number of elements 4, Type CLASS
Element Methodtable: 00007ffc951e6cc0
[0] 000001d3b9678788
[1] null
[2] null
[3] null
0:045> !dumpobj /d poi(000001d3b96787a8)
<Note: this object has an invalid CLASS field>
Invalid object

数组类是:

:045> !DumpClass /d 00007ffcf22f4480
Class Name:      System.Object[]
mdToken:         0000000002000000
File:            C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Parent Class:    00007ffcf22f5018
Module:          00007ffcf2221000
Method Table:    00007ffcf2949e80
Vtable Slots:    18
Total Method Slots:  1c
Class Attributes:    2101  
Transparency:        Transparent
NumInstanceFields:   0
NumStaticFields:     0

【问题讨论】:

    标签: windbg sos


    【解决方案1】:

    鉴于这个程序:

    using System;
    
    namespace WinDbgArrayAccess
    {
        class Program
        {
            static void Main()
            {
                Program[] justAnArray = new Program[20];
                for (int i =0; i<justAnArray.Length;i++) justAnArray[i] = new Program();
                Console.WriteLine("Access the elements of the array in WinDbg now!");
                Console.ReadLine();
            }
        }
    }
    

    你可以看到

    0:006> !DumpArray /d 0336243c
    Name:        WinDbgArrayAccess.Program[]
    MethodTable: 01914db0
    EEClass:     71967820
    Size:        92(0x5c) bytes
    Array:       Rank 1, Number of elements 20, Type CLASS
    Element Methodtable: 01914d60
    [0] 03362498
    [1] 033624a4
    [2] 033624b0
    [3] 033624bc
    [4] 033624c8
    [5] 033624d4
    ...
    

    现在你需要在内存的某个地方找到这些数字。由于我们几乎没有不同的起点,让我们从数组的地址开始:

    0:006> dp 0336243c L10
    0336243c  01914db0 00000014 03362498 033624a4
    0336244c  033624b0 033624bc 033624c8 033624d4
    0336245c  033624e0 033624ec 033624f8 03362504
    0336246c  03362510 0336251c 03362528 03362534
    

    现在,01914db0 是对象的类型(称为方法表,MT)。 0x140n20,这是数组的大小。在那之后,我们似乎有了03362498033624a4033624b0等元素。

    我们如何以编程方式访问它?好吧,现在很容易:

    0:006> .printf "%p",poi(0336243c+(2+3)*$ptrsize)
    033624bc
    

    2 是跳过 MT 和 Length,3 是数组的索引,为您提供第 4 个元素。

    【讨论】:

    • 感谢您解释您的方法。这将对我将来有所帮助。
    • 我使用了:.foreach (obj { !DumpHeap -short -live -mt 00007ffc951e7ab8}) { .printf "%p\n", ${obj}; !mex.do2 poi(poi(poi(poi(${obj}+0x10)+0x8)+0x10)+0x8); !mex.do2 poi(poi(poi(poi(${obj}+0x10)+0x8)+0x10)+0x10); } .. going +10+8+10+10 前两个字段。
    【解决方案2】:

    我能够通过从数组中前进poi(poi(array+10)+8)poi(poi(array+10)+10) 偏移来获得前两个元素

    0:298> .foreach (obj { !DumpHeap -short -live -mt 00007ffc951e7ab8}) { .printf "%p\n", ${obj}; !mex.do2 poi(poi(poi(poi(${obj}+0x10)+0x8)+0x10)+0x8); !mex.do2 poi(poi(poi(poi(${obj}+0x10)+0x8)+0x10)+0x10); }
    000001d379ac94a0
    [raw] 000001d379ac8bc8 "XYZ_String"
    [raw] 000001d379ac8c88 "XYZ_String_2"
    000001d379e87168
    [raw] 000001d379e86888 "ABCD_String"
    [raw] 000001d379e86948 "ABCD_String_2"
    000001d3b972a218
    

    【讨论】:

      猜你喜欢
      • 2022-11-16
      • 1970-01-01
      • 2019-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多