简单汇编知识二及pe优化减肥

作者在 2010-01-25 12:47:05 发布以下内容

跳转命令
-------------------------------------------------------------根据条件作出是否跳转的决定,通常前面会有一个判断语句,例如:

    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是从0000D0000009E000-1

LordPEPE编辑器中在这几个节点右键选“清除区段”。

 

第二步:调整节表属性

只是删除了节表项目和文件中内容还不行,还要设置好节属性。 可以通过编程实现资源节的RVA调整,使RVA偏移等于文件偏移,较麻烦,且.mackt存有输入表信息很多RVA值不好改动。 我们用简单的办法,不动它的RVA地址,只改变它的文件偏移。

 

PE编辑器中,打开区段,选择.rsrc节,编辑,因为删除的节首的ROffset0000D000,所以现在.rsrc节的节首ROffset0000D000,更改!

.rsrc下面的节.macktRaw_偏移 = .rsrc节的Raw_偏移 + .rsrc节的Raw_尺寸 = 0000D000 + 00005000 =00012000,故更改.mackt 节的Raw_偏移为 00012000 

 

还要调整一下.rsrc节上面的节.idata的节区大小,保证相邻节的VA地址是连续的

 

(.rsrc节的虚拟地址0009E000) - (.idata节的虚拟地址00007000) = 00097000 所以设置.idata的节区大小为97000

 

第三步:从文件中删除

HexWorkshop打开该文件,选择偏移0000D0000009E000-1全部删除!

 

保存,656K --> 76K,比起原先52K虽然还大了一点,但已经比较满意了。

 

减肥两大法则

1、          Contains(包含) 有标记的区段一般不能删除,没有标记的可优先考虑

2、          OD载入需要减肥的文件,忽略所有异常,打开内存镜像,分别在各个区段上F2下断,F9运行!如果程序能够跑起来的话,那么这个区段一般就可以删除掉了(无用/垃圾区段)!

心中有数

熟悉5中常见的语言特征以及特征区段!

 

附录

Contains

.text     代码段,我们反编译程序经常看到。

.data     数据快,程序初始化用。

.idata    输入表

.rsrc     全部资源,如图标,菜单,位图。

.reloc    保存基地址重定位。

破解@经历 | 阅读 1515 次
文章评论,共0条
游客请输入验证码
浏览2354340次