硬盘爱好者 发表于 2007-7-23 10:56:08

软件解密教学(收藏学习)

第1章 前言

  在上网前,我电脑知识的获取完全是靠书本和D版光盘,后来在1999年8月份上网后,一下子被这个神奇的网络所吸引,也感觉到自己的知识更加贫乏,通过她学到许多实用的知识。后来想找一些搞解密的朋友交流一下,但十分令人遗憾,那时国内的解密技术资料很缺乏,不成系统,大家交流的也有限,因此就想建个一站点,与大家共同探讨加密与解密的知识。

  在刚上网的一段时间里,在8中遇到网友灯心草,谈到共同建立一个解密站点,由于他忙于找工作,我就先尝试着建立了我的第一个主页:看雪学院。为什么取看雪这个名称?由于当时申请QICQ时取呢称时,外面正在下雪,故随意取了个名字"看雪",本想标新立意,没想给以后造成一些误解 ,后来大家都认识我了,也就懒得改名了。

  下面我们就谈谈如何学好这门技术:

  很多人都想学学做cracker,好象破了一个程序很风光的,人人都很佩服。 可是做一个cracker其实很累,需花费大量的时间,而且经常会碰壁,三五天毫无进展是极为平常的事情。

  做cracker的五个必要条件是: 1. 知识 2. 经验 3. 感觉 4. 耐心 5. 运气 。

  如果你刚开始学crack,也许你遇到不少麻烦,并且有点想退却,其实你不要着急,只要你认真学习,成功就在眼前。没有人是生来就什么都会的,如果你有问题,就大胆的去问你周围的人,多来我主页论坛请教。计算机水平不高怎么办?没关系,我也不是学计算机的,我自己的专业与电脑不沾边。只要努力学习就能成功。

  所谓知识只要你肯学就可以了,刚入门时如你没汇编知识是不行的,你要掌握一下这门编程语言,能看懂就能上手,但是你想很顺手的话,除了把汇编掌握好,还有编程的基本功夫,保护模式等技术。

  经验是跟你破解软件时间,掌握程度有关,接触多了,拿到一软件应该知道用哪种法比较省事,比较有把握。

  感觉这点不可言传,就象我们做语文题目时,一句话有语法错误一看就知道,这时我们有可能从语法上也说不上什么道道,就知它是错的,这就是语感。我们crack多了,也会有这方面的体会,拿一软件跟踪,到关键点时凭感觉就找到。

  耐心就不多说,成功与失败的关键也在这一步。

  运气也很关键,但运气是建立在你的扎实的基础功上的。

  另外我还要谈的一事是,当cracker目的不是破解软件,而是通过跟踪软件,了解程序思路,这样提高自己,使自己能写出更好的程序。 并且破解不在多,而在于你要掌握它,尽量了解注册码计算原理,最好能写出注册机,不能写也没关系,要弄懂它的算法。

  好了写了这么多到此,目的只是希望初学者们遇到困难时不要灰心,成功就在你们的眼前。

硬盘爱好者 发表于 2007-7-23 10:57:29

第2章 基础知识

第一节 软件保护

 软件的破解技术与保护技术这两者之间本身就是矛与盾的关系,它们是在互相斗争中发展进化的。这种技术上的较量归根到底是一种利益的冲突。软件开发者为了维护自身的商业利益,不断地寻找各种有效的技术来保护自身的软件版权,以增加其保护强度,推迟软件被破解的时间;而破解者则或受盗版所带来的高额利润的驱使,或出于纯粹的个人兴趣,而不断制作新的破解工具并针对新出现的保护方式进行跟踪分析以找到相应的破解方法。从理论上说,几乎没有破解不了的保护。对软件的保护仅仅靠技术是不够的,而这最终要靠人们的知识产权意识和法制观念的进步以及生活水平的提高。但是如果一种保护技术的强度强到足以让破解者在软件的生命周期内无法将其完全破解,这种保护技术就可以说是非常成功的。软件保护方式的设计应在一开始就作为软件开发的一部分来考虑,列入开发计划和开发成本中,并在保护强度、成本、易用性之间进行折衷考虑,选择一个合适的平衡点。

  在桌面操作系统中,微软的产品自然是独霸天下,一般个人用户接触得最多,研究得自然也更多一些。在DOS时代之前就有些比较好的软件保护技术,而在DOS中使用得最多的恐怕要算软盘指纹防拷贝技术了。由于DOS操作系统的脆弱性,在其中运行的普通应用程序几乎可以访问系统中的任何资源,如直接访问任何物理内存、直接读写任何磁盘扇区、直接读写任何I/O端口等,这给软件保护者提供了极大的自由度,使其可以设计出一些至今仍为人称道的保护技术;自Windows 95开始(特别是WinNT和Windows 2000这样严格意义上的多用户操作系统),操作系统利用硬件特性增强了对自身的保护,将自己运行在Ring 0特权级中,而普通应用程序则运行在最低的特权级Ring 3中,限制了应用程序所能访问的资源,使得软件保护技术在一定程度上受到一些限制。开发者要想突破Ring 3的限制,一般需要编写驱动程序,如读写并口上的软件狗的驱动程序等,这增加了开发难度和周期,自然也增加了成本。同时由于Win32程序内存寻址使用的是相对来说比较简单的平坦寻址模式(相应地其采用的PE文件格式也比以前的16-bit的EXE程序的格式要容易处理一些),并且Win32程序大量调用系统提供的API,而Win32平台上的调试器如SoftICE等恰好有针对API设断点的强大功能,这些都给跟踪破解带来了一定的方便。

第二节 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 为查表结果. ( ->AL )
2. 输入输出端口传送指令.
    IN   I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )
    OUTI/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位标志入栈.
    POPD32位标志出栈.

二、算术运算指令
───────────────────────────────────────
      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<OP2 )
    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/LOOPZCX不为零且标志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程序结束.

硬盘爱好者 发表于 2007-7-23 10:58:10

第三节 8088 汇编跳转

一、状态寄存器PSW(Program Flag)程序状态字寄存器,是一个16位寄存器,由条件码标志(flag)和控制标志构成,如下所示:1514131211109876543210    OFDFIFTFSFZF 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 72C=1有进位JNS79S=0正号JNC 73C=0无进位JO70O=1有溢出JZ/JE 74Z=1零/等于JNO71O=0无溢出JNZ/JNE 75Z=0不为零/不等于JP/JPE7AP=1奇偶位为偶JS78S=1负号JNP/IPO7BP=0奇偶位为奇
三、间接标志转移(8位寻址)
指令格式机器码测试格式如...则转移JA/JNBE(比较无符号数)77C或Z=0>  高于/不低于或等于JAE/JNB(比较无符号数)73C=0>=  高于或等于/不低于JB/JNAE(比较无符号数)72C=1<  低于/不高于或等于JBE/JNA(比较无符号数)76C或Z=1<=  低于或等于/不高于JG/JNLE(比较带符号数)7F(S异或O)或Z=0>  大于/不小于或等于JGE/JNL(比较带符号数)7DS异或O=0>=  大于或等于/不小于JL/JNGE(比较带符号数)7CS异或O=1<  小于/不大于或等于JLE/JNG(比较带符号数)7E(S异或O)或Z=1<=  小于或等于/不大于
四、无条件转移指令(fisheep译 fisheep@sohu.com)
操作码 伪码指令含义EB  cbJMP rel8相对短跳转(8位),使rel8处的代码位下一条指令E9  cwJMP rel16 相对跳转(16位),使rel16处的代码位下一条指令FF  /4JMP r/m16绝对跳转(16位),下一指令地址在r/m16中给出FF  /4JMP r/m32绝对跳转(32位),下一指令地址在r/m32中给出EA  cbJMP ptr16:16远距离绝对跳转, 下一指令地址在操作数中EA  cbJMP ptr16:32 远距离绝对跳转, 下一指令地址在操作数中FF  /5JMP m16:16远距离绝对跳转, 下一指令地址在内存m16:16中FF  /5JMP m16:32 远距离绝对跳转, 下一指令地址在内存m16:32中
五、16位/32位寻址方式(fisheep译 fisheep@sohu.com)

操作码伪码指令跳转含义 跳转类型跳转的条件(标志位)0F 87  cw/cdJA rel16/32大于near(CF=0 and ZF=0)0F 83  cw/cdJAE rel16/32大于等于near(CF=0)0F 82  cw/cdJB rel16/32小于near(CF=1)0F 86  cw/cdJBE rel16/32小于等于near(CF=1 or ZF=1)0F 82  cw/cdJC rel16/32进位near(CF=1)0F 84  cw/cdJE rel16/32等于near(ZF=1)0F 84  cw/cdJZ rel16/32为0near(ZF=1)0F 8F  cw/cdJG rel16/32大于near(ZF=0 and SF=OF)0F 8D  cw/cdJGE rel16/32 大于等于near(SF=OF)0F 8C  cw/cdJL rel16/32小于 near(SF<>OF)0F 8E  cw/cdJLE rel16/32小于等于near(ZF=1 or SF<>OF)0F 86  cw/cdJNA rel16/32 不大于near(CF=1 or ZF=1)0F 82  cw/cdJNAE rel16/32不大于等于near(CF=1)0F 83  cw/cdJNB rel16/32不小于near(CF=0)0F 87  cw/cdJNBE rel16/32不小于等于near(CF=0 and ZF=0)0F 83  cw/cdJNC rel16/32 不进位near(CF=0)0F 85  cw/cdJNE rel16/32不等于near(ZF=0)0F 8E  cw/cdJNG rel16/32不大于near(ZF=1 or SF<>OF)0F 8C  cw/cdJNGE rel16/32 不大于等于near(SF<>OF)0F 8D  cw/cdJNL rel16/32不小于near(SF=OF)0F 8F  cw/cdJNLE rel16/32 不小于等于near(ZF=0 and SF=OF)0F 81  cw/cdJNO rel16/32未溢出near(OF=0)0F 8B  cw/cdJNP rel16/32 不是偶数near(PF=0)0F 89  cw/cdJNS rel16/32 非负数near(SF=0)0F 85  cw/cdJNZ rel16/32非零(不等于)near(ZF=0)0F 80  cw/cdJO rel16/32 溢出near(OF=1)0F 8A  cw/cdJP rel16/32 偶数near(PF=1)0F 8A  cw/cdJPE rel16/32偶数near(PF=1)0F 8B  cw/cdJPO rel16/32 奇数near(PF=0)0F 88  cw/cdJS rel16/32负数near(SF=1)0F 84  cw/cdJZ rel16/32 为零(等于)near(ZF=1)
注:一些指令操作数的含义说明:
  rel8   表示 8 位相对地址
  rel16表示 16 位相对地址
  rel16/32 表示 16或32 位相对地址
  r/m16表示16位寄存器
  r/m32表示32位寄存器

硬盘爱好者 发表于 2007-7-23 10:59:01

第四节 浮点指令

  对下面的指令先做一些说明:
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)         

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标准







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)


硬盘爱好者 发表于 2007-7-23 10:59:31

第五节 分析技术

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

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

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

二、静态反汇编

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


三、动态跟踪分析

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

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

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

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

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

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

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

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

硬盘爱好者 发表于 2007-7-23 11:01:06

第3章 动态分析技术

第一节 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开始安装,出现(图一):
(图一)2、然后点击下一步,输入安装序列号(图二)(序列号一般在安装软件的readme.txt或其它说明文件里) (图二)3、然后下面几个画面是要求选定路径和安装组件,不久你会来到显卡配制对话框(图三): (图三)在显卡配制里两种方法:

①这种配制使SOFTICE激活状态时类似DOS全屏状态一样(也就是字符模式状态),在显卡列表选择你的显卡类型,Universal Vidoe Driver和Use monochrome card/monitor这两项不要选,然后点击Test按钮,在测试过程中你能看到各种颜色的字符,说明显卡测试通过,就可点击下一步了。

② 这种配制使SOFTICE在激活状态下类似windows应用程序的一个窗口那样,这样在调试时可避免显示器不停地在图形和字符模式转换,对提高显示器寿命大有好处。配制时,显卡列表一栏忽略,不用配制,只要把Universal Vidoe Driver这一项选上,然后test,如跳出如(图四)对话框,测试通过。(本人强烈推荐这种方式)


(图四) 4、再下一步是鼠标的配制(图五):
(图五)现在鼠标常见的一般是串行口或ps/2接口,你跟据自己的鼠标接口类型或位置选上合适的就可。如碰到鼠标在SOFTICE调试画面不能用或一用死机,可能是没选好正确的选项,你可在SOFTICE菜单里的,运行mosue setup这个菜单项重新配制鼠标。5、最后一步是询问以何种方式装载SOFTICE的主文件winice.exe(图六): (图六)首先要了解SOFTICE for 9x版本是如何装载的,在SOFTICE的安装目录下有winice.exe这个文件,windows启动到纯DOS环境下,运行winice.exe这个文件,将装载SOFTICE。
安装时默认将C:\PROGRA~1\NUMEGA\SOFTIC~1\WINICE.EXE这一行放时进Autoexec.bat(自动批处理文件),这样windows以后每次都运行Autoexec.bat这个文件,自动装载SOFTICE。另外,你可根据自身需要配制启动模式,具体参考第8步。6、然后安装程序将复制文件到硬盘里,来到最后一个对话框(图七): (图七)最后一项是电子注册,注册成功后,以后可在线升级SOFTICE版本,这里选最后一项Regiter later.7、至此安装完成,重新启动windows,微机先到DOS下,自动或手动运行相应批处理文件,运行其内的winice.exe文件,装载windows。8、启动菜单配制:通过配制启动菜单,启动时根据自己的需要选择是否装载SOFTICE。AUTOEXEC.BAT配制样例: @ECHO OFF

goto %config%
:SICE
C:\PROGRA~1\NUMEGA\SOFTIC~1\WINICE.EXE
goto common
:NORM
goto common
:common
CONFIG.SYS配制样例:

MENUITEM NORM,Windows 9x
MENUITEM SICE,Windows 9x with SoftICE
MENUDEFAULT NORM,2








㈡、SOFTICE配制1、Symbol Loader的使用

(图八) 你在开始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 &#39;78787878&#39; " 用命令s7878代替一串命令:S 30:0 L ffffffff &#39;78787878&#39;⑤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-Codes
NMI=ON
ECHOKEYS=OFF
NOLEDS=OFF
NOPAGE=OFF
SIWVIDRANGE=ON
THREADP=ON
LOWERCASE=OFF
WDMEXPORTS=OFF
MONITOR=0PHYSMB=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 &#39;78787878&#39; "
MACRO sname="S 0 L FFFFFFFF &#39;toye&#39; "
MACRO swide="s 0 l FFFFFFFF &#39;7&#39;,&#39;8,&#39;7&#39;,&#39;8,&#39;7&#39;,&#39;8,&#39;7&#39;,&#39;8,&#39;7&#39;,&#39;8,&#39;7&#39;,&#39;8,&#39;7&#39;,&#39;8&#39;,&#39;7&#39;,&#39;8&#39; "
MACRO reg="bpx regqueryvalueexa if *(esp->8)>=&#39;Soft&#39; 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&#39;t put this line. Now we have changed plug-ins load-method.
;Please copy your SYS to <TRW2000 Directory>\SYS, TRW2000 will load it
;automatic.
; Now, we don&#39;t support keyword LINES=, please use command LINES instead.
INIT="lines 35;wr 3;wd 4;wc 16"
F1=^HELP ; Command length CAN&#39;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

硬盘爱好者 发表于 2007-7-23 11:07:34

第二节 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中没有浮点窗口,不过有一个堆栈窗口。

(图一)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]
作用:执行程序,后面如果加地址,则执行到该地址为止。
注意: TRW2000 中G命令与SoftICE稍有不同,SoftICE中G命令必须是在当前段中,这时IP(EIP)为指定值才中断;而TRW2000则不管段址如何,只要IP(EIP)是指定的值便停下,TRW2000这个特性大大方便我们的操作。
2、P命令
语法: P
作用:单步执行程序。
只执行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]
start-address:执行起始地址;
count:指定SoftICE将单步跟踪多少次才停止。
作用:单步跟踪。
T命令相当于功能键F8,如没指定起始地址,将从CS:IP(EIP)指向的指令开始执行,此时当遇到 CALL、LOOP等指令时,T将跟踪进去。
注意: F8和F10功能键的主要差别就在这,遇到 CALL、LOOP等指令时,F10是路过,而F8是跟进去。
4、BPX命令
语法:BPX
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 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:B 字节;W 字;D 双字; S 短实型;L 长实型;T 10b长实型
作用:显示某内存区域的内容。
15、S命令
语法:S [-cu]
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 &#39;78787878&#39;.
16、E命令
语法:E ]
作用: 修改内存单元
17、U命令
语法:U ] |
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
作用:打开或关闭错误跟踪功能
由于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特有命令)
作用:&#39;pret&#39;(相当于按<F12>) 直至CS:EIP位于模块中,但比F12更实用,其可以快速回到你的当前程序领空,不用按多次F12了
23、SUSPEND命令(TRW2000特有命令)
作用: 暂停当前的线程,并退出 TRW2000,按热键返回,此命令相当方便。
24、ver blue命令(TRW2000特有命令)
如你的TRW2000背景颜色很暗,可通过此命令来调整背景。

硬盘爱好者 发表于 2007-7-23 11:11:41

  现在很多讲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

硬盘爱好者 发表于 2007-7-23 11:12:54

======== ED!SON&#39;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中
-
ED!SON, edison@ccnux.utm.my
2. SOFTICE/WIN
2.OO 快速入门 ========================================= 首先你应该对SOFTICE的屏幕有个大概的了解
|--------------------| | 寄存器窗 | 用 &#39;R&#39; 编辑 |--------------------|
| 数据窗 | 用 &#39;D&#39; 列出某个地址的数据, 用 &#39;E&#39; 编辑 |--------------------| | 代码窗 | 用 &#39;U&#39; 反汇编, &#39;A&#39;
加入汇编代码 |--------------------| | 命令窗 | 在这里输入命令和读出结果 |--------------------|
其它重要的功能键(在缺省的键定义下) &#39;H&#39;/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
按几次Ctrl+Up 直到你看到下面这几行。如果对汇编一点也不懂的话,看我加的
注解吧:
RET ; 函数结束 PUSH EBP ; 函数开始 MOV EBP, ESP
SUB ESP, 0000009C PUSH ESI > LEA EAX, ; EAX = EBP-34 PUSH EDI MOVE
ESI, ECX PUSH 32 ; 输入字符串的最大长度 > PUSH EAX ; 输入字符串的缓冲地址 PUSH 000003F4 ; 控制标识
PUSH DWORD PTR ; 对话框的句柄 CALL ; 取得输入
PUSH指令保存那些数值以供后面使用。我已经在重要的地方加上了一个 &#39;>&#39;字符 作上记号. 看这几行我们就知道字符缓冲区的地址保存在EAX中,而EAX等于
EBP-34。
所以我们来看看EBP-34那里有什么:

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

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

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

:d ebp-9c
数据窗口会显示出一大排数字 ─ 注册码!但是记住我前面说过的...两种注册
方式对应两个注册码....所以你把这些注册码抄下来以后,继续用F10单步运行 ....我们会遇到这些代码:
>
LEA EAX, ; EAX = EBP-68 LEA ECX, ; 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 &#39;96 Code: 12345
程序在 GetDlgItemTextA 处停住了,就象TaskLock一样。我们按F11回到调用它 的地方。用
Ctrl+Up卷动窗口直到看到这些:
MOV ESI, PUSH
1E ; 最大长度 PUSH 0040A680 ; 缓冲地址 PUSH 000003ED ; 控制柄 PUSH ESI ; 对话柄 CALL
数字40A680引起了我们的注意,看看那里有什么: :d 40a680
如果没有我们输入的名字,数据窗口里有些什么呢?好了,我们来研究下面的一
段代码:
PUSH 00 PUSH 00 PUSH 000003F6 ; 控制柄 MOV
EDI, 0040A680 ; 保存缓冲区地址 PUSH ESI ; 对话柄 CALL
GetDlgItemInt 和 GetDlgItemText差不多,但它从文字框中返回一个整数。 它出在EAX中返回来的,所以单步运行通过这些代码,再来看看寄存器窗....
对我而言是:
EAX=00003039
十六进制数3039是多少?
输入: :? 3039
我们得到:

00003039 0000012345 "09" ^ 16进制 ^ 十进制 ^ ASCII
正如你看到(和已经猜到)的那样,它是你输入的注册码。OK,下面怎么办?让
我们来看下面的代码:
MOV , 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 ; 读入40A680处的一字节 IMUL ECX, EAX ; ECX = ECX * EAX SHL ECX, 0A ; 左移
0A 次 ADD ECX, 0002F8CC ; 结果加上2F8CC MOV , 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 <string.h>
#include <stdio.h>
int main() { unsigned
long code; unsigned char buffer;
printf("CommandLine95
Keymaker by ED!SON &#39;96\n"); printf("Enter name: "); gets(buffer);
strupr(buffer); code = ( ((unsigned long)buffer * (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 ; 对话框柄 CALL
; 获得字符串
如果认为是C语言编译出来的话,这个CALL应该是这样:
GetDlgItemTextA(hwndDlg, 0x3F4, buffer, 0x32); ^
^ 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"这段文字 以后的那些
&#39;exp=&#39;的行首去掉&#39;;&#39;,为了节省内存,选择最重要的几个就可以了:
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编程手册
C.
如何与我联系 ================ On IRC (EFNet): In #Ucf96, #Cracking By e-mail: edison@ccnux.utm.my
OR an461165@anon.penet.fi On my homepage: http://www.geocities.com/SoHo/2680/cracking.html
======================================================================
译后记: 花了一个下午的时间(上班时间啊!),译完这篇拆解教程。不知大家看不看 得懂?ED!SON的文章是很浅显易懂的,我担心会让我毛手毛脚地闹出歧义来,
如果真有什么错误的话,帐应该算在我头上(请大家来信指出)。ED!SON的这 篇文章对初学者来说非常值得一读,我就是看完这篇文章以后,马上连续CRACK 了几个程序(就这么快、这么简单!)下次我就把CRACK
WINZIP6.2的过程讲讲 吧(WINZIP6.2的注册器已经泛滥成灾了,就当练习练习吧)。欢迎来信交流, 你CRACK了什么程序,别忘了告诉我你用的方法;如果觉得我翻译得还算看得下
去话,就给些鼓励吧。

shuaiji0077 发表于 2007-7-23 13:28:47

顶顶顶顶!!!!!!!!!!!!!
页: [1] 2
查看完整版本: 软件解密教学(收藏学习)