Windbg управляемые объекты poi для массивов первый элемент, второй элемент - PullRequest
0 голосов
/ 29 апреля 2020

Я могу использовать poi в сценариях windbg для обхода полей, а затем распечатать интересующее меня поле. Например, если у меня есть все объекты типа X, у которых есть поле X.y.z, где z является массив, где y имеет смещение 0x10, а z имеет смещение 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

Ответы [ 2 ]

2 голосов
/ 30 апреля 2020

Для данной программы:

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 - это тип объекта (называемый Method Table, MT). 0x14 - это 0n20, который является размером массива. И после этого, кажется, у нас есть элементы 03362498, 033624a4, 033624b0 et c.

Как мы получаем доступ к этому программно? Что ж, теперь все просто:

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

Где 2 - пропуск МТ и длины, а 3 - индекс массива, дающий вам 4-й элемент.

0 голосов
/ 30 апреля 2020

Мне удалось получить первые 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
...