您的位置:首页 > 其它

Source insight3.5 注册算法分析记录

2013-06-05 10:38 429 查看
在看雪看到了两篇关于Source insight的破解,一篇只大概讲了分析过程,另一篇只写了注册机。

Source insight也算是一个很牛的软件了,希望能破掉提升一下逆向能力

逆完之后才看见网上的人说这个算法比较简单,有些失落

Setp1: 查壳,没壳,VC6.0的MFC写的(有壳我也不会脱,我只会脱压缩壳哈哈)

Step2:打开软件注册随便按下按钮看看提示信息,然后在OD处找到对应位置,拉倒对应位置最上面(函数开头)

00448AC3      55                  push ebp
00448AC4      8BEC                mov ebp,esp
00448AC6      83EC 0C             sub esp,0C
00448AC9      C745 FC BC535E00    mov dword ptr ss:[ebp-4],Insight3.005E53BC
00448AD0      8365 F8 00          and dword ptr ss:[ebp-8],0
00448AD4      EB 07               jmp short Insight3.00448ADD
00448AD6      8B45 F8             mov eax,dword ptr ss:[ebp-8]
00448AD9      40                  inc eax
........................此处省略一万字.......................................
00448C32      68 6CE95300         push Insight3.0053E96C                       ; ASCII "You typed an invalid serial number."
00448C37      E8 22F2FBFF         call Insight3.00407E5E
00448C3C      59                  pop ecx
00448C3D      68 E8030000         push 3E8
00448C42      FF15 E4925200       call dword ptr ds:[<&KERNEL32.Sleep>]        ; kernel32.Sleep
00448C48    ^ E9 89FEFFFF         jmp Insight3.00448AD6
00448C4D      33C0                xor eax,eax
00448C4F      C9                  leave
00448C50      C2 0400             retn 4
上面有一个这样的CALL(如下代码,我说的是00448BD9处的那个)其后的je跳到了00448C32处(显示错误信息处)

00448BBF      68 BC535E00         push Insight3.005E53BC                       ; ASCII "AAAAAAAA"
00448BC4      E8 223FFFFF         call Insight3.0043CAEB
00448BC9      68 BC535E00         push Insight3.005E53BC                       ; ASCII "AAAAAAAA"
00448BCE      E8 BB540D00         call Insight3.0051E08E
00448BD3      59                  pop ecx
00448BD4      68 BC535E00         push Insight3.005E53BC                       ; ASCII "AAAAAAAA"
00448BD9      E8 59030000         call Insight3.00448F37
00448BDE      85C0                test eax,eax
00448BE0      74 50               je short Insight3.00448C32


证明这个CALL肯定跟序列号正确与否有关,而这个CALL之前还有几个CALL,而且根据程序的运行顺序,上面几个CALL是有运行的,而且它们的参数里面都有我输入的序列号"AAAAAAAA",所以不可能是没用的。

Step3: 所以现在就应该从地址00448BBF处开始分析:

.text:00448BBF push    offset Serial   ; char *
.text:00448BC4 call    sub_43CAEB
.text:00448BC9 push    offset Serial   ; String
.text:00448BCE call    __strupr
.text:00448BD3 pop     ecx
.text:00448BD4 push    offset Serial
.text:00448BD9 call    sub_448F37
.text:00448BDE test    eax, eax
.text:00448BE0 jz      short loc_
这里的jz就是跳到正确和错误信息了,好像很短,不过里面的call还是挺多要分析的,好在IDA把一些库函数都识别出来了

FYI, 我喜欢把OD和IDA一起开起来,各有各的优点,逆向时可以互补.

首先把调用了sub_43CAEB,内容如下

.text:0043CAEB ; =============== S U B R O U T I N E =======================================
.text:0043CAEB
.text:0043CAEB ; Attributes: bp-based frame
.text:0043CAEB
.text:0043CAEB ; int __stdcall sub_43CAEB(char *)
.text:0043CAEB sub_43CAEB proc near                    ; CODE XREF: sub_4288F5+6Dp
.text:0043CAEB                                         ; sub_43CB2F+40p ...
.text:0043CAEB
.text:0043CAEB var_4= dword ptr -4
.text:0043CAEB arg_0= dword ptr  8
.text:0043CAEB
.text:0043CAEB push    ebp
.text:0043CAEC mov     ebp, esp
.text:0043CAEE push    ecx
.text:0043CAEF push    [ebp+arg_0]                     ; Str
.text:0043CAF2 call    _strlen
.text:0043CAF7 pop     ecx
.text:0043CAF8 mov     ecx, [ebp+arg_0]
.text:0043CAFB lea     eax, [ecx+eax-1]
.text:0043CAFF mov     [ebp+var_4], eax
.text:0043CB02
.text:0043CB02 loc_43CB02:                             ; CODE XREF: sub_43CAEB+37j
.text:0043CB02 mov     eax, [ebp+var_4]
.text:0043CB05 cmp     eax, [ebp+arg_0]
.text:0043CB08 jb      short loc_43CB24
.text:0043CB0A xor     eax, eax
.text:0043CB0C mov     eax, [ebp+var_4]
.text:0043CB0F mov     al, [eax]
.text:0043CB11 push    eax
.text:0043CB12 call    sub_439682
.text:0043CB17 test    eax, eax
.text:0043CB19 jz      short loc_43CB24s
.text:0043CB1B mov     eax, [ebp+var_4]
.text:0043CB1E dec     eax
.text:0043CB1F mov     [ebp+var_4], eax
.text:0043CB22 jmp     short loc_43CB02
.text:0043CB24 ; ---------------------------------------------------------------------------
.text:0043CB24
.text:0043CB24 loc_43CB24:                             ; CODE XREF: sub_43CAEB+1Dj
.text:0043CB24                                         ; sub_43CAEB+2Ej
.text:0043CB24 mov     eax, [ebp+var_4]
.text:0043CB27 and     byte ptr [eax+1], 0
.text:0043CB2B leave
.text:0043CB2C retn    4
.text:0043CB2C sub_43CAEB endp
对应的伪代码(写得有点傻 别介意)

fun1(Serial);
{
eax=length
ecx=Serial
eax=Serial+eax-1
Var4=pointer to the last letter
label1:
if eax<Var4
al=*(eax) //取Serial最后一个字符放到al
fun2(eax)
{
Var5=ecx=Serial// it doesnt matter because later this value will not be used
if al!=20h
if al!=9h
Var5=0
else
Var5=1
else
Var5=1
eax=Var5
}
if eax==0
eax=Var4(pointer to the last letter)
return
Serial=Serial-1
goto:label1
}


然后用strupr函数将Serial转换为大写,传入函数sub_448F37,内容如下

.text:00448F37 ; =============== S U B R O U T I N E =======================================
.text:00448F37
.text:00448F37 ; Attributes: bp-based frame
.text:00448F37
.text:00448F37 sub_448F37 proc near                    ; CODE XREF: sub_447957+51p
.text:00448F37                                         ; sub_447B94+10Cp ...
.text:00448F37
.text:00448F37 arg_0= dword ptr  8
.text:00448F37
.text:00448F37 push    ebp
.text:00448F38 mov     ebp, esp
.text:00448F3A push    [ebp+arg_0]
.text:00448F3D call    sub_448E53
.text:00448F42 test    eax, eax
.text:00448F44 jz      short loc_448F50
.text:00448F46 push    [ebp+arg_0]
.text:00448F49 call    sub_449030
.text:00448F4E jmp     short loc_448F58
.text:00448F50 ; ---------------------------------------------------------------------------
.text:00448F50
.text:00448F50 loc_448F50:                             ; CODE XREF: sub_448F37+Dj
.text:00448F50 push    [ebp+arg_0]
.text:00448F53 call    sub_448F5C
.text:00448F58
.text:00448F58 loc_448F58:                             ; CODE XREF: sub_448F37+17j
.text:00448F58 pop     ebp
.text:00448F59 retn    4
.text:00448F59 sub_448F37 endp


伪码如下:

提示一下,里面的fun4和fun5等我没列出其汇编代码

fun3(Serial)
{
fun4(Serial)
{
fun5(&Serial,"ES3US",strlen("ES3US"))
{
ecx=eax=parameter3
Var6=ecx-1
if eax==0
return
eax=Serial
eax=[eax]
eax=UpperLetter(eax)
esi=eax
eax=pointer to a const string "ES3US" whose pointer store in the var ES3US
eax=[eax]
eax=UpperLetter(eax)
ecx=未大写之前的eax
if esi!=eax
eax=0
return
Serial=Serial+1
ES3US=ES3US+1
}
如果fun5返回0,则fun4也返回0,否则返回非0
}
//这里是最关键的,进去fun6和fun7可以分别看到有字符串ES3US和SI3US,就是说之前的代码
//是在分析应该选fun6还是fun7,现在不难猜测fun6和fun7都可以校验出Serial的真假来,大
//概是返回一个非0的数然后就会显示成功的注册信息吧
if fun4 return 0
this way:
fun6(Serial)
{

}
otherwise,this way:
fun7(Serial)
{

}
}

再贴个fun7的伪码算了,很多事情要做,要学C++,要学算法,要学Windows原理,最近又在学脱壳,还有英语。。忙死了!

fun7里面还有几个小函数用来测试和得出字符串Dest的,就没有进去看了

fun7(Serial)
{
if(!fun5(&Serial,"SI3US",strlen("SI3US")))
return (fail);
if(!test1(&Serial,Dest,VAR4))
return (fail);
if(!Dest))
return (fail);
var110=atoi(Dest)
var10c=0
loc FEA:
if(var10c<1e)
if var110=var10c*4
return(fail)
var10c=var10c+1
goto FEA
GetNum(Dest)
if(eax==VAR)
return(fail)
return(success)
}


鸡肋
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: