《加密与解密》- 第二章 - 动态分析技术 - 笔记

发布时间 2023-06-15 15:32:12作者: Carykd

2.1 OllyDbg

关于操作部分均略过,因为现在已经没啥必要用ollydbg了

请使用x64dbg的32位版本(即x32dbg,但是你要搜索x64dbg下载)


2.1.4 断点

常见断点:

  1. INT 3断点(软件断点)

    1. 快捷键:在所在行按F2
    2. 原理:调试器维护一组软件断点,并把断点位置的内存写为INT 3(也叫CC指令,因为内存中是0xCC)。如此一来,程序执行到断点时会执行INT 3,也就是触发INT 3异常,从而系统开始执行异常处理的过程。由于调试器存在,因此系统把异常交给调试器处理。调试器再通过当前地址判断是哪个断点,并写回原始内存
    3. 优点:数目不限
    4. 缺点:通过检测内存是否被修改可以查出来
  2. 硬件断点

    1. 原理:使用DRx调试寄存器,具体用DR0~DR3设定地址,DR7设定状态。当触发时抛出单步调试异常(INT )
    2. DRx作用:DR0~DR3保存需要监视的地址,DR4-DR5未公开,DR6调试寄存器组状态寄存器,DR7调试寄存器组控制寄存器
    3. 优点:速度躲开软件断点的检测
    4. 缺点:,只有4个,可删除硬件断点反调试
  3. 内存断点

    1. 原理:将所设地址所在的页设为不可写入不可读取,从而在访问时触发单步调试异常调试器取得并判断访问的地址是否为断点,若不是则继续运行,若则交给我们调试。
    2. 优点:避开检测内存修改反调试
    3. 缺点:降低速度(每次访问断点所在的页都会中断,然后判断要不要给我们调试。访问次数可能很多,判断次数因此很多,则速度变慢)
      (一些时候,内存断点硬件断点可以互用。但如果硬件断点失效内存断点也可能还有用
  4. 内存访问一次性断点

    1. 快捷键:ALT+M进入内存布局,然后选中需要下断点的段,按F2
    2. 功能:在读取或执行段的时候中断。
  5. 消息断点

    1. 本质:条件断点(见后文)
    2. 差别:INT 3启动前就能设置,消息断点只有在窗口被创建后才能设置
    3. 方法:点击句柄窗口,刷新后可得到句柄,选中句柄右键设置消息断点,适当设置即可
    4. 补充:
      1. 断点停在系统代码中,ALT+F9与CTRL+F9无法回到程序代码领空
      2. 程序代码所在区块设置内存访问一次性断点即可
  6. 条件断点

    1. 快捷键:SHIFT+F2或者命令行
    2. 本质:带有条件表达式的INT 3断点
    3. 类型
      1. 寄存器条件中断
SHIFT+F2:eax == 0x400000
命令行:不会((

表示当eax == 0x400000时停下
2. 按存储器条件中断

SHIFT+F2:streq(utf8(0x401232), "1234")
命令行:不会((

表示当0x401232处的指针指向的数据以utf-8解释所得字符串和“1234”相等时停下
7. 条件记录断点
1. 快捷键:SHIFT+F2
2. 语法:与前面一样,写好日志后,在日志条件窗口输入条件即可
8. 条件命令断点
1. 快捷键:SHIFT+F2
2. 语法:与前面一样,写好命令后,在命令条件窗口输入条件即可


2.1.5 插件

x64dbg技巧与插件

2.1.6 RUN跟踪

作用:记录运行时我们的每一次操作,从而后续分析可以参考这些操作

方法:进入跟踪页面,右键选择启动运行跟踪,然后选择保存目录

2.1.7 HIT跟踪

作用:划定大块代码,若通过则标记,从而方便判断执行流

方法:不会((,至今也没用过这个


2.1.8 调试符号

指为支持调试而摘录的调试信息

调试文件格式

1. CodeView格式
2. PDB格式(常见)
3. DBG格式(常见)
4. MAP格式(常见)

使用符号文件

掌握IDA导入即可,利用sync插件可以很轻松的实现IDA和x64dbg的同步调试,源代码看IDA的比x64dbg爽


2.1.9 加载程序

创建进程

程序拖进来或者F3选择文件打开

附加进程

意思是调试一个正在运行的进程

方法:ALT+A或者“文件>附加”

2.2 x64dbg

前文已经简介,仅补充部分

F2下断点,F9运行,CTRL+G跳转

dump rdx表示在内存窗口中跳转到rdx表示的地址

2.3 MDebug

从未用过或者听说,功能似乎不显眼,此处略去

2.4 Windbg

特点:可以分析内核dump文件

2.4.1 安装与配置

版本

一般选x64即可

工作空间

可以保存窗口布局

调试符号

PDB符号文件:每个都有唯一的33位特征签名,靠这区分同模块不同版本的符号文件

地址:_NT_SYMBOL_PATH

符号加载:调试前,一般默认加载了调试符号,如果没有的话使用ld命令加载,再用lm检查符号文件加载情况

符号分类:由于调试的内核版本可能不同,因此建议将符号文件分类以便于管理

表示:”模块名!符号名“,内核统一用”nt“模块名

例子:

ntdll!NtOpenProcess表示ntdll.dll中的NtOpenProcess函数

nt!NtOpenProcess表示内核中的NtOpenProcess函数(两者不同)

检索方法

格式:x [Options] Module!Symbol

支持特殊字符模糊匹配

源代码调试:Ctrl+P

2.4.2 调试过程

开始调试

创建进程:Ctrl+E

附加调试:F6

转到入口:Alt+1g @$exentry

调试命令

t F8/ F11 步入
p F10 步过
g F5 运行
ta addr 步入addr
pa addr 步过addr
tc [count] 步入调用第count个call前
pc [count] 步过调用第count个call前
tt 步入返回下次call前
pt 步过返回下次call前
th 步入到下次分支
ph 步过到下次分支
tb [count] 步入到第count次分支指令只适用内核
wt 自动追踪函数执行过程

pa @$ra:走出当前函数

2.4.3 断点命令

  • 软件断点
    • bp:跟地址或符号(功能复杂,此处略去)
    • bu:跟符号(bu kernel32!GetVersion)
    • bm:跟符号通配符(bm msvcr80d!print*)
  • 硬件断点
    • ba(与bp类似,功能复杂,此处略去)
  • 条件断点
    • bp/ba等后面可跟命令,用""括起
    • 功能强大复杂,此处略去
  • 管理断点
    • bl列出断点
    • bc删除断点
    • bd禁止断点
    • be启用断点
    • 可用 * 匹配
    • 例:bd 1-3,4 表示 禁止1-3,4号断点

2.4.4 栈窗口

查看栈回溯(k系列命令)

  • k:显示基地址返回地址函数名地址
  • kb:补充3个传参
  • kp:将参数和参数值以函数原型形式显示(必须符号完整)
  • kv:补充3个传参且增加FPO(栈指针省略信息)和调用约定
  • kd:列出栈中数据

2.4.5 内存命令

  1. 查看内存
    1. 格式:以d开头,查看指定地址的内存数据
    2. 整型:如byte,word等取首字母,有dbdw
    3. 浮点型:float对应df,double对应dD
    4. 指针:dp
    5. 字符串:ASCII:da;Unicode:du;ANSI:ds
    6. 数据结构dt [模块名!]类型名便于学习系统结构体
  2. 搜索内存
    1. 格式:s -[type] range pattern
      1. type表示类型,如”b,w,d,a,u“
      2. range表示地址范围,包含起始地址和终止地址或者起始地址和长度(长度大于256MB要用L?length)
      3. pattern表示搜索内容
  3. 修改内存
    1. 字符串:
      1. 格式:e{a|u|za|zu} address "String",za表示以\0结尾的ASCII字符串
      2. 例:eza 298438 "pediy" 表示在298438h处写入"pediy"
    2. 数值
      1. 格式:e{a|b|d|D|f|q|u|w} address [values]
      2. 例:eb 298438 70 65 64 69 79 表示在298438h处写入70 65 64 69 79,即"pediy"
  4. 观察内存属性
    1. !address表示显示指定地址的内存属性

2.4.6 脚本

性质:一种语言

伪寄存器

包含下述几种:

  • $exentry进程入口地址
  • $ip指令指针寄存器
  • $ra:函数返回地址
  • $retreg:函数返回值
  • $csp:栈顶
  • $tpid:进程标识(PID)
  • $tid:线程标识
  • $ea:最后一条被执行指令的有效地址
  • $p:最后一条被d命令打印的值
  • $bpNumber:对应断点地址
  • $t0~$t19:自定义伪寄存器

别名

分为固定别名和自定义别名

  • 固定别名
    • $u0~$u9,用r定义
r $.u0 = "Hello"   // 不要遗漏“.”符号!在u0前面
  • 自定义别名
    • 命令:as,ad,al
      • as:定义别名
        • 例:as /选项 别名 位置
        • 选项
          • /ma:ASCII字符串
          • /mu:Unicode字符串
          • /msa:ANSI_STRING字符串
          • /msu:UNICODE_STRING字符串
          • /e:指定的环境变量
          • /f:指定的文件内容
      • ad:删除别名
      • al:列出别名
0:000> da 04040dc          // 查看ASCII字符串
004040dc "runtime error"   // 回显

0:000> as /ma errorstring 04040dc  // 定义别名
0:000> al                          // 列出别名
Alias           Value              // 回显
-------         -------
errorstring     runtime error

表达式

  • 支持MASMC++表达式(默认MASM)
  • 求MASM用?符号,求C++用??符号
  • 鉴于水平不足,待后续学习时补充完成

流程控制语句

.if .else .elif                   // 分支和判断
.do .while .for .continue .break  // 循环
.block                            // 代码块

2.4.7 调试功能扩展

基本功能扩展

  • 扩展模块在windbg安装目录,启动时默认加载
  • !peb观察peb

加载自定义调试扩展

  • 可以自行加载扩展模块DLL
// 指定路径
_NT_DEBUGGER_EXTENSION_PATH // 环境变量
.extpath ExtensionPath // 搜索扩展模块DLL

// 扩展管理
.load DLL模块    // 加载扩展
.unload DLL模块  // 卸载扩展
.chain          // 显式已加载的扩展及搜索顺序

// 扩展执行
000:00>!xxx.yyy // xxx标识模块名,yyy表示命令

// 查看帮助
000:00>!help        // 查看首个模块的help
000:00>!xxx.help    // 查看xxx模块的help

自行编写扩展模块

  • 开发接口位于sdk目录