加密与解密 调试篇 动态调试技术 (五)-WinDbg

news2024/11/24 16:18:39

windbg主要厉害的地方是在他可以对内核调试

并且本身微软的产品 对windows调试适配度够高

注意 windbg给出的图形操作并不好用  主要是使用命令行来进行操作

我们省略安装

直接进入调试

file 

可以打开软件 可以附加

也可以分析dump文件


还可以进行内核和 远程调试

内核调试分为5种

NET  USB 1394 COM和本地调试


前面四种是双机调试模式  

附加进程的非入侵模式调试 dump文件调试和本地内核调试都是属于非实时调试模式
不能直接控制被调试目标的中断和运行

一般是用来观察的

也可以用来修改内存数据

1.开始调试

Ctrl+E 打开程序

F6可以附加调试

在windbg中反汇编代码默认停止在 ntdll.dll 的系统断点处

并不会停在程序入口处

我们需要在命令窗口 输入


g@$exentery 转到程序入口

2.这里给出目标的执行命令

单步跟踪命令
命令快捷键功能
tF8/F11跟踪执行,进入call
pF10单步执行,不进入call
gF5运行程序
pa 地址单步到指定地址 并且不进入call
ta 地址追踪到指定地址 并且进入call
pc [count]单步执行到下一个call调用
tc [count]追踪到下一个call调用,遇到call进行跟进
tb [count]

追踪到下一条分支指令 遇到call进行跟进

【只适用于内核调试】

pt单步执行到下一条call的返回
tt追踪到下一条call的返回,并且遇到call进行跟进
ph单步执行到下一条分支指令
th追踪执行到下一条分支指令,遇到call进行跟踪
wt自动追踪函数执行过程
$ra代表当前函数的的返回地址

所以使用
“pa @$ra”

来走出当前函数



pc和tc都是执行到下一个call指令

count用于指定 遇到call的个数

默认是1

如果count为1 pc和tc这两个指令是等价的

3.这里给出的是断点指令

1.软件断点

bp断点

bp[ID] [Options] [Address [Passes]] ["CommandString"]
ID : 指定断点

options:
/l :一次性断点
/c :指定最大调用深度 大于这个深度断点不工作
/C :指定最小调用深度 小于这个深度断点不工作


Address:
地址或符号 例如 MessageBoxW

Passes:忽略中断的次数

CommandString : 指定一组命令 当断点中断的时候 自动执行这些命令

用双引号来包裹指令  分号来区分多指令

bu断点

bu用于对某一个符号断点

bu kernel32!GetVersiono


和bp的区别:


bu是和符号关联 如果符号的地址改变了
断点会保持和源符号的关联


bp是和地址的关联 如果模块把地址的指令转移到其他地址
断点不会移动 依然是在原地址

并且 bu会保存在 windbg的工作空间 下次启动自动断点

bm断点

bm断点是支持一次性创建多个bp或bu断点的指令

例如 对 msvcr80d模块的 print开头的函数都进行断点

bm msvcr80d!print*

实例

TraceMe.exe

 自动在命令行处进行加载

我们设置断点

bp kernel32!GetVersion

然后使用g来运行程序

2.硬件断点

硬件断点可以实现 监视I/O访问等功能 这些是软件断点无法实现的

ba

ba[ID] Access Size [Options] [Address [Passes]] ["CommandString"]
ID : 指定断点

Access : 指定断点触发断点的访问方式

e :在读取指令或执行指令的时候触发断点
r :在读取指令的时候触发断点
w :在写入数据的时候触发断点
i :在执行输入/输出访问(I/O)触发断点

Size :
访问的长度  
在X86可以为 1,2,4 代表 字节 字 双字
在X64多了一个 8   8字节访问

Address : 断点的地址 地址值按Size的值进行内存对齐

Passes和CommandString
和软件断点用法一样

3.条件断点

软件断点和硬件断点都支持 条件断点

断点触发后 WinDbg会执行一些自定义的判断 并且执行命令

bp|bu|bm|ba _Adddress "j (Condition) 'OptionalCommands';'gc'"

bp|bu|bm|ba _Adddress ".if (Condition) {OptionalCommands} .else {gc}"

例子

bp kernel32!GetVersion ".if(@eax=0x12ffc4){}.else{gc}"

当 GetVersion调用的时候 检测 eax
如果值为 0x12ffc4就中断
否则 gc指令继续执行

但是当值为 0x12ffc4的时候 不一定能断下
因为在内核态   MASM会对 eax进行符号扩展


0x12ffc4会变为 0xFFFFFFFFc012ffc4


这个时候就可以使用 & 把eax的高位清零

bp kernel32!GetVersion ".if(@eax& 0x0`ffffffff)=0xc012ffc4{}.else{gc}"
例子2
在不中断的情况下 打印 CreateFileA的函数调用

bp kernel32!CreateFileA ".echo;.printf\"CreateFileA(%ma,%p,%p),ret=\",poi(esp+4),dwo(esp+8),dwo(esp+c);gu;.printf\"%N\",eaxl.echo;g"

4.管理断点

bl

bl 列出断点

bc bd be 来删除 禁止 启动断点



bd 1-3,4   禁止 1234断点

bc * 删除所有断点

 

 4.栈窗口

栈是观测函数调用的重要调试手段

因为 call指令会把返回地址记录在栈中

我们就可以通过遍历栈帧来追溯函数调用过程

这里我遇到一个问题 就是怎么一直在 系统领空

这里是我忘记了windbg会自动在系统断点停止


g @$exentry 

就可以调到程序领空

这里我们开始看栈中的函数

k命令

 

栈帧的基地址是通过EBP来访问的 所以是childebp


下面是返回地址 就是调用本函数的那条call指令的下一条地址 就是作为返回地址

kb命令

只用于显示放在栈上的前3个参数

 其他的k命令

kp 可以吧参数和参数值以函数的原型返回出来 包括

参数类型 名字 取值

kv命令可以在kb的基础上增加 栈指针省略信息和调用约定


kd命令用于列出栈的数据

内存命令

1.查看内存

d命令

d [类型][地址范围]

dd 4001000 L4

L4可以指定显示前4个

 字节

d命令有很多衍生

dw 双字word  

dd 四个字节

dq 八个字节

df 四个字节单精度浮点数格式

dD 八个字节双精度浮点数格式

dp 指针大小格式 在32位中为4字节 64中为 8字节

ASCII

da 表示字符串

db 表示字节和字符串

dc dword和ASCII

du 表示unicode字符串

dW 表示双字节word 和 ASCII

ds 用于显示 ANSI_STRING

dS 用于显示 UNICODE_STRING

二进制

dyb 表示二进制和字节

dyd 表示二进制和dword

结构

dt [模块名!]类型名 用于显示数据类型和数据结构

例如 

dt ntdll!* 可以列出NTDLL模块的所有结构

dt _PEB 可以显示 PEB的结构

地址

dds dps dqs 用于显示 地址和相关符号

拿 0040115Eh来举例子

 

 

 

 

 

 

 2.搜索指令

s指令

s - [type] range pattern

type :

搜索的数据类型 

b 比特
w word
d dword
a ascii
u unicode

默认为 b

range : 地址范围 可以用两个方式
1.起始地址+终止地址
2.起始地址+L(长度)

如果超过 256MB 使用 L?length


pattern:指定要搜索的内容 可以使用空格分隔要搜索的值

例如

s -u 400000 430000 "pediy"

在 400000 到 430000中 搜索 unicode字符串 pediy

s -a 0x000000000 L?0x7fffffff mytest

表示在 2GB的 user mode 内存空间中搜索 ASCII字符串mytest

3.修改内存

e命令

 写入字符串

e{a|u|za|zu} address "String"
za zu 是表示以 0 结尾的 ASCII 和 UNICODE 字符串

a u 表示不以0 结尾


例如

eaz 298438 "pediy"
就是在 298438 这个地址 写入 pediy这个ASCII 并且以0结尾

写入数值

e{a|b|d|D|f|q|u|w} address [values]


a ascii

b bite

d dword

D DOUBLE

f float

q 八个字节

u unicode

w word


eb 298438 70 65 64 69 79

会在 298438 写入 pediy 的数值形式

 

 

 4.观察内存属性

!address [Address]

5.脚本

windbg的脚本是一个语言

例如

我们想输出 helloword

.echo helloword

1.伪寄存器

windbg给了很多伪寄存器

在表达式中使用伪寄存器 必须要使用转义符 @

$exentry 当前进程的入口地址 运行 g @$exentry 可以到达程序入扣

$ip 当前的指针寄存器

$ra 当前函数的返回地址

$retreg  当前函数返回地址存在这个寄存器中

$csp 当前的栈指针 esp/rsp

$tpid 当前进程的标识

$tid 当前线程的标识

$ea 最后一天被执行指令的有效地址

$p 最后一条 d 命令打印的值

$bpNumber 对应断点的地址

$t0~$t19 自定义伪寄存器

 2.别名

类似 define宏

一个是固定别名

一个是自定义别名

固定别名

windbg提供了10个固定别名

$u0~$u9

在定义固定别名的时候需要使用 r 命令

r $.u0="helloword"
.echo $u0

自定义别名

自定义别名的命令有3个

as ad al


as为内存中的字符串定义别名

ad 删除别名     ad Name   ad *


al 列出别名
as /选项 别名名称 别名实体

选项的选择

/ma ASCII

/mu Unicode

/msa ANSI_STRING

/msu UNICODE_STRING

/e 指定的环境变量

/f 指定文件的内容

as /ma bookname 0040115e

 

3.表达式

windbg识别两个表达式  MASM / c++

默认使用MASM

.expr 可以显示表达式语法

使用

@@c++()可以指定c++表达式

@@masm()可以指定 masm表达式

MASM表达式

除了 +-*/这些算术运算符

还支持转型运算符

hi/low 可以得到32位数的高16 或 低16

by/wo 可以得到指定地址的地位1字节/1字的值

dwo/pwo 可以得到指定地址的DWORD/QWORD

poi 可以得到指定地址的指针长度

为了支持复杂的调试命令 Windbg还定义了特殊的运算符

$fnsucc(FnAddress,RetVal,Flag)

将RetVal作为 FnAddress处的函数的返回值 如果返回值是一个成功码

$fnsucc返回 true 否则false




$iment(Address)
返回加载模块列表中的映像入口地址


$scmp("string1","string2"):比较  -1 0 1
$sicmp("string1","string2"):比较  -1 0 1

它们的差别在于比较时是否忽略大小写。


$spat("string","pattern")
根据 string匹配 pattern 计算得到 true or false

$vvalid(Address,Length)判断Address起Length的内存是否有效
有效返回1 否则 0 

C++表达式

支持C++的操作符 
包括 . ->

C++会把数值作为十进制 所以 要加上 0x

注释

支持两个注释方式  * 和 $$

* 后所有都会被当做注释

$$ 到 ; 结束为注释

6.例子

我们的要求是 打开CreateFileA函数 并且判断是不是 c:1212.txt

如果是就断点 如果不是就继续

命令行是

bp kernel32!CreateFileA "$<D:\\test.txt"

在D:\\test.txt的内容是

as /ma ${/v:fname} poi(esp+4)
.if ($sicmp("${fname}","c:\1212.txt")=0) {.echo ${fname}} .else{gc}

我们打入断点指令后

g运行程序

 

发现在原本读取 1212.txt的地方中断了

到此 windbg的基础就结束了

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/650401.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

招商基金资深架构师教你如何搭建统一监控平台

随着数字化进程的加速和业务的高速发展&#xff0c;系统的复杂程度日益升级&#xff0c;为确保业务系统的连续性和稳定性&#xff0c;越来越多的企业想要建设统一的监控平台&#xff0c;但却不知道从哪里开始着手。比如&#xff1a; 有些企业会直接将监控系统页面集成到统一监…

SpringBoot配置文件application.yml的理解

一、存放位置分类 1.当前项目根目录下的config目录下 2.当前项目的根目录下 3.resources目录下的config目录下 4.resources目录下 按照这上面的顺序&#xff0c;4个配置文件的优先级依次降低。 二、自定义存放位置和自定义命名 自定义存放位置和自定义配置文件命令和appl…

Python从Excel读取数据并使用Matplotlib绘制成二维图像

本课程实现使用 Python 从 Excel 读取数据&#xff0c;并使用 Matplotlib 绘制成二维图像。这一过程中&#xff0c;将通过一系列操作来美化图像&#xff0c;最终得到一个可以出版级别的图像。本课程对于需要书写实验报告&#xff0c;学位论文&#xff0c;发表文章&#xff0c;做…

Vue中的虚拟Dom,diff算法,以及diff的优化

virtual dom&#xff1a; 关键词&#xff1a; 1、 template 2、渲染函数 3、 vnode(virtual dom) 4、patch(diff算法) 5、view Vue.js通过编译将template 模板转换成渲染函数(render ) &#xff0c;执行渲染函数就可以得到一个虚拟节点树 VNode 虚拟节点&#xff1a;它可以代…

C++ 中的新成员

C 中的动态内存分配 C 中通过 new 关键字进行动态内存申请 C 中的动态内存申请是基于类型进行的 delete 关键字用于内存释放 new 关键字和 malloc 函数的区别 new 关键字是 C 的一部分 malloc 是由 C 库提供的函数 new 以具体类型为单位进行内存分配 malloc 以字节为单位…

Jenkins ——pipeline入门教程

一、什么是pipeline 什么是Pipeline&#xff1f;简单来说&#xff0c;就是一套运行于Jenkins上的工作流框架&#xff0c;将原本独立运行于单个或者多个节点的任务连接起来&#xff0c;实现单个任务难以完成的复杂发布流程&#xff08;实用场景&#xff1a;将多个Jenkins构建任…

最优化方法Python计算:一元函数搜索算法——二次插值法

已知连续函数 f ( x ) f(x) f(x)在 x ∗ x^* x∗近旁存在最优解 x 0 x_0 x0​。对博文《最优化方法Python计算&#xff1a;连续函数的单峰区间计算》讨论的 f ( x ) f(x) f(x)单峰区间的包围算法稍加修改&#xff0c;可算得 f ( x ) f(x) f(x)包含 x 0 x_0 x0​的单峰区间 [ a …

pandas---删除重复行、映射、异常值检测与过滤、抽样

1. 删除重复行 使用duplicated()函数检测重复的行。 返回布尔类型的Series对象&#xff0c;每个元素对应一行&#xff0c;如果该行不是第一次出现&#xff0c;则元素为True。 def make_df(indexs, columns): data [[str(j)str(i) for j in columns] for i in indexs]df …

中国人民大学与加拿大女王大学金融硕士——用更长远的眼光,展望未来

职场中遇到瓶颈&#xff0c;大家都迫切希望改变自己所处的环境&#xff0c;但却不愿意改变自己&#xff0c;所以他们自己仍然是被束缚的。如果一个人不能够从自我拷问的状态中解脱出来&#xff0c;他就永远也不可能实现自己心中的目标。我们要用更长远的眼光去展望未来&#xf…

NAVIGATE 领航者峰会:记忆科技携手新华三,以存储创新释放数据价值

近日&#xff0c;由紫光集团和新华三集团主办的2023 NAVIGATE 领航者峰会在杭州举行。本届峰会的主题为“精耕务实&#xff0c;为时代赋智慧”&#xff0c;围绕该主题&#xff0c;国内外数千名技术领导者汇聚一堂&#xff0c;探讨数字经济的创新未来。作为IT硬件领域的重要厂商…

vue + g6 实现树级结构(compactBox 紧凑树)

G6文档 自定义节点 G6.registerNode("dom-node",{draw: (cfg, group) > {let str <div classitem-box catalog-node ${cfg.isSelected ? "is-selected" : ""} ${cfg.status}-box οnclickhandleDetail("${cfg.id}") id&quo…

JMeter压测如何分配业务比例?

在进行综合场景压测时&#xff0c;由于不同的请求&#xff0c;要求所占比例不同&#xff0c;那如何实现呢&#xff1f; 有人说将这些请求分别放到单独的线程组下&#xff0c;然后将线程组的线程数按照比例进行配置&#xff0c;这种方法不是很好&#xff0c;想想&#xff0c;不…

5G是如何提升通行能力的?5G毫米波到底有多快?

高速公路&#xff0c;可以通过多层交通、多条车道、车道方向、车辆容量、货物包装、驾驶司机等多个因素&#xff0c;提升通行能力。 我们把5G比作高速公路&#xff0c;那么&#xff0c;5G是如何提升自身通行能力的呢&#xff1f;5G毫米波&#xff0c;到底能有多快呢&#xff1f…

跨越时空的教育:在线培训系统的全球化

随着全球化的发展&#xff0c;跨越时空的教育已经成为现实。在线培训系统可以打破地域限制&#xff0c;让学生能够接受来自世界各地的教育资源。这种新型教育模式具有巨大的潜力和优势。 在线培训系统是指通过互联网提供的远程教育服务。它可以通过网络平台、视频教育、虚拟课…

如何优雅地使用Low Code提高开发效率

2023年&#xff0c;低代码热度有&#xff0c;但是在企业内部核心场景的落地比例不高&#xff0c;推进进展也没有想象中快。就算是这样&#xff0c;低代码赛道也在“暗流涌动”。 数字化趋势下&#xff0c;很多企业想要以数字化的手段进行降本增效。很多企业希望以低代码的模式…

【Turfjs的java版本JTS】前面讲了Turfjs可以实现几何计算,空间计算的功能,如果后端要做这项功能也有类似的类库,JTS

JTS Java Topology Suite 几何计算&#xff1a; 1. 前端js就用这个 Turfjs的类库。参考网站&#xff1a; 计算两线段相交点 | Turf.js中文网 2. 后端java语言就可以用 JTS这个类库&#xff0c;参考网站&#xff1a; JTS参考网站&#xff1a; 1. https://github.com/locatio…

【机器学习】神经网络代价函数和反向传播算法

神经网络的代价函数 接下来我会再规定若干符号代表的含义&#xff1a; L L L表示神经网络的总层数 s i s_i si​表示的是第i层的神经元数量 如果神经网络处理的是一个二元分类问题&#xff0c;那么他的第L层就只会有一个节点&#xff1b;如果处理的是一个多元分类问题&…

不知不觉创作一年了,谈谈我的创作经历

前言 大家好&#xff0c;我是小刘在C站&#xff0c;不知不觉创作1年啦&#xff0c;本次文章呢分享一下我这一路走来的经历吧 目录 前言 1.为什么写博客 2.第一篇文章 3.怎么坚持创作的&#xff1f; 4.自我介绍 5.收获 6.认识了哪些大佬呢&#xff1f; 7.未来规划 8.分…

【C++】STL的string容器介绍

目录 1、string容器 1.1声明一个c字符串 1.2string和c字符数组的比较 1.3string类操作函数介绍 1.3.1赋值操作 1.3.2字符串拼接 1.3.3字符串查找 1.3.4字符串替换 1.3.5字符串比较 1.3.6字符存取 1.3.7字符串插入 1.3.8字符串删除 1.3.9子串获取 1、string容器 在…

测试4年外包已上岸 , 我只能说这类公司能不去尽量别去···

我大学学的是计算机专业&#xff0c;毕业的时候&#xff0c;对于找工作比较迷茫&#xff0c;也不知道当时怎么想的&#xff0c;一头就扎进了一家外包公司&#xff0c;一干就是4年。现在终于跳槽到了互联网公司了&#xff0c;我想说的是&#xff0c;但凡有点机会&#xff0c;千万…