首页
社区
课程
招聘
[原创]CrackMe01 by petnt(源码已经公布在19楼)
发表于: 2009-2-16 21:51 9900

[原创]CrackMe01 by petnt(源码已经公布在19楼)

petnt 活跃值
12
2009-2-16 21:51
9900
收藏
免费 7
支持
分享
最新回复 (23)
雪    币: 82
活跃值: (10)
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
2
最近流行xor解码.后面没看,线程里干完了就差不多了吧.
2009-2-16 23:34
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
3
呵呵,自己也感觉有点猥琐,防秒爆的下策。
其实和算法关系不大。
2009-2-16 23:37
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
4
有点像纳皮尔的骨头
2009-2-17 09:52
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
5
感谢关注。
其实这是个游戏,只不过验证的时候我变通了一下。
要不然太直观的话可能10分钟甚至更短就能出注册码了。

如果到今天15:00它还有幸活着,我放出些提示。
2009-2-17 13:07
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
6
刚开始以为是魔方阵, 但是看你验的方法又没见过
只好排除掉. 上网查了一下只剩纳皮尔的骨头可猜了.

坐着看别人的解答.
2009-2-17 13:56
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
7
我的想法来源于一个风靡世界的游戏
虽然我变通出来的验证数字可能让你摸不到头脑
但你可能从取数的位置上找到点启发.
就提示这些了..希望能过得了今天!
2009-2-17 15:29
0
雪    币: 233
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
难道是数独?
2009-2-17 15:34
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
9
请教sessiondiy个问题:
有段加密的代码f5过不去,想从中剔出来,有办法吗
2009-2-17 15:42
0
雪    币: 442
活跃值: (43)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
我是新手大家都知道

随便看了下,错得太严重别笑我

我觉得好像是

必须是8位数,字母就用ASCII码

然后

(前7位数的阶乘*7)/(前7位数的和+7)*(第一个数的^2+最后一个数^2+162)=2298240
2009-2-17 16:13
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
11
不知耶.
我很少用IDA
2009-2-17 16:20
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
12
错的不是太严重,但确实是错了.
2009-2-17 16:27
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
13
那个是假的吧

累乘 div 累加 = X 到底是什么东东
数学太烂实在无法理解.
有空再手写一组正确的号码好了.
先暴再说
上传的附件:
2009-2-18 01:36
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
14
0x534B6824 佩服一下,看来XOR对sessiondiy已经没有秘密可言!
累乘 div 累加 = X 到底是什么东东

我直接写 累加=45 累乘=362880 那我的这一处就把整个算法暴露完了!
虽然这样写不敢保证是唯一解,但符合我这么多处(4处)验证的解可能不太可能再找出一个!
前两处也是一个道理,其实能想到数独就一切迎刃而解了
2009-2-18 09:06
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
15
虽然还没有注册码给出,但算法和成功提示已经解开了,我放出一个注册码给兄弟们再玩一会.
我会在大家玩的差不多的时候放出源码.感谢大家关注.

petnt

2424-39014B6E-383D4EE5-1975D657-081FBBCA-25838D08-5567
2009-2-18 17:39
0
雪    币: 2316
活跃值: (129)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
16
支持下。。。
2009-2-18 18:15
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
17
建议以后考虑一下穷人的电脑
50ms对我来说是不可能的事
2009-2-19 10:20
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
18
不是吧?当时我也在想这个问题,如果同步,过于明显.所以就想50ms差不多了吧,试验的几次都还可以.我的电脑也不快,两年前买的本本了,不至于出现你说的情况吧.
2009-2-19 12:40
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
19
算法来源于数独游戏,数独原形为:
int shudu[9][9]={
            0,7,0,0,0,0,0,0,2,
            0,0,2,7,0,3,0,0,6,
            8,3,0,6,0,0,0,0,0,
            0,0,0,4,0,0,6,5,7,
            0,0,5,0,0,0,8,0,0,
            4,1,7,0,0,5,0,0,0,
            0,0,0,0,0,4,0,6,9,
            9,0,0,3,0,8,1,0,0,
            1,0,0,0,0,0,0,7,0
        };
思路:用用户名定位坐标,将注册码转换成数字填入数独中的0位。


void CCrackMe01Dlg::OnOK() 
{
  // TODO: Add extra validation here
  int sum=0,sum1=0,sum2=1,sum3=0,x=0,y=0;
  int nUsize=m_cUserName.GetWindowTextLength();
  int nSsize=m_cSn.GetWindowTextLength();
  CString cSn;
  CString chSn;
  UpdateData(TRUE);
    //利用用户名的定位:

  for(int i=0;i<nUsize;i++)
  {
    sum+=m_UserName[i];
  }
  x=(sum%81)/9;
  y=(sum%81)%9;

    //不用解释了吧,很简单的定位,x,y即为定位出来的坐标。

    //注册码的转换:

  for(i=0;i<nSsize;i++)
  {
    if(m_Sn[i]!=0x2d)
    {
      cSn=cSn+m_Sn[i];
    }
    else
    {
      i++;
      break;
    }
  }
  if (i>8) 
  {
    MessageBox("注册失败!");
    CDialog::OnOK();
    return;
  }
  for(int k=0;k<5;k++)
  {
    for(chSn="";i<nSsize;i++)
    {
      if(m_Sn[i]!=0x2d)
      {
        chSn=chSn+m_Sn[i];
      }
      else
      {
        i++;
        break;
      }
    }
    chSn.Format("%d",(strtoul(chSn,NULL,16)==-1)?1:strtoul(chSn,NULL,16));
    cSn+=chSn;
  }
  for(;i<nSsize;i++)
  {
    if(m_Sn[i]!=0x2d)
    {
      cSn=cSn+m_Sn[i];
    }
    else
    {
      i++;
      break;
    }
  }
    //正确注册码第一部分为(以"-"分割)十进制数字,中间5部分为十六进制数字,第7部分为十进制数字(不足7部分可以,再长就不处理了)。
    //本想不这么麻烦的,用户直接写入10进制数字填进表里就OK的,后来为了迷惑观众,写的复杂了一点。

    //下面工作就是写入表格了:

  for(k=0,i=0;i<nSsize;i++)
  {
    
    for(;x<9;x++)
    {
      for(;y<9;y++)
      {
        if (shudu1[x][y]==0) break;
      }
      if (y==9) 
      {
        y=0;
        continue;
      }
      if (shudu1[x][y]==0) break;
    }
    if (x==9) 
    {
      x=0;
      k++;
      if (k<2) 
      {  
        i--;
        continue;
      }
      else break;
    }
    shudu1[x][y]=cSn[i]-0x30;
  }

    //下面的代码想给大家留下反调试的印象,实际上在为新进程运行赢得时间。
    //正如sessiondiy提到的,50ms在反应慢的机子上可能达不到效果,也就是永远也看不到注册成功。


  i=GetTickCount();
  ::CreateThread(NULL,NULL,ThreadProc,this,0,NULL);   //次线程中也有验证代码
  Sleep(50);
  k=GetTickCount();

    //下面为验证代码:(验证方法有些猥琐,没敢直接判断9个数字各不相同)
  //验证横竖格中的数字

  for (x=0;x<9;x++)
  {
    for(sum1=0,sum2=1,sum3=0,y=0;y<9;y++)
    {
      sum1+=shudu1[x][y];//45
      sum2*=shudu1[x][y];//362880
      sum3=sum3+shudu1[y][x]*shudu1[y][x];//=285
    }
    if((sum2/sum1)*sum3!=0x231180 || (k-i)<50 )
    {
      MessageBox("注册失败!");
      CDialog::OnOK();
      return;
    }
    else    //本想用它迷惑观众,后来才发现被C++优化掉了
    {
      if((sum2/sum1)*sum3==0x231180&& (k-i)<50)
      MessageBox("恭喜你,成功!");
      CDialog::OnOK();
      return;
    }
  }
  MessageBox("注册失败!");
  CDialog::OnOK();
}

//线程函数代码
DWORD WINAPI ThreadProc(LPVOID lpPara)
{

  int data[256]=
  {  0x119BA09E, 0x6649E324, 0x2942065D, 0x08F16AAD, 0x354B283F, 0x463F6AE3,0xe7
    //0x42D0C8BA, 0x35028B00, 0x7A096E79, 0x5BBA0289, 0x6600401B, 0x157402C7,0xc3
  };

  int shu[9][9];
  memcpy(shu,(((CCrackMe01Dlg *)lpPara)->shudu1),sizeof shu);//这里有些浪费
  //下面是验证9个小方格中的数字
  for(int x=0,y=0,i=0;i<9;i++)
  {
    x=(i/3)*3;
    y=(i%3)*3;
    for(int j=0,sum1=0,sum2=1;j<3;j++)
    {
      for(int k=0;k<3;k++)
      {
        sum1+=shu[x+j][y+k];
        sum2*=shu[x+j][y+k];
      }
    }
    if (sum2/sum1!=8064)
    {
      return 0;
    }

  }
  //利用部分数字得到解码key
  int sum=0,temp , k;
  for(k=0;k<4;k++)
  {
    temp=shu[6][k];
    _asm
    {        
      mov eax,temp
      mov edx,eax
      rol eax,13
      xor eax,0x14d28209
      add sum,eax
    }
  }
  //解码
  for(i=0;i<7;i++)
  {
    data[i]=data[i]^sum;
  }
  //分配内存并执行,刚学vc++,好多的实现方法都不会,中间加了汇编
  void *newaddr=VirtualAlloc(NULL,0x100,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  
  {
    memcpy(newaddr,data,25);
    _asm
    {
      mov eax,newaddr
      call eax
    }
  }
  //下面就是要运行的代码
/*  _asm
  {
    mov edx,0x42d0c8
    mov eax,dword ptr[edx]
    xor eax,0x7a096e79       //将提示中的"失败"改为"成功"
    mov dword ptr [edx],eax
    mov edx,0x401b5b
    mov word ptr[edx],0x1574 //修改关键代码
    ret
  }*/
  return 0;
}

//构造函数中的代码
CCrackMe01Dlg::CCrackMe01Dlg(CWnd* pParent /*=NULL*/)
  : CDialog(CCrackMe01Dlg::IDD, pParent)
{
  //省略了无关部分
  int shudu[9][9]={
            0,7,0,0,0,0,0,0,2,
            0,0,2,7,0,3,0,0,6,
            8,3,0,6,0,0,0,0,0,
            0,0,0,4,0,0,6,5,7,
            0,0,5,0,0,0,8,0,0,
            4,1,7,0,0,5,0,0,0,
            0,0,0,0,0,4,0,6,9,
            9,0,0,3,0,8,1,0,0,
            1,0,0,0,0,0,0,7,5
        };
  //可能大家已经注意到了最后一个数字是5而不是我前面给出的0,这是我另一个感觉猥琐的地方,下面会提到

  memcpy(shudu1,shudu,sizeof shudu1);
  DWORD oldProtect=0;
  
  void *addr=(LPVOID)0x401b5b;
  VirtualProtect(addr,8,PAGE_EXECUTE_READWRITE,&oldProtect);
  _asm
  {
    mov edx,addr
    mov word ptr[edx],0x1575
  }
  //上面的代码是在防爆破,也为我在线程中更改此处代码埋下伏笔。
}

//下面是猥琐的代码,请原谅我在说明中没有提到anti 及自校验的字眼,这个函数被用在了CCrackMe01Dlg::OnInitDialog()中
void CCrackMe01Dlg::ImportCheck()
{
  PIMAGE_NT_HEADERS pNtHeader=NULL;
  PIMAGE_DOS_HEADER pDosHeader=NULL;
  PIMAGE_IMPORT_DESCRIPTOR pIpt=NULL;
  DWORD pImageBase=NULL;
  
  //下面的代码将检查程序导入表中的函数是否被下了断点(前5个字节)
  _asm //当时是为了不留下痕迹才这样写的
  {
    mov eax,4
    shl eax,20
    mov pImageBase,eax
  }

  pDosHeader=(PIMAGE_DOS_HEADER)pImageBase;
  if(pDosHeader)
  {
    pNtHeader=(PIMAGE_NT_HEADERS)((pDosHeader->e_lfanew)+pImageBase);
    pIpt=(PIMAGE_IMPORT_DESCRIPTOR)((pNtHeader->OptionalHeader.DataDirectory[1].VirtualAddress)+pImageBase);
    
    for(PIMAGE_THUNK_DATA pIat;pIpt->FirstThunk||pIpt->ForwarderChain||pIpt->Name\
        ||pIpt->OriginalFirstThunk||pIpt->TimeDateStamp;pIpt++)
    {
      pIat=(PIMAGE_THUNK_DATA)(pIpt->FirstThunk+pImageBase);
      
      for(;pIat->u1.Function;pIat++)
      {
        char* iscc=(char*)(pIat->u1.Function);
        for(int i=0;i<5;++i,iscc++)
        {
          if((BYTE)(*iscc^0x12)==0xde)
          {
            return;
            //Cracker found!
          }
        }
      }
    }
  }
  //下面的代码是检测程序载入内存后代码段的校验值是否正确
  int codes=0x401,codee=0x424; //其实这样没效果,被优化了。
  codes*=0x1000;
  codee*=0x1000;
  for(int sum=0;codes<codee;codes++)
  {
    _asm
    {
      mov ecx,codes  
      movzx eax,byte ptr[ecx]
      mov edx,eax
      rol eax,19
      xor eax,edx
      add sum,eax
    }
  }
  if (sum==pNtHeader->OptionalHeader.CheckSum)
    shudu1[8][8]=0;//correct
  //看见了吗?这就是猥琐的所在,如果没通过检查,你面对的数独是一个死局!
  //请原谅我这么做,这可能浪费了你的时间,再次对此猥琐做法致歉。

}

如有疑问或建议,请跟帖,再次谢谢关注
2009-2-19 20:40
0
雪    币: 268
活跃值: (95)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
20
[QUOTE=petnt;580490]算法来源于数独游戏,数独原形为:
int shudu[9][9]={
          &...[/QUOTE]

学到不少,谢谢petnt~
2009-2-21 00:46
0
雪    币: 150
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
只想对MFC说
去他X的...
2009-2-21 01:15
0
雪    币: 209
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
很有意思的一个东西啊看了源码才知道
2009-2-22 17:49
0
雪    币: 64
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
呵呵 新手学习一下哈
2009-9-6 13:54
0
雪    币: 420
活跃值: (77)
能力值: ( LV13,RANK:500 )
在线值:
发帖
回帖
粉丝
24
petnt兄 。。。。
2009-9-7 09:57
0
游客
登录 | 注册 方可回帖
返回
//