第一个CRACKME.exe
首先运行程序,观察其功能,发现在它的Help
→Register
中有个验证的功能,随意输入字符串会弹出失败的提示。
使用x64dbg打开CRACKME.exe后,直接RUN(F9)进入程序。
通过之前的观察,不难发现其使用了一个MessageBoxA
作为失败的提示,所以使用bp MessageBoxA
下一个断点。
然后在CM程序中让程序调用这个MessageBoxA
,发现反汇编窗口中已经成功中断程序。
一个函数调用的时候,栈顶存储的就是函数的返回地址。
此时观察堆栈窗口,ESP的位置就是函数即将返回的地址,右键这个地址,在反汇编窗口中跟踪这个地址。
可以观察到,函数的调用位置就是在0x4013C1
。
x64dbg能判断函数名称是其通过传入的参数、调用的地址,找到其调用的dll分析的,dll里有导出表,导出表中有函数名。
在函数的调用位置的注释块上下可以找到No luck ...
的信息,再往上可以找到Great work ...
。
所以先找到程序在哪里调用的No luck ...
的逻辑,就可以找到程序判断的条件。因此在0x410364
下断点,重新运行程序,找到其调用的位置。
在je
比较的位置下断点,运行程序,在je
处中断时修改ZeroFlag
为的值为1
。
再运行程序,得到成功的提示。
但此时仅为一次性破解,需要对程序进行修改以达到永久破解的目的。
将je
指令修改为jmp
,跳过判断过程,然后保存可执行文件。
此程序在Win10下运行时会弹出两次窗口,可能是兼容性问题。
EFLAGS 标志寄存器
所有的JCC都由标志寄存器控制
带颜色的位是默认的。
其中:CF、PF、AP、ZF、SF、OF需要重点掌握。
在x64dbg中,EFLAGS/EFL的值为所有标志寄存器的16进制显示。
如EFLAGS 00000245
,转换成二进制为0010 0100 0101
(省略0);CF为1,PF为1,ZF为1。
进位标志寄存器:CF/Carry Flag
进位标志CF(Carry Flag):如果运算结果的最高位产生了一个进位或借位,那么其值为1,否则为0。
非最高位不进位时,CF值为0:
|
|
最高位进位时,CF值为1:
|
|
奇偶标志寄存器:PF/Parity Flag
奇偶标志寄存器反映运算结果中1的个数,如果1的个数是偶数,其值为1,否则为0。
当值为0时,其值也为1。
|
|
辅助进位标志寄存器: AF/Auxiliary Carry Flag
在发生以下情况时,辅助进位标志AF的值被设置位1,否则为0:
- 在字操作时,发生低字节像高字节进位或借位时
- 在字节操作时,发生低4位向高4位进位或借位时
|
|
运行后,辅助进位标志为1(满足条件1)。
|
|
运行后,辅助进位标志为1(满足条件2)。
零标志寄存器: ZF/Zero Flag
如果运算结果为0,其值为1,否则为0。
|
|
此时ZF为1。
|
|
MOV不属于运算操作,不影响标志寄存器。
一个数与其本身异或,结果为0
符号标志寄存器: SF/Sign Flag
用于反映运算结果的符号位,与运算结果的最高位相同。
|
|
此时SF为1。
溢出标志寄存器: OF/Overflow Flag
用于反映有符号数加减运算所得结果是否溢出。
如果运算结果超过当前运算位数所能表示的范围,则为溢出,其值为1,否则为0。
进位标志与溢出标志的区别:
- 进位标志表示无符号数运算结果是否超出范围
- 溢出标志表示有符号数运算结果是否超出范围
溢出主要是给有符号运算使用的,在有符号的运算中,有一下的规律:
|
|
无符号运算看CF,有符号运算看OF。
- 无符号、有符号都不溢出
|
|
- 无符号溢出、有符号不溢出
|
|
- 无符号不溢出、有符号溢出
|
|
- 无符号、有福海都溢出
|
|
方向标志寄存器 DF/Direction Flag
此寄存器用于控制串处理指令每次操作后SI, DI的增减。
当DF=0
时,每次操作后SI, DI递增。
当DF=1
时,每次操作后SI, DI递减。
计算指令
ADC 带进位加法
ADC指令将源操作数、进位标志位的值同时与目的操作数相加。
格式:
|
|
使用案例:
|
|
SBB 带借位减法
SBB指令将源操作数、进位标志位的值同时与目的操作数相减。
格式同ADC 带进位加法
。
XCHG 交换数据
XCHG指令将目标操作数与源操作数的值进行交换。
格式:
|
|
使用案例:
|
|
MOVS 内存间移动数据(串传送指令)
|
|
EDI, ESI可用于化简MOVS指令,且每次执行后EDI,ESI的值会加上操作数据宽度对应的地址差(如WORD宽度则 + 2)。此处EDI,ESI的加减可由
DF/Direction Flag
控制,0为加,1为减。
STOS 将寄存器AL/AX/EAX的值存储到EDI指定的内存单元
|
|
执行后,EDI的值会根据DF
递增或递减,如DWORD会递增会递减4。
REP 将计数寄存器ECX中指定的次数重复执行字符串指令
|
|