Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crackme160-003 #20

Open
xinali opened this issue Mar 9, 2018 · 0 comments
Open

Crackme160-003 #20

xinali opened this issue Mar 9, 2018 · 0 comments
Labels

Comments

@xinali
Copy link
Owner

xinali commented Mar 9, 2018

Crackme160-003

ollydbg版本: 吾爱破解改进版

这个crackme主要就是考察浮点数运算

测试数据name=33333, serial=666666

开始的操作和002基本相同,找到带有Wrong字符串的汇编代码调用部分,在该函数的开始部分设下断点,
Ctrl+F2,一直运行,直到第一次出现输入的name,可以认为这是算法的开始部分,一步一步分析
具体的分析加注释

第一部分

004081F2                   .  50            push eax                               ; /String = "?譕藬痉,??p???????铨?藿磀?巀?????譕??痿(??蕶秀倊???????�??诌嗿?痿,???瘵??篥.???嵀?????譕凬?僼痿(??蕶秀個??菿?????????�"
004081F3                   .  8B1A          mov ebx,dword ptr ds:[edx]             ; |
004081F5                   .  FF15 F8B04000 call dword ptr ds:[<&MSVBVM50.__vbaLen>; \__vbaLenBstr
004081FB                   .  8BF8          mov edi,eax                            ;  得到name.length
004081FD                   .  8B4D E8       mov ecx,dword ptr ss:[ebp-0x18]
00408200                   .  69FF 385B0100 imul edi,edi,0x15B38                   ;  edi=name.length*0x15B38
00408206                   .  51            push ecx                               ; /String = NULL
00408207                   .  0F80 B7050000 jo AfKayAs_.004087C4                   ; |
0040820D                   .  FF15 0CB14000 call dword ptr ds:[<&MSVBVM50.#rtcAnsi>; \rtcAnsiValueBstr
00408213                   .  0FBFD0        movsx edx,ax                           ;  anscii(name[0])
00408216                   .  03FA          add edi,edx                            ;  edi=name.length*0x15B38+anscii(name[0])
00408218                   .  0F80 A6050000 jo AfKayAs_.004087C4
0040821E                   .  57            push edi
0040821F                   .  FF15 F4B04000 call dword ptr ds:[<&MSVBVM50.__vbaStr>;  msvbvm50.__vbaStrI4
00408225                   .  8BD0          mov edx,eax                            ;  将edi转化为10进制赋值给edx

第二部分

004082EF                   .  D905 08104000 fld dword ptr ds:[0x401008]            ;  值为10
004082F5                   .  833D 00904000>cmp dword ptr ds:[0x409000],0x0
004082FC                   .  75 08         jnz short AfKayAs_.00408306
004082FE                   .  D835 0C104000 fdiv dword ptr ds:[0x40100C]           ;  除完之后st(0)=2
00408304                   .  EB 0B         jmp short AfKayAs_.00408311
00408306                   >  FF35 0C104000 push dword ptr ds:[0x40100C]
0040830C                   .  E8 578DFFFF   call <jmp.&MSVBVM50._adj_fdiv_m32>
00408311                   >  83EC 08       sub esp,0x8
00408314                   .  DFE0          fstsw ax
00408316                   .  A8 0D         test al,0xD
00408318                   .  0F85 A1040000 jnz AfKayAs_.004087BF
0040831E                   .  DEC1          faddp st(1),st                         ;  double(deci(serial))+2

第三部分

004083FB <AfKayAs_.这里*3>   .  DC0D 10104000 fmul qword ptr ds:[0x401010]           ;  (serial+10/5)*3
00408401                   .  83EC 08       sub esp,0x8
00408404                   .  DC25 18104000 fsub qword ptr ds:[0x401018]
0040840A                   .  DFE0          fstsw ax
0040840C                   .  A8 0D         test al,0xD
0040840E                   .  0F85 AB030000 jnz AfKayAs_.004087BF

第四部分

0040861A                   .  DC1D 28104000 fcomp qword ptr ds:[0x401028]
00408620                   .  DFE0          fstsw ax                               ;  重点关注指令
00408622                   .  F6C4 40       test ah,0x40
00408625                   .  74 07         je short AfKayAs_.0040862E
00408627                   .  BE 01000000   mov esi,0x1
0040862C                   .  EB 02         jmp short AfKayAs_.00408630
0040862E                   >  33F6          xor esi,esi
00408630                   >  8D55 E4       lea edx,dword ptr ss:[ebp-0x1C]
00408633                   .  8D45 E8       lea eax,dword ptr ss:[ebp-0x18]
00408636                   .  52            push edx                               ;  AfKayAs_.<ModuleEntryPoint>
00408637                   .  50            push eax                               ;  kernel32.BaseThreadInitThunk
00408638                   .  6A 02         push 0x2
0040863A                   .  FF15 80B14000 call dword ptr ds:[<&MSVBVM50.__vbaFre>;  msvbvm50.__vbaFreeStrList
00408640                   .  83C4 0C       add esp,0xC
00408643                   .  8D4D D8       lea ecx,dword ptr ss:[ebp-0x28]
00408646                   .  8D55 DC       lea edx,dword ptr ss:[ebp-0x24]
00408649                   .  51            push ecx
0040864A                   .  52            push edx                               ;  AfKayAs_.<ModuleEntryPoint>
0040864B                   .  6A 02         push 0x2
0040864D                   .  FF15 08B14000 call dword ptr ds:[<&MSVBVM50.__vbaFre>;  msvbvm50.__vbaFreeObjList
00408653                   .  F7DE          neg esi
00408655                   .  83C4 0C       add esp,0xC
00408658                   .  B9 04000280   mov ecx,0x80020004
0040865D                   .  B8 0A000000   mov eax,0xA
00408662                   .  894D 9C       mov dword ptr ss:[ebp-0x64],ecx
00408665                   .  66:85F6       test si,si
00408668                   .  8945 94       mov dword ptr ss:[ebp-0x6C],eax        ;  kernel32.BaseThreadInitThunk
0040866B                   .  894D AC       mov dword ptr ss:[ebp-0x54],ecx
0040866E                   .  8945 A4       mov dword ptr ss:[ebp-0x5C],eax        ;  kernel32.BaseThreadInitThunk
00408671                   .  894D BC       mov dword ptr ss:[ebp-0x44],ecx
00408674                   .  8945 B4       mov dword ptr ss:[ebp-0x4C],eax        ;  kernel32.BaseThreadInitThunk
00408677                   .  74 62         je short AfKayAs_.004086DB

注册机算法

serial = (deci(name.length*0x15B38 + anscii(name[0])) + 2) * 3 + 15

其中我们可以看出,前三部分相对来说都是比较容易理解的,关键部分就是在第四部分
第四部分最关键的部分

fcomp qword ptr ds:[0x401028]
fstsw ax                             
test ah,0x40
je short 0040862E

此时st(0)=compute_serial/input_serial,地址里面存的是1.0,也就是st(0)和1.0的比较,然后将status word放入ax中,可以从数据面板中看出来ax=0x0120=> ah=0x01h

ah: 0000 0001
40: 0100 0000

从下面的扩展知识我们可看到,test命令是为了探测C3位是否为1,即两值是否相等
相等,那么C3位为1,test结果ZF=0,不跳转 => 破解成功
不相等,那么C3位为0,test结果ZF=1,跳转 => 破解失败

扩展

浮点数运算

浮点数运算由专门的FPU(浮点运算器)完成,它由8个80位的寄存器和3个16位的状态寄存器组成,
其中8个80位的寄存器分别为st(0)-st(7)

8个80位寄存器组成了一个栈,每次出栈/进栈都是通过这个TOP值指定的,TOP值始终指向栈顶元素
举个例子:
现在要将value0value1value2压入这8个栈中,

  1. TOP指向st(0),将value0送入st(0)
  2. value1进入这个栈中,将value0送入st(1)中,并将value1送入st(0)
  3. value2进入这个栈中,将value1送入st(2)中,并将value1送入st(1)中,将value2送入st(0)

3个16位的寄存器分别为control word, status wordtag word(这里为了方便理解,不直接翻译)

control word状态字

img

各个状态位的标志含义

  1. 无限状态标志位IC(Infinity Control)
0 = Both -infinity and +infinity are treated as unsigned infinity (initialized state) 
1 = Respects both -infinity and +infinity
  1. 四舍五入控制位RC(Rounding Control)
00 = Round to nearest, or to even if equidistant (this is the initialized state) 
01 = Round down (toward -infinity) 
10 = Round up (toward +infinity) 
11 = Truncate (toward 0)
  1. 精确度控制位PC(Precision Control)
00 = 24 bits (REAL4) 
01 = Not used 
10 = 53 bits (REAL8) 
11 = 64 bits (REAL10) (this is the initialized state)
  1. 中断控制位(7, 5-0)
    IEM(Interrupt Enable Mask )决定是否中断可用,设置为0表示中断可用,为1表示中断不可用.
PM (bit 5) or Precision Mask 
UM (bit 4) or Underflow Mask 
OM (bit 3) or Overflow Mask 
ZM (bit 2) or Zero divide Mask 
DM (bit 1) or Denormalized operand Mask 
IM (bit 0) or Invalid operation Mask

status word

img

这里只重点关注C3,C2,C0

Opcode Mnemonic Description
D8 /2 FCOM m32fp Compare ST(0) with m32fp.
DC /2 FCOM m64fp Compare ST(0) with m64fp.
D8 D0+i FCOM ST(i) Compare ST(0) with ST(i).
D8 D1 FCOM Compare ST(0) with ST(1).
D8 /3 FCOMP m32fp Compare ST(0) with m32fp and pop register stack.
DC /3 FCOMP m64fp Compare ST(0) with m64fp and pop register stack.
D8 D8+i FCOMP ST(i) Compare ST(0) with ST(i) and pop register stack.
D8 D9 FCOMP Compare ST(0) with ST(1) and pop register stack.
DE D9 FCOMPP Compare ST(0) with ST(1) and pop register stack twice.

比较操作会影响C3, C2, C0

Condition C3 C2 C0
ST(0) > Source 0 0 0
ST(0) < Source 0 0 1
ST(0) = Source 1 0 0
Unordered* 1 1 1

NOTE: * Flags not set if unmasked invalid-arithmetic-operand (#IA) exception is generated.

tag word状态字

暂时未用到

浮点数运算重点操作指令

指令 说明
fstsw ax 将status word送入ax中
fdiv m32fp Divide ST(0) by m32fp and store result in ST(0)
fcomp m32fp Compare ST(0) with m32fp and pop register stack.
fmul m32fp Multiply ST(0) by m32fp and store result in ST(0)

VB逆向分析重点关注函数

  1. 数据类型转换
a) __vbaI2Str 将一个字符串转为8 位(1个字节)的数值形式(范围在 0 至 255 之间) 或2 个字节的数值形式(范围在 -32,768 到 32,767 之间)。
b)__vbaI4Str 将一个字符串转为长整型(4个字节)的数值形式(范围从-2,147,483,6482,147,483,647) 
c)__vbar4Str 将一个字符串转为单精度单精度浮点型(4个字节)的数值形式
d)__vbar8Str 将一个字符串转为双精度单精度浮点型(8个字节)的数值形式
e) VarCyFromStr (仅VB6库. 要调试,则在WINICE.DAT里必须有 OLEAUT32.DLL)字符串到变比型数据类型 
f) VarBstrFromI2 (仅VB6库. 要调试,则在WINICE.DAT里必须有 OLEAUT32.DLL)整型数据到字符串:
  1. 数据移动
a) __vbaStrCopy 将一个字符串拷贝到内存,类似于 Windows API HMEMCPY 
b) __vbaVarCopy 将一个变量值串拷贝到内存 
c) __vbaVarMove 变量在内存中移动,或将一个变量值串拷贝到内存
  1. 数学运算
a) __vbavaradd 两个变量值相加 
b) __vbavarsub 第一个变量减去第二个变量
c) __vbavarmul 两个变量值相乘
d) __vbavaridiv 第一个变量除以第二个变量,得到一个整数商 
e) __vbavarxor 两个变量值做异或运算
  1. 程序设计杂项
a) __vbavarfornext 这是VB程序里的循环结构, For... Next... (Loop) 
b) __vbafreestr 释放出字符串所占的内存,也就是把内存某个位置的字符串给抹掉
c) __vbafreeobj 释放出VB一个对象(一个窗口,一个对话框)所占的内存,也就是把内存某个位置的一个窗口,一个对话框抹掉
d) __vbastrvarval 从字符串特点位置上获取其值 
e) multibytetowidechar 将数据转换为宽字符格式,VB在处理数据之都要这样做,在TRW2000显示为7.8.7.8.7.8.7.8
f) rtcMsgBox 调用一个消息框,类似于WINDOWS里的messagebox/a/exa,此之前一定有个PUSH命令将要在消息框中显示的数据压入椎栈 
g) __vbavarcat 将两个变量值相连,如果是两个字符串,就连在一起 
h) __vbafreevar 释放出变量所占的内存,也就是把内存某个位置的变量给抹掉
i) __vbaobjset 
j) __vbaLenBstr 获得一个字符串的长度,注:VB中一个汉字的长度也为1
k) rtcInputBox 显示一个VB标准的输入窗口,类似window's API getwindowtext/a, GetDlgItemtext/a 
l) __vbaNew 调用显示一个对话框,类似 Windows' API Dialogbox 
m) __vbaNew2 调用显示一个对话框,类似 Windows' API Dialogboxparam/a 
n) rtcTrimBstr 将字串左右两边的空格去掉
  1. 比较函数
a) __vbastrcomp 比较两个字符串,类似于 Window's API lstrcmp 
b) __vbastrcmp 比较两个字符串,类似于 Window's API lstrcmp 
c) __vbavartsteq 比较两个变量值是否相等
d)__vbaFpCmpCy - Compares Floating point to currency. sp; Compares Floating point to currency
  1. 在动态跟踪,分析算法时,尤其要注意的函数
rtcMidCharVar 从字符串中取相应字符,VB中的MID函数,用法MID("字符串","开始的位置","取几个字符")
rtcLeftCharVar 从字符串左边取相应字符,VB中的用法:left("字符串","从左边开始取几个字符")
rtcRightCharVar 从字符串右边取相应字符,VB中的用法:Right("字符串","从右边开始取几个字符")
__vbaStrCat 用字符串的操作,就是将两个字符串合起来,在VB中只有一个&或+
__vbaStrCmp 字符串比较,在VB中只有一个=或<>
ASC()函数 取一个字符的ASC值,在反汇编时,还是有的movsx 操作数
  1. 在函数中的缩写
bool 布尔型数据(TRUE 或 FALSE) 
str 字符串型数据 STRING
i2 字节型数据或双字节整型数据 BYTE or Integer
ui2 无符号双字节整型数据 
i4 长整型数据(4字节) Long
r4 单精度浮点型数据(4字节) Single 
r8 双精度浮点型数据(8字节) Double
cy  (8 个字节)整型的数值形式 Currency
var 变量 Variant
fp  浮点数据类型 Float Point
cmp 比较 compare
comp 比较 compare

Btw:

__vbavartsteq系列的还有__vbavartstne 不等于 __vbavartstGe,__vbavartstGt,__vbavartstLe,__vbavartstLt等,比较大于或小于

Reference

FPU

FCOMP

VB程序逆向常用的函数

@xinali xinali added the crackme label Mar 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant