Jirairya

Misc


逆向知识小记

小端序标记法

计算机领域中,字节序(Byte Ordering)是多字节数据在计算机内存中存储或网络传输时各字节的存储顺序,主要分为两大类:小端序、大端序。

大端序和小端序的区别.png

数据类型为字节序时,其长度为1个字节,保存此类数据时,无论使用大端序还是小端序,字节顺序都是一样的。但数据长度为2个字节以上(含2个字节)时,采用不同字节序保存它们形成的存储顺序是不同的。采用大端序存储数据时,内存地址低位存储数据的高位,内存地址高位存储数据的低位,这是一种直观的字节存储顺序。采用小端序存储数据时,地址高位存储数据的高位,地址低位存储数据的低位,逆序存储方式,保存的字节顺序被倒转,最符合人类思维的字节序。

数据为单一时,无论采用大端序还是小端序保存,字节存储顺序都一样。只有在2两个字节以上时,大端序和小端序的存储顺序不同。还有如图中代码3-1中的“abcde”被保存在一个字符数组中,字符数组在内存中是连续的,无论采用大端序还是小端序,存储顺序都一样。

寄存器

寄存器是位于CPU的内部存储空间,都有自己的名字:

  • EAX,”累加器”(accumulator),扩展累加寄存器,在乘法和除法中被自动使用
  • EBX,”基地址”(base)寄存器, 在内存寻址时存放基地址。
  • ECX,计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。
  • EDX,则总是被用来放整数除法产生的余数。
  • ESP,扩展堆栈指针寄存器,寻址堆栈,极少用于普通的算术运算和数据传送。
  • ESI和EDI由高速内存数据传送指令使用,通常称为扩展源指针和扩展目的指针寄存器。
  • EBP,扩展帧指针寄存器,高级语言使用EBP引用堆栈上的函数参数和局部变量。
  • EIP,指令指针,存放下一条要执行的指令的地址。(指向当前执行的指令)有些程序可以修改EIP,使程序分支转移到新的地址执行。

寄存器.png

在EIP下有C、P、A、Z、S、T、D、O几个字母,它们表示标志。一般会在这些字母后加上F(FLAG),CF、PF、AF、ZF,这些标志表示用于条件分支,如:

  • 若ZF为1表示跳转
  • 若CF位1表示不跳转

EFLAGS 寄存器由控制CPU的操作或反映CPU某些运算的结果的独立二进制位构成。当某标志等于1时就说其被置位;等于0时候就说其被清除(或复位)

控制标志,控制CPU的操作。例如,某些标志位可以使CPU在每条指令执行后、检测到算术运算溢出后、进入虚拟8086模式或保护模式后中断。

状态标志,反映CPU执行的算术和逻辑运算的结果,包括溢出标志、符号标志、零标志、辅助进位标志、奇偶标志、进位标志:

  • 进位标志(CF):在无符号算术的运算结果太大而目的操作数无法容纳时置位
  • 溢出标志(OF):在有符号算术运算结果太大或太小而无目的操作数无法容纳时置位
  • 符号标志(SF):在算术或逻辑运算的结果位负时置位。
  • 零标志(ZF):在算术或逻辑运算结果为零时置位。
  • 辅助进位标志(AC):在算术运算导致8位操作数的位3到位4产生进位时置位。
  • 奇偶标志(PF):结果最低有效字节为1的位的数目位偶数时置位,否则PF复位。通常用于在数据有可能改变或丢失的情况下检查错误。

静态分析和动态分析的区别是在于“是否运行程序”,静态偏向于“纵览全局”,动态分析偏向于“细看局部”。在软件分析的时候,首先用二进制编辑器和IDA看全局,然后再用OllyDbug看局部。

OD对python亲和性高,WinDbg对堆内核领域的程序进行调试,分析rootkit用它。

汇编指令

该模块出自破解常用汇编指令.

1.软件破解常用汇编指令

cmp a,b // 比较a与b
mov a,b // 把b值送给a值,使a=b
ret // 返回主程序
nop // 无作用
call // 调用子程序,子程序以ret结尾
jejz // 相等则跳(机器码是74或84)
jnejnz // 不相等则跳(机器码是75或85)
jmp // 无条件跳(机器码是EB)
jb // 若小于则跳
ja // 若大于则跳
jg // 若大于则跳
jge // 若大于等于则跳
jl // 若小于则跳
pop xxx // xxx出栈
push xxx // xxx压栈

2.数据传输指令:

  • 通用数据传送指令.
MOV 传送字或字节.
MOVSX 先符号扩展,再传送.
MOVZX 先零扩展,再传送.
PUSH 把字压入堆栈.
POP 把字弹出堆栈.
PUSHA AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.
POPA DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.
PUSHAD EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.
POPAD EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.
BSWAP 交换32位寄存器里字节的顺序
XCHG 交换字或字节.( 至少有一个操作数为寄存器,段寄存器不可作为操作数)
CMPXCHG 比较并交换操作数.( 第二个操作数必须为累加器AL/AX/EAX )
XADD 先交换再累加.( 结果在第一个操作数里 )
XLAT 字节查表转换.
—— BX 指向一张 256 字节的表的起点, AL 为表的索引值 (0-255,
0-FFH); 返回 AL 为查表结果. ( [BX+AL]->AL )
  • 输入输出端口传送指令.
IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )
OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器 )
输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时,
其范围是 0-65535.

3.目的地址传送指令:

LEA 装入有效地址.
: LEA DX,string ;把偏移地址存到DX.
LDS 传送目标指针,把指针内容装入DS.
: LDS SI,string ;把段地址:偏移地址存到DS:SI.
LES 传送目标指针,把指针内容装入ES.
: LES DI,string ;把段地址:偏移地址存到ES:DI.
LFS 传送目标指针,把指针内容装入FS.
: LFS DI,string ;把段地址:偏移地址存到FS:DI.
LGS 传送目标指针,把指针内容装入GS.
: LGS DI,string ;把段地址:偏移地址存到GS:DI.
LSS 传送目标指针,把指针内容装入SS.
: LSS DI,string ;把段地址:偏移地址存到SS:DI.

4.标志传送指令:

LAHF 标志寄存器传送,把标志装入AH.
SAHF 标志寄存器传送,AH内容装入标志寄存器.
PUSHF 标志入栈.
POPF 标志出栈.
PUSHD 32位标志入栈.
POPD 32位标志出栈.

5.算术运算指令:

ADD 加法.
ADC 带进位加法.
INC  1.
AAA 加法的ASCII

##栈

栈(Stack)的用途广泛,通常用于存储局部变量、传递函数参数、保存函数返回地址等,调试程序时需要不断查看栈内存。

栈在内存进程中的作用如下:

  • 暂时保存函数内的局部变量
  • 调用函数时传递参数
  • 保存函数返回后的地址

栈是一种数据结构,按照FILO(先进后出)的原则存储数据。

栈.png

一个进程中,栈指针(ESP)初始状态指向栈底端。执行PUSH命令将数据压入栈时,栈顶指针就会上移到栈顶端。执行POP命令从栈中弹出数据时,若栈为空,则栈顶指针重新移动到栈底端。(栈是一种由高地址到低地址扩展的数据结构,栈是由下往上扩展的)栈是逆向扩展的。

例子: 栈的初始状态为,栈顶指针的值“12FF8C”,观察右下角的栈窗口,可以看到ESP指向的地址和其值。

栈的初始状态.png

在代码窗口中按F7键,执行401000地址处的PUSH100命令。

ESP值变为12FF**,比原来减少了4个字节。并且当前的栈顶指针指向12FF88地址,该地址中保存了100这个值。换言之,执行PUSH命令,数值100被压入栈中,ESP随之向上移动,即ESP的值减少了4个字节。 PUSH命令.png

再次按F7,执行401005地址处的POP EAX命令。

POP命令.png 执行POP EAX命令后,又增加了4个字节,变为12FF8C,栈又变成了初始状态。 栈中弹出数据后,ESP随之向下移动。

向栈压入数据时,栈顶指针变小,向低地址移动;从栈中弹出数据时,栈顶指针增加,向高地址移动

栈的特征:栈顶指针在初始状态下指向栈底。


上一篇 打补丁

下一篇 CrackMe1

Comments

Content