如何使用Windbg poi函数转储字符串 [英] how to dump string using Windbg poi function

查看:339
本文介绍了如何使用Windbg poi函数转储字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

调试windbg中的.Net字符串值 WinDbg和SoS,如何打印/转储大字符串? / a>显示将字符串转储到本地文件的脚本:

  $$将托管字符串转储到文件
$$平台x86
$$用法$$> a<c:\temp\dumpstringtofolder.txt6544f9ac 5000 c:\temp\stringtest
$$第一个参数是字符串方法表指针
$$第二个参数是需要使用的字符串的最小大小过滤字符串
$$第三个是文件的路径
.foreach($ string {!dumpheap -short -mt $ {$ arg1} -min $ {$ arg2}})
{

$$ MT字段偏移类型VT Attr值名称
$$ 65452978 40000ed 4 System.Int32 1实例71117 m_stringLengt h
$$ 65451dc8 40000ee 8 System.Char 1实例3c m_firstChar
$$ 6544f9ac 40000ef 8 System.String 0共享静态空

$$开始的字符串存储在第8个偏移量,可以从上面推导出
$$存储在第4个偏移量的字符串的大小
r @ $ t0 = poi($ {$ string} +4)* 2
.writemem $ {$ arg3} $ {$ string} .txt $ {$ string} +8 $ {$ string} +8 + @ $ t0
}

这个脚本在x86上。我修改代码并尝试使用.net 4.0,x64系统。



唯一的区别是偏移量是不同的。例如:

  $$ .net 4.0,偏移量不同
$$ MT字段偏移类型VT Attr值名称
$$ 000007fee4abc7e8 4000103 8 System.Int32 1实例460 m_stringLength
$$ 000007fee4abb328 4000104 c System.Char 1实例26 m_firstChar
$$ 000007fee4ab6900 4000105 10 System.String 0共享静态空

所以,我将代码更改为:

  r @ $ t0 = poi($ {$ string} +8)* 2 
.writemem $ {$ arg3} $ {$ string} .txt $ {$ string} + c $ {$ string} + c + @ $ t0

这里,我想知道功能poi, br />
1.为什么这里需要* 2?

2.我找到一个字符串地址,运行!do,像这样:

  0:000> ; !do 0x00000000ffad0de0 
名称:System.String
MethodTable:000007fef5da6738
EEClass:000007fef592ed68
大小:794(0x31a)字节
文件:C:\Windows\ Microsoft.Net \assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
字符串:jv15Rr2HXPn3 ....
字段:
MT字段偏移类型VT Attr值名称
000007fef5dac620 4000103 8 System.Int32 1实例384 m_stringLength
000007fef5dab160 4000104 c System.Char 1实例6a m_firstChar
000007fef5da6738 4000105 10 System.String 0共享静态空

我运行

  0:000> ? poi(0x00000000ffad0de0)+8 
评估表达式:8791627818816 = 000007fe`f5da6740

长度值为384,但输出值为错误(显示为8791627818816)。
什么是错误?



感谢您帮助我!



更新1):
我试过:

  0:000> r @ $ t0 = poi(0x00000000ffad0de0 + 8)
0:000> r @ $ t0
$ t0 = 0076006a00000180

结果似乎不正确。

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

  .echo $ {$ str} 
r @ $ t0 = poi($ {$ str} +8)* 2
.printf@ $ t0 is%d\\\
,@ $ t0
.echo $ {$ arg3} $ {$ str} .txt
.printf$ {$ str} + c:%p\\\
,$ {$ str} + c
.printf$ {$ str} + c + @ $ t0:%p\\\
,$ {$ str} + c + @ $ t0
$$。writemem $ {$ arg3} $ {$ str}。 txt $ {$ str} + c $ {$ str} + c + @ $ t0

然后我得到输出:

  0x00000000ffad4550 
@ $ t0是640
c:\stringtest\0x00000000ffad4550.txt
0x00000000ffad4550 + c:00000000ffad455c
0x00000000ffad4550 + c + @ $ t0:00ec00d4ffad47dc

然后我输出输出地址的.writemem:

  0:000> .writemem c:\stringtest\ss.txt 00000000ffad455c L0n640 
写入280字节。

我得到了正确的字符串,就像这样:

  / txrqcf ........... j7ULyzqxSmB3bpu 

我运行命令:

  0:000> .writemem c:\stringtest\ss.txt 00000000ffad455c 00ec00d4ffad47dc 
^范围错误

我收到错误范围错误,我查看了链接找出结果,但我不知道。

解决方案

poi($ {$ string} +8)是字符串的长度。



* 2是需要的,因为C#中的字符串是Unicode,对于写入内存,我们需要字节,而不是字符。



+ c是64位上char []的偏移量。这是从...开始的地址。

 ? poi(0x00000000ffad0de0)+8 

这是不正确的,因为poi(0x00000000ffad0de0) .NET对象的方法表,它是000007fef5da6738,然后添加8,这是7FEF5DA6740。



你想做的是

 ?大括号内的poi(0x00000000ffad0de0 + 8)



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

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


Debugging .Net String value in windbg and WinDbg and SoS, how do I print/dump a large string? show a script that dump the string to a local file:

$$ 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
}

this script is on x86. I modify the code and try on .net 4.0, x64 system.

the only difference is that the offset is different. for example:

    $$ .net 4.0 , the offset is different
$$                     MT    Field   Offset                 Type VT     Attr            Value Name
$$      000007fee4abc7e8  4000103        8         System.Int32  1 instance              460 m_stringLength
$$      000007fee4abb328  4000104        c          System.Char  1 instance               26 m_firstChar
$$      000007fee4ab6900  4000105       10        System.String  0   shared           static Empty

So, I change my code to:

  r@$t0=  poi(${$string}+8)*2
  .writemem ${$arg3}${$string}.txt ${$string}+c ${$string}+c+@$t0

Here, I wonder the function poi,
1. why here need '*2'?
2. I find a string address, run !do, like this:

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

I run

0:000> ? poi(0x00000000ffad0de0)+8
Evaluate expression: 8791627818816 = 000007fe`f5da6740

to get the length value of 384, but the output value is wrong(displayed is 8791627818816). What is wrong?

Thank you for helping me!

updated 1): I tried:

0:000> r@$t0= poi(0x00000000ffad0de0+8)
0:000> r@$t0
$t0=0076006a00000180

the result seems not correct.

Update 2): I tried to debug the script:

 .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

then I got the output:

0x00000000ffad4550
@$t0 is 640
c:\stringtest\0x00000000ffad4550.txt
0x00000000ffad4550+c: 00000000ffad455c
0x00000000ffad4550+c+@$t0: 00ec00d4ffad47dc

then I run the .writemem for the output address:

0:000> .writemem c:\stringtest\ss.txt 00000000ffad455c L0n640
Writing 280 bytes.

I got the correct string, it's like this:

/txrqcf...........j7ULyzqxSmB3bpu

I run the command:

0:000> .writemem c:\stringtest\ss.txt 00000000ffad455c 00ec00d4ffad47dc
                                                                      ^ Range error

I got the error Range error, I check the link to find out the result, but I have no idea.

解决方案

poi(${$string}+8) is the string length in characters.

*2 is needed because Strings in C# are Unicode and for writing memory, we need the bytes, not characters.

+c is the offset of the char[] on 64 bit. That's the start address to write from.

? poi(0x00000000ffad0de0)+8

This is incorrect, because poi(0x00000000ffad0de0) gives you the value of the method table of the .NET object, which is 000007fef5da6738 and then you add 8, which is 7FEF5DA6740.

What you want to do is

? poi(0x00000000ffad0de0+8) 

inside the braces.

To bypass the range error, use the L? syntax instead range start and range end:

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

这篇关于如何使用Windbg poi函数转储字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆