growuphappily 发表于 2020-3-31 21:29

一个KenGenMe的算法

本帖最后由 growuphappily 于 2020-4-1 09:30 编辑

0x00 前言
今天在逛CM区时就看到了这个KenGenMe
原帖名称:一个中等难度的算法逆向。。。
原帖地址:https://www.52pojie.cn/thread-1144833-1-1.html
作者:NuclearEngine
0x01 开搞
程序有VMP壳,所以直接带壳分析吧
程序长这样

是一个密匙生成器
直接来看关键算法吧
00301B70    55            push ebp
00301B71    8BEC            mov ebp,esp
00301B73    51            push ecx
00301B74    B8 B04C4600   mov eax,KeyGenMe.00464CB0                ; ASCII "www.52pojie.cn"
00301B79    8BC8            mov ecx,eax
00301B7B    EB 03         jmp short KeyGenMe.00301B80
00301B7D    8D49 00         lea ecx,dword ptr ds:
00301B80    8A10            mov dl,byte ptr ds:
00301B82    40            inc eax
00301B83    84D2            test dl,dl
00301B85^ 75 F9         jnz short KeyGenMe.00301B80
00301B87    53            push ebx
00301B88    56            push esi                                 ; KeyGenMe.00464CBC
00301B89    57            push edi                                 ; KeyGenMe.00464D1A
00301B8A    BF 004D4600   mov edi,KeyGenMe.00464D00                ; ASCII "www.52pojie.cnwww.52pojie."
00301B8F    2BC1            sub eax,ecx                              ; eax为长度
00301B91    8BF1            mov esi,ecx
00301B93    4F            dec edi                                  ; KeyGenMe.00464D1A
00301B94    8A4F 01         mov cl,byte ptr ds:
00301B97    47            inc edi                                  ; KeyGenMe.00464D1A
00301B98    84C9            test cl,cl
00301B9A^ 75 F8         jnz short KeyGenMe.00301B94
00301B9C    8BC8            mov ecx,eax
00301B9E    C1E9 02         shr ecx,0x2
00301BA1    F3:A5         rep movs dword ptr es:,dword ptr ds>
00301BA3    8BC8            mov ecx,eax
00301BA5    83E1 03         and ecx,0x3
00301BA8    B8 B04C4600   mov eax,KeyGenMe.00464CB0                ; ASCII "www.52pojie.cn"
00301BAD    F3:A4         rep movs byte ptr es:,byte ptr ds:[>
00301BAF    8BC8            mov ecx,eax
00301BB1    8A10            mov dl,byte ptr ds:
00301BB3    40            inc eax
00301BB4    84D2            test dl,dl
00301BB6^ 75 F9         jnz short KeyGenMe.00301BB1
00301BB8    BF 004D4600   mov edi,KeyGenMe.00464D00                ; ASCII "www.52pojie.cnwww.52pojie."
00301BBD    2BC1            sub eax,ecx                              ; 计长度
00301BBF    8BF1            mov esi,ecx
00301BC1    4F            dec edi                                  ; KeyGenMe.00464D1A
00301BC2    8A4F 01         mov cl,byte ptr ds:
00301BC5    47            inc edi                                  ; KeyGenMe.00464D1A
00301BC6    84C9            test cl,cl
00301BC8^ 75 F8         jnz short KeyGenMe.00301BC2
00301BCA    8BC8            mov ecx,eax
00301BCC    C1E9 02         shr ecx,0x2
00301BCF    F3:A5         rep movs dword ptr es:,dword ptr ds>
00301BD1    8BC8            mov ecx,eax
00301BD3    83E1 03         and ecx,0x3
00301BD6    B8 004D4600   mov eax,KeyGenMe.00464D00                ; ASCII "www.52pojie.cnwww.52pojie."
00301BDB    F3:A4         rep movs byte ptr es:,byte ptr ds:[>
00301BDD    8D50 01         lea edx,dword ptr ds:
00301BE0    8A08            mov cl,byte ptr ds:
00301BE2    40            inc eax
00301BE3    84C9            test cl,cl
00301BE5^ 75 F9         jnz short KeyGenMe.00301BE0
00301BE7    2BC2            sub eax,edx                              ; KeyGenMe.00464C00
00301BE9    BA 01000000   mov edx,0x1
00301BEE    8D78 FF         lea edi,dword ptr ds:
00301BF1    8955 FC         mov dword ptr ss:,edx         ; KeyGenMe.00464C00
00301BF4    8B0495 C0E84500 mov eax,dword ptr ds:
00301BFB    83F0 03         xor eax,0x3
00301BFE    33C9            xor ecx,ecx
00301C00    8BF0            mov esi,eax
00301C02    85FF            test edi,edi                           ; KeyGenMe.00464D1A
00301C04    0F88 7D000000   js KeyGenMe.00301C87
00301C0A    8D9B 00000000   lea ebx,dword ptr ds:
00301C10    8A81 B04C4600   mov al,byte ptr ds:
00301C16    02C1            add al,cl
00301C18    83FE 02         cmp esi,0x2
00301C1B    7F 2C         jg short KeyGenMe.00301C49
00301C1D    83FE 01         cmp esi,0x1
00301C20    75 11         jnz short KeyGenMe.00301C33
00301C22    0FBEC0          movsx eax,al
00301C25    83C0 03         add eax,0x3
00301C28    83F0 05         xor eax,0x5
00301C2B    3205 10E94500   xor al,byte ptr ds:
00301C31    EB 46         jmp short KeyGenMe.00301C79
00301C33    83FE 02         cmp esi,0x2
00301C36    75 41         jnz short KeyGenMe.00301C79
00301C38    0FBEC0          movsx eax,al
00301C3B    83C0 FD         add eax,-0x3
00301C3E    83F0 06         xor eax,0x6
00301C41    3205 14E94500   xor al,byte ptr ds:
00301C47    EB 30         jmp short KeyGenMe.00301C79
00301C49    83FE 03         cmp esi,0x3
00301C4C    75 0F         jnz short KeyGenMe.00301C5D
00301C4E    0FBE15 18E94500 movsx edx,byte ptr ds:
00301C55    0FBEC0          movsx eax,al
00301C58    83F0 07         xor eax,0x7
00301C5B    EB 0C         jmp short KeyGenMe.00301C69
00301C5D    83FE 04         cmp esi,0x4
00301C60    75 17         jnz short KeyGenMe.00301C79
00301C62    0FBE15 20E94500 movsx edx,byte ptr ds:
00301C69    0FBEC0          movsx eax,al
00301C6C    33C2            xor eax,edx                              ; KeyGenMe.00464C00
00301C6E    99            cdq
00301C6F    BB 19000000   mov ebx,0x19
00301C74    F7FB            idiv ebx
00301C76    8D42 41         lea eax,dword ptr ds:
00301C79    8881 004D4600   mov byte ptr ds:,al
00301C7F    41            inc ecx
00301C80    3BCF            cmp ecx,edi                              ; KeyGenMe.00464D1A
00301C82^ 7E 8C         jle short KeyGenMe.00301C10
00301C84    8B55 FC         mov edx,dword ptr ss:         ; user32.75C22F00
00301C87    42            inc edx                                  ; KeyGenMe.00464C00
00301C88    8955 FC         mov dword ptr ss:,edx         ; KeyGenMe.00464C00
00301C8B    83FA 0A         cmp edx,0xA
00301C8E^ 0F8E 60FFFFFF   jle KeyGenMe.00301BF4
00301C94    5F            pop edi                                  ; KeyGenMe.00464D1A
00301C95    5E            pop esi                                  ; KeyGenMe.00464CBC
00301C96    33C0            xor eax,eax
00301C98    5B            pop ebx
00301C99    8BE5            mov esp,ebp
00301C9B    5D            pop ebp
00301C9C    C3            retn
这是整个算法call
从一开始分析吧不要晕,坚持看下去,有很多代码是多余的
301B85这个jnz和上面三行是计算长度
这里有必要说一下这个计算长度是怎么工作的

00301B82    40            inc eax
00301B83    84D2            test dl,dl
00301B85^ 75 F9         jnz short KeyGenMe.00301B80

其中eax是一个字符串指针,指向字符串的第一个字符
eax
|
V
www.52pojie.cn终止字符(相当于C语言的\0)
此时在OD的寄存器窗口可以看到
EAX   XXXXXXXXASCII "www.52pojie.cn"
然后inc eax,就是把eax + 1
那么,eax就指向字符串的第二位了
    eax
      |
   V
www.52pojie.cn终止字符
此时在OD的寄存器窗口可以看到
EAX   XXXXXXXXASCII "ww.52pojie.cn"
就这样一直循环,直到eax指向终止字符,test eax,eax 是判断eax是否为零
`00301B8F    2BC1            sub eax,ecx                              ; eax为长度`
然后看这里,
这行把eax减去了ecx,ecx的值就是循环之前的eax的值
这么一减,长度就出来了
回归正题,下面的代码直到301BD6其实都没有什么用
看下一段关键算法
00301C0A    8D9B 00000000   lea ebx,dword ptr ds:
00301C10    8A81 B04C4600   mov al,byte ptr ds:
00301C16    02C1            add al,cl
00301C18    83FE 02         cmp esi,0x2
00301C1B    7F 2C         jg short KeyGenMe.00301C49
00301C1D    83FE 01         cmp esi,0x1
00301C20    75 11         jnz short KeyGenMe.00301C33
00301C22    0FBEC0          movsx eax,al
00301C25    83C0 03         add eax,0x3
00301C28    83F0 05         xor eax,0x5
00301C2B    3205 10E94500   xor al,byte ptr ds:
00301C31    EB 46         jmp short KeyGenMe.00301C79
00301C33    83FE 02         cmp esi,0x2
00301C36    75 41         jnz short KeyGenMe.00301C79
00301C38    0FBEC0          movsx eax,al
00301C3B    83C0 FD         add eax,-0x3
00301C3E    83F0 06         xor eax,0x6
00301C41    3205 14E94500   xor al,byte ptr ds:
00301C47    EB 30         jmp short KeyGenMe.00301C79
00301C49    83FE 03         cmp esi,0x3
00301C4C    75 0F         jnz short KeyGenMe.00301C5D
00301C4E    0FBE15 18E94500 movsx edx,byte ptr ds:
00301C55    0FBEC0          movsx eax,al
00301C58    83F0 07         xor eax,0x7
00301C5B    EB 0C         jmp short KeyGenMe.00301C69
00301C5D    83FE 04         cmp esi,0x4
00301C60    75 17         jnz short KeyGenMe.00301C79
00301C62    0FBE15 20E94500 movsx edx,byte ptr ds:
00301C69    0FBEC0          movsx eax,al
00301C6C    33C2            xor eax,edx                              ; KeyGenMe.00464C00
00301C6E    99            cdq
00301C6F    BB 19000000   mov ebx,0x19
00301C74    F7FB            idiv ebx
00301C76    8D42 41         lea eax,dword ptr ds:
00301C79    8881 004D4600   mov byte ptr ds:,al
00301C7F    41            inc ecx
00301C80    3BCF            cmp ecx,edi                              ; KeyGenMe.00464D1A
00301C82^ 7E 8C         jle short KeyGenMe.00301C10
这些就是真正的算法了
有很多跳转,都是根据esi的值来决定是否跳转的
但是我试了很多次,esi的值似乎是固定的值,是4
所以,算法就只有这些了
00301C0A    8D9B 00000000   lea ebx,dword ptr ds:
00301C10    8A81 B04C4600   mov al,byte ptr ds:
00301C16    02C1            add al,cl
00301C18    83FE 02         cmp esi,0x2
;中间省略.....
00301C62    0FBE15 20E94500 movsx edx,byte ptr ds:
00301C69    0FBEC0          movsx eax,al
00301C6C    33C2            xor eax,edx                              ; KeyGenMe.00464C00
00301C6E    99            cdq
00301C6F    BB 19000000   mov ebx,0x19
00301C74    F7FB            idiv ebx
00301C76    8D42 41         lea eax,dword ptr ds:
00301C79    8881 004D4600   mov byte ptr ds:,al
00301C7F    41            inc ecx
00301C80    3BCF            cmp ecx,edi                              ; KeyGenMe.00464D1A
00301C82^ 7E 8C         jle short KeyGenMe.00301C10
是不是很少了呢?
它会循环name长度*2次,其中第name长度+1次往后程序取出的字符都是终止字符(\0)
注册机:
#KeyGen000.py
def getLeftNumber(n1,n2):#取余数
    return int(float('0.' + str(n1 / n2).split('.')) * n2)
ecx = 0
name = input()
#name = 'www.52pojie.cn'
Serial = ''
for i in name:
    #print(ecx)
    #print(hex(getLeftNumber(ord(i) + ecx ^ 5,0x19)))
    #print(hex((ord(i) + ecx) ^ 5))
    Serial += chr(getLeftNumber((ord(i) + ecx )^ 5,0x19) + 0x41)
    ecx += 1
for ii in range(len(name)):
    Serial += chr(getLeftNumber((0 + ecx )^ 5,0x19) + 0x41)
    ecx += 1
print(Serial)
软件:
         
         (太大了,只能分卷上传,密码:52pojie.cn)

0x02 最后

别下次了,就这次,评分吧!!!

NuclearEngine 发表于 2020-3-31 22:04

厉害厉害
贴源码
PS :初中学的幼儿园算法(异或)
int caozuo={3,7,2,7,1,7,0,2,7,1,7};
int shuwei={5,6,7,8,5};
int chupro(int a,int b)
{
        int r2d=1;
        int bp=r1(a,b);
        if(r2d==1)
                bp=r2(a,b);
        int ans=a^b;
        return ans;
}
int chupro2(int a,int b)
{
        int r2d=1;
        int bp=r1(a,b);
        if(r2d==1)
                bp=r2(a,b);
        int ans=a^b;

        return ans;
}
int xadd(int a,int b)
{

        int r2d=1;
        int bp=r1(a,b);
        if(r2d==1)
                bp=r2(a,b);
        int heo=a+b;
        return heo^5;
}
int xjian(int a,int b)
{
        int r2d=1;
        int bp=r1(a,b);
        if(r2d==1)
                bp=r2(a,b);
        int cha=a-b;
        return cha^6;
}
int chen(int a,int b)
{
        int r2d=1;
        int bp=r1(a,b);
        if(r2d==1)
                bp=r2(a,b);
        int ji=a*b;
        return ji^7;
}
int chu(int a,int b)
{
        int r2d=1;
        int bp=r1(a,b);
        if(r2d==1)
                bp=r2(a,b);
        if(b==0) return 0;
        int shang=a/b;
        return shang^8;
}
char dy2(char a,int c)
{
        if(c==3)
        {
                a=chupro(chen(int(a),1.5),shuwei);
        }
        if(c==4)
        {
                a=chupro2(int(a),shuwei);
        }
        return a;
}

int mechine()
{
        strcat(pass,username);
        strcat(pass,username);
        int uslen=strlen(pass)-1;
        for(int w=1;w<=10;w++)
        {
                int wayt1=chupro(caozuo,3);
                for(int i=0;i<=uslen;i++)
                {
                        char ctr=username+i;
                        if(wayt1<=2)
                        {
                                if(wayt1==1)
                                {
                                        ctr=chupro(xadd(int(ctr),3),shuwei);
                                }
                                if(wayt1==2)
                                {
                                        ctr=chupro(xjian(int(ctr),3),shuwei);
                                }
                        }
                        if(wayt1>2)
                        {
                                if(wayt1==3)
                                {
                                        ctr=dy2(ctr,3)%25+65;
                                }
                                if(wayt1==4)
                                {
                                        ctr=dy2(ctr,4)%25+65;
                                }
                        }
                        pass=ctr;
                }
        }
        return 0;
}

growuphappily 发表于 2020-4-1 08:13

NuclearEngine 发表于 2020-3-31 22:04
厉害厉害
贴源码
PS :初中学的幼儿园算法(异或)


我也是断断续续逆了一天逆出来。。{:301_1008:}

兜OxO 发表于 2020-3-31 23:41

cullenlin123 发表于 2020-3-31 23:53

看不懂。但是觉得很厉害。我没在水。。说真的

ckypamym119 发表于 2020-4-1 00:38

感谢分享!!!

小橙吖 发表于 2020-4-1 01:01

谢谢分享

pwp 发表于 2020-4-1 04:38

能被Sound大佬加20分我想一定是个好贴。

飘缈孤鸿影 发表于 2020-4-1 07:31

膜拜大佬

爱奴 发表于 2020-4-1 08:08

感谢分享
页: [1] 2
查看完整版本: 一个KenGenMe的算法