windbg 关于L10比L9多更多行,和poi的含义
文章目录
- db esp
- db esp L10
- poi用法
- 为什么dd cb21ca7e会失败呢
db esp
在 WinDbg 中,db
是一个命令,用于显示内存地址中的数据,以字节(Byte)为单位。esp
是一个寄存器,代表“Extended Stack Pointer”,即扩展的栈指针寄存器,在32位x86架构中使用。在64位架构中,对应的寄存器是 rsp
。
当你在 WinDbg 中输入 db esp
命令时,你实际上是在请求调试器显示当前栈顶指针 esp
所指向的内存地址开始的一系列字节。这个命令通常用于查看栈上的数据,比如函数参数、局部变量或者返回地址等。
例如,如果 esp
的值是 0x0012FF7C
,那么 db esp
命令将会显示从 0x0012FF7C
开始的内存内容,通常会显示一系列的字节,直到你指定的长度或者默认长度为止。
0:000> db esp
0012ff7c 61 62 63 64 65 66 67 68-69 6a 6b 6c 6d 6e 6f 70 abcdefghijklmnop
在这个例子中,db esp
命令显示了从 esp
指向的地址开始的16个字节的内容,以十六进制和ASCII字符的形式展示。这对于调试栈溢出或者理解函数调用过程中的栈状态非常有用。
db esp L10
在 WinDbg 中,db
命令用于以字节(Byte)为单位显示内存内容,而 esp
是栈指针寄存器。当你想要显示 esp
指向的内存地址开始的特定数量的字节时,你可以使用 L
选项来指定长度。L10
表示你想要显示10个字节的内容。
所以,当你输入 db esp L10
命令时,WinDbg 会显示从 esp
寄存器指向的地址开始的10个字节的内容。这个命令对于查看栈上的数据非常有用,比如函数参数、局部变量或者返回地址等。
例如,如果 esp
的值是 0x0012FF7C
,那么 db esp L10
命令将会显示从 0x0012FF7C
开始的10个字节的内容:
0:000> db esp L10
0012ff7c 61 62 63 64 65 66 67 68-69 6a ab cdefghij
在这个例子中,db esp L10
命令显示了从 esp
指向的地址开始的10个字节的内容,以十六进制的形式展示。这对于调试栈溢出或者理解函数调用过程中的栈状态非常有用。每个字节之间用空格分隔,每8个字节后换行,以便于阅读。
好的,让我用更通俗的语言来解释一下:
当你在 WinDbg 中使用 db
命令时,你是在告诉调试器“嘿,我想看看内存里的东西”。esp
是一个指向你电脑内存中某个位置的指针,就像一个地址一样。L10
、L9
和 L8
是你告诉调试器你想看多少个字节(一个字节就是8位,可以表示一个数字或者一个字符)。
想象一下,内存就像一本电话簿,每一页有16个电话号码。当你对调试器说“我想看从这个地址开始的10个电话号码”,调试器就会打开电话簿,找到那个地址,然后给你看从那个地址开始的10个电话号码。但是,如果这10个号码没有正好填满一页,调试器会继续给你看那一页剩下的号码,直到填满一页为止。这就是为什么有时候你会看到比你请求的更多的信息。
所以,当你请求看10个字节时(db esp L10
),调试器会显示从 esp
指向的地址开始的10个字节,但如果这10个字节没有填满一行(16个字节),调试器会继续显示那一行剩下的字节,直到一行结束。这就是为什么你看到的输出看起来像是多于10个字节,实际上调试器只是在帮你把那一行填满。
当你请求看9个或8个字节时(db esp L9
或 db esp L8
),同样的事情会发生,但因为你请求的字节数更少,所以调试器只需要显示更少的额外字节来填满那一行。
简而言之,WinDbg 会显示你请求的字节数,但如果这些字节没有填满一行,它会显示额外的字节来完成那一行。这样做的目的是为了让输出看起来更整齐,更容易阅读。
poi用法
0:001> dd esp
000000c2`bb87f918 cb21ca7e 00007ffd 00000000 00000000
000000c2`bb87f928 00000000 00000000 00000000 00000000
000000c2`bb87f938 00000000 00000000 00000000 00000000
000000c2`bb87f948 ca487374 00007ffd 00000000 00000000
000000c2`bb87f958 00000000 00000000 00000000 00000000
000000c2`bb87f968 00000000 00000000 00000000 00000000
000000c2`bb87f978 cb19cc91 00007ffd 00000000 00000000
000000c2`bb87f988 00000000 00000000 00000000 00000000
0:001> dd 000000c2`bb87f918
000000c2`bb87f918 cb21ca7e 00007ffd 00000000 00000000
000000c2`bb87f928 00000000 00000000 00000000 00000000
000000c2`bb87f938 00000000 00000000 00000000 00000000
000000c2`bb87f948 ca487374 00007ffd 00000000 00000000
000000c2`bb87f958 00000000 00000000 00000000 00000000
000000c2`bb87f968 00000000 00000000 00000000 00000000
000000c2`bb87f978 cb19cc91 00007ffd 00000000 00000000
000000c2`bb87f988 00000000 00000000 00000000 00000000
0:001> dd cb21ca7e
00000000`cb21ca7e ???????? ???????? ???????? ????????
00000000`cb21ca8e ???????? ???????? ???????? ????????
00000000`cb21ca9e ???????? ???????? ???????? ????????
00000000`cb21caae ???????? ???????? ???????? ????????
00000000`cb21cabe ???????? ???????? ???????? ????????
00000000`cb21cace ???????? ???????? ???????? ????????
00000000`cb21cade ???????? ???????? ???????? ????????
00000000`cb21caee ???????? ???????? ???????? ????????
0:001> dd poi(esp)
00007ffd`cb21ca7e c93300eb f821a9e8 cccc90ff cccccccc
00007ffd`cb21ca8e 4865cccc 3025048b 48000000 16a88889
00007ffd`cb21ca9e ccc30000 cccccccc cccccccc cccccccc
00007ffd`cb21caae 4865cccc 3025148b 48000000 16a8928b
00007ffd`cb21cabe 6be90000 ccfffd38 cccccccc cccccccc
00007ffd`cb21cace 4865cccc 3025048b 4c000000 8b4cc98b
00007ffd`cb21cade 4801b2c2 16a8888b 43e90000 ccfffd44
00007ffd`cb21caee cccccccc cccccccc cccccccc cccccccc
0:001> dd cb21ca7e 00007ffd
^ Range error in 'dd cb21ca7e 00007ffd'
在 WinDbg 中,dd
命令用于以双字(dword,4字节)为单位显示内存内容。
-
dd esp
:这个命令显示了从esp
寄存器指向的地址开始的内存内容,以4字节为单位显示。输出显示了从地址000000c2
bb87f918` 开始的内存内容,每行显示4个双字(共16字节)。 -
dd 000000c2
bb87f918:这个命令与
dd esp相同,因为它直接使用了
esp` 寄存器的值作为起始地址。 -
dd cb21ca7e
:这个命令尝试显示从地址cb21ca7e
开始的内存内容。但是,这个地址看起来像是一个无效的地址(可能是一个非规范地址或者不在当前进程的地址空间内),因为输出显示了一系列的????????
,表示无法读取该地址的内存内容。 -
dd poi(esp)
:这个命令使用了poi
操作符来解引用esp
寄存器指向的地址,然后显示该地址指向的内存内容。这意味着它首先读取esp
指向的地址中的值(在这个例子中是cb21ca7e
),然后显示从cb21ca7e
开始的内存内容。这次,它成功地显示了内容,因为poi(esp)
得到的是一个有效的内存地址。 -
dd cb21ca7e 00007ffd
:这个命令尝试显示从地址cb21ca7e
开始到00007ffd
结束的内存范围。但是,这个命令格式不正确,因为dd
命令期望的是一个起始地址和一个长度(例如L10
表示显示10个双字),而不是两个地址。这就是为什么 WinDbg 报告了一个“Range error”。
为什么dd cb21ca7e会失败呢
0:001> dd poi(esp)
00007ffd`cb21ca7e c93300eb f821a9e8 cccc90ff cccccccc
00007ffd`cb21ca8e 4865cccc 3025048b 48000000 16a88889
00007ffd`cb21ca9e ccc30000 cccccccc cccccccc cccccccc
00007ffd`cb21caae 4865cccc 3025148b 48000000 16a8928b
00007ffd`cb21cabe 6be90000 ccfffd38 cccccccc cccccccc
00007ffd`cb21cace 4865cccc 3025048b 4c000000 8b4cc98b
00007ffd`cb21cade 4801b2c2 16a8888b 43e90000 ccfffd44
00007ffd`cb21caee cccccccc cccccccc cccccccc cccccccc
0:001> dd 00007ffd`cb21ca7e
00007ffd`cb21ca7e c93300eb f821a9e8 cccc90ff cccccccc
00007ffd`cb21ca8e 4865cccc 3025048b 48000000 16a88889
00007ffd`cb21ca9e ccc30000 cccccccc cccccccc cccccccc
00007ffd`cb21caae 4865cccc 3025148b 48000000 16a8928b
00007ffd`cb21cabe 6be90000 ccfffd38 cccccccc cccccccc
00007ffd`cb21cace 4865cccc 3025048b 4c000000 8b4cc98b
00007ffd`cb21cade 4801b2c2 16a8888b 43e90000 ccfffd44
00007ffd`cb21caee cccccccc cccccccc cccccccc cccccccc
在示例中,两个命令 dd poi(esp)
和 dd 00007ffd
cb21ca7e都成功地显示了从地址
00007ffdcb21ca7e
开始的内存内容,并且显示的内容是一致的。这说明在执行这两个命令时,内存中的这个区域是可访问的,并且包含了有效的数据。
这里的关键点是,poi(esp)
命令实际上是先读取 esp
寄存器指向的内存地址中的值,然后将这个值作为新的地址来访问内存。在例子中,esp
寄存器指向的内存地址中存储的值是 00007ffd
cb21ca7e,这是一个有效的内存地址,因此
dd poi(esp)` 命令能够成功地显示从这个地址开始的内存内容。
当你直接使用 dd 00007ffd
cb21ca7e命令时,你是在告诉 WinDbg 直接访问这个具体的内存地址,而不需要通过
esp` 寄存器。由于这个地址是有效的,并且在两次命令执行期间内存内容没有变化,所以两个命令显示的结果是一致的。
这种一致性表明,无论你是通过 poi(esp)
间接访问,还是直接指定地址访问,只要目标地址是有效的,你都能得到相同的内存内容。这也说明了为什么在之前的讨论中,dd cb21ca7e
命令失败了,而 dd poi(esp)
成功了:在那个特定的上下文中,cb21ca7e
可能被解释为一个不完整的地址(缺少了高位的模块基址),而 poi(esp)
提供了一个完整的、有效的地址。
在示例中,两个命令都正确地访问了同一个内存区域,并且显示了相同的数据。这说明在执行这些命令的时候,内存状态是稳定的,没有发生改变。