iawen 发表于 2009-1-5 17:24

一个电子相册制作软件的算法分析

目标软件:XXXXX电子相册制作软件(国产的,就只好XX了)
使用工具:OD
作者:chenguo

按正常流程来,先用Peid查壳,显示为:ASPack 2.12 -> Alexey Solodovnikov

算了,不脱了,直接查找一下特征:
push 0
retn
快速来到程序的OEP,然后F9运行起来!

通过F12堆栈暂停的方法,很快找到程序注册的关键点:0057BAA0   |> \8D55 F8   lea edx,dword ptr ss:
0057BAA3   |.8B83 FC0200>mov eax,dword ptr ds:
0057BAA9   |.E8 3A0FEDFF call music.0044C9E8                  ;计算出机器码
0057BAAE   |.8B45 F8   mov eax,dword ptr ss:         ;此时,堆栈难看到机器码了
0057BAB1   |.50          push eax
0057BAB2   |.8B45 F8   mov eax,dword ptr ss:
0057BAB5   |.50          push eax
0057BAB6   |.8D45 FC   lea eax,dword ptr ss:
0057BAB9   |.50          push eax
0057BABA   |.E8 D9E0FFFF call music.00579B98                  ;对机器码变形,算法分析关键CALL一
0057BABF   |.8D4D F4   lea ecx,dword ptr ss:
0057BAC2   |.BA CCC15700 mov edx,music.0057C1CC
0057BAC7   |.8B45 FC   mov eax,dword ptr ss:
0057BACA   |.E8 75E1FFFF call music.00579C44                  ;关键CALL二,此CALL后,堆栈出现了真码
0057BACF   |.8D55 D0   lea edx,dword ptr ss:

……………………………………
0057BB20   |.8B55 D4   mov edx,dword ptr ss:      ;假码
0057BB23   |.8B45 F4   mov eax,dword ptr ss:         ;真码
0057BB26   |.E8 7194E8FF call music.00404F9C
0057BB2B   |.74 17       je short music.0057BB44我们先跟进关键CALL :call music.00579B98,单步,很快就找到了对机器码变形的地方:003ABC81   |> /8B45 10   /mov eax,dword ptr ss:
003ABC84   |. |0FB67C30 FF |movzx edi,byte ptr ds:   ;按位取机器码的ASCII值到EDI
003ABC89   |. |EB 0B       |jmp short zxysys.003ABC96
003ABC8B   |> |8B45 0C   |/mov eax,dword ptr ss:       ;内循环
003ABC8E   |. |0FB64418 FF ||movzx eax,byte ptr ds:;按位取机器码的ASCII值,EBX-1为索引值
003ABC93   |. |33F8      ||xor edi,eax                        ;与EDI进行异或运算
003ABC95   |. |43          ||inc ebx
003ABC96   |> |8B45 0C   | mov eax,dword ptr ss:
003ABC99   |. |E8 0E78FFFF ||call zxysys.003A34AC
003ABC9E   |. |3BD8      ||cmp ebx,eax
003ABCA0   |.^|7E E9       |\jle short zxysys.003ABC8B          ;判断内循环是否结束
003ABCA2   |. |BB 01000000 |mov ebx,1
003ABCA7   |. |8D45 F8   |lea eax,dword ptr ss:
003ABCAA   |. |8BD7      |mov edx,edi
003ABCAC   |. |E8 4777FFFF |call zxysys.003A33F8
003ABCB1   |. |8B55 F8   |mov edx,dword ptr ss:
003ABCB4   |. |8D45 FC   |lea eax,dword ptr ss:
003ABCB7   |. |E8 F877FFFF |call zxysys.003A34B4
003ABCBC   |. |46          |inc esi
003ABCBD   |> |8B45 10      mov eax,dword ptr ss:
003ABCC0   |. |E8 E777FFFF |call zxysys.003A34AC
003ABCC5   |. |3BF0      |cmp esi,eax
003ABCC7   |.^\7E B8       \jle short zxysys.003ABC81         ;判断外循环是否结束相对C++来言,表示如下://设strM为保存机器码的字符串
//设strT为保存变形码的字符串
char strT={0};
int len=strlen(strM);
for(int i=0;i<len;i++){
    strT=strM;
    for(int j=0;j<len;j++)
      strT ^= strM;
}对于这个软件来说,要理解其算法,明白了这里也就差不多了,呵呵要!
不说其他了,我们先跟完第2个关键CALL:call music.00579C44吧:00579CA9   |. /0F8E 540100>jle music.00579E03
00579CAF   |. |8945 E0   mov dword ptr ss:,eax
00579CB2   |. |BE 01000000 mov esi,1
00579CB7   |> |83FE 01   /cmp esi,1
00579CBA   |. |74 0B       |je short music.00579CC7
00579CBC   |. |8D45 EC   |lea eax,dword ptr ss:
00579CBF   |. |8B55 E8   |mov edx,dword ptr ss:
00579CC2   |. |E8 71AFE8FF |call music.00404C38
00579CC7   |> |8D45 E8   |lea eax,dword ptr ss:
00579CCA   |. |E8 D1AEE8FF |call music.00404BA0
00579CCF   |. |8B45 EC   |mov eax,dword ptr ss:
00579CD2   |. |E8 81B1E8FF |call music.00404E58
00579CD7   |. |8BF8      |mov edi,eax
00579CD9   |. |D1FF      |sar edi,1
00579CDB   |. |79 03       |jns short music.00579CE0
00579CDD   |. |83D7 00   |adc edi,0
00579CE0   |> |85FF      |test edi,edi
00579CE2   |. |0F8E 110100>|jle music.00579DF9
00579CE8   |. |BB 01000000 |mov ebx,1
00579CED   |> |BA 549E5700 |/mov edx,music.00579E54
00579CF2   |. |8D45 D8   ||lea eax,dword ptr ss:
00579CF5   |. |E8 9E95E8FF ||call music.00403298
00579CFA   |. |8D45 D4   ||lea eax,dword ptr ss:
00579CFD   |. |8BD3      ||mov edx,ebx
00579CFF   |. |03D2      ||add edx,edx
00579D01   |. |8B4D EC   ||mov ecx,dword ptr ss:
00579D04   |. |8A5411 FE   ||mov dl,byte ptr ds:
00579D08   |. |8850 01   ||mov byte ptr ds:,dl
00579D0B   |. |C600 01   ||mov byte ptr ds:,1
00579D0E   |. |8D55 D4   ||lea edx,dword ptr ss:
00579D11   |. |8D45 D8   ||lea eax,dword ptr ss:
00579D14   |. |B1 02       ||mov cl,2
00579D16   |. |E8 4D95E8FF ||call music.00403268
00579D1B   |. |8D55 D8   ||lea edx,dword ptr ss:
00579D1E   |. |8D45 D0   ||lea eax,dword ptr ss:
00579D21   |. |E8 7295E8FF ||call music.00403298
00579D26   |. |8D45 D4   ||lea eax,dword ptr ss:
00579D29   |. |8BD3      ||mov edx,ebx
00579D2B   |. |03D2      ||add edx,edx
00579D2D   |. |8B4D EC   ||mov ecx,dword ptr ss:
00579D30   |. |8A5411 FF   ||mov dl,byte ptr ds:
00579D34   |. |8850 01   ||mov byte ptr ds:,dl
00579D37   |. |C600 01   ||mov byte ptr ds:,1
00579D3A   |. |8D55 D4   ||lea edx,dword ptr ss:
00579D3D   |. |8D45 D0   ||lea eax,dword ptr ss:
00579D40   |. |B1 03       ||mov cl,3
00579D42   |. |E8 2195E8FF ||call music.00403268
00579D47   |. |8D55 D0   ||lea edx,dword ptr ss:
00579D4A   |. |8D45 DC   ||lea eax,dword ptr ss:
00579D4D   |. |E8 AAB0E8FF ||call music.00404DFC
00579D52   |. |8B45 DC   ||mov eax,dword ptr ss:
00579D55   |. |E8 8AFFE8FF ||call music.00409CE4
00579D5A   |. |8845 E7   ||mov byte ptr ss:,al
00579D5D   |. |BA 549E5700 ||mov edx,music.00579E54
00579D62   |. |8D45 D8   ||lea eax,dword ptr ss:
00579D65   |. |E8 2E95E8FF ||call music.00403298
00579D6A   |. |8D45 D4   ||lea eax,dword ptr ss:
00579D6D   |. |8BD6      ||mov edx,esi
00579D6F   |. |03D2      ||add edx,edx
00579D71   |. |8B4D F0   ||mov ecx,dword ptr ss:
00579D74   |. |8A5411 FE   ||mov dl,byte ptr ds:
00579D78   |. |8850 01   ||mov byte ptr ds:,dl
00579D7B   |. |C600 01   ||mov byte ptr ds:,1
00579D7E   |. |8D55 D4   ||lea edx,dword ptr ss:
00579D81   |. |8D45 D8   ||lea eax,dword ptr ss:
00579D84   |. |B1 02       ||mov cl,2
00579D86   |. |E8 DD94E8FF ||call music.00403268
00579D8B   |. |8D55 D8   ||lea edx,dword ptr ss:
00579D8E   |. |8D45 D0   ||lea eax,dword ptr ss:
00579D91   |. |E8 0295E8FF ||call music.00403298
00579D96   |. |8D45 D4   ||lea eax,dword ptr ss:
00579D99   |. |8BD6      ||mov edx,esi
00579D9B   |. |03D2      ||add edx,edx
00579D9D   |. |8B4D F0   ||mov ecx,dword ptr ss:
00579DA0   |. |8A5411 FF   ||mov dl,byte ptr ds:
00579DA4   |. |8850 01   ||mov byte ptr ds:,dl
00579DA7   |. |C600 01   ||mov byte ptr ds:,1
00579DAA   |. |8D55 D4   ||lea edx,dword ptr ss:
00579DAD   |. |8D45 D0   ||lea eax,dword ptr ss:
00579DB0   |. |B1 03       ||mov cl,3
00579DB2   |. |E8 B194E8FF ||call music.00403268
00579DB7   |. |8D55 D0   ||lea edx,dword ptr ss:
00579DBA   |. |8D45 CC   ||lea eax,dword ptr ss:
00579DBD   |. |E8 3AB0E8FF ||call music.00404DFC
00579DC2   |. |8B45 CC   ||mov eax,dword ptr ss:
00579DC5   |. |E8 1AFFE8FF ||call music.00409CE4
00579DCA   |. |3245 E7   ||xor al,byte ptr ss:
00579DCD   |. |8845 E6   ||mov byte ptr ss:,al
00579DD0   |. |8D45 C4   ||lea eax,dword ptr ss:
00579DD3   |. |8A55 E6   ||mov dl,byte ptr ss:
00579DD6   |. |E8 A5AFE8FF ||call music.00404D80
00579DDB   |. |8B45 C4   ||mov eax,dword ptr ss:
00579DDE   |. |8D55 C8   ||lea edx,dword ptr ss:
00579DE1   |. |E8 C2FDFFFF ||call music.00579BA8
00579DE6   |. |8B55 C8   ||mov edx,dword ptr ss:
00579DE9   |. |8D45 E8   ||lea eax,dword ptr ss:
00579DEC   |. |E8 6FB0E8FF ||call music.00404E60
00579DF1   |. |43          ||inc ebx
00579DF2   |. |4F          ||dec edi
00579DF3   |.^|0F85 F4FEFF>|\jnz music.00579CED
00579DF9   |> |46          |inc esi
00579DFA   |. |FF4D E0   |dec dword ptr ss:
00579DFD   |.^|0F85 B4FEFF>\jnz music.00579CB7
00579E03   |> \8B45 F8   mov eax,dword ptr ss:呵呵中,这么一大段,其实现的东东其实很简单!
完全是作者把算法复杂化了,直白的说C++代码展示如下:for(int i=0;i<len;i++)
    strT ^= 0x41;明白了吧,就是按位将变形得到的字符串与0x41这个常量进行案件或运算!
然后转成ASCII杩的文本格式输出就是真码了,呵呵
我这里偷了个巧,直接输出了:
for(int i=0;i<8;i++)
    printf("%02X",strT);
完整的算法代码如下:
#include<iostream>
#include<stdio.h>
using namespace std;

int main()
{
        cout<<"请软件你的机器码:\n";
        char strM={0};
        cin>>strM;

        char strT={0};
        int len=strlen(strM);
        for(int i=0;i<len;i++){
                strT=strM;
                for(int j=0;j<len;j++)
                        strT ^= strM;
        }
        for(int i=0;i<len;i++)
                strT ^= 0x41;
       
        //cout<<strT<<endl;
        cout<<"\n请你的注册码是:\n";
       
        for(int i=0;i<8;i++)
                printf("%02X",strT);
       
        cout<<"\n请按任意键退出…………";
        getchar();
        getchar();
       
        return 0;
}


[ 本帖最后由 chenguo 于 2009-1-5 17:26 编辑 ]

creantan 发表于 2009-1-5 17:32

沙发。。学习下。。:D

iawen 发表于 2009-1-5 17:49

晕倒,沙发竟然被你给抢了,我哭,:Q

Hmily 发表于 2009-1-6 18:32

chenguo算法分析的很好,学习~

iawen 发表于 2009-1-6 21:09

原帖由 Hmily 于 2009-1-6 18:32 发表 http://www.52pojie.cn/images/common/back.gif
chenguo算法分析的很好,学习~

晕倒,要不要扔你一个臭鸡蛋??:L

qq227479645 发表于 2009-1-6 21:10

好技术` 谢谢了 `

snake88888 发表于 2009-1-7 23:21

谢谢楼主了,努力学习:victory: :victory: 中。

zhou2x 发表于 2009-1-10 09:46

感谢分享,学习!支持!!

zy7873445 发表于 2009-1-11 15:35

好东西呀   学习一下!

leektt 发表于 2009-1-11 17:22

高手.....

呵呵...找找这个软件也去看下吧.
页: [1]
查看完整版本: 一个电子相册制作软件的算法分析