跳转命令
-------------------------------------------------------------根据条件作出是否跳转的决定,通常前面会有一个判断语句,例如:
CMP AX,BX
JZ XX //jump zero
上面两条命令意为用 AX 减 BX,它的值如果为 0 则跳转到 XX 的标号行。
常用的跳转命令有:
JZ/JE 相等或为零为则跳转
JNZ/JNE 不相等或不为零则跳转
JL/JLE 小于/小于或等于则跳转
JG/JGE 大于/大于或等于则跳转
JMP 无条件跳转
-------------------------------------------------------------
比较语句
-------------------------------------------------------------
CMP AX,BX //AX 寄存器减去 BX 寄存器的内容
AND AX,BX //AX 与 BX 做“与运算”
OR AX,BX //AX 与 BX 做“或运算”
TEST AX,BX 与 AND AX,BX 命令有相同效果
XOR AX,AX 使 AX 的内容清零,每个寄存器与自己作异或运算等于清零动作
-------------------------------------------------------------
子程序
-------------------------------------------------------------
一个子程的模样长得像这个样子
CALL 15F:334422
子程式是个很重要的概念,它是主程式的一个分支,用来做特定动作。
打个比方:你要上班,先你是走路到车站,然后上车,然后下车,然后走到自己的办公室。
这里如果要把上班编为一段程式的话,那么就可以把“走路”、“搭车”、“走到办公室”做为分支程式来处理。
说得再通俗一点就是:你要破解的程式不可能就是一条主程式到底,肯定会呼叫下面的子程式,由子程式来处理你发送的注册信息,然后比较,然后标记是否注册正确,这些都是靠它来完成的。
所以说,破解的关键在于,你找准程式在哪儿将会作注册判断,并进入那个注册子程式,仔细观察,你就成功了。(子程式的返回码是 RET)
-------------------------------------------------------------
算术运算
-------------------------------------------------------------
ADD AX,BX 加法运算 AX=AX+BX
SUB AX,BX 减法运算 AX=AX-BX
INC AX 寄存器加一 AX=AX+1
DEC AX 寄存器减一 AX=AX-1
MUL 乘法运算
DIV/idiv 除法运算
-------------------------------------------------------------
数据操作
-------------------------------------------------------------
MOV AX,BX 数据传送指令,将 BX 的值移送到 AX 中
XCHG AX,BX 将 AX 与 BX 的值互换
8086/8088指令集
为了便于查询,这里分类列出8086/8088汇编指令:
数据传送指令
MOV
功能: 把源操作数送给目的操作数
语法: MOV 目的操作数,源操作数
格式: MOV r1,r2 或 MOV r,m 或 MOV m,r 或 MOV r,data
XCHG
功能: 交换两个操作数的数据
语法: XCHG
格式: XCHG r1,r2 或 XCHG m,r 或 XCHG r,m
PUSH,POP
功能: 把操作数压入或取出堆栈
语法: PUSH 操作数 POP 操作数
格式: PUSH r 或 PUSH M 或 PUSH data POP r 或 POP m
PUSHF,POPF,PUSHA,POPA // PUSHFD POPFD PUSHAD POPAD
功能: 堆栈指令群
格式: PUSHF POPF PUSHA POPA
LEA,LDS,LES
功能: 取地址至寄存器
语法: LEA r,m LDS r,m LES r,m
XLAT(XLATB)
功能: 查表指令
语法: XLAT XLAT m
算术运算指令
ADD,ADC
功能: 加法指令
语法: ADD OP1,OP2 ADC OP1,OP2
格式: ADD r1,r2 ADD r,m ADD m,r ADD r,data
影响标志: C,P,A,Z,S,O
SUB,SBB
功能:减法指令
语法: SUB OP1,OP2 SBB OP1,OP2
格式: SUB r1,r2 SUB r,m SUB m,r SUB r,data SUB m,data
影响标志: C,P,A,Z,S,O
INC,DEC
功能: 把OP的值加一或减一
语法: INC OP DEC OP
格式: INC r/m DEC r/m
影响标志: P,A,Z,S,O
NEG
功能: 将OP的符号反相(取二进制补码)
语法: NEG OP
格式: NEG r/m
影响标志: C,P,A,Z,S,O
MUL,IMUL
功能: 乘法指令
语法: MUL OP IMUL OP
格式: MUL r/m IMUL r/m
影响标志: C,P,A,Z,S,O(仅IMUL会影响S标志)
DIV,IDIV
功能:除法指令
语法: DIV OP IDIV OP
格式: DIV r/m IDIV r/m
CBW,CWD //change byte word // change word dword
功能: 有符号数扩展指令
格式: CBW CWD
AAA,AAS,AAM,AAD
功能: 非压BCD码运算调整指令
格式: AAA AAS AAM AAD
影响标志: A,C(AAA,AAS) S,Z,P(AAM,AAD)
DAA,DAS
功能: 压缩BCD码调整指令
格式: DAA DAS
影响标志: C,P,A,Z,S
字符串操作指令
MOVSB,MOVSW,MOVSD
功能: 字符串传送指令
格式: MOVSB MOVSW MOVSD
标志位: 无
CMPSB,CMPSW,CMPSD
功能: 字符串比较指令
格式: CMPSB CMPSW CMPSD
标志位: C,P,Z,S,O
SCASB,SCASW //scansb
功能: 字符串搜索指令
格式: SCASB SCASW
标志位: C,P,Z,S,O
LODSB,LODSW,STOSB,STOSW
功能: 字符串载入或存贮指令
格式: LODSB LODSW STOSB STOSW
标志位: 无
REP,REPE,REPNE
功能: 重复前缀指令集
格式: REP 指令S REPE 指令S REPNE 指令S
标志位: 依指令S而定
位运算指令集
AND,OR,XOR,NOT,TEST
功能: 执行BIT与BIT之间的逻辑运算
格式: AND r/m,r/m/data OR r/m,r/m/data XOR r/m,r/m/data TEST r/m,r/m/data NOT r/m
影响标志: C,O,P,Z,S(其中C与O两个标志会被设为0) NOT指令不影响任何标志位
SHR,SHL,SAR,SAL
功能: 移位指令
格式: SHR r/m,data/CL SHL r/m,data/CL SAR r/m,data/CL SAL r/m,data/CL
影响标志: C,P,Z,S,O
ROR,ROL,RCR,RCL
功能: 循环移位指令
格式: ROR r/m,data/CL ROL r/m,data/CL RCR r/m,data/CL RCL r/m,data/CL
影响标志: C,P,Z,S,O
程序流程控制指令
CLC,STC,CMC
功能: 设定进位标志
格式: CLC STC CMC
标志位: C
CLD,STD
功能: 设定方向标志
格式: CLD STD
标志位: D
CLI,STI
功能: 设定中断标志
格式: CLI STI
标志位: I
CMP
功能: 比较OP1与OP2的值
格式: CMP r/m,r/m/data
标志位: C,P,A,Z,O
JMP
功能: 跳往指定地址执行
格式: JMP 地址
JXX
功能: 当特定条件成立则跳往指定地址执行
格式: JXX 地址
XX为下列值:
A: ABOVE,当C=0,Z=0时成立
B: BELOW,当C=1时成立
C: CARRY,当CF=1时成立
CXZ: CX寄存器的值为0(ZERO)时成立
E: EQUAL,当Z=1时成立
G: GREATER(大于),当Z=0且S=0时成立
L: LESS(小于),当S不为零时成立
N: NOT(相反条件),需和其它符号配合使用
O: OVERFLOW,O=1时成立
P: PARITY,P=1时成立
PE: PARITY EVEN,P=1时成立
PO: PARITY ODD,P=0时成立
S: SIGN,S=1时成立
Z: ZERO,Z=1时成立
LOOP
功能: 循环指令集
语法: LOOP 地址
LOOPE(Z)
格式:LOOPNE(Z) 地址
标志位: 无
CALL,RET
功能: 子程序调用,返回指令
语法: CALL 地址 RET RET n
标志位: 无
INT,IRET
功能: 中断调用及返回指令
语法: INT n IRET
标志位: 在执行INT时,CPU会自动将标志寄存器的值入栈,在执行IRET时则会将堆栈中的标志值弹回寄存器
处理器状态控制指令
NOP
功能: 空操作指令。不执行任何操作,但要花费CPU一个机器周期
格式: NOP
HLT
功能: 暂停指令。CPU不执行任何操作,一直处于暂停状态,但IP指向HLT的下一条指令。
格式: HLT
脱离HLT状态的方式:1、CPU复位;2、CPU响应中断
ESC,WAIT,LOCK
功能: 用于多处理器系统。其中ESC是交权指令;WAIT是等待指令;LOCK是总线封锁指令
pe减肥及优化
区段减肥,去除垃圾区段,重建PE。
这个需要一点PE知识,没有也不要紧,跟着一起学,积累经验。
备份好脱壳程序,区段减肥有时过量会导致程序无法运行。
这次区段减肥只是例子,大家要学会举一反三。
-----------------------------------------------------------
目标程序是用Armadillo CopyMem-ll +Debug-Blocker加壳的98记事本,原程序52K --> 436K,脱壳后文件大小达到了656K,比脱壳前多出了10几倍.
加壳前文件的区段
----------------------------------------------------------
节区名称 节区大小 虚拟地址 Raw_尺寸 Raw_偏移 节区属性
----------------------------------------------------------
.text 00003FD4 00001000 00004000 00001000 60000020
.data 0000084C 00005000 00001000 00005000 C0000040
.idata 00000E02 00006000 00001000 00006000 40000040
.rsrc 00004FB8 00007000 00005000 00007000 40000040
.reloc 00000AC6 0000C000 00001000 0000C000 42000040
加壳后文件的区段
----------------------------------------------------------
节区名称 节区大小 虚拟地址 Raw_尺寸 Raw_偏移 节区属性
----------------------------------------------------------
.text 00004022 00001000 00000000 00000000 60000020
.data 0000083C 00006000 00000000 00000000 C0000040
.idata 00005E3C 00007000 00000000 00000000 40000040
.reloc 00000ADE 0000D000 00000000 00000000 42000040
.text1 00030000 0000E000 00014000 00001000 E0000020
.adata 00010000 0003E000 00005000 00015000 E0000020
.data1 00010000 0004E000 00006000 0001A000 C0000040
.reloc1 00010000 0005E000 00002000 00020000 42000040
.pdata 00030000 0006E000 0002A000 00022000 C0000040
.rsrc 00005000 0009E000 00005000 0004C000 40000040
脱壳后文件节表:
----------------------------------------------------------
节区名称 节区大小 虚拟地址 Raw_尺寸 Raw_偏移 节区属性
----------------------------------------------------------
.text 00004022 00001000 00003FD4 00001000 60000020
.data 0000083C 00006000 0000084C 00005000 C0000040
.idata 00005E3C 00007000 00005E02 00006000 C0000040
.reloc 00000ADE 0000D000 00000AC6 0000C000 42000040 *********
.text1 00030000 0000E000 00020000 0000D000 E0000020 *********
.adata 00010000 0003E000 00010000 0002D000 E0000020 *********
.data1 00010000 0004E000 00010000 0003D000 C0000040 *********
.reloc1 00010000 0005E000 00010000 0004D000 42000040 *********
.pdata 00030000 0006E000 00030000 0005D000 C0000040 *********
.rsrc 00005000 0009E000 00005000 0008D000 40000040
.mackt 00001000 000A3000 00001000 00092000 E0000060
其中.rsrc是文件资源节,.mackt节是imprec修复输入表时候新加的节。
容易发现有用的节只有
----------------------------------------------------------
节区名称 节区大小 虚拟地址 Raw_尺寸 Raw_偏移 节区属性
----------------------------------------------------------
.text 00004022 00001000 00004022 00001000 60000020
.data 0000083C 00006000 0000083C 00005000 C0000040
.idata 00005E3C 00007000 00005E3C 00006000 C0000040
.rsrc 00005000 00009E00 00005000 0008D000 40000040
.mackt 00001000 000A3000 00001000 00092000 E0000060
其他节都是脱壳后留下的无用的垃圾,所以只要将它们删掉就可以了达到我们减肥的效果了。当然对具体的壳也要删除的节也不同,具体问题具体分析吧:)。
进入正题
第一步:从节表中删除
先纪录这几个节的起始位置,几个节的Raw是从0000D000到0009E000-1
LordPE中PE编辑器中在这几个节点右键选“清除区段”。
第二步:调整节表属性
只是删除了节表项目和文件中内容还不行,还要设置好节属性。 可以通过编程实现资源节的RVA调整,使RVA偏移等于文件偏移,较麻烦,且.mackt存有输入表信息很多RVA值不好改动。 我们用简单的办法,不动它的RVA地址,只改变它的文件偏移。
用PE编辑器中,打开区段,选择.rsrc节,编辑,因为删除的节首的ROffset为0000D000,所以现在.rsrc节的节首ROffset为0000D000,更改!
.rsrc下面的节.mackt的Raw_偏移 = .rsrc节的Raw_偏移 + .rsrc节的Raw_尺寸 = 0000D000 + 00005000 =00012000,故更改.mackt 节的Raw_偏移为 00012000
还要调整一下.rsrc节上面的节.idata的节区大小,保证相邻节的VA地址是连续的
(.rsrc节的虚拟地址0009E000) - (.idata节的虚拟地址00007000) = 00097000 所以设置.idata的节区大小为97000
第三步:从文件中删除
HexWorkshop打开该文件,选择偏移0000D000到0009E000-1,全部删除!
保存,656K --> 76K,比起原先52K虽然还大了一点,但已经比较满意了。
“减肥两大法则”
1、 Contains(包含) 有标记的区段一般不能删除,没有标记的可优先考虑
2、 用OD载入需要减肥的文件,忽略所有异常,打开内存镜像,分别在各个区段上F2下断,F9运行!如果程序能够跑起来的话,那么这个区段一般就可以删除掉了(无用/垃圾区段)!
“心中有数”
熟悉5中常见的语言特征以及特征区段!
附录
Contains
.text 代码段,我们反编译程序经常看到。
.data 数据快,程序初始化用。
.idata 输入表
.rsrc 全部资源,如图标,菜单,位图。
.reloc 保存基地址重定位。