一个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 最后
别下次了,就这次,评分吧!!! 厉害厉害
贴源码
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;
} NuclearEngine 发表于 2020-3-31 22:04
厉害厉害
贴源码
PS :初中学的幼儿园算法(异或)
我也是断断续续逆了一天逆出来。。{:301_1008:} 看不懂。但是觉得很厉害。我没在水。。说真的 感谢分享!!! 谢谢分享 能被Sound大佬加20分我想一定是个好贴。 膜拜大佬 感谢分享
页:
[1]
2