windbg


持续更新

前言

基础命令

  • r 显示所有寄存器信息及发生core所在的指令
    • r eax,edx 显示eax,edx寄存器信息
    • r eax=5,edx=6 对寄存器eax赋值5,edx赋值为6
  • go 运行程序
    • go 地址 运行到指定地址
  • gu 执行到函数返回
  • p 单步执行
    • p 2 步进执行两条指令
  • pc 执行到下一个函数调用处停下
  • pa 地址 执行到指定地址处停下
  • pt 执行到返回指令为止
  • t 步入
  • q 退出调试
  • .attach PID 附加进程
  • .detach 结束会话

断点命令

  • bl 列出所有断点
  • bc * 清除所有断点
    • bc 1 3 5 清除1号、2号、5号断点
  • bd * 禁用所有断点
    • bd 1 2 5 禁用1号、2号、5号断点
  • be * 启用所有断点
    • be 1 2 5 启用1号、2号、5号断点
  • bp main 在main函数开头设置一个断点
  • bp 0x7c801b00 在7c801b00地址处放置一个断点
  • bp main.exe+0x1032 在模块MyDll.dll偏移0x1032处放置一个断点
  • bp @$exentry 在进程的入口放置一个断点
  • bm message_* 匹配message_开头的函数,并在这些函数起始处都打上断点

内存查看与修改

查看内存

  • d 地址 显示内存数据,默认以字节和ASCII显示
    • d eip 显示eip寄存器开始的内存数据,默认以字节和ASCII显示
  • db 地址 按照字节模式显示内存数据,并且显示 ASCII 字符
    • db eip 显示eip寄存器开始的内存数据,显示 ASCII 字符
  • dd 地址 按照双字模式显示内存数据
    • dd eip 显示eip寄存器开始的内存数据
  • dq 地址 按照四字模式显示内存数据
    • dq eip 显示eip寄存器开始的内存数据
  • dD 按照双精度浮点数的模式显示内存数据。
  • da 按ASCII模式显示
  • du 按Unicode模式显示
  • ds 按字符串模式显示。
  • dt 显示内存中的已知数据结构模板

修改内存

  • e 地址 数据 修改任意内存地址的值
  • eb 地址 数据 以字节形式写入
  • ed 地址 数据 以双子形式写入
  • ea 地址 数据 以ASCII字符形式写入
  • eu 地址 数据 以Unicode字符形式写入

反汇编

  • u 反汇编当前eip寄存器地址的后8条指令
  • ub 反汇编当前eip寄存器地址的前8条指令
  • u main.exe+0x10 L20 反汇编main.exe+0x10地址后20条指令
  • uf lyshark::add 反汇编lyshark类的add函数
  • uf /c main 反汇编main函数
  • ub 000c135d L20 查看地址为000c135d指令前的20条指令内容

内存统计与信息

  • !address -summary 显示进程的内存统计信息
  • !address -f:stack 查看栈的内存信息
  • !address 0x77c000s 查看该地址处的内存属性

线程与进程操作

  • | 列出调试进程

  • !dml_proc 显示当前进程信息

  • .tlist -v 列出所有运行中的进程

  • ~ 列出线程

    • ~. 查看当前线程
  • ~* 显示所有线程的堆栈信息

    • ~0s // 查看主线程
    • ~* k 所有线程堆栈信息
  • ~* r 所有线程寄存器信息

  • ~# 查看导致当前事件或异常的线程

  • ~N 查看序数为N的线程

  • ~~[n] 查看线程ID为n的线程 n为16进制

  • ~Ns 切换序数为N的线程为当前调试线程

  • ~~[n]s // 切换线程ID为n的线程为当前调试线程 n为16进制

  • ~3f 把三号线程冻住

  • ~2u 把二号线程解冻

  • !teb 显示线程环境块信息

  • !peb 显示进程环境块信息

  • !exchain 显示当前异常的详细信息

  • ~N n Suspend序数为N的线程

  • ~N m Resume序数为N的线程

进程与线程的其它操作

  • !runaway 显示当前进程的所有线程用户态时间信息
    • !runaway f 显示当前进程的所有线程用户态、内核态、存活时间信息
  • !locks 显示死锁
  • !cs 列出CriticalSection(临界段)的详细信息
  • .formats 1d78 格式化输出PID
  • !handle 查看所有句柄的ID

堆栈操作

  • k 显示当前调用堆栈

  • kn 带栈编号显示当前调用堆栈

  • kb 打印出前3个函数参数的当前调用堆栈

    • kb 5 只显示最上的5层调用堆栈
  • kv 在kb的基础上增加了函数调用约定、FPO等信息

  • kp 显示每一层函数调用的完整参数,包括参数类型、名字、取值

  • kd 打印堆栈的地址

  • kD 从当前esp地址处,向高地址方向搜索符号(注:函数是符号的一种)

  • .frame 显示当前栈帧

    • .frame n 显示编号为n的栈帧(n为16进制数)
    • .frame /r n 显示编号n的栈帧(n为16进制数) 并显示寄存器变量
    • .frame /c n 设置编号n的栈帧为当前栈帧(n为16进制数)
  • !uniqstack 显示所有线程的调用堆栈

  • !findstack kernel32 2 显示包含kernel32模块(用星号标出)的所有栈的信息

  • !heap -s 显示进程堆的个数

  • dt _HEAP 00140000 选取一个堆的地址,打印该堆的内存结构

  • !heap -a 00140000 选取一个堆的地址,打印该堆的信息,比上面打印内存命令更详细直观

  • dds 02a9ffec // 从02a9ffec地址处,向高地址方向搜索符号(注:函数是符号的一种)

  • dds // 执行完dds 02a9ffec后,可通过dds命令继续进行搜索

系统模块与PE文件检索

  • lm 列出所有模块对应的符号信息

  • lmv 列出所有模块对应的符号信息

  • lmt 列出所有模块的基地址和偏移

  • lmf 列出所有DLL的具体路径

  • lmvm ntdll 查看ntdll.dll的详细信息

  • !lmi ntdll 查看ntdll.dll的详细信息

  • ld * 为所有模块加载符号

  • ld kernel32 加载kernel32.dll的符号

  • x*! 列出加载的所有符号信息

  • x ntdll!* 列出ntdll.dll中的所有符号

  • x ntdll!nt* 列出ntdll.dll模块中所有nt开头的符号

  • x /t /v ntdll!* 带数据类型、符号类型和大小信息列出符号

  • x kernel32!*Load* 列出kernel32模块中所有含Load字样的符号

  • !dlls -a // 列出镜像文件PE结构的文件头

  • !dlls -l // 按照顺序列出所有加载的模块

  • !dlls -c ntCreateFile // 查询指定函数所在的模块

  • !dlls -c ntdll.dll // 列出特定模块头信息

  • !dlls -s -c ntdll.dll // 列出ntdll.dll的节区

  • !dlls -v -c ntdll // 查看ntdll.dll的详细信息

其它命令

符号操作

  • .sympath 查看当前符号查找路径
  • .sympath c:\symbols 将符号查找路径设为:c:\symbols
  • .sympath+ c:\symbols // 将c:\symbols添加到符号查找路径集合中
  • .reload // 为所有已加载模块载入符号信息
  • .reload /f /v // f:强制立即模式(不允许延迟载入) v:详细模式
  • .reload /f @"c:\windows\System32\verifier.dll" // 为指定模块加载符号信息
  • dt -rv _TEB
  • dt -rv _PEB
  • dt -v _PEB @$PEB
  • dt _PEB_LDR_DATA
  • dt _TEB ny LastErrorValue 只查看TEB(thread’s environment block)结构成员LastErrorValue

结构体与符号搜索命令

  • dt ntdll!_peb* *是通配符;显示所有peb打头的结构体名称;
  • dt -rv ntkrnlmp!*Object* 枚举ntkrnlmp中带”Object”的结构体名称;
  • dt -v ntdll!* # 列出ntdll中的全部结构体,导出的函数名也会列出
  • dt ntdll!*file* # 下面命令将列出ntdll导出的文件操作相关的函数名
  • dt _FILE_INFORMATION_CLASS 查看一个结构定义
  • dt _eprocess 显示当前进程的_eprocess结构体
  • dt _eprocess 地址 显示指定地址的_eprocess结构体
  • dt nt!_TEB

符号与类型信息操作命令

  • !dh 进程基地址 显示文件PE头
  • dt ntdll!* // 显示ntdll里的所有类型信息
  • dt ntdll!_* 列出 ntdll 中结构体

转存与打开文件命令

  • .dump 文件名 转存文件
  • .opendump 打开文件

源码调试

内核调试

待施工

lab

格蠹汇编:从堆里抢救丢失的博客

  • 调试
1
2
3
4
5
6
7
8
# 查看模块
lm
# 查看线程
~
# 列一下堆
!heap
# 列出用户态空间中的所有区域
!address
  • 搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
s -u 10000 l9000000 "当年在交大"
# s搜索内存
# -u指定要搜索的字符串为Unicode格式
# 10000是起始地址
# l9000000指定了搜索的长度,即从起始地址开始的9000000字节
# “当年在交大”这是要搜索的字符串

# 查看内存地址以Unicode解释的形式
du 001b5942 L1000

# 查看前8个字节
db 001b5942-8

# 加入Unicode标志
eb 001b5942-8 ff fe
#eb以字节格式编辑内存,以字节格式写入指定的内存地址。
#ff fe是想要写入的字节值

# 在执行确定修改成功
db 001b5942-8
  • 保存到文件
1
2
3
4
5
.writemem c : \\ edu\blog.txt 001b5942 L1458
# .writemem 这是写入内存内容到文件的命令
# 第一个参数为目标文件路径
# 001b5942这是起始的内存地址
# l1458这是内存内容的长度,表示从指定地址开始写入1458个字节的内容。