RSS| 首页| 山顶道| 布珞阁¹| GoodUI| 土产| 关于

第一次破解
2007.03.29 21:49 bruce:

一直以来看别人破解蛮好玩,硬是没有下功夫研究,
从什么softice开始到现在ida32什么的倒是装了,只能看别人用的份。

今天逮住机会破了一个简单的,算第一次吧。

一个破软件,看着几个学生用vb写的,现在发行下来,限制必须特定的U盘运行。目标是做到能随处运行

先搜了一些VB反编译的,最后找到SMARTCHK,检查错误前在辨别一串数字 1955767153。
我猜辨别U盘要么是读智能卡,要么就是读序列号。那普通的U盘,应该跟盘的序列号有关。不了一算,果然就是盘的序列号。
看到根目录上有个SN.txt刚好是这个序列号,因此认为改了这个SN.txt就可以了,结果不是。
用IDA32打开程序,找到弹出对话框的的方法设断点,找到了执行代码的程序处。
好家伙,居然是写死在代码里,他发出去的U盘序列号肯定都是一样的。
sn.jpg
简单的汇编试着看了个大概,比较读出的盘序列号和那个序列号比较,如果等于0就继续。
把这个jz改为jmp不就万事大吉了。

可惜IDA也不会用,以为直接可以改二进制,问朋友们,在hyne的协助下,找到埋藏好久不用winhex直接把对应的JZ:74 改为了JMP:EB
保存后大功告成。

还好练手的是个很简单的加密
工具不能少,基本功不能少,以后没事了慢慢破解当娱乐吧。
看着汇编的流程蛮有意思的。

第二节 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: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位标志出栈.

  二、算术运算指令

  ───────────────────────────────────────

  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:DI 目标串段寄存器:目标串变址.

  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译 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译 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)

  

分类  日经| 3个评论


3个评论
  1. roy_hu 留言:

    呵呵,“8088 汇编速查手册”?

  2. 天上星 留言:

    你小子,真TMD悠闲呀。。。。。羡慕中!!!

  3. zzw 留言:

    老布的爱好就是广泛…

垃圾太厉害了
说几句吧






*注意: 回复可能需要审查.您不必重复提交.