• 标 题:spacecad 3.0.1.273
  • 作 者:空手剑客
  • 时 间:2003年10月17日 09:52
  • 链 接:http://bbs.pediy.com

软件名称:spacecad
整理日期:2003.10.17
最新版本:3.0.1.273
使用平台:Win9x/Me/NT/2000/XP
发布公司:http://www.spacecad.com/
软件简介:火箭造型,弹道计算

加密方式:用户名+注册码
功能限制:试用30天,启动过程中出现注册窗体。
PJ工具:pelord ,win32dasm
PJ日期:2003-10-15
作者申明:只是学习,请不用于商业用途或是将本文方法制作的注册机任意传播,造成后果,本人一概不负。
收获:参考着课本,加上实践,基本对PE文件结构了解,可以增加或修改PE的功能
×××××××××××××××××××××××××××
看雪老大你这下明白我一买到书立刻看到PE结构一章了吧:)
×××××××××××××××××××××××××××
该软件未注册有30天的试用期,在启动过程中,将出现一个大大的对话框,提示用了多少天,输入注册码,网上定购等等,可以不理睬继它继续启动,进入主程序后好像没有什么限制。在启动过程中出现的窗体是调用pxr.dll。经检查程序
没有加密,采用DELPHI编写,本打算调试出注册机,可惜功力不够,一怒之下决定爆破。既然是与时间有关的,那就朝时间函数下手:GetSystemTime,GetLocalTime。爆破的目标就朝向调用时间函数的地方,让他乖乖调用我的时间函数:使得到的当前日期永远不变,你想设定为多少就多少,具体时间还是系统的时间(否则,时间将永远停止^_^)

下面是自己写的GetTime函数,以及反汇编的结果。
void GetTime(LPSYSTEMTIME lpSystemTime)
{
//这里设置的日期只是一个初始值,具体日期要使用后面的程序设定
    GetLocalTime(lpSystemTime);
    lpSystemTime->wYear=2003; 
    lpSystemTime->wMonth=10;
    lpSystemTime->wDayOfWeek=1; 
    lpSystemTime->wDay=1; 
}

:6E7011F8 55                      push ebp
:6E7011F9 89E5                    mov ebp, esp
:6E7011FB 83EC08                  sub esp, 00000008
:6E7011FE 83EC0C                  sub esp, 0000000C
:6E701201 FF7508                  push [ebp+08]

* Reference To: KERNEL32.GetLocalTime, Ord:0120h
                                  |
:6E701204 E8F7170000              Call GetLocalTime 
:6E701209 83C40C                  add esp, 0000000C
:6E70120C 8B4508                  mov eax, dword ptr [ebp+08]
:6E70120F 66C700D407              mov word ptr [eax], 07D3
:6E701214 8B4508                  mov eax, dword ptr [ebp+08]
:6E701217 66C740020A00            mov [eax+02], 000A
:6E70121D 8B4508                  mov eax, dword ptr [ebp+08]
:6E701220 66C740040100            mov [eax+04], 0001
:6E701226 8B4508                  mov eax, dword ptr [ebp+08]
:6E701229 66C740060100            mov [eax+06], 0001
:6E70122F C9                      leave
:6E701230 C20400                  ret 0004

利用LordPe给两个文件(spacecad.exe,pxr.dll)各增加一个区块,初始令Vsize=1000,Rsize=200
在新增区块开头输入上述指令对应的机器码,将咱的钩子先造出来的说。
注意:
  :6E701204 E8F7170000              Call GetLocalTime 
这一句的机器码需要手工计算一下,方法是:用GetLocalTime或者GetSystemTime的入口地址减去当前的地址,再减去当

前指令长度5

以我的操作结果为例:
spacecad新增区块中上面指令的VA为6fd00c,检查GetLocalTime的入口为4012ac,那么跳转地址为:4012ac-6fd00c-5=FFD

042CB,则对应的机器码为E8CB42D0FF。至于具体为什么这么排列,那就不用说了吧(-:

到此只是加入了自己的GetTime函数,钩子造好了,还要装上去呢,OK,找需要装的地方:凡是调用GetSystemTime,GetL

ocalTime函数的地方统统装上,检查一下:
spacecad.exe共有四处:402bd6,40b100,40b12c,40b178
pxr.dll共有两处:40939c,4093e8
把他们统统改为 call GetTime,对应的机器码计算方法和上面一样。

运行一下吧,我KAO,嘣嘣地出了两个错误提示框:一个是没有找到30 day key,另一个是什么系统错误,不理他。哈哈,原先那个大大的窗体没了,可惜这两个框比较难看,没办法,水平有限,将就吧。

经过上面的修改后,程序得到的日期永远是2003-10-1,如果我在2004-1-1安装怎么办?下面的程序就起作用了:获得当前的日期,分别补丁到spacecad.exe和pxr.dll。这下子就没问题了,你想什么时间装就随便吧,不过万一出了千万年虫问题怎么办?^_^


#include <iostream>
#include <stdlib.h>
#include <fstream>
using namespace std;

int dat[4];  //存储需要写入到文件的时间数据 
int offset[4]={0x1a,0x23,0x2c,0x35}; //需要补丁的地方
int base[2]={0x106a00,0x2d4000};//dll和exe的补丁基址 ,也即所增加的段偏移地址 

void patch_file(string filename,int base);//文件打补丁,将安装日期固化到程序 

int main(int argc, char *argv[])
{
  cout<<"******** attention *********
"<<endl;  
  cout<<"** 1. copy  \"pxr.dll\" to system dir replacing old file
"<<endl;
  cout<<"**   for win2k ,it's winnt\system\system32
"<<endl;
  cout<<"**   for win98 ,it's windows\system
"<<endl;
  cout<<"** 2. copy \"spacecad.exe\" to program dir replacing old file"<<endl;
  cout<<"*****************************
"<<endl<<endl;
  LPSYSTEMTIME lpSystemTime=new SYSTEMTIME;
  GetLocalTime(lpSystemTime);
    //获得当前时间,仅对年月日进行修改,具体时间保留不动 
  dat[0]=lpSystemTime->wYear; 
  dat[1]=lpSystemTime->wMonth;
  dat[2]=lpSystemTime->wDayOfWeek; 
  dat[3]=lpSystemTime->wDay; 
  delete lpSystemTime;
  patch_file("pxr.dll",base[0]);
  patch_file("spacecad.exe",base[1]);
   
  system("PAUSE");  
  return 0;
}

void patch_file(string filename,int base)
{
  ofstream file(filename.c_str(),std::ios::in | std::ios::out | std::ios::binary);
  if(file==NULL)
  {
    cout<<"error opening "<<filename<<endl;
    system("PAUSE");  
    exit(0);
  }
  
  for(int i=0;i<=3;i++)
  {
    file.seekp(base+offset[i]);//找到需要补丁的位置,写入数据 
    file.write((char *)&dat[i],2);
  }  
  file.close();
  cout<<"succeeding patch "<<filename<<" !"<<endl;  
}