鉴于我们敬爱的小小猪已经公开了苍龙逐曰v1.2的解密补丁,所以我决定公开我对其原始加密过的苍龙逐曰v1.2的加密方式的一些分
析结果^_^
下述结论通过对dradon.exe的跟踪和反汇编得来(对不住了啊,传说中的坏蛋^_^)
7个文件被分割,它们是 r1.grp , r2.grp ,r3.grp , s1.grp , s2.grp , s3.grp ,z.dat.
这7个文件的前500bytes被切下来保存到log.grp中,顺序为r1.grp , r2.grp ,r3.grp , s1.grp , s2.grp , s3.grp ,z.dat(z.exe)
其余部分保存在 rg1.gpr , rg2.grp , rg3.grp , sg1,grp ,sg2.grp , sg3.grp , zd.dat
对应关系为
log.grp offset[0,499] + rg2.grp = r1.grp
log.grp offset[500,999] + rg3.grp = r2.grp
log.grp offset[1000,1499] + rg1.grp = r3.grp
log.grp offset[1500,1999] + sg2.grp = s1.grp
log.grp offset[2000,2499] + sg3.grp = s2.grp
log.grp offset[2500,2999] + sg1.grp = s3.grp
log.grp offset[3000,3499] + zd.dat = z.dat(z.exe)
4个文件被改名:它们是
kdef.idx <---> zd2.dat
kdef.grp <---> zd3.dat
talk.idx <---> zd4.dat
talk.grp <---> zd5.dat
dragon.exe在每次启动的时候,还原上述7+4个文件,然后创建play.bat进程,游戏得以正常进入...退出时,逆向操作...游戏运行中
可能(没有仔细跟踪)会检测游戏是否被切出到windows桌面,若是,逆向操作...
根据上述结论,我们可以解释:
1.为什么游戏不能直接由play.bat启动?因为游戏的启动文件z.dat(z.exe)的前500bytes被搞走了...
2.为什么游戏不能修改?因为r*.grp,s*.grp不完整。地址不对。
3.为什么把v1.1的r*.grp s*.grp,z.dat覆盖到v1.2的目录中游戏仍然不可运行?因为 talk.* kdef.*被改名了。
4.如果把v1.1的r*.grp s*.grp,z.dat,talk.* kdef.* 全部拷入v1.2的目录中会怎么样?对不起,我没有试,不清楚。
再谈谈dardon.exe,这个东东最大的弱点是它在启动play.bat之前,一定要将游戏恢复成解密状态,也就是说,当你正在玩v1.2时,
游戏是完全解密的。这样的话就毫无安全性可言。因为想把这几个解密后的文件拷出来的方法太多了,不是单纯的靠检测游戏是否被
切出来就能避免的了的,比如,通过共享的网络把它拷出来...
根据上述结论,我们可以写出一个还原程序完成dragon.exe启动play.bat前做的事:一次运行,终生不用再受dradon.exe的摆布(我
顺便修正了片头动画的路径,删掉了解密后不再需要的文件,同时保留当前的存档,恢复在dos/dosbox下的运行)^_^
源码如下:
#include <stdio.h>
#define COMBO_FILE_COUNT 7
#define RENAME_FILE_COUNT 4
#define CLEAN_FILE_COUNT 17
#define COMBO_FILE_HEAD_LENGTH 500
#define COMBO_READ_BUFFER_LENGTH 4096
#define SHOWTIT_LENGTH 18
#define PLAY_LENGTH 45
int main()
{
const char *szComboDstFileName[COMBO_FILE_COUNT] =
{"r1.grp","r2.grp","r3.grp","s1.grp","s2.grp","s3.grp","z.exe"};
const char *szComboSrcFileBodyName[COMBO_FILE_COUNT] =
{"rg2.grp","rg3.grp","rg1.grp","sg2.grp","sg3.grp","sg1.grp","zd.dat"};
const char *szComboSrcFileHeadName = "log.grp";
const char *szRenameDstFileName[RENAME_FILE_COUNT] = {"kdef.idx","kdef.grp","talk.idx","talk.grp"};
const char *szRenameSrcFileName[RENAME_FILE_COUNT] = {"zd2.dat","zd3.dat","zd4.dat","zd5.dat"};
const char *szCleanFileList[CLEAN_FILE_COUNT]=
{"rg1.grp","rg2.grp","rg3.grp","sg1.grp","sg2.grp","sg3.grp","zd.dat","zd2.dat","zd3.dat","zd4.dat","zd5.dat","log.g
rp","logo.txt","logo.gif","dragon.exe","z.com","logo.scr"};
const char szShowtitContent[SHOWTIT_LENGTH] = "@flivwav tit2 tit";
const char szPlayContent[PLAY_LENGTH] = "@echo off\r\ncall showtit.bat\r\nz.exe\r\necho on ";
const char *szShowtitFileName = "Showtit.bat";
const char *szPlayFileName = "play.bat";
const char *szMSGProcessFile = "An error occured when processing the file:";
const char *szMSGSuccess = "Crack successful!\n\nPlease run play.bat to play the game!";
const char *szMSGFail = "Crack failed!";
unsigned char ucReadBuffer[COMBO_READ_BUFFER_LENGTH];
int iReadLength;
unsigned int i;
unsigned char ucSuccessFlag = 1;
FILE *pfComboFileHead;
FILE *pfComboFileBody;
FILE *pfComboFileDst;
FILE *pfShowtitAndPlay;
/*generate all seperated files */
pfComboFileHead = fopen(szComboSrcFileHeadName,"rb");
if(pfComboFileHead != NULL)
{
for(i = 0 ; i < COMBO_FILE_COUNT ; i++)
{
pfComboFileBody = fopen(szComboSrcFileBodyName[i],"rb");
pfComboFileDst = fopen(szComboDstFileName[i],"wb");
if(pfComboFileBody != NULL && pfComboFileDst != NULL)
{
iReadLength = fread(ucReadBuffer,1,COMBO_FILE_HEAD_LENGTH,pfComboFileHead);
if(iReadLength == COMBO_FILE_HEAD_LENGTH)
{
fwrite(ucReadBuffer,COMBO_FILE_HEAD_LENGTH,1,pfComboFileDst);
}
else
{
printf("\n%s%s\n",szMSGProcessFile,szComboSrcFileHeadName);
ucSuccessFlag = 0;
break;
}
do
{
iReadLength = fread
(ucReadBuffer,1,COMBO_READ_BUFFER_LENGTH,pfComboFileBody);
fwrite(ucReadBuffer,iReadLength,1,pfComboFileDst);
}while(!feof(pfComboFileBody));
fclose(pfComboFileBody);
fclose(pfComboFileDst);
}
else
{
if(pfComboFileBody == NULL)
{
printf("\n%s%s\n",szMSGProcessFile,szComboSrcFileBodyName[i]);
}
else
{
printf("\n%s%s\n",szMSGProcessFile,szComboDstFileName[i]);
}
ucSuccessFlag = 0;
}
}
fclose(pfComboFileHead);
}
else
{
printf("\n%s%s\n",szMSGProcessFile,szComboSrcFileHeadName);
ucSuccessFlag = 0;
}
if(ucSuccessFlag == 1)
{
/*rename the target file*/
for(i = 0 ; i < RENAME_FILE_COUNT ; i++)
{
if(rename(szRenameSrcFileName[i],szRenameDstFileName[i]) != 0)
{
printf("\n%s%s\n",szMSGProcessFile,szRenameSrcFileName[i]);
ucSuccessFlag = 0;
}
}
}
if(ucSuccessFlag == 1)
{
/*Modify showtit.bat and play.bat , corrcet the wrong path of title cartoon and earse the logo*/
pfShowtitAndPlay = fopen(szShowtitFileName,"wb");
if(pfShowtitAndPlay != NULL)
{
fwrite(szShowtitContent,SHOWTIT_LENGTH - 1,1,pfShowtitAndPlay);
fclose(pfShowtitAndPlay);
}
pfShowtitAndPlay = fopen(szPlayFileName,"wb");
if(pfShowtitAndPlay != NULL)
{
fwrite(szPlayContent,PLAY_LENGTH - 1,1,pfShowtitAndPlay);
fclose(pfShowtitAndPlay);
}
/*Delete all useless file*/
for(i = 0 ; i < CLEAN_FILE_COUNT ; i++)
{
remove(szCleanFileList[i]);
}
printf("\n%s\n",szMSGSuccess);
}
else
{
printf("\n%s\n",szMSGFail);
}
return 0;
}
疑问:
通过对小小猪发布的官方解密补丁的比对,我发现有两个文件dragon.exe并没有操纵,但是加密版和解密版不同,它们是:
alldef.grp, allsin.grp
Comparing files ALLDEF.GRP and ..\ALLDEF.GRP 前面的是加密版本,后面的是解密版本
0007033C: 01 00
0007033E: 5A 00
00070340: 3B 00
00070341: 04 00
00070346: 62 00
00070347: 1C 00
00070348: 62 00
00070349: 1C 00
0007034A: 62 00
0007034B: 1C 00
0007034E: 28 00
00070350: 25 00
00070352: 01 00
00070354: 5B 00
0007035C: 96 00
0007035D: 18 00
0007035E: 96 00
0007035F: 18 00
00070360: 96 00
00070361: 18 00
00070364: 2A 00
00070366: 25 00
Comparing files ALLSIN.GRP and ..\ALLSIN.GRP 前面是加密版本,后面的是解密版本
004E72D0: 5A FF
004E72D1: 00 FF
004E72D4: 5B FF
004E72D5: 00 FF
原因不外乎下面3个:
1.偶的功底不够,落下了这两个。
2.小小猪在发布补丁的时候又升级了。
3.小小猪在发布补丁的时候发错了.....
恳请达人指点一二...........
收工............ |