12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
查看: 1384|回复: 0

逆向之汇编学习总结

[复制链接]

3782

主题

3782

帖子

214748万

积分

超级版主

Rank: 8Rank: 8

积分
2147483647
发表于 2019-11-1 01:04:05 | 显示全部楼层 |阅读模式
数据宽度

或许你曾经有这样的疑惑,有符号数在二进制的表示中,以1开头的表示为负数,那么10000000是表示的-1还是128呢 ?
在这里引入数据宽度的概念,即8位二进制数能够存储的数据范围为-128~127,很显然,上面存储的数,在数据宽度为8位时,表示-1,同理-127表示为10000001,-2表示为11111110,这里关于原码、补码的概念不加以赘述,其本质都是为了表示数值。
基于x86架构的CPU的数据宽度为32位,表示正负范围为:0~7FFFFFFF 80000000~FFFFFFFF
计量单位有:byte、word、dword、qword,分别表示字节,字,双字,四字,单字节表示8位。
逻辑运算

运算符说明实例&(and)按位与,同时为1,才能得110110011 & 10110101 = 10110001|(or)按位或,存在1时,结果为110110011 | 10110101 = 10110011^(xor)按位异或,不同时,结果为110110011 ^ 10110101 = 00000110!(not)按位非,单运算符,结果取反!10110011=01001100异或加密解密
加密数据:00110001
密钥:00010101
加密结果:00110001 ^ 00010101 = 00100100
解密:00100100 ^ 00010101 = 00110001
基本指令

mov

格式:mov 目标操作数,源操作数
作用:拷贝源操作数到目标操作数。
注意:
1、源操作数可以是立即数、通用寄存器、段寄存器、或者内存单元. 2、目标操作数可以是通用寄存器、段寄存器或者内存单元. 3、操作数的宽度必须一样. 4、源操作数和目标操作数不能同时为内存单元.指令说明MOV r/m8,r8将8位寄存器的内容拷贝到8位寄存器或8位的内存中。MOV r/m16,r16将16位寄存器的内容拷贝到16位寄存器或16位的内存中。MOV r/m32,r32将32位寄存器的内容拷贝到32位寄存器或32位的内存中。MOV r8,r/m8将8位寄存器或8位的内存操作数拷贝到8位寄存器中。MOV r16,r/m16将16位寄存器或16位的内存操作数拷贝到16位寄存器中。MOV r32,r/m32将32位寄存器或32位的内存操作数拷贝到32位寄存器中。MOV r8, imm8将8位立即数的内容拷贝到8位寄存器中。MOV r16, imm16将16位立即数的内容拷贝到16位寄存器中。MOV r32, imm32将32位立即数的内容拷贝到32位寄存器中。以上指令取自Intel白皮书,释义如下:
r 通用寄存器           m 代表内存                            imm 代表立即数                           r8 代表8位通用寄存器               m8 代表8位内存imm8 代表8位立即数
lea

LEA指令将存储器操作数mem的4位16进制偏移地址送到指定的寄存器,这里,源操作数必须是存储器操作数,目标操作数必须是通用寄存器。
格式:lea r,m。
功能:获取内存编号而非内存中的内容。

别问,问就是背

addandorxornotsubADD AL, imm8AND AL, imm8OR AL, imm8XOR AL, imm8NOT r/m8SUB AL, imm8ADD AX, imm16AND AX, imm16OR AX, imm16XOR AX, imm16NOT r/m16SUB AX, imm16ADD EAX, imm32AND EAX, imm32OR EAX, imm32XOR EAX, imm32NOT r/m32SUB EAX, imm32ADD r/m8, imm8AND r/m8, imm8OR r/m8, imm8XOR r/m8, imm8SUB r/m8, imm8ADD r/m16,imm16AND r/m16,imm16OR r/m16,imm16XOR r/m16,imm16SUB r/m16,imm16ADD r/m32,imm32AND r/m32,imm32OR r/m32,imm32XOR r/m32,imm32SUB r/m32,imm32ADD r/m16, imm8AND r/m16, imm8OR r/m16, imm8XOR r/m16, imm8SUB r/m16, imm8ADD r/m32, imm8AND r/m32, imm8OR r/m32, imm8XOR r/m32, imm8SUB r/m32, imm8ADD r/m8, r8AND r/m8, r8OR r/m8, r8XOR r/m8, r8SUB r/m8, r8ADD r/m16, r16AND r/m16, r16OR r/m16, r16XOR r/m16, r16SUB r/m16, r16ADD r/m32, r32AND r/m32, r32OR r/m32, r32XOR r/m32, r32SUB r/m32, r32ADD r8, r/m8AND r8, r/m8OR r8, r/m8XOR r8, r/m8SUB r8, r/m8ADD r16, r/m16AND r16, r/m16OR r16, r/m16XOR r16, r/m16SUB r16, r/m16ADD r32, r/m32AND r32, r/m32OR r32, r/m32XOR r32, r/m32SUB r32, r/m32
OD技巧

快捷键

ctrl+g : 跳转到指定输入地址
ctrl+f:搜索命令的位置
f2 : 设置断点,切换断点
f8: 单步步过
f9:运行
f12:暂停
窗口布局



  • 数据窗口和其他窗口的数据位置相反,为小端序,即高位数据存放在低位地址。
  • 命令接口常用命令:

    • dd、dw、db,按四字、双字、字节显示对应内存数据。

缓存清理

有时OD打开之后,会出现反汇编窗口一段代码变灰或者提示哪里下了断点的情况,这是OD同级目录下的udd文件夹下的缓存文件导致的,删掉里面的文件即可解决该问题。
寄存器

通用寄存器主要用途编号(二进制)32位16位8位EAXAXAL累加器000ECXCXCL计数001EDXDXDLI/O指针010EBXBXBLDS段的数据指针011ESPSPAH堆栈指针100EBPBPCHSS段的数据指针101ESISIDH字符串操作的源指针;SS段的数据指针110EDIDIBH字符串操作的目标指针;ES段的数据指针11132位专用寄存器主要用途存储数据的范围EIP保存当前下一条运行指针地址0 - 0xFFFFFFFF
辅以神兵OD,逆向美哉!



内存

基本概念

寄存器位于CPU内部,执行速度快,但比较贵;而内存通过引脚与CPU相连,速度相对较慢,但成本较低,所以可以做的很大。寄存器和内存没有本质区别,都是用于存储数据的容器,都是定宽的。
内存的数量特别庞大,无法每个内存单元都起一个名字,所以用编号来代替,我们称计算机CPU是32位或者64位,主要指的就是内存编号的宽度(寻址宽度),而不是寄存器的宽度。
计算机内存的每一个字节会有一个编号(即内存编号的单位是字节),编号从0开始,32位计算机的编号最大是32位,也就是FFFFFFFF,也就是说,32位计算机内存寻址的最大范围是FFFFFFFF+1 , 即4GB,这也是为什么我们在一个XP的系统上面如果物理内存超过4G是没有意义的原因。
[内存编号]表示地址,每个内存单元的宽度为8,超过8位的数据会溢出到下一个内存单元。
内存读写


  • 内存读:mov eax,dword ptr ds:[0x0012FF34]
  • 内存写:mov dword ptr ds:[0x0012FF34],0x12345678
  • ptr: Point 代表后面是一个指针 (指针的意思就是里面存的不是普通的值,而是个地址)
  • 注意:地址编号不要随便写,因为内存是有保护的,并不是所有的内存都可以直接读写(需要特别处理)

寻址公式

1. [立即数]
#内存读mov eax,dword ptr ds:[0x19FF74]#内存写mov dword ptr ds:[0x19FF74],0xAABBCCDD#获取内存编号lea ecx,dword ptr ds:[0x19FF74]
2. [reg]
#内存读mov ecx,0x19ff74mov eax,dword ptr ds:[ecx]#内存写mov dword ptr ds:[ecx],0x87654321#获取内存编号lea eax,dword ptr ds:[ecx]
3. [reg+立即数]
#内存读mov ecx,0x19ff74mov eax,dword ptr ds:[ecx+4]#内存写mov dword ptr ds:[ecx+0xd],0x87654321#获取内存编号lea eax,dword ptr ds:[ecx+4]
*4. [reg+reg{1,2,4,8}]**:注意,这里只能取1,2,3,4中的一个。
#内存读mov ecx,0x19ff74mov edx,2mov eax,dword ptr ds:[ecx+edx*4]#内存写mov dword ptr ds:[ecx+edx*4],0x87654321#获取内存编号lea eax,dword ptr ds:[ecx+edx*4]
*5. [reg+reg{1,2,4,8}+立即数]**
#内存读mov ecx,0x19ff74mov edx,2mov eax,dword ptr ds:[ecx+edx*4+4]#内存写mov dword ptr ds:[ecx+edx*4+4],0x87654321#获取内存编号lea eax,dword ptr ds:[ecx+edx*4+4]
堆栈操作

堆栈模型

压入数据
#模拟栈顶栈底mov ebx,0x13ffdc  #basemov edx,0x13ffdc  #top#方式1mov dword ptr ds:[edx-4],0xaaaaaaaasub edx,4#方式2sub edx,4mov dword ptr ds:[edx],0xaaaaaaaa#方式3mov mov dword ptr ds:[edx-4],0xaaaaaaaalea edx,dword ptr ds:[edx-4]#方式4lea edx,dword ptr ds:[edx-4]mov mov dword ptr ds:[edx],0xaaaaaaaa读取数据
#通过base加偏移读取第n个压入的数,n需指定mov esi,dword ptr ds:[ebx-4*n]#通过top加偏移读取mov esi,dword ptr ds:[ebx+4*(n-1)]弹出数据
#方法1mov ecx,dword ptr ds:[edx]lea edx,dword ptr ds:[edx+4]#方法2mov esi,dword ptr ds:[edx]add edx,4#方法3lea edx,dword ptr ds:[edx+4]mov edi,dword ptr ds:[edx-4]push指令:完成上述模拟的压入数据操作,ebx和esp分别为占地和栈顶,由cpu调配,随着压栈操作而自动变化,与容器宽度有关加减2或4。

  • push r32:esp-4
  • push r16:esp-2
  • push m16:esp-2
  • push m32:esp-4
  • push imm8/imm16/imm32:esp-4

pop指令:完成上述模拟的弹出数据操作,ebx和esp分别为占地和栈顶,由cpu调配,随着出栈操作而自动变化。

  • pop r32:esp+4
  • pop r16:esp+2
  • pop m16:esp+2
  • pop m32:esp+4

pushad指令:将8个通用寄存器的内容压栈,现场保护。

popad指令:pushad的逆操作,恢复现场。
标志寄存器

别问,问就是背


CF

进位标志(Carry Flag),如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。
MOV AX,0xFF00ADD AX,0x0101
PF

奇偶标志PF(Parity Flag):奇偶标志PF用于反映运算结果中最后一个字节中“1”的个数的奇偶性,如果“1”的个数为偶数,则PF的值为1,否则其值为0。
00010011 00010010 mov ax,0x131200010011 00010011 偶数 ,最后一字节为奇数-->p=0add ax,100010011 00010100 奇数,最后一字节为偶数-->p=1add ax,1


  • 特别的,当最低有效字节为0时,PF=1
AF

辅助进位标志(Auxiliary Carry Flag),在发生下列情况时,辅助进位标志AF的值被置为1,否则其值为0:

  • 在字操作时,发生低字节向高字节进位或借位时;
  • 在字节操作时,发生低4位向高4位进位或借位时。
MOV AX,0x100fADD AX,0x4
ZF

零标志(Zero Flag):零标志ZF用来反映运算结果是否为0,如果运算结果为0,则其值为1,否则其值为0。

SF

符号标志(Sign Flag):符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。
mov al,0x82add al,1
OF

溢出标志(Overflow Flag):溢出标志OF用于反映有符号数加减运算所得结果是否溢;如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0。
最高位进位与溢出的区别:

  • 进位标志表示无符号数运算结果是否超出范围.
  • 溢出标志表示有符号数运算结果是否超出范围.
是否溢出的判别规律:


  • 正 + 正 = 正 如果结果是负数,则说明有溢出
  • 负 + 负 = 负 如果结果是正数,则说明有溢出
  • 正 + 负 永远都不会有溢出.

DF

方向标志位,默认从右操作数到左操作数,可以通过CLD和STD指令修改DF的值。

  • 清方向位指令CLD(Clear Direction Flag):DF←0
  • 置方向位指令STD(Set Direction Flag):DF←1
相关指令

ADC

带进位加法(C位参与运算),两边不能同时为内存,且数据宽度要一致。
格式:ADC  R/M,R/M/IMM

  • ADC AL,CL
  • ADC BYTE PTR DS:[19ff74],2
  • ADC BYTE PTR DS:[19ff74],AL

SBB

带借位减法(C位参与运算),两边不能同时为内存,且数据宽度要一致。
格式:SBB  R/M,R/M

  • SBB AL,CL
  • SBB BYTE PTR DS:[19ff74],2
  • SBB BYTE PTR DS:[19ff74],AL

XCHG

交换数据,两边不能同时为内存,且数据宽度要一致。
格式:XCHG  R/M,R/M

  • XCHG AL,CL
  • XCHG DWORD PTR DS:[19ff74],EAX
  • XCHG BYTE PTR DS:[19ff74],AL

MOVS

移动数据,把ESI存储的内存地址中的数据复制到EDI存储的内存地址中,每复制一次,两个操作数均向上或下偏移4/2/1个字节(地址递增或递减,便于复制下一串内容),当D=0时递增,D=1时递减。

  • MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI],简写为movsb
  • MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI],简写为MOVSW
  • MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI],简写为movsd


STOS

将AL/AX/EAX的值存储到[EDI]指定的内存单元,D=0时地址递增,D=1时地址递减。

  • STOS BYTE PTR ES:[EDI],简写为STOSB
  • STOS WORD PTR ES:[EDI],简写为STOSW
  • STOS DWORD PTR ES:[EDI],简写为STOSD

REP

按计数寄存器 (ECX) 中指定的次数重复执行字符串指令。

JCC

比较指令

cmp

格式:CMP  R/M,R/M/IMM
该指令是比较两个操作数,实际上,它相当于SUB指令,但是相减的结果并不保存到第一个操作数中;只是根据相减的结果来改变零标志位的(其他标志位也可以更改),当两个操作数相等的时候,零标志位置1。

test

指令格式:TEST  R/M,R/M/IMM
该指令在一定程序上和CMP指令时类似的,两个数值进行操作,结果不保存,但是会改变相应标志位;用这个指令,可以确定某寄存器是否等于0。

jmp

无条件转移指令,仅可以修改EIP的值,相当于mov eip,立即数/寄存器。
格式:jmp 寄存器/立即数
call

call指令用于调用子程序,先将当前的EIP压栈保存,然后jmp 目标地址,相当于:
PUSH eipmov eip,地址A/寄存器格式:call 地址A/寄存器
ret

ret指令用于回到程序调用点,与call配套使用,先将eip出栈,然后jmp eip,相当于:
lea esp,[esp+4]mov eip,[esp-4]格式:ret
别问,问就是背

指令解释条件例子JE、JZ结果为0时跳转(相等时跳转)ZF=1cmp al,al jz 0x19ff74JNE, JNZ结果不为零则跳转(不相等时跳转)ZF=0cmp al,cl jnz 0x19ff74JS结果为负则跳转SF=1mov al,1 sub al,3 js 0x19ff74JNS结果为非负则跳转SF=0mov al,2 sub al,1 jns 0x19ff74JP, JPE结果中1的个数为偶数则跳转PF=1cmp al,al jp 0x19ff74JNP, JPO结果中1的个数为偶数则跳转PF=0mov al,1 cmp al,0xff jnp 0x19ff94JO结果溢出了则跳转OF=1mov al,07f add al,4 jo 0x19ff74JNO结果没有溢出则跳转OF=0mov al,07f add al,0 jno 0x19ff74JB, JNAE小于则跳转 (无符号数)CF=1mov al,2 mov cl,1 cmp cl,al jb 0x19ff90JNB, JAE大于等于则跳转 (无符号数)CF=0mov al,2 mov cl,1 test cl,al jb 0x19ff90JBE, JNA小于等于则跳转 (无符号数)CF=1 or ZF=1cmp al,al jbe 0x19ff90JNBE, JA大于则跳转(无符号数)CF=0 and ZF=0mov al,2 mov cl,1 cmp al,cl jnbe 0x19ff90JL, JNGE小于则跳转 (有符号数)SF≠ OFmov al,1 mov cl,2 cmp al,cl jl 0x19ff74JNL, JGE大于等于则跳转 (有符号数)SF=OFmov al,1 mov cl,2 cmp cl,al jnl 0x19ff74JLE, JNG小于等于则跳转 (有符号数)ZF=1 or SF≠ OFmov al,2 mov cl,1 cmp cl,al jle 0x19ff90JNLE, JG大于则跳转(有符号数)ZF=0 and SF=OFmov al,2 mov cl,1 cmp cl,al jnle 0x19ff90first crackme

程序链接
信息收集


设置断点

在Win32弹窗接口下断点:bp MessageBoxA

运行程序



跟踪堆栈

右键堆栈窗口栈顶处[0019FDB4],Follow In Disassember,观察反汇编窗口,如下:

破解尾声

禁用掉之前win32的断点后,再次点击小三角运行程序,并输入注册信息,点击确定,观察反汇编窗口,如下:

跟踪堆栈,回溯上判断程序的入口,在jcc指令处设置断点,并清除其它断点,然后修改jcc指令为相反逻辑,如下:


保存程序

先将断点取消,然后右键反汇编窗口,选择Copy to executable->All Modifications,这是跳转到保存结束的界面,右键反汇编窗口选择save即可。

新的征程

运行破解之后的程序CRACKME233.EXE,如果输入注册信息包含数字的话,第一次弹窗仍然为判断失败的提示,点击确定后才弹出判断成功的提示,接下来想办法干掉第一次判断失败的提示!

来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-4-20 14:28 , Processed in 0.125000 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表