zoukankan      html  css  js  c++  java
  • Windbg 内存命令 《第四篇》

      内存是存储数据、代码的地方,通过内存查看命令可以分析很多问题。相关命令可以分为:内存查看命令和内存统计命令。内存统计命令用来分析内存的使用状况。

    一、查看内存

      有非常丰富的内存查看命令,它们被容易为d*格式,如下所示:

    • d[类型] [地址范围]

      d代表Display,类型包括:字符、字符串、双字等。具体来说,d*命令共有这几种:d、da、db、dc、dd、dD、df、dp、dq、du、dw、dW、dyb、dyd、ds、dS。

      1、内存类型

      基本类型

    • dw = 双字节WORD格式;
    • dd = 4字节DWORD格式 ;
    • dq = 8字节格式;
    • df = 4字节单精度浮点数格式;
    • dD =8字节双精度浮点数格式;
    • dp = 指针大小格式,32位系统下4字节,64位系统下为8字节;

      基本字符串

    • da = ASCII字符串格式;
    • du = UNICODE字符串格式;
    • db =字节 + ASCII字符串;
    • dW = 双字节WORD + ASCII字符串;
    • dc = 4字节DWORD + ASCII字符串;

      高级字符串:

    • ds = ANSI_STRING类型字符串格式;
    • dS = UNICODE_STRING类型字符串格式;

      二进制 + 基本类型

    • byb = 二进制 + 字节;
    • byd = 二进制 + DWORD值;

      /c 列数:指定列数。默认情况下,列数 等于16除以列长,如dd命令的默认列数即为4列(=16/4)。例:

    • dd  /c  8

      此命令每列显示8个DWORD数,即32字节内容。

      /p:此选项用来显示物理内存信息,只能用于内核模式中。不使用此命令时,都将显示虚拟内存信息。如:

    • d  /p  [地址范围]

      L 长度: 默认情况下,d命令只显示固定长度的内存,一般为128或64字节。L可指定长度,如下面的命令将显示地址0×80000000开始处的0×100个字节内容:

    • db  0×80000000  L100 

      2、数组形式内存

      难能可贵的是,d*命令还能够以数组形式显示一段内存信息,包括:dda, ddp、 ddu、dds、dpa、dpp、dpu、dps、dqa、dqp、dqu、dqs。

      何谓“以数组形式显示”呢?这一组命令能够将指定地址处的内容,作为一系列指针,进而显示指针所指处内容。听上去有点拗口吧,读者这样想会清楚些:前一组命令显示address值,本节这一组命令显示*address值。

      程序代码中如有类似“char *array[10]”的数组变量,可使用这些命令显示数组内容。下面会有例子。这一系列命令实则由第一组命令演化而来,可分为三组:

    • 4字节DWORD为单位的dd*系列数组指令;
    • 指针长度为单位的dp*系列数组指令;
    • 8字节为单位的dq*系列数组指令。

      3、查看链表内存

      最后,d*命令的另一个变体是以链表形式显示内存内容。命令如下:

    • dl  开始地址

      默认情况下,以正向从头到尾遍历链表;也可反向(由尾向头)遍历,指定b开关选项:

    • dl  b  尾地址

      应注意的是,命令dl是Display List的缩写,这里的链表不能是用户自定义的链表,而专指符合LIST_ENTRY或SINGLE_LIST_ENTRY格式的链表。

    二、内存信息

      系统的内核空间很大的,想知道这么广大的内存空间里面都有些什么东西吗?想要知道一个内存地址,到底是被一个内核栈使用着,亦或被堆管理器使用着吗?我们这一节就领大家看看内存的地理概况。首先看Address命令:

    • !address  [地址]

      显示进程或系统的内存状态、信息,!address是最好的工具。不加任何参数,在用户模式下此命令将以内存块为单位,列出从地址0开始到0×80000000(略小于)的全部地址空间信息;内核模式下,将列出从地址0×80000000开始到0xFFFFFFFF(略小于)的全部地址空间信息;如指定地址值,则将显示此地址所在内存块的内存信息(此命令在Vista以后系统中,不能在内核模式下正常使用,此Bug应会在Windbg的以后版本中被修正)。下面分别截取了用户与内核空间中的内存信息片段:

    0:009> !address                            
    
            BaseAddress      EndAddress+1        RegionSize     Type       State                 Protect             Usage
    ------------------------------------------------------------------------------------------------------------------------
    +        0`00000000        0`00010000        0`00010000             MEM_FREE    PAGE_NOACCESS                      Free       
    +        0`00010000        0`00020000        0`00010000 MEM_MAPPED  MEM_COMMIT  PAGE_READWRITE                     Heap64     [ID: 1; Handle: 0000000000010000; Type: Segment]
    +        0`00020000        0`00021000        0`00001000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                       
    +        0`00021000        0`00030000        0`0000f000             MEM_FREE    PAGE_NOACCESS                      Free       
    +        0`00030000        0`00031000        0`00001000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                       
    // 省略很多...

      上图截取了两段用户区内存,第一段从0开始,长度0×10000,状态为释放(FREE),表明这一段地址空间不可用;第二段从0×10000开始,长度0×1000,属于私有内存,状态为已提交,保护模式为可读写,此内存块被用于环境块。

      下面给大家解释一下内存块中的几个值:

      内存类型:即Type值,共有四种:第一种是什么都不是,即尚未被使用的;第二种是MEM_IMAGE,即地址映射于一个可执行镜像文件片段,如DLL文件;第三种是MEM_ MAPPED,即地址映射于不可执行的镜像文件片段,如页文件;第四种是MEM_PRIVATE,即私有有内存,这里的私有是针对进程而言的,私有内存无法在多个进程间共享;

      保护模式:即Protect值,上例中见识了两种保护模式,NOACCESS和READWRITE。从字面即很容易理解其意思,前者是不能做任何访问的,因为空闲内存是无效内存;后者则可读可写,但不能执行,说明是保存数据的地方。所有可用的保护包括:PAGE_NOACCESS(不可访问),PAGE_READONLY(只读),PAGE_READWRITE(读写),PAGE_EXECUTE(可执行), PAGE_EXECUTE_READ(执行并可读),PAGE_EXECUTE_READWRITE(执行并可读写),PAGE_WRITECOPY(写时拷贝),PAGE_EXECUTE_WRITECOPY(执行,并写时拷贝), PAGE_GUARD(保护)。

      内存状态:即State值,共三种:MEM_FREE,即空闲内存;MEM_RESERVED,即保留内存,保留内存尚不能被实际使用,但其地址空间已被预留,尚需一个提交动作。最后是MEM_COMMIT,即内存已被提交,正在被使用。

      内存用途:即Usage值,有这样一些值和用途。RegionUsageIsVAD:表示此地址区域已被分配;RegionUsageFree:代表此地址区域已被释放,既没有保留也没有被提交,将来可以申请使用;

    • RegionUsageImage:代表此地址区域被映射到二进制文件的镜像;Region UsageStack:代表此地址区域用于线程栈;RegionUsageTeb:代表此地址区域用于保存目标进程的所有线程的TEB结构;
    • RegionUsageHeap:代表此地址区域用于堆内存;RegionUsage Pdb:代表此地址区域用于保存目标进程的PEB结构;RegionUsageProcessParameters:代表此内存块用于保存目标进程的启动参数;
    • RegionUsageEnviromentBlock:代表此地址区域用于保存目标进程的环境块。

      用户环境下可使用下面的命令显示内存统计信息,包括内存用途、内存类型、内存状态。

    • !address  -summary
    0:009> !address  -summary
    
    --- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
    Free                                    101        0`7a5ba000 (   1.912 Gb)           95.60%
    Image                                   294        0`022b8000 (  34.719 Mb)  38.49%    1.70%
                                     7        0`0113a000 (  17.227 Mb)  19.10%    0.84%
    Stack32                                  51        0`01100000 (  17.000 Mb)  18.84%    0.83%
    Heap32                                   26        0`006e0000 (   6.875 Mb)   7.62%    0.34%
    MappedFile                               12        0`0069e000 (   6.617 Mb)   7.34%    0.32%
    Stack64                                  51        0`00440000 (   4.250 Mb)   4.71%    0.21%
    Other                                     8        0`001c1000 (   1.754 Mb)   1.94%    0.09%
    Heap64                                    9        0`00190000 (   1.563 Mb)   1.73%    0.08%
    TEB64                                    17        0`00022000 ( 136.000 kb)   0.15%    0.01%
    TEB32                                    17        0`00011000 (  68.000 kb)   0.07%    0.00%
    PEB64                                     1        0`00001000 (   4.000 kb)   0.00%    0.00%
    PEB32                                     1        0`00001000 (   4.000 kb)   0.00%    0.00%
    
    --- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
    MEM_PRIVATE                             181        0`02f11000 (  47.066 Mb)  52.17%    2.30%
    MEM_IMAGE                               295        0`022b9000 (  34.723 Mb)  38.49%    1.70%
    MEM_MAPPED                               18        0`0086c000 (   8.422 Mb)   9.34%    0.41%
    
    --- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
    MEM_FREE                                101        0`7a5ba000 (   1.912 Gb)           95.60%
    MEM_RESERVE                              94        0`02f5d000 (  47.363 Mb)  52.50%    2.31%
    MEM_COMMIT                              400        0`02ad9000 (  42.848 Mb)  47.50%    2.09%
    
    --- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal
    PAGE_EXECUTE_READ                        56        0`01414000 (  20.078 Mb)  22.26%    0.98%
    PAGE_READONLY                           129        0`0117a000 (  17.477 Mb)  19.37%    0.85%
    PAGE_READWRITE                          153        0`004b5000 (   4.707 Mb)   5.22%    0.23%
    PAGE_WRITECOPY                           26        0`0004c000 ( 304.000 kb)   0.33%    0.01%
    PAGE_READWRITE|PAGE_GUARD                34        0`00048000 ( 288.000 kb)   0.31%    0.01%
    PAGE_EXECUTE_READWRITE                    2        0`00002000 (   8.000 kb)   0.01%    0.00%
    
    --- Largest Region by Usage ----------- Base Address -------- Region Size ----------
    Free                                      0`030b0000        0`6cf40000 (   1.702 Gb)
    Image                                     0`75d71000        0`00879000 (   8.473 Mb)
                                     0`7f0e0000        0`00f00000 (  15.000 Mb)
    Stack32                                   0`00cd0000        0`000fd000 (1012.000 kb)
    Heap32                                    0`02f13000        0`0019d000 (   1.613 Mb)
    MappedFile                                0`01a90000        0`002cf000 (   2.809 Mb)
    Stack64                                   0`00160000        0`00039000 ( 228.000 kb)
    Other                                     0`006b0000        0`00181000 (   1.504 Mb)
    Heap64                                    0`02b90000        0`000bf000 ( 764.000 kb)
    TEB64                                     0`7ef76000        0`00002000 (   8.000 kb)
    TEB32                                     0`7ef78000        0`00001000 (   4.000 kb)
    PEB64                                     0`7efdf000        0`00001000 (   4.000 kb)
    PEB32                                     0`7efde000        0`00001000 (   4.000 kb)

      上图分别以内存使用、内存类型、内存状态显示用户空间内存统计信息。

      和!address命令类似的,用户模式下还有下面两个命令可用:

    • !vprot  [地址]
    • !vadump  [-v]

      命令!vprot显示指定内存块的信息,侧重于内存保护信息;命令!vadump显示整个内存空间信息,dump者倾泻也,开启-v选项将显示详细(Verbose)信息。

      上面讲过,用户环境下使用“!address  –summary”可显示用户空间的内存统计信息;现在再看两个内核命令,在内核环境下显示内存的统计信息:

    • !memusage

      此命令从物理内存角度显示内存统计信息。无数个页表信息将被打印出来,可以说是“最内存”的信息。此命令会查看所有的页帧,所以运行时会非常地耗时。

    • !vm

      此命令从虚拟内存的角度显示内存统计信息,不仅能从全局角度显示虚拟内存的使用情况,还能以进程为单位显示内存使用情况。

    三、其他命令

      内核模式下,查看文件缓存信息,命令格式如下:

    • !filecache

      此命令在用户内核模式下,显示文件缓存和页表状态。每一行信息表示一个虚拟地址控制块 (VACB)。虚拟地址控制块可能对应着一个命名文件,也可能对应着一个元数据块。如果对应着一个命名文件,则此文件名称将被显示,否则显示元数据名称。

      实验:查看文件缓存

    很多软件都使用文件缓存的方式保存数据,比如Office Word。直接查看WORD文档,由于其
    内部格式不透明,故而不便分析。但如果使用WORD打开一个txt文本文档,它就会以文本文档
    的方式来处理之,并且依旧使用文件缓存的方式。
    
    读者用WORD打开一个TXT文档(比如:测试.txt)。
    运行内核调试器并执行!filecache命令,在打印信息中查找“测试.txt”。

      用户模式下查看堆信息,命令格式如下:

    • !heap

      下面的清单显示了某个进程中共有4个堆:

    0:004> !heap -a
    Index   Address  Name      Debugging options enabled
      1:   00150000
        Segment at 00150000 to 00250000 (00031000 bytes committed)
    
      2:   00250000
        Segment at 00250000 to 00260000 (00006000 bytes committed)
    
      3:   00260000
        Segment at 00260000 to 00270000 (00003000 bytes committed)
    
      4:   00390000
        Segment at 00390000 to 003a0000 (00008000 bytes committed)
        Segment at 01370000 to 01470000 (0007b000 bytes committed)

      堆资源是属于进程的,每个进程都会创建若干个堆,如C运行时堆、进程默认堆等。以第一个堆为例,地址范围是[0x150000,0x250000],已经有0×31000个字节被申请提交。

  • 相关阅读:
    多个手机号逗号分开
    字符转码
    短信发送AZDG加密算法
    判断手机所属三大运营商 移动、联通、电信
    MD5加密 时间差 流水号等方法
    VS2012的创建单元测试功能
    Oracle数据库操作类及连接方法
    python生成器,函数,数组
    javascript的单线程
    linux下/var/run目录下.pid文件的作用
  • 原文地址:https://www.cnblogs.com/kissdodog/p/3730598.html
Copyright © 2011-2022 走看看