willJ 发表于 2011-10-23 20:58

菜鸟分析下一个简单的KeyGenMe软件

本帖最后由 xiangshen 于 2011-10-24 14:16 编辑

标题:菜鸟分析下一个简单的KeyGenMe软件发言人:willjhw E-mail:466684954@qq.com时间:2011/10/23详细信息:
软件背景资料

运行平台:Win XP
文件名称:KeyGenMe.exe
程序类型:KeyGenMe
文件大小:4.00KB

使用工具

OllyDBG
PEID

说明:这是我写的第一篇算法分析的破文,难免有错误存在,望各位大侠指点。
首先用PEID查壳,效果如下:
可以看见这个程序是汇编写的在004012DE处下个断点然后程序跑起来,输入Name:abc Password:0123456789断在了下面:
004012DE    E8 4F000000   call    00401332//跟进这个call
004012E3    68 53304000   push    00403053                         ; ASCII "ZWATRQLCGHPSXYENVBJDFKMU"
.
.
.
00401332    33C0            xor   eax, eax
00401334    B9 00000000   mov   ecx, 0
00401339    BE 23304000   mov   esi, 00403023                  ; ASCII "0123456789"
0040133E    8A06            mov   al, byte ptr
00401340    EB 10         jmp   short 00401352
00401342    0FB6C0          movzx   eax, al
00401345    80B8 50314000 0>cmp   byte ptr , 2
0040134C    75 0A         jnz   short 00401358
0040134E    41            inc   ecx
0040134F    8A0431          mov   al, byte ptr
00401352    3C 00         cmp   al, 0
00401354^ 77 EC         ja      short 00401342                   ; 判断注册码是否为空
00401356    EB 07         jmp   short 0040135F
00401358    C605 44304000 4>mov   byte ptr , 40            ; 这儿应该跳过才对
0040135F    BE 00304000   mov   esi, 00403000                  ; ASCII "abc"


完成了两个功能:1.
Password为大写字母2.
.将用户名ascii div 0X18 余数保存起来
00401364    33C9            xor   ecx, ecx
00401366    B8 01000000   mov   eax, 1
0040136B    33D2            xor   edx, edx
0040136D    C705 45304000 0>mov   dword ptr , 0
00401377    B9 00000000   mov   ecx, 0                           ; 开始测试用户名
0040137C    8A0C32          mov   cl, byte ptr          ; 取当前用户名ascii到cl
0040137F    80F9 00         cmp   cl, 0
00401382    74 09         je      short 0040138D                   ; 是否已经取完
00401384    42            inc   edx                              ; 取用户名长度到edx
00401385    000D 45304000   add   byte ptr , cl            ; 累加用户名ascii到cl
0040138B^ EB EA         jmp   short 00401377
0040138D    A1 45304000   mov   eax, dword ptr
00401392    B9 18000000   mov   ecx, 18
00401397    99            cdq                                    ; 扩展用户名长度edx为eax高位
00401398    F7F9            idiv    ecx                              ; eax/18
0040139A    8815 4F304000   mov   byte ptr , dl            ; 存放余数
004013A0    8A0D 44304000   mov   cl, byte ptr
004013A6    80F9 40         cmp   cl, 40
004013A9    75 05         jnz   short 004013B0
004013AB    E9 45010000   jmp   004014F5
004013B0    E9 CB000000   jmp   00401480//jmp到了下一个call
004013B5    C3            retn


继续跟进call里面去
00401510    A0 24304000   mov   al, byte ptr
00401515    3C 45         cmp   al, 45                           ; 将注册码第二位和0x45比较
00401517^ 75 DC         jnz   short 004014F5                   ; 第二次检查
00401519    BF 96124000   mov   edi, 00401296
0040151E    B9 00010000   mov   ecx, 100
00401523    B0 99         mov   al, 99
00401525    34 55         xor   al, 55                           ; 99与55异或
00401527    F2:AE         repne   scas byte ptr es:         ; 搜索关键字'U'
00401529    85C9            test    ecx, ecx
0040152B    74 06         je      short 00401533                   ; 第三次检查
0040152D    5E            pop   esi
0040152E    33F6            xor   esi, esi
00401530    57            push    edi
00401531^ EB C2         jmp   short 004014F5
00401533    C3            retn


上面的代码说明输入的password里不能有U确定了第二位为E
00401485    33DB            xor   ebx, ebx
00401487    BF 80144000   mov   edi, 00401480
0040148C    83EF 60         sub   edi, 60
0040148F    B8 DE000000   mov   eax, 0DE
00401494    83F0 12         xor   eax, 12                        ; 0de与12异或
00401497    B9 59000000   mov   ecx, 59
0040149C    F2:AE         repne   scas byte ptr es:
0040149E    85C9            test    ecx, ecx
004014A0    74 06         je      short 004014A8                   ; 又是检查
004014A2    5E            pop   esi
004014A3    33F6            xor   esi, esi
004014A5    57            push    edi
004014A6    EB 4D         jmp   short 004014F5
004014A8    C3            retn
004012E3    68 53304000   push    00403053                         ; ASCII "ZWATRQLCGHPSXYENVBJDFKMU"
004012E8    E8 C9000000   call    004013B6
004012ED    E8 DC010000   call    004014CE
004012F2    6A 00         push    0
004012F4    FF75 08         push    dword ptr


上面将常量字符串"ZWATRQLCGHPSXYENVBJDFKMU"压入在跟进4012e8去
004013B6    55            push    ebp
004013B7    8BEC            mov   ebp, esp
004013B9    68 23304000   push    00403023                         ; ASCII "0123456789"
004013BE    E8 7D010000   call    00401540                         ; 求注册码长度
004013C3    83F8 0A         cmp   eax, 0A                        ; 注册码长度是否为10
004013C6    0F85 29010000   jnz   004014F5
004013CC    BE 23304000   mov   esi, 00403023                  ; ASCII "0123456789"
004013D1    B8 00000000   mov   eax, 0
004013D6    BB 00000000   mov   ebx, 0
004013DB    33C9            xor   ecx, ecx
004013DD    EB 06         jmp   short 004013E5                   ; 开始累加注册码的ascii和到ebx
004013DF    8A0C30          mov   cl, byte ptr
004013E2    03D9            add   ebx, ecx
004013E4    40            inc   eax
004013E5    83F8 09         cmp   eax, 9
004013E8^ 72 F5         jb      short 004013DF
004013EA    8BC3            mov   eax, ebx
004013EC    B9 09000000   mov   ecx, 9
004013F1    99            cdq
004013F2    F7F9            idiv    ecx                              ; ascii和/长度
004013F4    A3 4A304000   mov   dword ptr , eax          ; 存放商
004013F9    8B7D 08         mov   edi, dword ptr



00401406   /76 02         jbe   short 0040140A
00401408   |2C 18         sub   al, 18
0040140A   \A2 4E304000   mov   byte ptr , al
0040140F    33C0            xor   eax, eax
00401411    A0 4E304000   mov   al, byte ptr
00401416    8A2438          mov   ah, byte ptr
00401419    8A36            mov   dh, byte ptr
0040141B    38F4            cmp   ah, dh                           ; 开始比较了
0040141D    0F85 D2000000   jnz   004014F5


确定password的第一位是用户名之和除以0x18的余数再去那个常量字符找对应的位数
00401453    A2 4E304000   mov   byte ptr , al
00401458    33C0            xor   eax, eax
0040145A    A0 4E304000   mov   al, byte ptr
0040145F    80EE 41         sub   dh, 41
00401462    8AD6            mov   dl, dh
00401464    41            inc   ecx
00401465    02C2            add   al, dl
00401467    3C 18         cmp   al, 18
00401469    76 02         jbe   short 0040146D
0040146B    2C 18         sub   al, 18
0040146D    8A2438          mov   ah, byte ptr
00401470    8A3431          mov   dh, byte ptr
00401473    38F4            cmp   ah, dh
00401475    75 7E         jnz   short 004014F5
00401477    83F9 08         cmp   ecx, 8
0040147A^ 72 D7         jb      short 00401453
这个是确定password的3到9位
004014CE    BE 23304000   mov   esi, 00403023                  ; ASCII "0123456789"
004014D3    A1 4A304000   mov   eax, dword ptr
004014D8    8A5E 09         mov   bl, byte ptr
004014DB    38D8            cmp   al, bl
004014DD    75 16         jnz   short 004014F5                   ; 又是比较
004014DF    B8 6C304000   mov   eax, 0040306C                  ; ASCII "Great Job!"
004014E4    8BD8            mov   ebx, eax
004014E6    83C3 0B         add   ebx, 0B
004014E9    6A 00         push    0
004014EB    50            push    eax
004014EC    53            push    ebx
004014ED    6A 00         push    0
004014EF    E8 B4000000   call    <jmp.&user32.MessageBoxA>


这个是最后位password的确定,过了就call出正确的MessageBoxA来最后一位的确定是password前九位之和除以9的商
下面是对应的注册机代码,是用c写的
#include <stdio.h>
#include <string.h>

const char biao = "ZWATRQLCGHPSXYENVBJDFKMU";

int main (void)
{
        char name, mima;
        int SumName, LenName, i, Temp;
        printf ("Name:");
        scanf("%s",name);
        SumName = 0;
        LenName = 0;
        LenName = strlen(name);
        //printf("%d",LenName);
        for (i = 0; i < LenName; i++)
        {
                SumName = SumName + (int)name;////求出用户名字节之和到SunName
                if (SumName > 255)
                {
                SumName = SumName - 256;
                }
        }

        mima = 'E';//密码第二位必须为E
        mima = biao;//密码第一位
        Temp = SumName % 24 + SumName % 24;
        if (Temp > 24)
        {
                Temp = Temp - 24;
        }
        mima = biao;//密码第三位
        for (i = 3; i <= 8;i++)//循环求出密码4到9位
        {
                Temp = (int)mima - 65 + Temp;
                if (Temp > 24)
                {
                        Temp = Temp - 24;
                }
                mima = biao;
        }
        Temp = 0;
        for (i = 0; i < 9; i++)
        {
                Temp = Temp + (int)mima;
        }
        Temp = Temp / 9;//最后一位前九位之和除以长度
        //printf ("\n%c\n",Temp);
        mima = (char)Temp;
        printf("PASSWORD:");
        for (i = 0; i < 10; i++)
        {
                printf ("%c",mima);
        }
        printf ("\n");
        return 0;
}




看来注册机大家应该明白很多了吧罗罗嗦嗦讲了一大堆,希望大家能够明白我的意思!最后把附件给传上来


紫薰 发表于 2011-10-23 21:03

这个很给力啊!感谢分享

火星 - 地球上没有新新鲜事...
http://huoxing.de

willJ 发表于 2011-10-23 21:12

回复 紫薰 的帖子

希望以后多多和大家交流

tys5234 发表于 2011-10-23 23:19

用易语言写是不是简单点

willJ 发表于 2011-10-24 08:32

回复 tys5234 的帖子

惭愧,我不会E语言也。。。

love815 发表于 2011-10-24 09:12

分析得不错哦,

鬼刀 发表于 2011-10-24 11:26

很不错 学习了

Tiger 发表于 2011-10-24 15:42

很不错的 学习了,谢谢

Shiny 发表于 2011-10-24 20:48

{:1_932:}膜拜 牛逼

willJ 发表于 2011-10-25 15:15

回复 Shiny 的帖子

应该我膜拜你,你都是独步武林了,我是菜鸟
页: [1] 2 3 4
查看完整版本: 菜鸟分析下一个简单的KeyGenMe软件