首页
社区
课程
招聘
[下载]剑走偏锋姊妹篇--模拟注册获取注册码
发表于: 2009-9-23 21:44 10754

[下载]剑走偏锋姊妹篇--模拟注册获取注册码

2009-9-23 21:44
10754
【文章标题】: 剑走偏锋姊妹篇--模拟注册获取注册码
【文章作者】: xuecrack
【软件名称】: GIF Movie Gear V4.2汉化版
【下载地址】: 自己搜索下载
【使用工具】: WinHex, Spy,VC6.0中文版
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】

  首先声明一下:本文没有高深的技术,纯粹一些总结,高手可一笑飞过。另作者水平有限,错误难免,若各位大侠不吝赐教
  则幸甚乐甚!
  
  上次写了一篇文章《剑走偏锋,另辟蹊径获取加密信息》( http://bbs.pediy.com/showthread.php?t=97156)讲从内存中
  获取闪讯用户用户名和密码信息的,写的不甚详细。今天这篇文章也是讲从内存中获取信息的,不过是在一系列的模拟手工
  操作之后。
  
  
  
  【本文思路】
  模拟一系列的手工操作,然后从软件内存中获取我们所要的信息。当反汇编发现算法流程很繁复甚至一时半会无法分析出的
  时候,抑或想偷懒^_^也可以参考这种方法。
  
  【本文所提方法适用条件】
  1、通过一系列操作之后,所需获取的信息某一时机以明文方式出现在软件内存中
  2、所需获取的信息有一定规则,可识别
  
  GIF Movie Gear V4.2汉化版正符合以上条件。GIF Movie Gear V4.2内存截图如下:红色的是注册码,蓝色的是用户名



  
  
  
  
  【通常注册共享软件的方法】
  运行软件,点击“注册”或“激活”菜单,在注册窗口填写注册信息,确认,软件对输入的信息进行计算,符合一定的条件
  则注册成功,否则注册失败。
  
  今天拿来开刀的是一个gif图片制作软件“GIF Movie Gear”,这个软件的算法分析文章网上很多,本文不分析算法,只是
  模拟其注册的每一个过程,然后在内存中窃取注册信息。
  
  【GIF Movie Gear的手工注册流程】
  
  1、双击运行GIF Movie Gear的可执行文件movgear.exe,弹出程序主窗口。
  2、点击菜单“帮助”-“注册”弹出注册窗口。
  3、填写用户名,注册码后单击“确定”按钮。
  4、软件计算,或注册成功或注册失败,弹出消息框提示。
  
  过程截图如下




  
  
  【我的想法】:用模拟完成以上步骤,只要输入用户名,就能获取到对应注册码。略去细节,大致流程:
  A、用ShellExecute执行movgear.exe。
  
  B、用FindWindow 获取主窗口句柄,找到“注册”菜单标识,给其投递 WM_COMMAND 消息,模拟点击菜单,弹出注册窗口。
  
  C、通过 GetWindow 函数得到注册窗口的句柄。
     获取注册窗口“用户名”文本框句柄,给其发送 WM_SETTEXT 消息,模拟填写用户名。
     获取注册窗口“确定”按钮句柄,发送 BM_CLICK 消息,模拟点击“确定”按钮。
     这里要注意的是,这软件只填写用户名就会调用注册码计算代码,不管所填注册码是否为空,所以上面不需要模拟填写
     注册假码。
  
  D、打开GIF Movie Gear程序进程,在一定内存地址范围内搜索注册码,并获取之,然后用 TerminateProcess 终止GIF 
     Movie Gear进程,并输出有效注册码。
  
  上面ABCD四个步骤对应前面的1234流程。
  
  我写了个小程序,就像一个黑匣子,对内输入用户名,对外显示正确的注册码。程序运行界面如下:



  细节请参考我写的代码,注释很详细,VC6.0平台,Win Xp Sp3下编译通过。
  


/****************************************************************
程序作用:  自动获取 GIF Movie Gear 注册码
程序原理:  
程序作者:  wyART QQ:243261920
代码日期:  2009-09-022
修改日期:  2009-09-023
****************************************************************/

#include<iostream>
#include<windows.h>
using namespace std;
int main(int argc, char* argv[])
{
  
  DWORD  pId,dwRdAddr;
  BYTE  RdData,RdData1,RdData2;
  BYTE  UsrKey[40];
  char  userName[100];
  char  st[100];
  
  //改变控制台标题,外观
  system("title GIF Movie Gear KeYgEn");
  system("color 0a");

  //执行movgear.exe 程序
  ShellExecute(NULL,"open","movgear.exe",NULL,NULL,SW_HIDE);
     //等待程序初始化完成           
  Sleep(1000);

  //获取GIF Movie Gear主窗口句柄
  HWND    hWnd=FindWindow("GIF Movie Gear","GIF Movie Gear");
  if (0==hWnd)
  {
    cout<<"Get GIF Movie Gear Window Handle Error ! "<<endl;
    return 0;
  }

  //投递消息,模拟鼠标点击“帮助”-->“注册”菜单,40036可由测试得到
  PostMessage(hWnd,WM_COMMAND,40036,NULL);

  //为注册窗口生成等待时间
  Sleep(200);

  //获取注册窗口句柄,方法用SPY查看
  HWND HwndSubWnd=GetWindow(hWnd,GW_HWNDPREV);
  HwndSubWnd=GetWindow(HwndSubWnd,GW_HWNDPREV);
  
  if (0==HwndSubWnd)
  {
    cout<<"Get Reg Window Handle Error!"<<endl;
    return 0;
  }
  //为不影响控制台程序操作,隐藏注册窗口
  ShowWindow(HwndSubWnd, SW_HIDE); 

  //使控制台程序重新获得焦点
  HWND hConsole=FindWindow(NULL,"GIF Movie Gear KeYgEn");
  if(hConsole)
    SetForegroundWindow(hConsole);


  //获取注册窗口“用户名”文本框句柄
  HWND HwndEdit=FindWindowEx(HwndSubWnd,NULL,"Edit",NULL);
  if (0==HwndEdit)
  {
    cout<<"Get RegWindow Edit Control Handle Error!"<<endl;  
    return 0;
  }

  cout<<"Please Input UserName: ";
  cin>>userName;

  //发送消息,设置注册窗口“用户名”文本框文字
  SendMessage(HwndEdit,WM_SETTEXT,0,(LPARAM)(LPCTSTR)(userName));  

  //获取注册窗口“确定”按钮句柄
  HWND HwndCmdOK=FindWindowEx(HwndSubWnd,NULL,"Button","确定");
  if (0==HwndCmdOK)
  {
    cout<<"Get RegWindow Command OK's Handle Error!"<<endl;
    return 0;
  }

  //向注册窗口“确定”按钮投递单击消息
  PostMessage(HwndCmdOK,BM_CLICK,0,0);

  //获取主窗口线程ID
  DWORD threadID=GetWindowThreadProcessId(hWnd,&pId);

  //打开主窗口进程,获取进程句柄
  HANDLE hPro= OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE ,FALSE,pId);
  if(NULL == hPro)
  {
    cout<<"Can't Open    GIF Movie Gear    Memory!"<<endl;
    return 0;
  }

  //在范围13a000h~140000h内查找闪讯用户信息,该范围由经验而得
  //注册码形式 “FSXPQN-DTHKSP-Z8YT2T-2ARCFK”
  //识别注册码的简单方法,读取到第一个“-”出现的位置,位置加7仍为“-”,位置加14仍然是“-”,则可以断定是注册码
  dwRdAddr=0x13a000;
  while (dwRdAddr<0x140001)
  {
    ReadProcessMemory(hPro,(LPVOID)dwRdAddr,&RdData,1,NULL);
    if (RdData==45)           //"-"
    {  
      ReadProcessMemory(hPro,(LPVOID)(dwRdAddr+7),&RdData1,1,NULL);
      ReadProcessMemory(hPro,(LPVOID)(dwRdAddr+14),&RdData2,1,NULL);
      if (RdData1==45 && RdData2==45 )         //"-"      
        break;    
    
    }
      
    dwRdAddr++;
  }

  //读取信息失败就关闭进程句柄,退出程序
  if(dwRdAddr>0x140000)
  {
    cout<<"读取信息失败!"<<endl;
    CloseHandle(hPro);
    return 0;
  }
  //赋值 dwRdAddr 为注册码开始的位置
  dwRdAddr-=6;

  //输出注册码开始的内存地址的十六进制值
  cout<<"RegCode Address: 0x"<<hex<<dwRdAddr<<endl;

  //把注册码读取到UsrKey
  ReadProcessMemory(hPro,(LPVOID)dwRdAddr,UsrKey,28,NULL);
  TerminateProcess(hPro,0);
  CloseHandle(hPro);
  
  //格式化十六进制值为ASCII格式注册码
  sprintf(st,"%s",UsrKey);

  //输出注册信息
  cout<<endl<<"RegUser: "<<userName<<endl;
  cout<<"RegCode: "<<st<<endl;

  //暂停
  system("pause >nul"); 
  return 0;
}


  
--------------------------------------------------------------------------------

  【一点随想】
  1、很多东西完全搞懂,完全弄明白固然很好,但是很多事情我们是没有时间去弄明白,搞清楚的。就像我们的文字是汉字,
  汉字是谁的发明不可考了;就像我们整天用电脑,我们未必需要具体知道CPU的细节,主板的每个元件。时光匆匆,有些东
  西好用、会用就行。

  2、虽然解决问题的方法有高低之分,但是能实质性分析并解决问题也不错。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年09月23日

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (20)
雪    币: 403
活跃值: (29)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
2
不好意思,分类搞错了,  我这里改不了
请斑竹帮下忙,改成“【分享】剑走偏锋姊妹篇--模拟注册获取注册码 ”,感谢!
2009-9-23 21:47
0
雪    币: 238
活跃值: (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
厉害,这个办法好强呀
2009-9-24 00:09
0
雪    币: 1491
活跃值: (985)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
4
很好很强大!!!
  谢谢共享!!
2009-9-24 10:07
0
雪    币: 231
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
不错的思路。嘿嘿!学习了。
2009-9-24 10:38
0
雪    币: 3006
活跃值: (774)
能力值: ( LV15,RANK:1395 )
在线值:
发帖
回帖
粉丝
6
不错的思路,学习一下
2009-9-24 10:43
0
雪    币: 218
活跃值: (11)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
7
很好,学习了
2009-9-24 11:01
0
雪    币: 110
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
很好,学习了
2009-9-24 15:01
0
雪    币: 1355
活跃值: (344)
能力值: ( LV13,RANK:920 )
在线值:
发帖
回帖
粉丝
9
哈哈,内存注册机
2009-9-25 09:35
0
雪    币: 2325
活跃值: (1058)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
10
内存注册机,学习了
2009-9-25 09:59
0
雪    币: 237
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
注册码是不是一定会出现在内存里面的?
不考虑需要利用网络验证的情况。
2009-9-27 15:12
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
学习了 这个算是内存注册机吧
2009-9-27 16:27
0
雪    币: 219
活跃值: (508)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
对明码比较的才可以吧
2009-9-27 18:05
0
雪    币: 119
活跃值: (353)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
这个 这个...... 奇怪的思路
2009-9-27 18:34
0
雪    币: 233
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
现在明码比较的软件应该不多了吧.
2009-9-27 23:02
0
雪    币: 403
活跃值: (29)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
16
注册码在一定的时机一定会出现在内存里面。
2009-9-29 19:52
0
雪    币: 403
活跃值: (29)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
17
这个,嘿嘿,只是个思路,不一定要用来读取注册码的Y,也可以干点其他事情,请看拙文《剑走偏锋》。
2009-9-29 19:55
0
雪    币: 11
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
是的,明码比较不多,但是思路与套路很好
2009-9-29 21:13
0
雪    币: 219
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
获取注册码新思路  学习一下
2009-10-13 09:39
0
雪    币: 60
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
思路很好,可是现在这样容易比较的注册码不多了吧?
2009-10-18 21:23
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
如果注册码没有'-'分割符的话,查找起来也是挺麻烦的
比如,固定位数的数字和字母混合等,需要自己写算法在内存空间里查找匹配
2010-5-17 10:33
0
游客
登录 | 注册 方可回帖
返回