Debugging 如何使用Windbg poi函数转储字符串

Debugging 如何使用Windbg poi函数转储字符串,debugging,windbg,Debugging,Windbg,并显示将字符串转储到本地文件的脚本: $$ Dumps the managed strings to a file $$ Platform x86 $$ Usage $$>a<"c:\temp\dumpstringtofolder.txt" 6544f9ac 5000 c:\temp\stringtest $$ First argument is the string method table pointer $$ Second argument is the Min size of

并显示将字符串转储到本地文件的脚本:

$$ Dumps the managed strings to a file
$$ Platform x86
$$ Usage $$>a<"c:\temp\dumpstringtofolder.txt" 6544f9ac 5000 c:\temp\stringtest
$$ First argument is the string method table pointer
$$ Second argument is the Min size of the string that needs to be used filter the strings
$$ Third is the path of the file
.foreach ($string {!dumpheap -short -mt ${$arg1}  -min ${$arg2}})
{ 

  $$ MT        Field      Offset               Type  VT     Attr    Value Name
  $$ 65452978  40000ed        4         System.Int32  1 instance    71117 m_stringLength
  $$ 65451dc8  40000ee        8          System.Char  1 instance       3c m_firstChar
  $$ 6544f9ac  40000ef        8        System.String  0   shared   static Empty

  $$ start of string is stored in the 8th offset, which can be inferred from above
  $$ Size of the string which is stored in the 4th offset
  r@$t0=  poi(${$string}+4)*2
  .writemem ${$arg3}${$string}.txt ${$string}+8 ${$string}+8+@$t0
}
因此,我将代码更改为:

  r@$t0=  poi(${$string}+8)*2
  .writemem ${$arg3}${$string}.txt ${$string}+c ${$string}+c+@$t0
在这里,我想知道函数poi,
1.为什么这里需要“*2”
2.我找到一个字符串地址,快跑!这样做:

0:000> !do 0x00000000ffad0de0
Name:        System.String
MethodTable: 000007fef5da6738
EEClass:     000007fef592ed68
Size:        794(0x31a) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      jv15Rr2HXPn3....
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
000007fef5dac620  4000103        8         System.Int32  1 instance              384 m_stringLength
000007fef5dab160  4000104        c          System.Char  1 instance               6a m_firstChar
000007fef5da6738  4000105       10        System.String  0   shared           static Empty
/txrqcf...........j7ULyzqxSmB3bpu
我跑

0:000> ? poi(0x00000000ffad0de0)+8
Evaluate expression: 8791627818816 = 000007fe`f5da6740
获取长度值384,但输出值错误(显示为8791627818816)。 怎么了

谢谢你帮助我

更新1): 我试过:

结果似乎不正确

更新2): 我尝试调试脚本:

 .echo ${$str}
  r@$t0=  poi(${$str}+8)*2
  .printf "@$t0 is %d\n", @$t0
  .echo ${$arg3}${$str}.txt
  .printf "${$str}+c: %p\n", ${$str}+c
  .printf "${$str}+c+@$t0: %p\n", ${$str}+c+@$t0
  $$.writemem ${$arg3}${$str}.txt ${$str}+c ${$str}+c+@$t0
然后我得到了输出:

0x00000000ffad4550
@$t0 is 640
c:\stringtest\0x00000000ffad4550.txt
0x00000000ffad4550+c: 00000000ffad455c
0x00000000ffad4550+c+@$t0: 00ec00d4ffad47dc
然后对输出地址运行.writeme:

0:000> .writemem c:\stringtest\ss.txt 00000000ffad455c L0n640
Writing 280 bytes.
我得到了正确的字符串,如下所示:

0:000> !do 0x00000000ffad0de0
Name:        System.String
MethodTable: 000007fef5da6738
EEClass:     000007fef592ed68
Size:        794(0x31a) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      jv15Rr2HXPn3....
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
000007fef5dac620  4000103        8         System.Int32  1 instance              384 m_stringLength
000007fef5dab160  4000104        c          System.Char  1 instance               6a m_firstChar
000007fef5da6738  4000105       10        System.String  0   shared           static Empty
/txrqcf...........j7ULyzqxSmB3bpu
我运行命令:

0:000> .writemem c:\stringtest\ss.txt 00000000ffad455c 00ec00d4ffad47dc
                                                                      ^ Range error
我得到了错误范围错误,我检查了以找出结果,但我不知道。

poi(${$string}+8)是字符串长度(以字符为单位)

*2是必需的,因为C#中的字符串是Unicode,并且为了写入内存,我们需要字节,而不是字符

+c是64位字符[]的偏移量。这是写入的起始地址

? poi(0x00000000ffad0de0)+8
这是不正确的,因为poi(0x00000000ffad0de0)为您提供.NET对象的方法表的值,即000007fef5da6738,然后添加8,即7FEF5DA6740

你想做的是

? poi(0x00000000ffad0de0+8) 
在支架里面

要绕过范围错误,请使用L?语法改为范围开始和范围结束:

.writemem ${$arg3}${$str}.txt ${$str}+c L? @$t0
poi(${$string}+8)是以字符为单位的字符串长度

*2是必需的,因为C#中的字符串是Unicode,并且为了写入内存,我们需要字节,而不是字符

+c是64位字符[]的偏移量。这是写入的起始地址

? poi(0x00000000ffad0de0)+8
这是不正确的,因为poi(0x00000000ffad0de0)为您提供.NET对象的方法表的值,即000007fef5da6738,然后添加8,即7FEF5DA6740

你想做的是

? poi(0x00000000ffad0de0+8) 
在支架里面

要绕过范围错误,请使用L?语法改为范围开始和范围结束:

.writemem ${$arg3}${$str}.txt ${$str}+c L? @$t0

这表明什么:?poi(0x00000000ffad0de0+8)0:000>?poi(0x00000000ffad0de0+8)显示:求值表达式:33214502518391168=0076006a`00000180几乎在那里。0x180=0n384,这是您看到的64位值的低位DWORD。尝试对双字使用dwo运算符:?dwo(0x00000000ffad0de0+8)这显示了什么:?poi(0x00000000ffad0de0+8)0:000>?poi(0x00000000ffad0de0+8)显示:求值表达式:33214502518391168=0076006a`00000180几乎在那里。0x180=0n384,这是您看到的64位值的低位DWORD。尝试对双字使用dwo运算符:?dwo(0x00000000ffad0de0+8)谢谢你,我真的很感谢你!谢谢你,我真的很感激你!