风之非觞 发表于 2009-10-21 22:21:13

占楼,分析看看

2005ljb 发表于 2009-10-21 22:44:06

用户名:hhwsljb
注册码:52C92
没学过编程,不会写注册机。。。/:L /:L /:L

cell 发表于 2009-10-21 23:48:32

诶。。现在的技术只能爆破。。算法位置知道,只是算法分析不会。。抽空补习补习。。

pptppt 发表于 2009-10-22 00:08:51

好热闹啊,支持猫兄!/:good
name:pptppt
code:1=7>6   也不知道这个是什么算法?应该是1=7-6吧,呵呵,开个玩笑!

算法:F1(x)=F2(y),这样就可以做到内存中不出现明码了,但函数可逆的话,逆推就可以得到注册码了。/:017

MOV 发表于 2009-10-22 00:14:55

楼上 就是是高手啊呵呵

hflywolf 发表于 2009-10-22 00:32:12

code:1=7>6   也不知道这个是什么算法?应该是1=7-6吧,呵呵,开个玩笑!


1=7>6 等式是成立的7本来就大于6 /:017逆推需要技巧,目前在研究中。。。。/:L

先贴个伪代码给大家看看(加了点注释,凑合着看吧)

对话框的回调函数伪代码如下:


signed int __stdcall DialogFunc(HWND a1, UINT a2, WPARAM a3, LPARAM a4)
{
int v4; // eax@6
signed int result; // eax@8
int v6; // eax@22
__int16 v7; // ST0E_2@22
HICON v8; // eax@4
HWND v9; // eax@4
LONG v10; // eax@4
HWND v11; // eax@4
LONG v12; // eax@4
LRESULT v13; // eax@8
HFONT v14; // eax@8
DWORD v15; // eax@8
HWND hWnd; // @4
HANDLE ho; // @8
char pv; // @8
char v19; // @8
ints; // @21
int v21; // @22
__int16 v22; // @24

if ( a2 == 16 )
{
    EndDialog(a1, 0);
    return 1;
}
if ( a2 == 272 )
{
    v8 = LoadIconA(hInstance, (LPCSTR)0x3E8);
    SendMessageA(a1, 0x80u, 1u, (LPARAM)v8);
    hCursor = LoadCursorA(hInstance, (LPCSTR)0x7D0);
    v9 = GetDlgItem(a1, 110);
    hWnd = v9;
    v10 = SetWindowLongA(v9, -4, (LONG)sub_40135B);
    SetWindowLongA(hWnd, -21, v10);
    v11 = GetDlgItem(a1, 111);
    hWnd = v11;
    v12 = SetWindowLongA(v11, -4, (LONG)sub_40135B);
    SetWindowLongA(hWnd, -21, v12);
    return 1;
}
if ( a2 == 312 )
{
    v4 = GetDlgCtrlID((HWND)a4);
    if ( v4 != 110 && v4 != 111 )
    {
      result = 0;
    }
    else
    {
      v13 = SendMessageA((HWND)a4, 0x31u, 0, 0);
      ho = (HANDLE)v13;
      GetObjectA((HANDLE)v13, 60, &pv);
      v19 = 0;
      v14 = CreateFontIndirectA((const LOGFONTA *)&pv);
      ho = v14;
      SelectObject((HDC)a3, v14);
      SetTextColor((HDC)a3, 0xFF0000u);
      v15 = GetSysColor(15);
      SetBkColor((HDC)a3, v15);
      DeleteObject(ho);
      result = (signed int)GetStockObject(5);
    }
    return result;
}
if ( a2 != 273 )
    return 0;
if ( a3 != 1 )
{
    if ( a3 == 2 )
      EndDialog(a1, 0);
    return 1;
}
if ( !GetDlgItemTextA(a1, 101, &String, 200) )         //以上都是跟窗口消息有关的,从这里开始就是算法部份了
{
LABEL_29:
    SetDlgItemTextA(a1, 104, "输入的序列号不正确");
    return 1;
}
if ( byte_403000 != 2 && byte_403000 != 3 )   //byte_403000存放的值是用来判断程序是使用keymark注册机三种对话框样式的其中一种
{
    if ( byte_403000 == 3 && !GetDlgItemTextA(a1, 103, byte_403350, 200) )
      goto LABEL_29;
}
else
{
    if ( !GetDlgItemTextA(a1, 102, byte_403288, 200) )
      goto LABEL_29;
}
dword_4031BC = (int)& s;
if ( (char)((unsigned int)lstrlenA(byte_403288) >> 2) > 2 )//注册码长度不能大于11(汗,我猜是不能大于8吧 codelen / 4 < 2)
    goto LABEL_36;
v21 = sub_401494((unsigned __int8 *)byte_403288) + 2009;   //调用sub_401494 CALL 将注册码计算得到某个值再+2009 记为 h1
ho = 0;
v6 = lstrlenA(&String);
v7 = v6;
do
{
    LOWORD(ho) = *(_BYTE *)(v6 + 4207039) + (_WORD)ho;   //这个循环是依次将用户名各位上的字符ASCII值进行累加记sun
    LOBYTE(v6) = (_BYTE)v6 - 1;
}
while ( (_BYTE)v6 );
LOWORD(hWnd) = v7;                                 //v7=用户名长度
v22 = (unsigned __int8)String;
__asm
{
    finit
    fild    word ptr                         
    fidiv   word ptr                         // sun / 用户名长度
    frndint                                          // 取整(sun) (四舍五入)
    fiadd   word ptr                         // 取整(sun)+用户名长度
    fild    word ptr
    fild   
    fxch    st(1)                              
    fprem                                              // sun mod 用户名第一个字符的ASCII值
    fmulp   st(1), st                                  // 上面的求的的余数 * 用户名第一个字符的ASCII值
    faddp   st(1), st                                  // 上面的积 + (取整(sun)+用户名长度)
    fld   flt_403042                                 // 403042 存放个浮点数 121.0
    fmulp   st(1), st                                  // 121.0 * (上面的积 + (取整(sun)+用户名长度)) 记为h2
    fisub                                 // h1=h2-h1看是否为0
    fist                                  
}
if ( v21 )                                           //为0则注册成功
LABEL_36:
    ExitProcess(0);
sub_4014E4((int)"Q29uZ3JhdHVsYXRl", (int)Text);   //调用解密字符串的CALL
sub_4014E4((int)"R29vZCBKb2Ih", (int)Caption);
MessageBoxA(0, Text, Caption, 0x40u);
while ( & s != (int *)dword_4031BC )
    ;
SetDlgItemTextA(a1, 104, "BY WildCatIII 091021");
return 1;
}

sub_401494的伪代码如下:


int sub_401494(unsigned __int8 *a1)//*a1传入的参数就是存放注册码的首地址
{
unsigned __int8 *v1; // edi@1
char v2; // dl@3
int v3; // ebx@3
unsigned __int8 *v4; // edi@3
signed int v5; // esi@3
unsigned __int8 v6; // al@4
char v7; // al@5
char v9; // al@2
int v10; // esi@3

v1 = a1;
do
    v9 = *v1++;
while ( v9 );
v10 = a1 - v1;
v3 = 0;
v4 = a1;
v2 = 0;
v5 = ~v10;//v5就是注册码的长度
while ( v5 )
{
    v6 = *v4;
    if ( *v4 < 0x41u )   //0x41 就是字符"A"的ASCII值
    {
      v7 = v6 - 48;      //小于0x41 就将字符的ASCII值减去0x30(字符"0"的ASCII值)
    }
    else
    {
      v2 = 32 * ((v6 < 0x57u) + v2);    //0x57 就是字符"W"的ASCII值,这里用v6和0x57比较,作用是如果v6小于0x57 用1和v2相加,如果不小于就用0和v2相加
      v7 = v2 + v6 - 87;
    }
   (v7 & 0xF) << 4 * ((_BYTE)v5 - 1);//这里相当于v3 += (v7 mod 16)^(4*(注码长度-1))
    ++v4;
    --v5;
}
return v3;

}


最后告诉大家一个秘密就是:
F8到下面这条指令时
004012BA   .DA65 F4       fisub   dword ptr

看下St(0)的值 或看下"提示信息"窗口(就是反汇编窗口与数据窗口之间那个地方)中"st=" 后面的数值
用这个数值减下2009 然后转成十六进制就是注册码了(那个sub_401494的CALL有点心猥琐/:017)

[ 本帖最后由 hflywolf 于 2009-10-25 10:07 编辑 ]

MOV 发表于 2009-10-22 01:24:34

楼上都不知道该有什么来称呼你/:good /:good /:good

hackwm 发表于 2009-10-22 01:50:15

明天尝试下看看能否逆出一样的KeyMakeMe不

lixy8888 发表于 2009-10-22 08:09:00

来晚了哈

wan 发表于 2009-10-22 09:02:26

楼上的狼好猛,全逆出来了~
页: 1 2 [3] 4
查看完整版本: KeyMakeMe 20091021