Windbg-<hresult 0x80004002 =“”>,无效的类型转换,别名为vs。

时间:2019-03-27 14:08:48

标签: casting alias windbg

美好的一天,

我有一个Windbg脚本,该脚本使用.do循环在堆栈的框架周围进行迭代。对于每帧,它都使用!for_each_local$spat ("@#Local","foo")来匹配我感兴趣的初始外观。然后,我使用dx @$t2 =进行分配,并最终打印出我感兴趣的内容,即dx @$t2 = ((foobase*) this)->m_current->m_name-大多数情况下可以正常工作。

每一次,框架中都会有this,无法成功地使用dx进行投射,因此就好像需要barbase,而不是{ {1}} ... foobase似乎还可以,因为我已经将其包装在dx中,因此它最终包含导致脚本退出的 something (尽管尝试.foreach (output { dx @$t2 = ((foobase*) this)->m_current->m_name }) {})。

起初我并没有真正意识到发生了什么,但是执行.catch可以帮助我确定内容为.printf "%ma\n", @$t2,我认为暗示了无效的类型转换-如果是这样的话,这是很有意义的。我的脚本行在需要<HRESULT 0x80004002>时使用foobase

如果是正确的,我正在寻找一种检查方法,然后再进一步研究脚本并尝试访问我知道的详细信息,这将导致脚本退出。

似乎想出了一种复杂的方法...但是我想问问是否还有更好的方法...

barbase

是否可以在不使用别名的情况下检查.frame 0a $$ a frame with barbase, not foobase dx @$t2 = ((foobase*) this)->m_name .printf "%ma\n", @$t2 $$ prints <HRESULT 0x80004002> as /c CastCheck .printf "%ma", @$t2 .if ($spat(@"${CastCheck}","<HRESULT 0x80004002>") = 1) { .printf "yes" } .else { .printf "no" } $$ prints yes 是否包含无效转换的指示符?

我之所以这样问,是因为使用别名引起了我很多困惑……在我的脚本中(要使其正常工作,而且看起来确实工作得很好),我不得不使用$t2而不是{ {1}}(我可以在“命令窗口”中使用aS很好,而且我不太理解为什么为什么阅读文档后需要更改为as),并且我还需要以分号结束行(与脚本中的其他行不同),并且我需要在as之前紧接着使用aS,然后再快速使用,否则别名似乎迷路,以某种方式...所以您可以说使用此别名给我带来了一些麻烦。

因此,是否有 a)一种简单的方法来预先检查我正在查看的内容是ad /q CastCheck;还是aS,还是 b) 在投射尝试后是否检查foobase是否包含此barbase?如果我执行$t2,它会显示<HRESULT 0x80004002> ... .printf "%d", @$t2也代表什么吗?

或者其他任何想法(或问题)。

编辑:

我要尝试 并用命令窗口中的2个短代码来说明我的意思...其中第00帧包含一个5可以强制转换为5,然后。this可以很好地工作,并且第0a帧包含foobase的{​​{1}}(但是我的脚本仍然没有期望它,并且我希望能够满足它的需求)... printf仍将{em>东西放在this中...我希望能够检测到它垃圾(或者预先检测,如果barbasedx,我什至不应该尝试$t10,因为它毫无意义,而且我对此也不感兴趣)。

dx

这是thisbarbase,甚至没有0:038> .frame 00 00 00000006`3e2bc930 00007ffe`926293a8 BlahBlahBlah 0:038> dx @$t10 = ((foobase *) this)->m_name @$t10 = ((foobase *) this)->m_name : 0x869c7b8 : "nice string" [Type: char *] 0:038> .printf "%ma\n", @$t10 nice string 的地方:

this

当放入循环中时,我发现当我尝试检查返回的字符串的长度时,脚本将在第0a帧上以barbase退出由m_name

基本上,在第二个代码段中,我想要一种方法来检查0:038> .frame 0a 0a 00000006`3e2bd220 00007ffe`91ec7780 BlahBlahBlah 0:038> dx @$t10 = ((foobase *) this)->m_name @$t10 = ((foobase *) this)->m_name : 0x2265646f00000005 : "--- memory read error at address 0x2265646f`00000005 ---" [Type: char *] 0:038> .printf "%ma\n", @$t10 <HRESULT 0x80004002> 是否为不是一个不错的字符串(可能是Memory access error?),或者甚至更好,根本不做dx$t10,因为我可以检查<HRESULT 0x80004002>dx,而不是.printf

这是否更有意义,还是我应该重新开始?

2 个答案:

答案 0 :(得分:1)

您尝试过,但是仍然含糊不清

您能解释一下.frame的必要性吗?
然后DX这个??

您可以将任何地址投射为任何类型

例如,在第一次运行中,我将其强制转换为正确的类型并枚举所有框架

在下一轮中,我将转换为伪类型并枚举

在这两个帧中只有一个具有this指针

当类型正确时,它会返回正确的成员

假的时候,它会返回假的东西

0:000> !for_each_frame dx ((Student *) this)->Name
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
00 000000c5`d6f6f8c0 00007ff7`2818117c thisptr!Student::PrintStudent+0x9 [f:\src\thisptr\thisptr.cpp @ 20] 
((Student *) this)->Name                 : 0x7ff7282153e0 : "dave" [Type: char *]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
01 000000c5`d6f6f8f0 00007ff7`281b6c20 thisptr!main+0x2c [f:\src\thisptr\thisptr.cpp @ 33] 
Error: Unable to bind name 'this'

它找到了这个,但是找不到会员名称

0:000> !for_each_frame dx ((ntdll!_EPROCESS *) this)->Name
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
00 000000c5`d6f6f8c0 00007ff7`2818117c thisptr!Student::PrintStudent+0x9 [f:\src\thisptr\thisptr.cpp @ 20] 
Error: Unable to bind name 'Name' <<<<<<
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
01 000000c5`d6f6f8f0 00007ff7`281b6c20 thisptr!main+0x2c [f:\src\thisptr\thisptr.cpp @ 33] 
Error: Unable to bind name 'this' 

您知道此指针的类型是什么,为什么要强制转换它?

您可以通过各种命令找到该ptr的类型,其中一些命令如下所示

0:000> dx this
this                 : 0xc5d6f6f910 [Type: Student *] <<<
    [+0x000] Roll             : 1 [Type: int]
    [+0x008] Name             : 0x7ff7282153e0 : "dave" [Type: char *]
    [+0x010] Marks            : 72.300000 [Type: double]


0:000> ?? this 
class Student * 0x000000c5`d6f6f910  <<<
   +0x000 Roll             : 0n1
   +0x008 Name             : 0x00007ff7`282153e0  "dave"
   +0x010 Marks            : 72.299999999999997158 


0:000> x /t this
000000c5`d6f6f8f0 class Student * this = 0x000000c5`d6f6f910  <<<


0:000> x /v /t this
prv local  000000c5`d6f6f8f0    8 class Student * this = 0x000000c5`d6f6f910

0:000> dt this 
Local var @ 0xc5d6f6f8f0 Type Student*
0x000000c5`d6f6f910 
   +0x000 Roll             : 0n1
   +0x008 Name             : 0x00007ff7`282153e0  "dave"
   +0x010 Marks            : 72.299999999999997158 


0:000> dt /v this 
Local var [AddrFlags 90  AddrOff 0000000000000030  Reg/Val rsp (7)] @ 0xc5d6f6f8f0 Type Student*
0x000000c5`d6f6f910 class Student, 5 elements, 0x18 bytes
   +0x000 Roll             : 0n1
   +0x008 Name             : 0x00007ff7`282153e0  "dave"
   +0x010 Marks            : 72.299999999999997158 
   <function> Student     void (
    int, 
    char*, 
    double)+000000c5`d6f6f910
   <function> PrintStudent     void ( void )+000000c5`d6f6f910

0:000> dt /v /t this 
Local var [AddrFlags 90  AddrOff 0000000000000030  Reg/Val rsp (7)] @ 0xc5d6f6f8f0 Type Student*
0x000000c5`d6f6f910 class Student, 5 elements, 0x18 bytes
   +0x000 Roll             : 0n1
   +0x008 Name             : 0x00007ff7`282153e0  "dave"
   +0x010 Marks            : 72.299999999999997158 
   <function> Student     void (
    int, 
    char*, 
    double)+000000c5`d6f6f910
   <function> PrintStudent     void ( void )+000000c5`d6f6f910

答案 1 :(得分:0)

添加另一个答案以强调javascript的用法,而不是解析文本

javascript脚本支持已添加到windbg安静很久了 并得到了很大的改善

(要尝试使用最新的javascript功能,请在最新的Windows 10版本中使用windbg预览)

x / v / t或dv / t提供此指针的类型

javascript为这些对象提供了targetType属性

这是使用方法

使用以下内容创建一个.js文件foo.js

function typethis ( somevar ) 
{
    host.diagnostics.debugLog( somevar.targetType ,  "\t" , JSON.stringify(somevar) , "\n"  )
}

在windbg做

.load jsprovider
.scriptload x:\..\\..\foo.js
dx @$scriptcontents.functionname(argument) to run the script

结果将是

0:000> .load jsprovider
0:000> .scriptload f:\wdscr\typthis.js
JavaScript script successfully loaded from 'f:\wdscr\typthis.js'
0:000> dx @$scriptContents.typethis( this )
Student *   {"Roll":1,"Name":{},"Marks":72.3}
@$scriptContents.typethis( this )