• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2021-03-19 13:52 Aet 隐藏边栏 |   抢沙发  6 
文章评分 3 次,平均分 5.0

调试器

关于调试器。

调试器类型

  • 用户态调试器
  • 内核态调试器

用户态调试器

  1. 查看调试目标的状态
    1. 线程、内存、寄存器以及进程空间中打开的内核对象等
  2. 修改调试目标的状态
  3. 实时调试
  4. 分析包含进程快照的转储文件
    1. 事后调试

调试工具

  1. cdb.exe
    1. 字符界面
    2. 可以对windows用户态的内存和结构进行底层分析
  2. ntsd.exe
    1. 与cdb类似
  3. windbg.exe

内核态调试器

  1. 可以从整体上来分析计算机系统
  2. 对于内核态调试器而言,每个进程或线程都只是一组数据结构,它们的内存地址与系统中安装的物理内存有着直接的关联,如果有内存页没有被加载到物理内存,就无法查看对应的内存信息
  3. 可以修改整个计算机的状态
    1. 实时内核调试
  4. 主要被设备驱动程序开发人员使用
  5. 可以加载内核态的转储文件

调试工具

  1. kd.exe
  2. windbg.exe

调试器命令

标准命令

  1. 以可执行文件的方式实现的命令
  2. 不需要任何前缀

元命令

  1. 另一种以可执行文件实现的命令
  2. 命令以.开头

扩展命令

  1. 可以在调试目标上执行的其他的功能
  2. 命令以!开头

调试器配置

符号文件

  1. 编译器和链接器在创建.exe.dll.sys以及其他可执行文件(二进制文件或映像)的时候,创建的一些其他附加文件。

符号文件内容

  1. 全局变量的名字和地址
  2. 函数名、地址以及原型
  3. 帧指针优化数据
  4. 局部变量的名字和地址
  5. 源文件路径以及每个符号的行号
  6. 变量、结构等的类型信息

寄存器

  1. 根据调试器中设置的寄存器掩码来显示寄存器的值

关于命令

  1. 命令r可以访问处理器中的寄存器
  2. 命令rm显示寄存器掩码
  3. 命令rm ?显示寄存器掩码各个位的含义
  4. 命令rm 0将寄存器掩码设置为零

伪寄存器

  • 不同平台的指令指针寄存器的名字存在差异,所以调试器引入了伪寄存器对应到不同的硬件架构上

$ip

  • X86
    • $ip = eip
  • X64
    • $ip = rip
  • Itanium
    • $ip = iip

$ra

  • 当前函数的返回地址

$retreg

  • 主要的值寄存器,函数调用返回的结果将放在这里
  • X86
    • $retreg = eax
  • X64
    • $retreg = rax
  • Itanium
    • $retreg = ret0

$csp

  • X86
    • $csp = esp
  • X64
    • $csp = rsp
  • Itanium
    • $csp = psp

$proc

  1. 当前的进程
  2. 包含的是用户态的进程环境块地址

$thread

  1. 当前的线程
  2. 包含的是用户态的线程环境块地址

$tpid

  1. 当前进程的标识

$tid

  1. 当前线程的标识

调用栈

  1. 记录在执行完当前函数之后程序继续执行的地址
  2. 栈内存区域是由栈寄存器控制的
  3. X86处理器的栈通常朝着低地址方向增长
  4. X86处理器的栈的栈顶地址保存在栈指针寄存器中,也就是esp

函数和栈

  1. 当进入函数时,编译器将生成所谓的栈帧,栈帧的基指针是通过寄存器ebp来维护的。
  2. 函数前导指令将把ebp的当前值保存在栈上,然后将当前栈帧的基指针值加载到ebp中,这个值,将会在ebp中一直保留直到执行函数后继指令。
  3. 在函数中,编译器通过将ebp与正偏移相加来获得函数参数的地址;编译器通过将ebp与负偏移来取得在函数中分配的局部变量的地址。
  4. 在后继指令中,函数执行之前保留的ebp的值,将被重新加载到ebp中。这样在完成函数调用之后,寄存器ebp的值将会恢复到函数调用之前的值。

关于命令

  1. 命令k可以分析当前的栈
  2. 命令kp将在一行内显示所有参数
  3. 命令kP将把每个参数单独显示一行
  4. 命令kp 5将显示调用栈中的前5个函数
  5. 命令kb 将显示在栈上传递给函数的前3个函数
  6. 命令kf 将显示在调用栈上函数所使用的栈大小
  7. 手动重新构造栈
    1. dc esp
    2. k = a b c,a,b,c为dc esp显示内容的前3条
  8. 命令bp 将设置一个断点
  9. 命令bc * 将清除所有断点
  10. 命令bm将在参数中指定一个符号模式,后果就是在所有与这个模式匹配的地址上都将设置一个断点
  11. 命令bu 将设置一个延迟断点,只有当这个断点所在的模块被加载时,延迟断点才会成为一个真正的断点
  12. 命令dv 将显示局部变量的值
  13. 命令dv aa*将显示与aa匹配的变量的值
  14. 命令dv /i将在第二列显示符号类型和参数类型
  15. 命令dv /v将显示变量的储存位置
  16. 命令dv /v将显示变量的储存位置
  17. 命令dt可以将一块内存按照作为参数传给它的数据结构的类型来解析
  18. 命令dc 用来查看一个堆块
    1. dc @ecx 14
    2. ln 00401504
    3. dt KBTest @ecx
  19. 命令!peb 将显示进程环境块的内容,如调试目标的启动参数
  20. 命令!teb 将显示线程环境块的内容
  21. 命令!gle 将抽取出错误码并且显示格式化的字符串
  22. 命令t 用于单步执行代码
    1. 汇编模式跟踪代码时,t每次执行一条汇编指令
    2. 源代码模式跟踪代码时,t每次可能会执行多条汇编指令
    3. 1+t:step/trace by source line
    4. 1-t:none
  23. 命令p将把整个函数调用视作一条语句来执行
  24. 命令pc将使代码的执行停止在下一个子例程的调用处
  25. 命令g表示无条件的恢复调试目标的执行
  26. 命令g <address>表示将调试目标执行到指定地址
  27. 命令gu将使调试目标执行完当前函数并且返回到调用者
  28. 命令wt能够获得被调函数的一些信息
  29. 命令~能够列出所有线程
  30. 命令~0s将切到0号线程
  31. 命令.frame将改变上下文并且控制对dv命令所能显示的局部变量
  32. 命令.thread将设置当前的线程的上下文到当前的寄存器上
  33. 命令!error能够找出与错误相关的一些信息
  34. 命令.formats能够以各种格式来显示参数
  35. 命令bp test::call "gu;.if (eax!=1){g}",条件断点的格式
  36. 命令!process可以获取目标进程中EPROCESS结构的地址
  37. 命令!object能够获取到一个结构的头地址,然后基于该地址来设置内存访问断点

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0 最后编辑于:2021-11-20
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享