命令脚本,就是将完成某个特定任务的相关命令组合在一起,保存在脚本文件里,加载到Windbg里执行,达到我们的目的。你可以理解为脚本就是一种语言,就像c或者汇编,但是他不需要编译器将其编译为可执行文件,而是由解释器将其内容翻译为对应的动作。而Windbg的脚本就是利用Windbg作为解释器,将脚本内容翻译为实际的动作。
既然可以作为一种语言,那么它就具有一般语言通常包含的要素:数据类型、变量、表达式、语句、函数等,下面我们分别简单讲一下。

一、数据类型
关于数据类型,Windbg的帮助里没有明确列举,但是,在使用时一般会遇到,数值和字符串这两种。

  • 数值
    数值没有太多需要解释的,和所有编程语言里的整数含义一样,在表示的时候有进制之分。
    代码:

    2进制  0b
    8进制  0n
    10进制  0t
    16进制  0x

  • 字符串
    字符串用一对 ” 括起来。比如上面的 ”hello windbg”。

二、变量
在windbg中变量的定义很特别,实际上,它并没有变量这个概念,所以,在学习的时候会觉得很别扭。不过,我们换个思路就容易了,变量实际上就是为了保存临时结果, 如果只想保存一些数值,那么伪寄存器(参考Windbg命令的语法规则系列)应该是比较好的选择,windbg提供了20个伪寄存器$t0-$t19,供命令保存临时数值变量。称他们为伪寄存器是有原因的,首先对他们的操作和寄存器一样,都是使用r命令,在C++表达式里都前面需要加@符,但是他们又不是真正的寄存器,只是windbg定义的名字而已。使用这些伪寄存器也是很方便的:

代码:

0:000> r $t0=0x123
0:000> r $t0
$t0=00000123 0:000> r eax
eax=004c1b89 0:000> r $t0=@eax
0:000> r $t0
$t0=004c1b89

从上面的例子也可以看出r命令后面的@是可以省略的。

三、别名
别名和变量还有些区别,变量是在执行过程中取他的值,而别名更像是宏,在解释时直接用内容替换原始操作数。别名有两种,一种是固定名字的,一种是自定义的。

  • 固定名字别名
    固定名字别名和伪寄存器很类似,Windbg提供了10个,$u0-$u9。使用的时候依然是r命令,不过要在“u”前面加个“.”,像下面这样:

    代码:

    0:000> r $.u0 = "123"
    0:000> .echo $u0
    123

    从上面的例子可以看出一旦别名被定义了,到使用他的时候,Windbg会把别名替换为内容。

  • 自定义别名
    自定义别名会复杂一些,但是,有了它的存在,我们才可以为内存中的一些字符串定义别名。操作自定义别名有3个命令:as,ad,al。
    As 定义一个别名,其强大之处在于,可以指定一个内存地址,然后将内存中的内容定义为别名。

    代码:

    0:000> .dvalloc 10
    Allocated 1000 bytes starting at 00010000
    0:000> ea 00010000 "123456"
    0:000> as /ma ${/v:test} 0x00010000
    0:000> .echo test
    123456

    上面的命令将0x00010000地址的定义为一个别名,由于as使用了/ma选项,所以将内容当做一个’\0’结尾的ASCII字符串来解析,${}是别名解释器,后面再讲。除了/ma选项以外as还有一些其他强大的选项:

    代码:

    /ma  参数指定的内存地址当做ASCII字符串。
    /mu  参数指定的内存地址当做Unicode字符串。
    /msa  参数指定的内存地址当做ANSI_STRING字符串。
    /msu  参数指定的内存地址当做UNICODE_STRING字符串。
    /f  别名等于参数指定文件的内容。
    /e  别名等于参数指定的环境变量。

    al显示已经定义的别名,ad删除已经定义的别名,接着刚才的例子继续输入以下命令:

    代码:

    0:000> al
    Alias Value
    ------- -------
    test 123456
    0:000> ad ${/v:test}
    0:000> al
    No aliases

    可以看的很明显吧。
    现在我们来解释一下例子里那个长得很奇怪的${},这个东西叫别名解释器,把别名放在后面的大括号里面,Windbg就知道里面是个别名,需要被翻译。其实不用这个符号也可以,不过写到复杂脚本的时候就可能出问题,谁用谁知道,我就不再发散了,建议是最好用。这个解释器也有选项,上面的/v:就是一个。
    /v:  保持别名原样,不翻译,在定义和删除的时候用。
    /n:  如果别名定义就翻译为内容,否则不做任何翻译。
    /f:  如果别名定义就翻译为内容,否则翻译为空。
    /d:  如果别名被定义,翻译为1,否则翻译为0,相当于#ifdef。

四、表达式
Windbg提供了两种表达式:汇编表达式和C++表达式(参考Windbg命令的语法规则系列)。两种表达式的操作符和操作数都略有区别。
默认是汇编表达式,求汇编表达式的值用?,求C++表达式的值用??。
汇编表达式里能用的操作符除了+、-、*、/这些算数运算符以外还有一些类似转型运算符,比如poi,有时候大家断到一个函数,第一参数是个字符串指针,想打印这个字符串怎么办?可以这样 dd esp+4,然后再从结果中da一次,有了poi,一行命令就可以做到,dd poi(esp+4)。

C++表达式就更加丰富了,几乎所有的C++表达式都可以用,包括.和->操作符,想让Windbg将表达式按C++方式解释,需要在表达式前面加@@c++()。

五、语句
都说了脚本要按照编程的思想来写,既然是编程,怎么能少得了流程控制语句呢?Windbg支持以下流程控制语句:
.if
.else
.elif
.for
.while
.break
.continue
.do
.printf  格式化输出,熟悉吧。
.block  语句块
$$  注释,长得好奇怪

这里面,.block要单独说说,所谓语句块,其实就是用{}括起开的一堆语句,包括.if、.else后面的语句其实都是语句块,语句块内部的别名(还记得吗)在进入块的时候会被翻译,进入块以后,如果修改了别名的定义,那么在本块内的后续语句中是无效的(还记得别名是原样替换吗),所以,如果需要在后续语句中生效,需要把后面的语句放到一个单独的语句块里,也就是用{}把他们包含起来,但是Windbg又不能识别直接用{}包含起来的东西,于是就出现了.block,看到这里,请切记,如果需要别名被翻译,一定要把他放到语句块里。

六、函数(内建)
这里只讲两个内建函数$scmp和$sicmp都是字符串比较,一个区分大小写,一个不区分大小写。这两个函数有一个毛病,那就是参数只接受字符串字面量,就是说,你只能写$scmp(“123”,”123”),不能写$scmp(poi(esp+4),”123”),好了,有人急了,不能这样写,要这两个函数有什么用?不急,我们可以利用别名(这就是别名最有用的地方),还是接着刚才那个例子:

代码:

0:000> as /ma ${/v:test} 00010000
0:000> ? $scmp("${test}","123456")
Evaluate expression: 0 = 00000000
0:000> ? $scmp("${test}","123457")
Evaluate expression: -1 = ffffffff

这样就可以比较变量字符串了。

好了,有了以上知识,写一个windbg脚本应该就有基础了,剩下的就是要看大家知道多少“API”了,更详细的信息需要在Windbg的帮助里挖掘了。

最后贴一个完整的例子,利用脚Hook CreateFileW,这个例子虽然不长,但是都是精华啊,哈哈。
代码:

.dvalloc /b 0x79990000
ew 0x79990000 0xc033
ed 0x79990002 0x00001cc2
bp kernel32!CreateFileW "
as /mu ${/v:filename} poi(esp+);
.block{
.if ($sicmp(\"${filename}\", \"c:\\1.txt\") == 0){
.echo \"open 1.txt\";
r eip=0x79990000
}
}
ad ${/v:filename};
gc;
"

七、执行

先来一段简单的脚本
代码:

.echo “hello windbg”

这条命令会显示“hello windbg”这个字符串,把它保存到c:\1.txt文件,然后在Windbg的命令窗口里输入:
$><c:\1.txt  回车,

看看屏幕上出现了什么?

Windbg将1.txt里的内容当做一条Windbg的命令执行了。这就是一个简单的脚本。$><,根据这个例子,很容易看出它的作用是将脚本文件交给Windbg解释,由他完成了将一个txt变成Windbg命令的关键转换。其实你知道了这个,Windbg脚本就算入门了,我们可以把很多命令写在这个文件里,然后用$><装载执行。

下面来说下Windbg脚本加载执行的相关命令,总共有5个相关命令,$ <$ > <$$ <$$ > < ,并 $$ >< 命令读取指定的脚本的内容文件中并使用作为其内容调试器命令输入 。如下:

$<Filename
$><Filename
$$< Filename
$$>< Filename
$$>a< Filename [arg1 arg2 arg3 ... ]

参数:

  • 文件名
    指定包含有效的调试器命令文本的文件。 文件名称必须遵守 Microsoft Windows 文件命名约定。 文件名称可能包含空格。
  • argn

    指定任意数量的调试程序要传递给脚本的字符串参数。 调试器会将窗体 $ 任何字符串替换 {$argn} 中具有相应的脚本文件argn之前执行脚本。 参数不得包含引号或分号。 多个自变量必须以空格分隔;如果参数包含的空格,则必须用引号引起来。 所有自变量是可选的。

环境:

模式

用户模式下,内核模式

目标

实时、 崩溃转储

平台

全部

详细说明:

$$ <$ < 令牌执行按原义找到脚本文件中的命令。 但是,对于 $ < 可以指定任何文件名,其中包括一个包含分号。 因为 $ < 允许以文件的文件名中使用分号作为不能连接 $ < 与其他调试程序命令,因为为命令分隔符和文件名称的一部分,不能使用分号。

$$ > <$ > < 令牌执行按字面意思找到脚本文件中的命令这意味着它们打开脚本文件,用分号,替换所有回车符和执行单个命令块为生成的文本。 如同 $ < 已经讨论过, $ > < 变体允许文件的名称包含分号,这意味着不能串联 $ > < 与其他调试程序命令。

$$ > <$ > < 令牌是很有用,如果运行的脚本中包含调试器命令程序。

除非您有包含分号的文件名,不需要使用两种 $ <$ > <

$$ >< 令牌使调试器能够在将参数传递给脚本。 如果文件名包含空格,则必须用引号引起来。 如果提供的参数太多了,将忽略多余的参数。 如果未提供的参数太少,任何令牌的窗体 $ 源文件中 {$argn} 位置n大于提供的参数数量将保留在其文本的形式,并且将不替换为任何内容。 可以按照此命令使用分号和其他命令;存在分号终止参数列表。

当调试器执行的脚本文件时中, 显示的命令和相应的输出调试器命令窗口。 当达到脚本文件的末尾时,控制权返回给调试器。

下表总结了如何使用这些令牌。

令牌 允许包含分号的文件名 允许其他命令之间用分号分隔的串联 会将到单个命令块 允许脚本参数

$<

$><

$$<

$$><

$$>a<

$ <$ > <$$ < ,和 $$ > < 命令回显的脚本中包含的命令文件,并显示这些命令的输出。 $$ >< 命令不会将回显在脚本文件中,找到的命令,但只显示其输出。可以嵌套的脚本文件。 如果调试器遇到其中一个令牌中的脚本文件,执行将移至新的脚本文件,并完成新的脚本文件时,返回到前一个位置。 也可以调用脚本以递归方式。在 WinDbg 中,你可以粘贴调试器命令窗口中的其他命令文本。

参考:

https://blog.csdn.net/superliuxing/article/details/19206985

Windbg命令脚本的更多相关文章

  1. Windbg命令脚本流程控制语句详解

    在Windbg命令脚本一文里,我们介绍了命令脚本语言的的组成要素,在本文里将对语句进行展开的讲解.这些语句主要是流程控制的语句,比如我们常见的条件分子和循环语句等. ; (命令分隔符) 分号(:)字符 ...

  2. windbg命令分类与概述

    WinDBG的大多数功能是以命令方式工作的, 本系列将介绍WinDBG的三类命令, 标准命令, 元命令和扩展命令. =============== 标准命令 =============== 标准命令用 ...

  3. windbg命令行选项

    我们不仅可以通过GUI的方式使用Windbg,还可以通过命令行的方式使用它,且在有些需求和使用场景下,只能使用命令行模式  windbg命令行使用以下语法: windbg [ -server Serv ...

  4. WinDbg 命令三部曲:(一)WinDbg 命令手册

    本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 系列博文 <WinDbg 命令三部曲:(一)WinDbg 命令手册> <WinDb ...

  5. WinDbg 命令三部曲:(三)WinDbg SOSEX 扩展命令手册

    本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 系列博文 <WinDbg 命令三部曲:(一)WinDbg 命令手册> <WinDb ...

  6. WinDbg 命令三部曲:(二)WinDbg SOS 扩展命令手册

    本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 系列博文 <WinDbg 命令三部曲:(一)WinDbg 命令手册> <WinDb ...

  7. windbg命令学习3

    3.进程与线程: 既可以显示进程和线程列表,又可以显示指定进程或线程的详细信息.调试命令可以提供比taskmgr更详尽的进程资料,在调试过程中不可或缺. 3.1. 进程命令 进程命令包括以下:显示进程 ...

  8. WinDbg 命令手册

    WinDbg 命令三部曲:(一)WinDbg 命令手册   本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 系列博文 <WinDbg 命令三部 ...

  9. 如何写gdb命令脚本

    作为UNIX/Linux下使用广泛的调试器,gdb不仅提供了丰富的命令,还引入了对脚本的支持:一种是对已存在的脚本语言支持,比如python,用户可以直接书写python脚本,由gdb调用python ...

随机推荐

  1. golang中,map作为函数参数是如何传递的

    当你声明一个map的时候: m := make(map[int]int) 编译器会调用 runtime.makemap: // makemap implements a Go map creation ...

  2. Spring Boot 优雅的配置拦截器方式

    https://my.oschina.net/bianxin/blog/2876640 https://cs.xieyonghui.com/java/55.html 其实spring boot拦截器的 ...

  3. Ambari深入学习(III)-开源使用及其改进思考

    Ambari采用的不是一个新的思想和架构,也不是完成了软件的新的革命,而是充分利用了一些已有的优秀开源软件,巧妙地把它们结合起来,使其在分布式环境中做到了集群式服务管理能力.监控能力.展示能力.这些优 ...

  4. Spring-Cloud之Spring-Boot框架-1

    一.Spring Boot 是由 Pivotal 团队开发的 Spring 框架,采用了生产就绪的观点 ,旨在简化配置,致力于快速开发. Spring Boot 框架提供了自动装配和起步依赖,使开发人 ...

  5. .net Dapper 实践系列(3) ---数据显示(Layui+Ajax+Dapper+MySQL)

    目录 写在前面 产生问题 解决方案 写在前面 上一小节,我们使用Dapper 里事务实现了一对多关系的添加.这一小节,主要记录如何使用Dapper 实现多表的查询显示. 产生问题 在mvc控制器中查询 ...

  6. mysql 8.0.17 安装与使用

    目录 写在前面 MySQL 安装 重置密码 使用图形界面软件 Navicat for SQL 写在前面 以前包括现在接到的项目,用的最多的关系型数据库就是SqlServer或者Oracle.后来因为接 ...

  7. 无法定位 Local Database Runtime 安装。请验证 SQL Server Express 是否正确安装以及本地数据库运行时功能是否已启用。

    错误描述: 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. (provide ...

  8. prometheus2.0 联邦的配置

    参考:https://blog.51cto.com/lee90/2062252 官网对于联邦的介绍:https://prometheus.io/docs/prometheus/latest/feder ...

  9. map小列

    // 有关学生信息的头文件student.h代码如下 #include #include using namespace std; struct Student                    ...

  10. Java自学-控制流程 continue

    Java的 continue语句 继续下一次循环 示例 1 : continue 如果是双数,后面的代码不执行,直接进行下一次循环 public class HelloWorld { public s ...