基础汇编知识以及 OD 的使用。

数值表示

二进制-b(binary)、十进制-d(decimalism)、十六进制-h(hexadecimal)

字长:

  • bit:位
  • byte:字节–1byte=8bit
  • word:字–1word=2byte=16bit
  • dword:双字–1dword=2word=4byte=32bit
  • qword:四字–1qword=2dword=4word=8byte=64bit

通用寄存器

  • EAX:累加器(accumulator),是加法乘法指令的缺省寄存器。还可以用来存储函数返回值
  • ECX:重复 REP 和 LOOP 指令的计数器(counter)
  • EDX:用于存放整数除法产生的余数
  • EBX:在内存寻址时用来存放基地址(base)
  • ESP:当前线程的栈顶指针,压入栈的数据越多,ESP 越小,每入栈一次减小 4 字节
  • EBP:当前线程的栈底指针
  • ESI/EDI:源/目标索引寄存器,字符串操作中,DS:ESI 指向源串,ES:EDI 指向目标串。
  • EIP:存放下一个 CPU 指令的内存地址,执行完后读取下一指令

标志寄存器

  • CF:进位标志(可检查无符号操作是否溢出)
  • OF:零标志
  • SF:符号标志
  • PF:溢出标志(补码溢出)

寄存器寻址

  • 立即数寻址:MOV EAX, 123H
  • 寄存器寻址:MOV EAX, EBX(EBX 中存放操作数)
  • 直接寻址:MOV EAX, [12345678H](操作数以 [] 为地址)
  • 寄存器间接寻址:MOV EAX, [EBX](操作数的地址为 EBX 中存储的值)

基本汇编指令

数据传输

指令 作用
MOV 赋值
PUSH 入栈
POP 出栈
LEA 取地址
MOVSX 符号传送
PUSHAD 将所有 32 位通用寄存器压入栈
POPAD 将所有 32 位通用寄存器取出栈

算术运算

指令 作用
ADD 加法
INC 自加
SUB 减法
DEC 自减
CMP 比较
MUL 乘法
DIV 除法
IDIV 符号整除
IMUL 符号乘法
NEG 求补

逻辑运算

指令 作用
AND 与运算
OR 或运算
NOT 非运算
XOR 异或运算
TEST 与运算(只对标志位修改,对操作数没有影响)
SHL 逻辑左移
SAL 算术左移
SHR 逻辑右移
SAR 算术右移
ROL 循环左移
ROR 循环右移
RCL 进位循环左移
RCR 进位循环右移

转移指令

指令 作用
JMP 跳转
JA 大于时跳转(>)
JNA 不大于时跳转(<=)
JAE 大于等于时跳转(>=)
JB 小于时跳转(<)
JNB 不小于时跳转(>=)
JBE 小于等于时跳转(<=)
JE 相等时跳转(==)
JNE 不等于时跳转(!=)
JNBE 不小于等于时跳转(>)
JG 大于时跳转(有符号)(>)
JNG 不大于时跳转(有符号)(<=)
JGE 大于等于时跳转(有符号)(>=)
JL 小于时跳转(有符号)(<)
JNL 不小于时跳转(有符号)(>=)
JLE 小于等于时跳转(有符号)(<=)
JNGE 不大于等于时跳转(有符号)(<)
JNLE 不小于等于时跳转(有符号)(>)
JZ ZF 为 0 时跳转
JNZ ZF 不为 0 时跳转
JS 有符号时跳转
JNS 无符号时跳转

JGE:Jump if Greater or Equal

循环指令

指令 作用
LOOP 循环(改变 ECX 的值)
JCXZ 循环(不改变 ECX 的值)

串指令

指令 作用
MOVS[B/W/D] 传送字节串/字串/双字串
CMPS[B/W/D] 比较字节串/字串/双字串
SCAS[B/W/D] 扫描字节串/字串/双字串
LODS[B/W/D] 加载源变址字节串/字串/双字串
STOS[B/W/D] 保存字节串/字串/双字串
REP 重复

其他指令

指令 作用
INT 终止程序
CALL 调用函数
RET 过程返回
NOP
CLD 方向清零

OD 初探

静态调试与动态调试:
静态调试就是在不执行程序的情况下,人工地对源代码的语法和逻辑分析;动态调试则是在编译、链接、运行的整个过程中,观察如寄存器内容、函数执行情况等状态来分析调试

  • L(og):日志信息
  • E(xecute modules):模块信息
  • M(emory map):内存映射信息
  • T(hreads):线程信息
  • W(indows):窗口信息
  • H(andles):句柄信息
  • C:当前线程上下文
  • K:调用链信息
  • ……

OD 调试快捷键

快捷键 功能
ctrl+g 跳转到指定位置
ctrl+e 编辑指定区域
space 编辑汇编代码
f4 执行到光标位置处
f2 断点(Int3)
; 添加注释
: 添加标签名
* 返回到正在运行的地方
-(+) 返回到上(下)一个光标处
enter 跟随跳转/跟入调用内部
f3 打开一个新的可执行程序
ctrl+f2 重新运行当前调试的程序
f9 运行选定的程序进行调试
f12 暂时停止被调试程序的执行
f7 单步进入被调试程序的 call 中
f8 步过被调试程序的 call
ctrl+f9 执行直到返回

第一次调试(helloworld.exe)

关于 PE 文件的 EntryPoint。打开 CFF,将 PE 文件拖入:

其中,ImageBase 和 AddressOfEntryPoint 指向的地址即为 EntryPoint

找到 main 函数

  • 代码执行:通过 F7 单步步入,一步一步执行到弹框跳出时,进入 main 函数
  • 层层推进:通过 F8 单步步过,快速跳过每个函数,跳出弹框后,进入 main 函数
  • 字符串检索:根据弹框上方的字符串,右键智能搜索查找,找到后直接进入 main 函数
  • API 检索法:通过运行程序可以判断文件句柄是 MessageBox,在模块中找到后依次设置断点,运行程序,在主函数断电处停下
  • 特征法:根据 C 语言的反汇编特征进行判断

修改内容

Fact.exe

jge 表示大于或等于时跳转。当输入数字 n 时,EDX 存放值 n,ECX 中的值初始化为 1,[local.3] 中的值也为 1,每次循环时,ECX 中的值自加一,[local.3] 的值为自身再乘上 ECX 中的值。当 ECX 等于 EDX 时跳出循环,而不再进行下一次乘法,最后 [local.3] 中的值为(n-1)!,故应该将 jge 修改为 jg 即可

参考网站

https://www.cnblogs.com/qq78292959/archive/2012/07/20/2600865.html
https://blog.csdn.net/qq_34717555/article/details/77727176
https://blog.csdn.net/hanchaoman/article/details/9187093


re

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

WEB入门(一)
Apache Rewrite(路由重写)