分享

汇编与机器码

 wwwijhyt图书馆 2014-05-09
8088 汇编速查手册一、数据传输指令
───────────────────────────────────────
它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.
1. 通用数据传送指令.
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 )
2. 输入输出端口传送指令.
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汇编与机器码 - 梦想之鹰 - 梦想之鹰的天空I.
LFS 传送目标指针,把指针内容装入FS.
例: LFS DI,string ;把段地址:偏移地址存到FS汇编与机器码 - 梦想之鹰 - 梦想之鹰的天空I.
LGS 传送目标指针,把指针内容装入GS.
例: LGS DI,string ;把段地址:偏移地址存到GS汇编与机器码 - 梦想之鹰 - 梦想之鹰的天空I.
LSS 传送目标指针,把指针内容装入SS.
例: LSS DI,string ;把段地址:偏移地址存到SS汇编与机器码 - 梦想之鹰 - 梦想之鹰的天空I.
4. 标志传送指令.
LAHF 标志寄存器传送,把标志装入AH.
SAHF 标志寄存器传送,把AH内容装入标志寄存器.
PUSHF 标志入栈.
POPF 标志出栈.
PUSHD 32位标志入栈.
POPD 32位标志出栈.

二、算术运算指令
───────────────────────────────────────
  ADD 加法.
ADC 带进位加法.
INC 加 1.
AAA 加法的ASCII码调整.
DAA 加法的十进制调整.
SUB 减法.
SBB 带借位减法.
DEC 减 1.
NEC 求反(以 0 减之).
CMP 比较.(两操作数作减法,仅修改标志位,不回送结果).
AAS 减法的ASCII码调整.
DAS 减法的十进制调整.
MUL 无符号乘法.
IMUL 整数乘法.
以上两条,结果回送AH和AL(字节运算),或DX和AX(字运算),
AAM 乘法的ASCII码调整.
DIV 无符号除法.
IDIV 整数除法.
以上两条,结果回送:
商回送AL,余数回送AH, (字节运算);
或 商回送AX,余数回送DX, (字运算).
AAD 除法的ASCII码调整.
CBW 字节转换为字. (把AL中字节的符号扩展到AH中去)
CWD 字转换为双字. (把AX中的字的符号扩展到DX中去)
CWDE 字转换为双字. (把AX中的字符号扩展到EAX中去)
CDQ 双字扩展. (把EAX中的字的符号扩展到EDX中去)

三、逻辑运算指令
───────────────────────────────────────
  AND 与运算.
OR 或运算.
XOR 异或运算.
NOT 取反.
TEST 测试.(两操作数作与运算,仅修改标志位,不回送结果).
SHL 逻辑左移.
SAL 算术左移.(=SHL)
SHR 逻辑右移.
SAR 算术右移.(=SHR)
ROL 循环左移.
ROR 循环右移.
RCL 通过进位的循环左移.
RCR 通过进位的循环右移.
以上八种移位指令,其移位次数可达255次.
移位一次时, 可直接用操作码. 如 SHL AX,1.
移位>1次时, 则由寄存器CL给出移位次数.
如 MOV CL,04
SHL AX,CL

四、串指令
───────────────────────────────────────
 DS:SI 源串段寄存器 :源串变址.
ES汇编与机器码 - 梦想之鹰 - 梦想之鹰的天空I 目标串段寄存器:目标串变址.
CX 重复次数计数器.
AL/AX 扫描值.
D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量.
Z标志 用来控制扫描或比较操作的结束.
MOVS 串传送.
( MOVSB 传送字符. MOVSW 传送字. MOVSD 传送双字. )
CMPS 串比较.
( CMPSB 比较字符. CMPSW 比较字. )
SCAS 串扫描.
把AL或AX的内容与目标串作比较,比较结果反映在标志位.
LODS 装入串.
把源串中的元素(字或字节)逐一装入AL或AX中.
( LODSB 传送字符. LODSW 传送字. LODSD 传送双字. )
STOS 保存串.
是LODS的逆过程.
REP 当CX/ECX<>0时重复.
REPE/REPZ 当ZF=1或比较结果相等,且CX/ECX<>0时重复.
REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复.
REPC 当CF=1且CX/ECX<>0时重复.
REPNC 当CF=0且CX/ECX<>0时重复.

五、程序转移指令
───────────────────────────────────────
 1>无条件转移指令 (长转移)
JMP 无条件转移指令
CALL 过程调用
RET/RETF过程返回.
2>条件转移指令 (短转移,-128到+127的距离内)
( 当且仅当(SF XOR OF)=1时,OP1 JA/JNBE 不小于或不等于时转移.
JAE/JNB 大于或等于转移.
JB/JNAE 小于转移.
JBE/JNA 小于或等于转移.
以上四条,测试无符号整数运算的结果(标志C和Z).
JG/JNLE 大于转移.
JGE/JNL 大于或等于转移.
JL/JNGE 小于转移.
JLE/JNG 小于或等于转移.
以上四条,测试带符号整数运算的结果(标志S,O和Z).
JE/JZ 等于转移.
JNE/JNZ 不等于时转移.
JC 有进位时转移.
JNC 无进位时转移.
JNO 不溢出时转移.
JNP/JPO 奇偶性为奇数时转移.
JNS 符号位为 "0" 时转移.
JO 溢出转移.
JP/JPE 奇偶性为偶数时转移.
JS 符号位为 "1" 时转移.
3>循环控制指令(短转移)
LOOP CX不为零时循环.
LOOPE/LOOPZ CX不为零且标志Z=1时循环.
LOOPNE/LOOPNZ CX不为零且标志Z=0时循环.
JCXZ CX为零时转移.
JECXZ ECX为零时转移.
4>中断指令
INT 中断指令
INTO 溢出中断
IRET 中断返回
5>处理器控制指令
HLT 处理器暂停, 直到出现中断或复位信号才继续.
WAIT 当芯片引线TEST为高电平时使CPU进入等待状态.
ESC 转换到外处理器.
LOCK 封锁总线.
NOP 空操作.
STC 置进位标志位.
CLC 清进位标志位.
CMC 进位标志取反.
STD 置方向标志位.
CLD 清方向标志位.
STI 置中断允许位.
CLI 清中断允许位.

六、伪指令
───────────────────────────────────────
  DW 定义字(2字节).
PROC 定义过程.
ENDP 过程结束.
SEGMENT 定义段.
ASSUME 建立段寄存器寻址.
ENDS 段结束.
END 程序结束.

8088 汇编跳转一、状态寄存器

PSW(Program Flag)程序状态字寄存器,是一个16位寄存器,由条件码标志(flag)和控制标志构成,如下所示:

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
        OF DF IF TF SF ZF   AF   PF   CF


条件码:
①OF(Overflow Flag)溢出标志。溢出时为1,否则置0。
②SF(Sign Flag)符号标志。结果为负时置1,否则置0.
③ZF(Zero Flag)零标志,运算结果为0时ZF位置1,否则置0.
④CF(Carry Flag)进位标志,进位时置1,否则置0.
⑤AF(Auxiliary carry Flag)辅助进位标志,记录运算时第3位(半个字节)产生的进位置。有进位时1,否则置0.
⑥PF(Parity Flag)奇偶标志。结果操作数中1的个数为偶数时置1,否则置0.

控制标志位:
⑦DF(Direction Flag)方向标志,在串处理指令中控制信息的方向。
⑧IF(Interrupt Flag)中断标志。
⑨TF(Trap Flag)陷井标志。

二、 直接标志转移(8位寻址)

指令格式 机器码 测试条件 如...则转移  
  指令格式 机器码 测试条件 如...则转移
JC 72 C=1 有进位 JNS 79 S=0 正号
JNC 73 C=0 无进位 JO 70 O=1 有溢出
JZ/JE 74 Z=1 零/等于 JNO 71 O=0 无溢出
JNZ/JNE 75 Z=0 不为零/不等于 JP/JPE 7A P=1 奇偶位为偶
JS 78 S=1 负号 JNP/IPO 7B P=0 奇偶位为奇

三、间接标志转移(8位寻址)

指令格式 机器码 测试格式 如...则转移
JA/JNBE(比较无符号数) 77 C或Z=0 >  高于/不低于或等于
JAE/JNB(比较无符号数) 73 C=0 >=  高于或等于/不低于
JB/JNAE(比较无符号数) 72 C=1 <  低于/不高于或等于
JBE/JNA(比较无符号数) 76 C或Z=1 <=  低于或等于/不高于
JG/JNLE(比较带符号数) 7F (S异或O)或Z=0 >  大于/不小于或等于
JGE/JNL(比较带符号数) 7D S异或O=0 >=  大于或等于/不小于
JL/JNGE(比较带符号数) 7C S异或O=1 <  小于/不大于或等于
JLE/JNG(比较带符号数) 7E (S异或O)或Z=1 <=  小于或等于/不大于

四、无条件转移指令(fisheep译 http://huangdekai1.blog.163.com/blog/static/305714162013810114532233/mailto:fisheep@sohu.com)

操作码 伪码指令 含义
EB  cb JMP rel8 相对短跳转(8位),使rel8处的代码位下一条指令
E9  cw JMP rel16 相对跳转(16位),使rel16处的代码位下一条指令
FF  /4 JMP r/m16 绝对跳转(16位),下一指令地址在r/m16中给出
FF  /4 JMP r/m32 绝对跳转(32位),下一指令地址在r/m32中给出
EA  cb JMP ptr16:16 远距离绝对跳转, 下一指令地址在操作数中
EA  cb JMP ptr16:32 远距离绝对跳转, 下一指令地址在操作数中
FF  /5 JMP m16:16 远距离绝对跳转, 下一指令地址在内存m16:16中
FF  /5 JMP m16:32 远距离绝对跳转, 下一指令地址在内存m16:32中

五、16位/32位寻址方式(fisheep译 http://huangdekai1.blog.163.com/blog/static/305714162013810114532233/mailto:fisheep@sohu.com)


操作码 伪码指令 跳转含义 跳转类型 跳转的条件(标志位)
0F 87  cw/cd JA rel16/32 大于 near (CF=0 and ZF=0)
0F 83  cw/cd JAE rel16/32 大于等于 near (CF=0)
0F 82  cw/cd JB rel16/32 小于 near (CF=1)
0F 86  cw/cd JBE rel16/32 小于等于 near (CF=1 or ZF=1)
0F 82  cw/cd JC rel16/32 进位 near (CF=1)
0F 84  cw/cd JE rel16/32 等于 near (ZF=1)
0F 84  cw/cd JZ rel16/32 为0 near (ZF=1)
0F 8F  cw/cd JG rel16/32 大于 near (ZF=0 and SF=OF)
0F 8D  cw/cd JGE rel16/32 大于等于 near (SF=OF)
0F 8C  cw/cd JL rel16/32 小于 near (SF<>OF)
0F 8E  cw/cd JLE rel16/32 小于等于 near (ZF=1 or SF<>OF)
0F 86  cw/cd JNA rel16/32 不大于 near (CF=1 or ZF=1)
0F 82  cw/cd JNAE rel16/32 不大于等于 near (CF=1)
0F 83  cw/cd JNB rel16/32 不小于 near (CF=0)
0F 87  cw/cd JNBE rel16/32 不小于等于 near (CF=0 and ZF=0)
0F 83  cw/cd JNC rel16/32 不进位 near (CF=0)
0F 85  cw/cd JNE rel16/32 不等于 near (ZF=0)
0F 8E  cw/cd JNG rel16/32 不大于 near (ZF=1 or SF<>OF)
0F 8C  cw/cd JNGE rel16/32 不大于等于 near (SF<>OF)
0F 8D  cw/cd JNL rel16/32 不小于 near (SF=OF)
0F 8F  cw/cd JNLE rel16/32 不小于等于 near (ZF=0 and SF=OF)
0F 81  cw/cd JNO rel16/32 未溢出 near (OF=0)
0F 8B  cw/cd JNP rel16/32 不是偶数 near (PF=0)
0F 89  cw/cd JNS rel16/32 非负数 near (SF=0)
0F 85  cw/cd JNZ rel16/32 非零(不等于) near (ZF=0)
0F 80  cw/cd JO rel16/32 溢出 near (OF=1)
0F 8A  cw/cd JP rel16/32 偶数 near (PF=1)
0F 8A  cw/cd JPE rel16/32 偶数 near (PF=1)
0F 8B  cw/cd JPO rel16/32 奇数 near (PF=0)
0F 88  cw/cd JS rel16/32 负数 near (SF=1)
0F 84  cw/cd JZ rel16/32 为零(等于) near (ZF=1)

注:一些指令操作数的含义说明:
  rel8 表示 8 位相对地址
  rel16 表示 16 位相对地址
  rel16/32 表示 16或32 位相对地址
  r/m16 表示16位寄存器
  r/m32 表示32位寄存器

浮点指令
对下面的指令先做一些说明:
st(i):代表浮点寄存器,所说的出栈、入栈操作都是对st(i)的影响
src,dst,dest,op等都是指指令的操作数,src表示源操作数,dst/dest表示目的操作数
mem8,mem16,mem32,mem64,mem80等表示是内存操作数,后面的数值表示该操作数的内存位数(8位为一字节)
x <- y 表示将y的值放入x,例st(0) <- st(0) - st(1)表示将st(0)-st(1)的值放入浮点寄存器st(0)

1. 数据传递和对常量的操作指令

指令格式
指令含义
执行的操作

FLD src
装入实数到st(0)
st(0) <- src (mem32/mem64/mem80)

FILD src
装入整数到st(0)
st(0) <- src (mem16/mem32/mem64)

FBLD src
装入BCD数到st(0)
st(0) <- src (mem80)



FLDZ
将0.0装入st(0)
st(0) <- 0.0

FLD1
将1.0装入st(0)
st(0) <- 1.0

FLDPI
将pi装入st(0)
st(0) <- ?(ie, pi)

FLDL2T
将log2(10)装入st(0)
st(0) <- log2(10)

FLDL2E
将log2(e)装入st(0)
st(0) <- log2(e)

FLDLG2
将log10(2)装入st(0)
st(0) <- log10(2)

FLDLN2
将loge(2)装入st(0)
st(0) <- loge(2)



FST dest
保存实数st(0)到dest
dest <- st(0) (mem32/mem64)

FSTP dest

dest <- st(0) (mem32/mem64/mem80);然后再执行一次出栈操作

FIST dest
将st(0)以整数保存到dest
dest <- st(0) (mem32/mem64)

FISTP dest

dest <- st(0) (mem16/mem32/mem64);然后再执行一次出栈操作

FBST dest
将st(0)以BCD保存到dest
dest <- st(0) (mem80)

FBSTP dest

dest<- st(0) (mem80);然后再执行一次出栈操作


2.比较指令

指令格式
指令含义
执行的操作

FCOM
实数比较
将标志位设置为 st(0) - st(1) 的结果标志位

FCOM op
实数比较
将标志位设置为 st(0) - op (mem32/mem64)的结果标志位



FICOM op
和整数比较
将Flags值设置为st(0)-op 的结果op (mem16/mem32)

FICOMP op
和整数比较
将st(0)和op比较 op(mem16/mem32)后;再执行一次出栈操作



FTST
零检测
将st(0)和0.0比较

FUCOM st(i)

比较st(0) 和st(i) [486]

FUCOMP st(i)

比较st(0) 和st(i),并且执行一次出栈操作

FUCOMPP st(i)

比较st(0) 和st(i),并且执行两次出栈操作

FXAM

Examine: Eyeball st(0) (set condition codes)


3.运算指令

指令格式
指令含义
执行的操作

加法

FADD
加实数
st(0) <-st(0) + st(1)

FADD src

st(0) <-st(0) + src (mem32/mem64)

FADD st(i),st

st(i) <- st(i) + st(0)

FADDP st(i),st

st(i) <- st(i) + st(0);然后执行一次出栈操作

FIADD src
加上一个整数
st(0) <-st(0) + src (mem16/mem32)

减法

FSUB
减去一个实数
st(0) <- st(0) - st(1)

FSUB src

st(0) <-st(0) - src (reg/mem)

FSUB st(i),st

st(i) <-st(i) - st(0)

FSUBP st(i),st

st(i) <-st(i) - st(0),然后执行一次出栈操作

FSUBR st(i),st
用一个实数来减
st(0) <- st(i) - st(0)

FSUBRP st(i),st

st(0) <- st(i) - st(0),然后执行一次出栈操作

FISUB src
减去一个整数
st(0) <- st(0) - src (mem16/mem32)

FISUBR src
用一个整数来减
st(0) <- src - st(0) (mem16/mem32)

乘法

FMUL
乘上一个实数
st(0) <- st(0) * st(1)

FMUL st(i)

st(0) <- st(0) * st(i)

FMUL st(i),st

st(i) <- st(0) * st(i)

FMULP st(i),st

st(i) <- st(0) * st(i),然后执行一次出栈操作

FIMUL src
乘上一个整数
st(0) <- st(0) * src (mem16/mem32)

除法

FDIV
除以一个实数
st(0) <-st(0) /st(1)

FDIV st(i)

st(0) <- st(0) /t(i)

FDIV st(i),st

st(i) <-st(0) /st(i)

FDIVP st(i),st

st(i) <-st(0) /st(i),然后执行一次出栈操作

FIDIV src
除以一个整数
st(0) <- st(0) /src (mem16/mem32)

FDIVR st(i),st
用实数除
st(0) <- st(i) /st(0)

FDIVRP st(i),st

FDIVRP st(i),st

FIDIVR src
用整数除
st(0) <- src /st(0) (mem16/mem32)



FSQRT
平方根
st(0) <- sqrt st(0)



FSCALE
2的st(0)次方
st(0) <- 2 ^ st(0)

FXTRACT
Extract exponent:
st(0) <-exponent of st(0); and gets pushed

st(0) <-significand of st(0)



FPREM
取余数
st(0) <-st(0) MOD st(1)

FPREM1
取余数(IEEE),同FPREM,但是使用IEEE标准[486]





FRNDINT
取整(四舍五入)
st(0) <- INT( st(0) ); depends on RC flag



FABS
求绝对值
st(0) <- ABS( st(0) ); removes sign

FCHS
改变符号位(求负数)
st(0) <-st(0)



F2XM1
计算(2 ^ x)-1
st(0) <- (2 ^ st(0)) - 1

FYL2X
计算Y * log2(X)
st(0)为Y;st(1)为X;将st(0)和st(1)变为st(0) * log2( st(1) )的值



FCOS
余弦函数Cos
st(0) <- COS( st(0) )

FPTAN
正切函数tan
st(0) <- TAN( st(0) )

FPATAN
反正切函数arctan
st(0) <- ATAN( st(0) )

FSIN
正弦函数sin
st(0) <- SIN( st(0) )

FSINCOS
sincos函数
st(0) <-SIN( st(0) ),并且压入st(1)

st(0) <- COS( st(0) )





FYL2XP1
计算Y * log2(X+1)
st(0)为Y; st(1)为X; 将st(0)和st(1)变为st(0) * log2( st(1)+1 )的值

处理器控制指令

FINIT
初始化FPU


FSTSW AX
保存状态字的值到AX
AX<- MSW

FSTSW dest
保存状态字的值到dest
dest<-MSW (mem16)





FLDCW src
从src装入FPU的控制字
FPU CW <-src (mem16)

FSTCW dest
将FPU的控制字保存到dest
dest<- FPU CW





FCLEX
清除异常






FSTENV dest
保存环境到内存地址dest处 保存状态字、控制字、标志字和异常指针的值

FLDENV src
从内存地址src处装入保存的环境


FSAVE dest
保存FPU的状态到dest处 94字节


FRSTOR src
从src处装入由FSAVE保存的FPU状态






FINCSTP
增加FPU的栈指针值
st(6) <-st(5); st(5) <-st(4),...,st(0) <-?

FDECSTP
减少FPU的栈指针值
st(0) <-st(1); st(1) <-st(2),...,st(7) <-?





FFREE st(i)
标志寄存器st(i)未被使用






FNOP
空操作,等同CPU的nop
st(0) <-st(0)

WAIT/FWAIT
同步FPU与CPU:停止CPU的运行,直到FPU完成当前操作码



FXCH
交换指令,交换st(0)和st(1)的值
st(0) <-st(1)

st(1) <- st(0)


分析技术
在进行软件的破解、解密以及计算机病毒分析工作中,一个首要的问题是对软件及病毒进行分析。这些软件都是机器代码程序,对于它们分析必须使用静态或动态调试工具,分析跟踪其汇编代码。

一、从软件使用说明和操作中分析软件

  欲破解一软件,首先应该先用用这软件,了解一下功能是否有限制,最好阅读一下软件的说明或手册,特别是自己所关心的关键部分的使用说明,这样也许能够找点线索。

二、静态反汇编

 所谓静态分析即从反汇编出来的程序清单上分析,从提示信息入手进行分析。目前,大多数软件在设计时,都采用了人机对话方式。所谓人机对话,即在软件运行过程中,需要由用户选择的地方,软件即显示相应的提示信息,并等待用户按键选择。而在执行完某一段程序之后,便显示一串提示信息,以反映该段程序运行后的状态,是正常运行,还是出现错误,或者提示用户进行下一步工作的帮助信息。为此,如果我们对静态反汇编出来的程序清单进行阅读,可了解软件的编程思路,以便顺利破解。 常用的静态分析工具是W32DASM、IDA和HIEW等。


三、动态跟踪分析

 虽然从静态上可以了解程序的思路,但是并不可能真正了解地了解软件的细节,如静态分析找不出线索,就要动态分析程序,另外,碰到压缩程序,静态分析也无能为力了,只能动态分析了。所谓动态分析是利用SOFTICE或TRW2000一步一步地单步执行软件。为什么要对软件进行动态分析呢?这主要是因为:

1、许多软件在整体上完成的功能,一般要分解成若干模块来完成,而且后一模块在执行时,往往需要使用其前一模块处理的结果,这一结果我们把它叫中间结果。如果我们只对软件本身进行静态地分析,一般是很难分析出这些中间结果的。而只有通过跟踪执行前一模块,才能看到这些结果。另外,在程序的运行过程中,往往会在某一地方出现许多分支和转移,不同的分支和转移往往需要不同的条件,而这些条件一般是由运行该分支之前的程序来产生的。如果想知道程序运行到该分支的地方时,去底走向哪一分支,不进行动态地跟踪和分析是不得而知的。

2、有许多软件在运行时,其最初执行的一段程序往往需要对该软件的后面各个模块进行一些初始始化工作,而没有依赖系统的重定位。

3、有许多加密程序为了阻止非法跟踪和阅读,对执行代码的大部分内容进行了加密变换,而只有很短的一段程序是明文。加密程序运行时,采用了逐块解密,逐块执行和方法,首先运行最初的一段明文程序,该程序在运行过程中,不仅要完成阻止跟踪的任务,而且还要负责对下一块密码进行解密。显然仅对该软件的密码部分进行反汇编,不对该软件动态跟踪分析,是根本不可能进行解密的。

由于上述原因,在对软件静态分析不行的条件下,就要进行动态分析了。哪么如何有效地进行动态跟踪分析呢?一般来说有如下几点:

1、对软件进行粗跟踪
所谓粗跟踪,即在跟踪时要大块大块地跟踪,也就是说每次遇到调用CALL指令、重复操作指令REP.循环操作LOOP指令以及中断调用INT指令等,一般不要跟踪进去,而是根据执行结果分析该段程序的功能。

2、对关键部分进行细跟踪

 对软件进行了一定程度的粗跟踪之后,便可以获取软件中我们所关心的模块或程序段,这样就可以针对性地对该模块进行具体而详细地跟踪分析。一般情况下,对关键代码的跟踪可能要反复进行若干次才能读懂该程序,每次要把比较关键的中间结果或指令地址记录下来,这样会对下一次分析有很大的帮助。软件分析是一种比较复杂和艰苦的工作,上面的几点分析方法,只是提供了一种基本的分析方法。要积累软件分析的经验需要在实践中不断地探索和总结。


hacker 2005-05-05 19:23
动态分析技术
SoftICE与TRW2000安装安装与配制

SOFTICE 有几个平台的版本,DOS,WINDOWS 3.0,Windows 95/98,WINDOWS NT,等。 由于现在最普及的操作系统是 Windows 95/98、Windows NT、Windows Millennium、Windows2000因此就讲讲SOFTICE在这几个平台安装时的一些注意事项。

一、SOFTICE for win9x安装与配制

  1、显卡安装
  2、鼠标安装
  3、Autoexec.bat和config.sys配制
  4、Symbol Loader
  5、winice.dat配制
二、SOFTICE for Windows Millennium
三、SOFTICE for NT/2K安装与配制
四、TRW2000安装


 SOFTICE的安装与配制

一、SOFTICE for win9x安装与配制

㈠、SOFTICE安装 

1、SOFTICE目前最新版本是4.05,如你的系统是win9x,就请下载for win9x版本的SOFTICE,建议下载SOFTICE的最新版本,这样稳定性好些。运行setup.exe开始安装,出现

通过配制启动菜单,启动时根据自己的需要选择是否装载SOFTICE。

AUTOEXEC.BAT配制样例:

@ECHO OFF


goto %config%

:SICE
C:\PROGRA~1\NUMEGA\SOFTIC~1\WINICE.EXE
goto common

:NORM
goto common

:common


CONFIG.SYS配制样例:

[MENU]
MENUITEM NORM,Windows 9x
MENUITEM SICE,Windows 9x with SoftICE
MENUDEFAULT NORM,2

[NORM]

[SICE]

[common]




在开始SOFTICE的菜单里有一项ymbol Loader快捷方式,运行后,在其菜单EDIT→SOFTICE Initialization Settings选项,打开后如图(图八)。这里你就可配制SOFTICE了。

①General选项

在Initialization string里,你可填上需要SOFTICE一启动自动运行的命令。如:

WD 2; WC 14; FAULTS OFF; IXHERE OFF; IYHERE OFF; set font 2;lines 40;x;(各行以分号分开)

②Exports选项

在这里可添加相关的DLL文件,以便在SOFTICE下拦截这些DLL的函数。特别是破解VB程序时,定要将VB运行库装载进去。

③Keyboard Mappings选项

这里配制各功能热键。如:F5="^x;"用F5键代替命令X.

④Macro Definitions选项

宏定义,你可定制各种命令宏,以方便平时的操作。
如:s7878="S 30:0 L ffffffff '78787878' " 用命令s7878代替一串命令:S 30:0 L ffffffff '78787878'

⑤Remote Debugging

利用网络远程调试配制。

注:以上所有配制好后的参数,都保存在winice.dat文件里。

2、winice.dat配制

在Windows 9x下 SoftICE配制除了用上面的方法外,也可通过文件winice.dat来实现的。Soft-ICE 在启动的时候通过它装入一些 DLL/EXE 的信息。
你可在SOFTICE安装目录下发现winice.dat,可用任何文本编辑软件打开它(如记事本)。如我机子里的winice.dat:(你可参考我的来修改你的winice.dat)


--------------------------------------------------------------------------------
; 注意分号后是描述语言,不被执行。PENTIUM=ON;<=Pentium Op-CodesNMI=ONECHOKEYS=OFFNOLEDS=OFFNOPAGE=OFFSIWVIDRANGE=ONTHREADP=ONLOWERCASE=OFFWDMEXPORTS=OFFMONITOR=0
PHYSMB=128;<=这个值是你的物理内存大小
SYM=1024
HST=256;<=历史缓冲区为256K
TRA=8
MACROS=32;<=宏操作的最大个数,此处是32个
DRAWSIZE=2048;<= 我的显卡内存是2MB ,此处值是你显卡内存大小

INIT=" wd 2;wc 20;FAULTS OFF; IXHERE OFF; IYHERE OFF; set font 2;lines 40;code on;x;";<=初始化,此处默认的是800*600分分辨率
;如你是全屏请换上:lines 57

F1="h;"
F2="^wr;"
F3="^src;"
F4="^rs;"
F5="^x;"
F6="^ec;"
F7="^here;"
F8="^t;"
F9="^bpx;"
F10="^p;"
F11="^G @SS:ESP;"
F12="^p ret;"
SF3="^format;"
CF8="^XT;"
CF9="TRACE OFF;"
CF10="^XP;"
CF11="SHOW B;"
CF12="TRACE B;"
AF1="^wr;"
AF2="^wd;"
AF3="^S 0 L FFFFFFFF 8B,CA,F3,A6,74,01,9F,92,8D,5E,08;";<=VB3特征字符串
AF4="^s 0 l ffffffff 56,57,8B,7C,24,10,8B,74,24,0C,8B,4C,24,14,33,C0,F3,66,A7;" ;<=VB4特征字符串
AF5="^s 0 l ffffffff FF,75,E0,E8,85,EF,FF,FF,DC,1D,28,10,40,00,DF,E0,9E,75,03;" ;<=VB5特征字符串
                           
AF8="^XT R;"
AF11="^dd dataaddr->0;"
AF12="^dd dataaddr->4;"
CF1="altscr off; lines 60; wc 32; wd 8;"
CF2="^wr;^wd;^wc;"

;<=以下是宏操作命令:
MACRO s7878="S 30:0 L ffffffff '78787878' "
MACRO sname="S 0 L FFFFFFFF 'toye' "
MACRO swide="s 0 l FFFFFFFF '7','8,'7','8,'7','8,'7','8,'7','8,'7','8,'7','8','7','8' "
MACRO reg="bpx regqueryvalueexa if *(esp->8)>='Soft' do "d(esp->14)" "
MACRO bpxpe="bpx loadlibrarya do "dd esp->4" "
MACRO bpxgeta="bpx GetDlgItemTextA; bpx getwindowtexta; bpx getdlgitemint; bpx getdlgitemtext;"


; ***** Examples of sym files that can be included if you have the SDK *****
; Change the path to the appropriate drive and directory
;LOAD=c:\windows\system\user.exe
;LOAD=c:\windows\system\gdi.exe
;LOAD=c:\windows\system\krnl386.exe
;LOAD=c:\windows\system\mmsystem.dll
;LOAD=c:\windows\system\win386.exe

; Exports - change the path to the appropriate drive and directory

EXP=c:\windows\system\advapi32.dll ;<=这四行前不要加分号,否则不被装载,SOFTICE可能什么也拦不到 :
EXP=c:\windows\system\kernel32.dll
EXP=c:\windows\system\user32.dll
exp=c:\windows\system\gdi32.dll
exp=c:\windows\system\comctl32.dll ;


; 如你要破解VB程序,下面的VB运行库将要装载,SOFTICE默认值是没有这几行,你需手动加上。

;EXP=c:\windows\system\msvbvm60.dll;<= Visual Basic 6 具体参考第十五课VB破解
EXP=c:\windows\system\msvbvm50.dll ;<= Visual Basic 5 注意在这五个DLL中最好不要同时装载2个以上
; EXP=c:\windows\system\vb40032.dll;<= Visual Basic 4(32bit)
; EXP=c:\windows\system\vb40016.dll;<=Visual Basic 4(16-bit)较少见
; EXP=c:\windows\system\vbrun300.dll;<=Visual Basic 3


;EXP=c:\windows\system\vga.drv;
;EXP=c:\windows\system\vga.3gr
;EXP=c:\windows\system\sound.drv
;EXP=c:\windows\system\mouse.drv
;EXP=c:\windows\system\netware.drv
;EXP=c:\windows\system\system.drv
;EXP=c:\windows\system\keyboard.drv
;EXP=c:\windows\system\toolhelp.dll
;EXP=c:\windows\system\shell.dll
;EXP=c:\windows\system\commdlg.dll
;EXP=c:\windows\system\olesvr.dll
;EXP=c:\windows\system\olecli.dll
;EXP=c:\windows\system\mmsystem.dll
;EXP=c:\windows\system\winoldap.mod
;EXP=c:\windows\progman.exe
;EXP=c:\windows\drwatson.exe
; ***** Examples of export symbols that can be included for Windows 95 *****
; Change the path to the appropriate drive and directory
EXP=c:\windows\system\kernel32.dll
EXP=c:\windows\system\user32.dll
EXP=c:\windows\system\gdi32.dll
EXP=c:\windows\system\comdlg32.dll
EXP=c:\windows\system\shell32.dll
EXP=c:\windows\system\advapi32.dll
EXP=c:\windows\system\shell232.dll
EXP=c:\windows\system\comctl32.dll
;EXP=c:\windows\system\crtdll.dll
;EXP=c:\windows\system\version.dll
EXP=c:\windows\system\netlib32.dll
;EXP=c:\windows\system\msshrui.dll
EXP=c:\windows\system\msnet32.dll
EXP=c:\windows\system\mspwl32.dll
;EXP=c:\windows\system\mpr.dll



 启动windows装载SOFTICE后,咦!怎么没反应,没调试画面!哈哈,别着急,按CTRL+D看看,再按一下回到windows下,或按F5也能回来。此时调试窗口象windows开的一窗口,如是象全屏DOS一样窗口,那就是安装显卡时,参数没选好,此时按上文修正即可。下面的命令是调整 SOFTICE窗口状态:

  set font n(n=1,2,3)设置字体;本人建议set font 2(在800*600条件下)
  set origin x,y(x,y)锁定窗口;
  lines n n=(25-128)设置显示行数;本人建议lines 40
  Ctrl+Alt+光标键 移动窗口;
  Ctrl+Alt+home 重设窗口位置原点(0,0);
  Ctrl+L 刷新。

如你以默认winice.dat启动SOFTICE,有可能需用WD打开数据窗口;用SET FONT 2 设置字体等重复工作。你可在winice.dat文件内设置自动执行命令操作,方法是在INIT这一行,各命令用分号分开,如:

INIT=" WD 2; WC 14; FAULTS OFF; IXHERE OFF; IYHERE OFF; set font 2;lines 40;x;"这样配制后界面类似TRW2000。(这些是在800*600条件下的情况,如你不是此分辩率可调整set font n;lines n)

二、SOFTICE for Windows Millennium

 由于Windows Millennium没有了DOS平台,因此不能用常用的方法来安装SOFTICE,在此平台上可以运行SOFTICE for WIN9x版本和TRW2000版本。要实现SOFTICE在Windows Millennium平台的安装,需要工具Winice Loader,安装过程如下:

1 正常安装Windows Millennium,如在C:\WIN98ME;
2 正常安装Softice 405 Build 334;
3 复制WINICE.EXE、WINICE.DAT、SIWVID.386 三个文件到 C:\WIN98ME下;
4 从Winice Loader内解压 LOADER.EXE,复制这个文件到C:\WINME98\SYSTEM\VMM32\ 下.
5 重新启动系统。

三、SOFTICE for NT/2K安装与配制

1、SOFTICE for NT/2k的安装与for 9x版本差不多,所不同的是在第五步:装载SOFTICE方式选择

你可根据需要选择不同的装载方式,注:如你选择了Manual方式,要装载SOFTICE,需要来SOFTICE的菜单里运行选项:START SOFTICE快捷方式来装载SOFTICE。

2、在NT下,配制SOFTICE是用SOFTICE Loader(从你的开始菜单选),选择Edit/SoftICE,一般的选项是初始化,这里你可参考手册了解不同的开关选项的详细描述。如:

CODE ON; FAULTS OFF; I3HERE OFF; WD 3; WF; X;

其它两个重要的选项是Symbols & Exports。如果你拥有自己系统的SDK(软件开发工具包),你可用SOFTICE装载并调试它。那些没有SDK应该用exports选项从%WINNT%/System32 目录下增加下面的DLL文件。

advapi32.dll, comctl32.dll, comdlg32.dll, gdi32.dll, kernel32.dll, msvbvm(50/60).dll (如果需要), msvcrt.dll (如果需要), ole32.dll, oleaut32.dll, shell32.dll, user32.dll, version.dll.



四、TRW2000的安装与配制

㈠、TRW2000安装


TRW安装简单多了,没SOFTICE那样复杂,但目前TRW2000不支持windows NT。它发布版本是一个ZIP压缩包,才200多K。只要将其解压缩到一个目录下,然后运TRW2000.EXE即可 , 无须安装或者重启计算机。


激活方式同SOFTICE不一样:

1. Ctrl + M 特权级0级的热键,能够立即中断Win9x。 相当于 Soft-ICE 的热键 Ctrl+D.

2. Ctrl + N 特权级3级的热键。 在绝大多数时候,我们并不需要在0级上中断。 Ctrl + N可以中断Windows的特权级3级的前台线程。 这应该是我们最常用的。

其它指令同SOFTICE兼容,也就说你在上一节学得东西完全可用在TRW2000上。

但是TRW2000有许多更新的思想,具体看后面几课介绍及范例。

另外,TRW2000可支持plug-ins,也可装载dll文件,在1.15版本以上,在安装目录下有一DLL目录,如你特别需要的dll复制到此目录,即可装载,如破解VB时,就需要将VB dll复制此目录,具体参考后面的VB破解。

其它的请读其Readme.

㈡、TRW2000的配制

TRW2000的配制是通过其安装目录下的

TRW2000.ini 来实现的,你可按自己的需要配制它(一般按默认即可)。

; TRW2000 Initialize file

; Please modify it as your habit .

;rem PLUGS=C:\PLUGS\HELLO.SYS
;No, you don't put this line. Now we have changed plug-ins load-method.
;Please copy your SYS to \SYS, TRW2000 will load it
;automatic.

; Now, we don't support keyword LINES=, please use command LINES instead.
INIT="lines 35;wr 3;wd 4;wc 16"

F1=^HELP ; Command length CAN'T be longer than 15 characters !
; This command length is 5 charcaters .
F3=^SRC
F4=^RS
F5=^X
F6=^EC
F7=^HERE
F8=^T
F9=^BPX
F10=^P
F12=^PRET

;HOTKEY=320D ;Ctrl+M
;R3HOTKEY=310E ;Ctrl+N

GRAPHICS=ON ;Use graphics mode driver

VESA=OFF

VGA=ON

INTELLIMOUSE=ON ;If your mouse is a intellmouse, set this to ON

WINMOUSE=ON ;If you found your mouse is not work properly, try it to ON. But we do NOT recommend this, because it maybe decrease stabilization.

;HST=256 ;History buffer size, default = 256k

SYMBUFFER=1024

CAPITAL=ON

WONDER=ON

TESTMODE=OFF



㈡、SOFTICE配制


hacker 2005-05-05 19:24
SoftICE与TRW2000操作入门

  由于TRW2000命令和操作完全兼容SoftICE,因此如不特殊说明,在本文对SoftICE的叙说都适合TRW2000。
  SoftICE的所有操作都发生在一个可以随时可激活的调试窗口中,在这个窗口中可以监视Windows应用程序和系统的运行。
一、 调试窗口简介
  我们假设你的SoftICE己经正常运行,此时在Windows里按"Ctrl+D"键就可以呼出SoftICE的调试窗口,当需要返回到Windows系统时,再按"Ctrl+D"键,也可使用X命令或按F5键。激活的调试窗口如图2.14所示,分为寄存器窗口、数据窗口、代码窗口、浮点窗口和命令窗口等部分。
如是在TRW2000环境下,激活是按"CTRL+N",和SoftICE不同的是TRW2000中没有浮点窗口,不过有一个堆栈窗口。
1、寄存器窗口
  在这里可以观察到各种寄存器的当前值,如数据寄存器EAX、EBX、ECX、EDX和控制寄存器(EIP和PSW)等,有一点要注意了,由于我们是在 Windows平台下,所以看到的都是80386寄存器集,其与16位寄存器差别在前多了一字符"E",意为16位寄存器扩展。
2、数据窗口
  在数据窗口显示指定内存处中的数据,以十六进制和ASCII同时显示,这可以说是我们的眼睛,因此有必要了解一下各部分的含义。



(图二)

①号位置的0030:这是段选择器。
  在Windows的保护模式下CS、DS、ES、SS、FS和GS不叫段寄存器,叫段选择器。在保护模式中,内存分为了好多的段,在TRW200下用GDT就可以看到段的编号、类型、开始物理地址、大小、属性。让我们看看编号0030是什么东西:



(图三)

  这个段是32位数据类型,长度为4G ,我们还可以看到很多的段,它们有可能会指向同一个物理地址,但它们的类型,属性可能不同。如一些段指向的地址是不可读写的,但另外一个段指向的同一物理地址是可读写的!如果我们通过不可写的那段的编号放到段选择器,然后进行读写操作,肯定死掉了。 但换了另外一个段对同一个地方读写那就没问题!保护模式的内存管理挺有趣的,感兴趣的不妨看看这方面的书,当然作为初学者只需稍微了解就可。
②号位置00000000:此处表示内存的虚拟地址。
③号位置的值是当前内存的数据,以十六进制表示。
④号位置的值是"③"处值的另一种表示方法:ASCII码。
3、代码窗口
  此处显示的是当前程序的代码,因为不管是什么程序,最终在CPU执行时都是以机器语言方式,而汇编语言和机器语言是一一对应的,因此SoftICE为了方便我们理解,把所监视的代码以汇编代码形式显示在我们面前。例如:



(图四)


①段选择器;
②虚拟地址;
机器码:这就是CPU执行的机器代码,此处是以十六进制表示。你可用Code on/off打开或关闭这项的显示。
汇编指令:和机器码对应的程序代码。
4、堆栈窗口
  这个是TRW2000特有的,通过它很方便监视堆栈的状况。
5、命令窗口
  这是各种命令执行的地方,在屏幕底部的动作状态行显示执行命令的各种提示,以及可提供指令语法帮助。
6、程序领空
  所谓领空,实际上是指:在某一时刻,CPU 的 CS:IP(EIP) 所指向的某一段代码的所有者所在的区域。此例中SoftICE所停下来时光标所指的那一句代码是属于KERNEL32.DLL的,因此就叫 KERNEL32.DLL领空,在图2.14中,可看到的领空名是KERNEL32!.text,那我怎么知道它就是KERNEL32.DLL文件呢?这个主要是经验,KERNEL32.DLL是Windows系统文件,在SoftICE里显示领空名时不显示扩展名,只是显示前一部份。

二、SoftICE常用命令简介

由于SoftICE命令操作较多,在此就把几个常用的命令介绍一下,其它详细说明请参考附录的"SoftICE手册"。
1、 G命令
语法:G [=start-address] [break-address]
作用:执行程序,后面如果加地址,则执行到该地址为止。
注意: TRW2000 中G命令与SoftICE稍有不同,SoftICE中G命令必须是在当前段中,这时IP(EIP)为指定值才中断;而TRW2000则不管段址如何,只要IP(EIP)是指定的值便停下,TRW2000这个特性大大方便我们的操作。
2、P命令
语法: P [ret]
作用:单步执行程序。
只执行P时,相当于按下F10键。在汇编模式中,当遇到 CALL、INT、LOOP、REP指令时,P将不跟踪进去,直到这些指令执行完毕,控制才返回SoftICE,换句话说,P命令是"跨"过这些指令的。
P RET 命令相当于快捷键 F12。SoftICE将一直单步执行直到它找到一条返回语句(RET、RETF),也就是说让SoftICE一直执行代码,直到出现 RET (XXXX) 命令,再跳出来拦截,这时,当前 IP(EIP) 会是停在 RET (XXXX) 后的某一条语句上,通常是在某一个CALL XXXXXXXX 后面。由于我们通常用SoftICE在某些底层的Windows函数上设置断点,所以 F12 是很管用的。因为程序的作者用的是高级语言,Windows又是提倡"透明",不希望程序员知道底层的操作,而只提供给他们高层的接口,而相当多的高级函数调用某个一定的底层函数,所以当你在底层函数上下断点,再用F12,就可以知道他用的是什么函数了。
3、T命令
语法:T [=start-address] [count]
start-address:执行起始地址;
count:指定SoftICE将单步跟踪多少次才停止。
作用:单步跟踪。
T命令相当于功能键F8,如没指定起始地址,将从CS:IP(EIP)指向的指令开始执行,此时当遇到 CALL、LOOP等指令时,T将跟踪进去。
注意: F8和F10功能键的主要差别就在这,遇到 CALL、LOOP等指令时,F10是路过,而F8是跟进去。
4、BPX命令
语法:BPX [address] [IF expression] [DO "command1;command2;..."]
address :断点所在的线性地址;
IF expression:条件表达式,只有条件为"真"时,SoftICE才在断点处弹出;
Do command:当SoftICE弹出时,自动执行的一些命令。
作用:在可执行语句上设置(或清除)断点。
BPX 用来在指令处下断点,程序一旦执行到此,SoftICE就会弹出。当光标在代码窗口中时,直接打入BPX就会在光标所在语句处设断点,再打BPX 就取消。BPX的快捷键是 F9,当光标在代码窗口中时,按F9就是设定(取消)。
BPX 也可用函数名来作地址参数:格式为"BPX 函数名"。
这个函数名可以是任意一个API函数、虚拟机指令、DLL文件的引出函数等等,功能强劲。例:
:bpx messageboxa(不用区分大小写)//只要程序调用了此函数,SoftICE将中断;
:bpx GetWindowTexta if EAX==8 // 当调用GetWindowTexta函数时EAX=8,SoftICE将中断;
:BPX GetWindowTexta do "d EAX"// 当 GetWindowTexta被中断,自动显示EAX的值。
注意: TRW2000与SoftICE条件格式有点不同,如在SoftICE下的是:bpx loadlibrarya do "dd esp->4",而相同的用法在TRW2000中是:bpx loadlibrarya do "dd *(esp+4)" 。另外SoftICE中用鼠标双击指令行可设断,而TRW2000中不行,只能按F9.
5、BPM命令
语法:BPM[size] address [条件表达式] DO[执行的命令]
size:内存单元大小,B为字节(默认);W 为字;D 为双字;
verb:所进行的操作,R为读;W为写;RW为读写(默认);X 为执行。
作用:设置内存访问断点。
注意: BPM用了DR3-DR0寄存器,所以最多只能设四个断点。
6、BMSG命令
语法:BMSG window-handle [条件表达式] DO[执行的命令]
window-handle:消息发向的窗口句柄,即消息名
作用:在Windows的消息上下断点。
Windows本身是由消息驱动的, 所以跟踪一个消息会得到相当底层的答案。如:
我们执行记事本程序(Notepad),然后Ctrl+D激活SoftICE输入:
   :bmsg wm_char
   :g
然后回到Notepad中,随便按一个键,SoftICE就激活了;原因在于我们在按键消息上设置了断点(退出SoftICE别忘下命令"BC *"清除刚才下的断点)。
7、BL命令
语法:BL
作用:显示当前所设的断点
注意: SoftICE会把所有断点按从0开始的编号列出,而TRW2000是从1开始编号列出。
8、BC命令
语法:BC list | *
list:可以清除指定编号的断点,多个时中间用空格或逗号隔开。
* :清除所有的断点。
作用:清除一个或多个断点
9、BD命令
语法: BD list | *
list:可以是单个,也可以是一系列断点,中间用空格或逗号隔开。
* :禁止所有的断点
作用:使一个或多个断点失效。
10、BE命令
语法:BE list | *
作用:使一个或多个断点恢复有效。
用来恢复前次用 BD 命令使之失效的断点。 (每当新定义断点或编辑断点时,系统自动将其置为有效)
11、BPE命令
语法:BPE index_number(断点索引号)
作用:编辑一个已存在的断点。
12、R命令
语法:R 寄存器名
作用:显示或更改寄存器的内容。
其可更改所有的寄存器的值。此命令较常用的一个功能是更改状态寄存器(PSW )的值,格式:R FL 标志位。比如当前 Z标志位(零位)为置位状态,执行"r fl z"之后会被清除;如果C标志位为清除状态,那么"r fl c"将使之置位。
注意: 利用此命令很方便在一些跳转指令上改变方向。
13、A命令
语法:A [地址]
作用:进入小汇编状态,可直接写入汇编代码。
如不加地址值,直接在当前CS:IP(EIP)处汇编。用SoftICE内置的汇编器在内存中写入汇编代码。汇编器支持标准的80x86指令集,包括386、486、Pentium、Pentium-Pro、MMX协处理器,新版的SoftICE还支持AMD的3D Now!、PII、PIII的特有指令集。
14、D命令
语法:D[size] [address [l length]]
size:B 字节;W 字;D 双字; S 短实型;L 长实型;T 10b长实型
作用:显示某内存区域的内容。
15、S命令
语法:S [-cu][address L length data-list]
address:搜索的起始地址
length :搜索的长度(字节长)
data-lis:可以是一系列字节,也可以是字符串,字符串可以用单引号,也
可以用双引号括住.
-c :使查找区分大小写
-u :查找Unicode 编码的字符串.
作用:在内存中搜寻特定数据,如果找到数据,那将在数据窗口中显示出来,如果在找到后,你还要继续查找,使用不带参数的S命令。由于S命令忽略不在内存中的页面,因此你可以使用32位平面地址数据段描述符30h在整个4GB(0~FFFFFFFFh )空间查找。如:
s 30:0 l FFFFFFFF "78787878" //在此令在内存中查找字串"78787878"位置。
注意: TRW2000中S命令的字串应是单引号(而SoftICE皆可)。如:s 30:0 l FFFFFFFF '78787878'.
16、E命令
语法:E[size] [address [data-list]]
作用: 修改内存单元
17、U命令
语法:U [address [l length]] | [symbol-name]
address :段:偏移量或选择符:偏移量
symbol-name:将从指定的函数开始反汇编
length :反汇编的长度(字节)
作用: 反汇编指令
你可以利用此命令抓取汇编代码,运行LOADER32后,将历史缓冲区(history buffer)调大些(默认为256,不能放足够多的缓冲数据)。然后切换到SoftICE调试画面下,来到你要抓取的地方,反汇编这些代码,如:U CS:EIP L 1000 ,立即按Ctrl+D返回到Windows环境,再次来到symbol loader程序,选择"File/Save SoftICE History As…"。
注意: 在TRW2000下可以直接反汇编代码输出到一个文件:
u 401000,402000 >路径/myfile。
18、FAULTS命令
语法:FAULTS [on | off]
作用:打开或关闭错误跟踪功能
由于SoftICE做为一个DEBUGGER,FAULTS 默认为ON,所以一旦CPU有非法指令,SoftICE就会不停地弹出。
19、?命令
语法:? 表达式
作用:计算一个表达式的值
一个非常高级的计算器,另外由于可以显示ASCII,所以可以很方便地在各种数制之间察看。
20、.命令
语法: .
作用:在代码窗口中定位当前指令
当你在代码窗口中上下浏览时,有可能走得很远,那么这时一个"."命令会让你在下一瞬间回到SoftICE当前所在的CS:EIP处。
21、EXP命令
语法: EXP [函数名]
作用: 显示DLL中的出口函数
函数名可以指定出其前几个字符, 可以用?来做替代不定字符,这样你就可查找相关函数及其是哪个DLL文件了。这对于你在Win2K系统上非常实用,Win2K系统的 KERNEL32.DLL中许多函数形式和Windows 9x可能不同,用此命令你就可找到正确的函数名了。
22、PMODULE命令(TRW2000特有命令)
作用:'pret'(相当于按<F12>) 直至CS:EIP位于模块中,但比F12更实用,其可以快速回到你的当前程序领空,不用按多次F12了
23、SUSPEND命令(TRW2000特有命令)
作用: 暂停当前的线程,并退出 TRW2000,按热键返回,此命令相当方便。
24、ver blue命令(TRW2000特有命令)
如你的TRW2000背景颜色很暗,可通过此命令来调整背景。


hacker 2005-05-05 19:25
常用Win32 API函数简介


  现在很多讲Windows程序设计的书都是讲基于MFC库和OWL库的Windows设计,对Windows实现的细节都鲜有讨论,而调试程序都是和系统底层打交道,所以有必要掌握一些Win32 API函数的知识,这样我们可快捷地找出程序调用错在哪?是哪个参数出了问题。
  Windows 程序模块包括KERNEL、USER和GDI,其中KERNEL完成内存管理、程序的装人与执行和任务调度等功能,它需要调用原MS―DOS中的文件管理、磁盘输入输出和程序执行等功能;USER是一个程序库,它用来对声音、时钟、鼠标器及键盘输入等操作进行管理;GDI是一功能十分丰富的子程序库,它提供了图形与文字输出、图象操作和窗口管理等各种与显示和打印有关的功能。上述KERNEL、USER和GDI模块中的库函数可被应用程序调用,也可被其他程序模块调用。把包含库函数的模块称为输出者(export)。你应明白为什么跟踪软件时经常在KERNEL32!.text和USER32.text 等系统领空转的问题吧。
  这里列出几个经常碰到的Win 32 API函数,它们都是存在Windows系统核心文件KERNEL32.DLL中和视窗管理文件USER32.DLL中。
Windows 函数是区分字符集的:A表示ANSI,W表示Wide,即Unicode (Wide character-set),前者就是通常使用的单字节方式,但这种方式处理象中文这样的双字节字符不方便,容易出现半个汉字的情况。而后者是双字节方式,方便处理双字节字符。Windows的所有与字符有关的函数都提供两种方式的版本。尽管你编程时使用GetWindowText,但实际上编译程序会根据设置自动调用GetWindowTextA或GetWindowTextW。函数的最后一个字母告诉我们函数是使用单字节还是双字节字符串。
1、 Hmemcpy函数
void hmemcpy(hpvDest, hpvSource, cbCopy)
void _huge* hpvDest; // 目的数据地址
const void _huge* hpvSource; // 源数据地址
long cbCopy; // 数据大小 (Bytes)
这个函数在KERNEL32.DLL中,它很常用,俗称万能断点,但一般的编程书籍上很少提到,原因它是底层的东西,没有特殊需要,一般不直接调用。但的确它是很有用的!有意思的是它执行的操作很简单,只是将内存中的一块数据拷贝到另一个地方。
注意:此函数只在Windows 9x系统上有效,在Win NT/2K系统上相关的函数是memcpy,但在Win NT/2K上不同于Windows 9x上,很少再调用memcpy来处理数据了,用此函数设断基本上什么也拦不住。
2、 GetWindowText函数
此函数在USER32.DLL用户模块中,它的作用是复制指定窗口中的字符到缓冲区。函数原型:
int GetWindowText(
HWND hWnd//欲获取文字的那个窗口的句柄
LPTSTR lpString //预定义的一个缓冲区,至少有cch+1个字符大小;随同窗口文字载入
int nMaxCount//lpString缓冲区的长度
);
16位:GetWindowText
32位:GetWindowTextA,GetWindowTextW
3、 GetDlgItemText
此函数在USER32.DLL用户模块中,它的作用是返回对话框中某一个窗口的标题或文字。函数原型:
UINT GetDlgItemText(
HWND hDlg, // 对话框句柄
int nIDDlgItem, //控制标识符
LPTSTR lpString, / 预定义的一个字符缓冲区
int nMaxCount// 字符缓冲区的长度
);
16位:GetDlgItemText
32位:GetDlgItemTextA,GetDlgItemTextW
4、 MessageBox函数
此函数是在USER32.DLL用户模块中,它的作用创建、显示和操作信息框。函数原型:
int MessageBox(
HWND hWnd, //窗口句柄
LPCTSTR lpText, // 信息框中文字的地址
LPCTSTR lpCaption, // 信息框标题地址
UINT uType // 信息框类型
);
16位:MessageBox
32位:MessageBoxA,MessageBoxW

拆解教程

========================================================================
ED!SON's Windows 95 拆解教程 V1.00 (中文翻译: JIM TYAN) ========================================================================
附:ED!SON教程的示范程序下载
目录
======== 1. Windows 拆解简介 2. SoftICE for windows 2.00 快速入门 3. 如何找注册码 3.1 Task Lock
3.00 - 一个简单的、仅有注册号保护的拆解例子 3.2 Command Line 95 - 容易的“用户名/注册号"注册方式的拆解 4. 为Command
Line 95制作注册器 5. 当程序调用一个函数时,PUSH和CALL这些指令是如何工作的 6. 关于VB程序
附录
======== A. 如何让SOFTICE载入符号 B. 函数的语法 C. 到哪里获取软件 D. 如何与我联系
1.
WINDOWS拆解简介 =================================== 拆解一个WINDOWS程序要比拆解一个在DOS下运行的程序要容易得多。因为在WINDOWS
中,只要WINDOWS的函数被使用了,想对任何真正要寻找蛛丝马迹的人隐藏什么东西 是比较困难的。
你需要的第一个(常常也是唯一的一个)工具就是SoftICE/Win
2.oo, 它是NuMega 出品的一个非常强大的调试工具。有些人发现它很难用,但我会教你如何使用它进行 有效的调试,也希望你们能够明白我将要告诉你们的:-)。
你应该看看在附录A 中有 关SoftICE/Win 2.oo的一些资料。我在安装SoftICE中从来没有碰到任何问题, 如果 你碰到了,我只好让你查它的参考手册了。
你所需要的所有软件的URL列在附录C中

2. SOFTICE/WIN
2.OO 快速入门 ========================================= 首先你应该对SOFTICE的屏幕有个大概的了解
|--------------------| | 寄存器窗 | 用 'R' 编辑 |--------------------|
| 数据窗 | 用 'D' 列出某个地址的数据, 用 'E' 编辑 |--------------------| | 代码窗 | 用 'U' 反汇编, 'A'
加入汇编代码 |--------------------| | 命令窗 | 在这里输入命令和读出结果 |--------------------|
其它重要的功能键(在缺省的键定义下) 'H'/F1 - 在线帮助 F5/Ctr+D - 运行 F8 - 单步执行,切入子程序和中断
F10 - 单步执行,跳过子程序和中断 F11 - 跳出子程序,回到CALL的下一条指令
3.
如何寻找注册码 ============================= 最容易的练习莫过于找个共享软件来试试把它注册。
3.1
Task Lock 3.00 - 一个简单的、仅有注册号保护的拆解例子 =================================================================
这是一个简单的保护,只有一个而且不会变化的注册码。
3.1.1 检查程序 ===========================
它是16 bit程序,还是32 bit的? 在哪里输入注册信息? 在它的帮助里有没有 发现关于注册的一些线索?在你继续往下读之前,去把它们找一找!
....你现在应该在找吧!.....你是在找吗?.....你找到了吗?....... 好,你现在知道了,它是一个32位的WINDOWS
95应用程序,你可以在一个选择了 “Register|Register..."菜单就会弹出来的对话框中,输入一个注册码来注册 程序。通过阅读它的帮助,你也知道可以有两种注册方式:Individual和Site
License。所以这里对合法的注册码就可能有两次核对。
3.1.2 捕捉注册代码 ===========================
注册码通常在普通的WINDOWS文字框中输入。为了检查输入的注册码, 程序必须 采用下面这些函数中的一个来把文字框中的内容读出来。
16-bit 32-bit ------ ------ GetWindowText GetWindowTextA,
GetWindowTextW GetDlgItemText GetDlgItemTextA, GetDlgItemTextW
32-BIT函数的最后一个字母告诉我们函数是使用单字节还是双字节字符串。双字
节的注册码是很少见的。
也许你已经体会到我的意思了...“如果我能在GetWindowText时中断...",
你 的确能这样做!但是你首先必须确认这些符号已经由SOFTICE载入了(详见附录A)
在SoftICE中设定一个“陷阱"(实际上我们叫断点),你得先按Ctrl+D进入调
试状态,然后用命令BPX,后面跟著是函数的名字或者内存地址。因为Task Lock 是32位程序,所以我们在GetWindowTextA处设一个断点。 如果这个不行,
我们 可以再试其它的。
象这样在SoftICE中输入:

:bpx getwindowtexta
如果你得到“No LDT"这样的错误信息,就要注意不要运行其它程序。我已经注
意到Norton Commander/Dos 会干扰这个功能。 你可以列出所有断点来检查一下 是否设好断点: :bl
你会看到这样的信息:
00) BPX USER32!GetWindowTextA C=01
你可以再按一次Ctrl+D,从SoftICE中退出,。
好了,不管怎么样,你已经设定好了断点以捕捉任何对GetWinowTextA的调用。 现在我们来在该输入注册码的地方输入一些数字,然后按下OK....你只得到了
一个信息框告诉你输入的注册码是无效的。看来不是GetWindowTextA....我们 来试试GetDlgItemTextA。首先删除旧的断点: :bc 0
(0 表示在断点列表中的第0个断点)
然后设定新的断点: :bpx getdlgitemtexta
再来试一次.....
3.1.3 在调试器中
===================== 哇!行了!你已经在SoftICE中了,就在函数GetDlgItemTextA开始的地方。按 F11键,回到调用函数的地方。现在你到了SGLSET.EXE的内部,如果你还没把握
的话,看看代码窗和数据窗中间的一行,你应该看到这样的东西:
----------SGLSET!.text+1B13----------
你可以这样禁止一个断点:
:bd 0
以后想再开启它的话,可以这样:
:be
0
代码窗的第一行是:

CALL [USER32!GetDlgItemTextA]
按几次Ctrl+Up 直到你看到下面这几行。如果对汇编一点也不懂的话,看我加的
注解吧:
RET ; 函数结束 PUSH EBP ; 函数开始 MOV EBP, ESP
SUB ESP, 0000009C PUSH ESI > LEA EAX, [EBP-34] ; EAX = EBP-34 PUSH EDI MOVE
ESI, ECX PUSH 32 ; 输入字符串的最大长度 > PUSH EAX ; 输入字符串的缓冲地址 PUSH 000003F4 ; 控制标识
PUSH DWORD PTR [ESI+1C] ; 对话框的句柄 CALL [USER32!GetDlgItemTextA] ; 取得输入
PUSH指令保存那些数值以供后面使用。我已经在重要的地方加上了一个 '>'字符 作上记号. 看这几行我们就知道字符缓冲区的地址保存在EAX中,而EAX等于
EBP-34。
所以我们来看看EBP-34那里有什么:

:d ebp-3
你应该能在数据窗中看到你输入的东西。下面我们得来找开始核对输入注册码的
地方。按F10一步一步地单步运行直到你发现与EBP-34有点关系的地方.... 你不 用单步运行多久,就会看到这些代码:

> LEA EAX, [EBP+FFFFFF64] ; EAX = EBP-9C LEA ECX, [EBP-34]
; ECX = EBP-34 PUSH EAX ; 保存 EAX PUSH ECX ; 保存 ECX > CALL 00403DD0 ; Call 一子程序
ADD ESP, 08 ; 删除保存的信息 TEST EAX, EAX ; 检查返回值 JNZ 00402BC0 ; 如果不是零的话跳转
对我来说,马上就可以看出这象是一个字符比较程序。它们工作起来就是这样: * 输入两个字符串 如果相同就返回零 否则返回非零
那为什么程序要用一个字符串来和你输入的相比较呢?看它是不是合法的!(可 能你已经想到了)。那么是什么东西躲在 [EBP+FFFFFF64]
? SoftICE处理负数 还不是很好,所以得算算:
100000000 - FFFFFF64
= 9C
在 SoftICE 用这样的命令:

:? 0-FFFFFF64
100000000 对SoftICE来说太大了,但它还是给出了相同的结果。
现在是...来看看什么东西躲在EBP-9C那里的时候了...这样输入命令:

:d ebp-9c
数据窗口会显示出一大排数字 ─ 注册码!但是记住我前面说过的...两种注册
方式对应两个注册码....所以你把这些注册码抄下来以后,继续用F10单步运行 ....我们会遇到这些代码:
>
LEA EAX, [EBP-68] ; EAX = EBP-68 LEA ECX, [EBP-34] ; ECX = EBP-34 PUSH EAX ; 保存
EAX PUSH ECX ; 保存 ECX > CALL 00403DD0 ; 再次调用子程序 ADD ESP, 08 ; 删除保存的信息 TEST
EAX, EAX ; 检查返回结果 JNZ 00402BFF ; 如果非零跳转
你在EBP-68处找到了什么?不错吧...另一个注册码。
:d ebp-68
我们的练习结束了,希望一切顺利。

3.2 Command Line 95 -容易的用户名/注册码方式的注册、注册器 =================================================================
这是一个非常好的例子,注册码的计算也很简单。
3.1.1 检查程序 ===========================
检查程序以后你知道它是32位的应用程序,要求输入名字和注册码。 让我们开始!
3.1.2
捕捉代码 =========================== 我们象拆解TaskLock那样 ─ 设置断点。我们可以在两个可能性最大的两个函数 都设上断点:GetWindowTextA
和 GetDlgItemTextA. 按下Ctrl+D 进入SoftICE, 然后:

:bpx getwindowtexta :bpx getdlgitemtexta
接下来进入注册对话框,输入一个名字和一些数字(多数情况下是一个整数),
我是这么写的,然后按OK....
Name: ED!SON '96 Code: 12345
程序在 GetDlgItemTextA 处停住了,就象TaskLock一样。我们按F11回到调用它 的地方。用
Ctrl+Up卷动窗口直到看到这些:
MOV ESI, [ESP+0C] PUSH
1E ; 最大长度 PUSH 0040A680 ; 缓冲地址 PUSH 000003ED ; 控制柄 PUSH ESI ; 对话柄 CALL [User32!GetDlgItemTextA]
数字40A680引起了我们的注意,看看那里有什么: :d 40a680
如果没有我们输入的名字,数据窗口里有些什么呢?好了,我们来研究下面的一
段代码:
PUSH 00 PUSH 00 PUSH 000003F6 ; 控制柄 MOV
EDI, 0040A680 ; 保存缓冲区地址 PUSH ESI ; 对话柄 CALL [User32!GetDlgItemInt]
GetDlgItemInt 和 GetDlgItemText差不多,但它从文字框中返回一个整数。 它出在EAX中返回来的,所以单步运行通过这些代码,再来看看寄存器窗....
对我而言是:
EAX=00003039
十六进制数3039是多少?
输入: :? 3039
我们得到:

00003039 0000012345 "09" ^ 16进制 ^ 十进制 ^ ASCII
正如你看到(和已经猜到)的那样,它是你输入的注册码。OK,下面怎么办?让
我们来看下面的代码:
MOV [0040A548], EAX ; 返回注册码 MOV
EDX, EAX ; 同时保存在DX中
3.1.3 计算注册码 ==========================
这样注册码就算出来了
MOV ECX, FFFFFFFF ; 这几行计算字符长度 SUB
EAX, EAX ; . REPNZ SCASB ; . NOT ECX ; . DEC ECX ; ECX <-- 长度 MOVSX EAX, BYTE
PTR [0040A680] ; 读入40A680处的一字节 IMUL ECX, EAX ; ECX = ECX * EAX SHL ECX, 0A ; 左移
0A 次 ADD ECX, 0002F8CC ; 结果加上2F8CC MOV [0040A664], ECX
验证合法性....
CMP ECX, EDX ; 比较 JZ 00402DA6 ; 如果相同就....
当你运行到比较这一步时,就可以得到你真正的注册码:

:? ecx
对我而言它是: 000DC0CC 0000901324
也就是说我的正确的注册码是901324.
按F5或者Ctrl+D让它运行,然后用正确的注册码(十进制)再来一次。这一次
成功了!
4. 为COMMAND LINE 95制作注册器 =========================================
我们把上面计算注册码的代码翻译成C语言程序。 最明了的计算公式就是:
code=((uppercase_first_char
* length_of_string) << 0x0A) + 0x2f8cc;
注(1):
别忘了一件事 就是把所有字符转成大写 (2): "<< 0x0A" 实际上就是 "乘以 2^10"
完整的程序就是:
#include
#include
int main() { unsigned
long code; unsigned char buffer[0x1e];
printf("CommandLine95
Keymaker by ED!SON '96\n"t汇编与机器码 - 梦想之鹰 - 梦想之鹰的天空; printf("Enter name: "t汇编与机器码 - 梦想之鹰 - 梦想之鹰的天空; gets(buffer);
strupr(buffer); code = ( ((unsigned long)buffer[0] * (unsigned
long)strlen(buffer)) << 0x0A) + 0x2f8cc;

printf("Your code is: %lu", code);

return 0; }
爽吧?
4.
当程序调用一个函数时,PUSH和CALL这些指令是如何工作的 ============================================================================
我们重新来看看TaskLock中的这段代码:
PUSH 32 ; 字符串最大长度 PUSH
EAX ; 字符缓冲区地址 PUSH 000003F4 ; 控制标识 PUSH DWORD PTR [ESI+1C] ; 对话框柄 CALL [USER32!GetDlgItemTextA]
; 获得字符串
如果认为是C语言编译出来的话,这个CALL应该是这样:
GetDlgItemTextA(hwndDlg, 0x3F4, buffer, 0x32); ^ [ESI+1C]
^ EAX
PUSH把数据保存在叫做堆栈的地方。每个PUSH把新的数据放在堆栈的顶部,被调
用的子程序就挨个地检查躺在堆栈中的数据,按照定义来使用它们。
附录
A. 让SoftICE载入符号 ============================== 你可以用exp getwindowtext命令来检查SoftICE是否已经为GetWindowText装入
了符号,象这样: :exp getwindowtext
如果你没有得到所有GetWindowText函数的列表,你就得编辑\SIW95\WINICE.DAT,
在"Examples of export symbols that can be included for chicago"这段文字 以后的那些
'exp='的行首去掉';',为了节省内存,选择最重要的几个就可以了:
kernel32.dll
user32.dll gdi32.dll
编辑完后,重新起动计算机使其生效。
B. 函数语法 ============================ 如果你看看下面的函数声明,对我们上面讲到的函数调用就容易明白了:
int GetWindowText(int windowhandle, char *buffer, int maxlen);
int GetDlgItemText(int dialoghandle, int controlid, char *buffer, int maxlen);
int GetDlgItemInt(int dialoghandle, int controlid, int *flag, int type);
这些函数的详细描述,可参考Windows/Win32编程手册


hacker 2005-05-05 19:28
静态分析技术

基础知识

一、虚拟地址和偏移量转换

  由于Windows程序是运行在386保护模式下,在保护模式下,程序访问存储器所使用的逻辑地址称为虚拟地址(Virual Address,VA)。与实地址模式下的分段地址类似,虚拟地址也可写成"段:偏移量"的形式,这里的段是指段选择器。

  文件执行时将被映像到指定内存地址中,这个初始内存地址称为基址(ImageBase)。在Windows NT中,缺省的值是10000h;对于DLLs,缺省值为400000h。在Windows 9x中,10000h不能用来装入32位的执行文件,因为该地址处于所有进程共享的线性地址区域,因此Microsoft将Win32可执行文件的缺省基地址改变为400000h。

  相对虚拟地址(Relative Virual Address,RVA)表示此段代码在内存中相对于基地址的偏移。即:相对虚拟地址(RVA)=虚拟地址(VA)-基址(ImageBase)。

  文件中的地址与内存中表示不同,它是用偏移量(File offset)来表示的。

  在SoftICE和W32Dasm下显示的地址值是内存地址(memory offset),或称之为虚拟地址(Virual Address,VA)。而十六进制工具里,如:Hiew、Hex Workshop等显示的地址就是文件地址,称之为偏移量(File offset) 或物理地址(RAW offset)。

  在实际操作时,使用 RVA-Offset之类的转换器很容易查出字串RVA和偏移量的值。
以 Pc_offset(光盘\tools\offset)此工具为例说说如何将SoftICE下看到的虚拟地址(Virual Address,VA)转换成十六进制工具里的偏移量(File offset),运行该软件打开记事本程序,在Memory Address(内存地址)输入虚拟地址(Virual Address,VA)的值:40117D,点击"Do it"按钮将显示己转换成文件偏移量(File offset),

二、文件类型分析

  文件分析是静态分析程序的第一步,通过相关工具显示欲调试文件的信息,如它是用什么语言写的,是否加壳等。常用的文件分析工具有TYP、Gtw或FileInfo。其中 FileInfo(光盘\tools\file\File analysers)由于识别文件类型较多,使用方便,在这一节简单地讲讲它的用法。
FileInfo运行时是DOS界面,支持Windows长文件名,能识别DOS、NE、PE等各种文件类型和壳。
  语法:fi <*.*>
     "fi /r"or "/s" 列出当前目录和子目录所有的文件信息;
     "fi /f" 仅列出能识别的文件
  由于每次要进入DOS窗口运行程序相当不便,在这可创建快捷方式,把要分析的文章复制到FileInfo目录下,用鼠标双击FileInfo主文件即可。FileInfo快捷方式如图二。在快捷方式中的命令行中可以键入相关参数,如:FI.EXE /l /p+,此后用鼠标双击FileInfo快捷方式,会自动分析出FileInfo当前目录内的所有文件,不包含子目录。


W32Dasm简介

 W32Dasm是一个强大的反汇编工具,操作简单,使用方便。通常被程序员使用,当然也可被用来Crack软件了,很适合Cracker使用。我在这把与crack相关的功能简述如下:

1.0 开始
2.0 保存反汇编文本文件和创建方案文件
3.0 反汇编文本代码的基本操作
4.0 复制汇编代码文本
5.0 装载32位的汇编代码动态调试
6.0 运行,暂停或终止程序
7.0 单步跟踪程序
8.0 设置激活断点
9.0 偏移地址和虚拟地址转换

1.0 开始

1.1 运行W32Dasm,在这里以windows95自带的计算器为例:calc.exe。

1.2 从Disassembler(反汇编)菜单选择Disassembler Options(反汇编程序选项)选项将出现如下对话框

.3 在Disassembler(反汇编)菜单,选择Open File(打开文件)选项或按工具栏按钮

1.4 选择你要打开的文件就可。
注意:你反汇编文件后,如字符己超过屏幕外,这时你要选择合适的字体(在Font字体选项中Select Font选择字体) ,然后设为默认字体(Save Default Font)即可。 当然一般以默认值就可。

2.0 保存反汇编文本文件和创建方案文件(Save The Disassembly Text and Create A Project File )

略。

3.0 反汇编源代码的基本操作

3.1 转到代码开始(Goto Code Start)

在工具栏按或从菜单的转到(Goto)选项选择转到代码开始(Goto Code Start) 或按Ctrl S, 这样光标将来到代码的开始处,用户可通过双击鼠标或用shift+上下光标键改变光标的位置。

注:代码的开始处是反汇编代码列表清单汇编指令的开始,而不是代码运行的起点,程序运行的起点称为程序入口点(Program Entry Point)

3.2 转到程序入口点(Goto Program Entry Point)

在工具栏按或菜单的转到(Goto)选项选择 转到程序入口点(Goto Program Entry Point)或按F10,这样光标将来到程序入口点(Entry Point),这里就是程序执行的起始点,一般动态调试时LOAD时也就停在此处。

3.3 转到页(Goto Page)

在工具栏按或菜单的转到(Goto)选项选择转到页(Goto Page)或按F11,这时跳出一对话框,输入页数可跳转到相关页面去

3.4 转到代码位置(Goto Code Location)

在工具栏按或菜单的转到(Goto)选项选择转到代码位置(Goto Code Location)或按F12,一个对话框将出现,充许用户输入代码偏移地址,以跳转到此位置上去。


3.5 执行文本跳转(Execute Text Jump)

这功能是在Execute Text(执行文本)菜单选项里的,执行跳跃(Execute Jump)功能激活条件是光标在代码的跳转指令这行上(这时光条是高亮度的绿颜色)。此时工具条Jump To按钮也激活。如图:

此时按或菜单选项Execute Jump(执行跳跃)或按右光标键,光条将来到跳转指令所指到的位置。在这例子里,将来到:004076CE xor eax,eax 这一行代码处:

如要返回到上一次跳跃,请参考3.6.

3.6 返回到上一次跳跃Return From Last Jump

这功能是在Execute Text(执行文本)菜单选项里的,此指令仅仅是在 执行文本跳转功能完成后才激活。当这条件成立时,按钮将激活。按或在菜单里选项返回到上一次跳跃(Return From Last Jump)或按左光标键,光条将返回到上一次跳跃位置处。

3.7 执行呼叫Execute Text Call


这功能是在Execute Text(执行文本)菜单选项里的,此功能激活的条件是光条在CALL指令一行。在这一行时光条将发绿,按钮将激活。执行时光条将会来到CALL所指的地址处。
如下图: 光条在0040751D call 004073D4 一行。

此时按或在菜单的执行呼叫(Execute Text Call)或按右光标键,光条将来到CALL所指的地址004073D4这一行。

如要返回到刚才起点的0040751D call 004073D4 一行,参考3.8的返回呼叫。

3.8 返回呼叫(Return From Last Call)

这功能是在Execute Text(执行文本)菜单选项里的,此指令仅仅是在执行呼叫Execute Text Call功能完成后才激活。当这条件成立时,按钮将激活。按或在菜单里选项返回呼叫(Return From Last Call)或按左光标键,光条将返回到上一次呼叫位置处。

3.9 导入功能(Imported)

在菜单功能选项里,其作用主要是查看import函数。按或在菜单功能选项里的导入(Imports)命令,执行后将列出当前文件的Import函数。

你可双击这些项目,光条将来到调用这些函数的代码处。
注意:如果代码多处引用了这些函数,你双击这个项目函数时,光条将在调用了其的几个位置代码处循环.
你也可用copy all或copy view复制import函数。

3.10 出口功能(Exported)

在菜单功能选项里,其作用主要是查看Export函数。按或在菜单功能选项里的出口(Exports)命令,执行后将列出当前文件的Exports函数。

注意:一般EXE文件没有exported,DLL文件有exported函数。

3.11 裁判(References)

在这个菜单选项里有菜单参考(MENU), 对话参考(DIALOG) or (串式数据参考STRING DATA),分别对应按钮:,或。

注意:其中(串式数据参考STRING DATA)功能破解时很常用。

4.0 复制汇编代码文本

W32dasm充许打印或复制指定行的汇编代码。首先你将鼠标移到W32DASM的最左边单击,将会出现一个小红点,再按住shift键,移到你需要的下一行,再单击鼠标一下,将选中一段,按CTRL+C复制或在菜单选项反汇编里的拷贝指定的行(Copy Lines of Text)功能或按,把数据复制到剪贴板里。如:

5.0 装载32位的汇编代码动态调试

5.1 反汇编windows自带的计算器程序 calc.exe.

5.2 选择菜单调试选项中的加载处理(Load Process),或按Ctrl+L.出现一个加载对话框,你可输入选项命令。现在你可按装载(load)按钮。

Calc.exe现在被W32DASM动态调试,将出现左右两个调试窗口(如下图),在初始化calc.exe程序后,指令将停留在入口点(Entry Point)处。

左边的调试窗口列出各种状态器如:CPU寄存器,CPU控制寄存器,断点,活动的DLL,段寄存器等等;

6.0 运行,暂停或终止程序

6.1 在右调试窗口,按运行(RUN)按钮或按F9,calc.exe将运行起来。

按暂停(PAUSE)按钮或空格键,程序将暂停,这在单步跟踪时经常用到。

按终止(TERMINAT)按钮,程序将停止,退出动态调试环境。

7.0单步跟踪程序

7.1 重新加载 calc.exe

7.2 在程序加载后,停留在入口点,你可按F7或F8单步调试程序,这两个键所不同的是F7是跟进CALL里,F8是路过。

7.3 进入自动调试按 (F5) 和结束自动调试按 (F6) 。

8.0设置激活断点

8.1 重新加载 calc.exe

8.2 在W32DASM的菜单转到选项转到代码处(goto code)功能,填上403198,按确定,你将在W32Dasm的主窗口(此时可能最小化了,把其还原即可)来到403198地址一行。光条在这一行显亮绿色,按F2或用鼠标左点击最左边(同时按住CTRL)设置断点。

这时如断点设置成功,光条最左边有一小段黄条,显示此行为断点。如下图:
如果断点不在这里,整行光条将是黄色的。

当断点设置好后,在左调试窗口中的断点小窗口显示断点情况(右边有一*):



此时按F2或(鼠标左键+CTRL),断点将取消。

8.3 此时按F9程序将运行到相关断点时停止。

9.0 偏移地址和虚拟地址转换

W32DASM、 SOFTICE和Hiew(Decode模式)显示的地址都是虚拟地址,但是在Hiew(Decode模式)下,F5功能键查找的地址是偏移地址,因此必须将虚拟地址转换成偏移地址,才能找到正确的地址。常用的方法是在W32DASM下将绿色的光条移到某一行代码上 , 在窗口底部有一行字指示其偏移地址 , 如虚似地址:Code DaTa@0040534e而偏移地址为:@Offset 0000474Eh. 这就是偏移地址。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多