2007-4-27 22:07
Miliardo
[技术]关于加密插件的编写
最近似乎有人问到如何对吉里吉里2/KAG3的游戏进行加密解密,在此我向大家介绍一下标准的加解密方法。
吉里吉里中标准的加密解密需要一个成对的DLL来进行。
吉里吉里的官方插件源代码中,包含了一对加密解密插件的样例。
我对源代码的注释进行了一些翻译,希望能够对大家有些帮助。
加密插件的源代码如下:
[code]
//---------------------------------------------------------------------------
#include <windows.h>
//---------------------------------------------------------------------------
/*
本工程是对 XP3 文件中保存的文件进行加密的样例。
加密算法需要保证在解密时不造成性能上的障碍,因此最好较为简单。
此外,解密函数(被指定为 TVPSetXP3ArchiveExtractionFilter 的函数)
要能够对一个文件中任意偏移值开始的,任意大小的数据包进行解密,此外
必须保证每次调用解密函数都能够在调用返回的时候得到结果。也就是说,
超过这个界限的加密方法,例如说“交换字节顺序”一类依赖于前后字节的
加密方法都不能够被使用。
这些限制对于加密函数也一样适用。
从现实的角度来说,大概可以理解为只能够使用“对每个字节进行异或、加
减”一类的算法。
但是,因为每个字节、每个数据块都拥有不同的偏移值,每个文件拥有不同
的散列(Hash)值,所以可以按照偏移值、散列值进行一些局部性的加密,
也就是不同的字节、不同的文件,可以使用不同的加密方式。
如果进行了加密,不使用对应的吉里吉里用解密插件就无法读取 XP3 文件。
这意味着,在将来吉里吉里本体被移植到 Windows 平台之外时,作品能够直
接在其它平台上正常运行的可能性被大幅降低。
当对作品进行保护的重要性,高于作品的开放性和可移植性时,可以考虑使
用这个插件。
这个 DLL 的名称需要被设置为 xp3enc.dll,此外,必须和Releaser放在同一
个目录下。
*/
//---------------------------------------------------------------------------
//#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
// DLL 进入点
return 1;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/*
定义加密文件用的函数。函数名称为在 XP3ArchiveAttractFilter_v 之后加上
这个函数使用的接口版本。
现在的接口版本是 2 。
(版本 1 在吉里吉里2 2.23 beta1之后不能使用。)
函数的参数传递方法一定要使用 _stdcall。
在这里指定的函数名一定要写入 def 文件的 exports 节中,从 DLL 中导出。
*/
extern "C" void __stdcall XP3ArchiveAttractFilter_v2(
unsigned __int32 hash,
unsigned __int64 offset, void * buffer, long bufferlen)
{
// 接口版本 2 可以接受并使用以下的参数
// hash : 输入文件(解密后)内容的32位 Hash (散列)值
// offset : "Buffer" 成员所指向的数据偏离这个文件头部的偏移值
// (当文件被压缩时,将显示文件为压缩状态下的字节偏移
// 值)
// buffer : 指向要加密的数据的指针。当文件被压缩时,给出的是文
// 件被压缩前的数据。
// ( 本函数不能更改压缩后的文件数据 )
// bufferlen : "buffer" 参数给出的数据块的长度
// 在这里作为范例,我们示范把数据和 hash 最后一字节进行 XOR 的方法。
int i;
for(i = 0; i < bufferlen; i++) ((unsigned char*)buffer)[i] ^= hash;
}
//---------------------------------------------------------------------------
[/code]
将这段代码编译成DLL,并且导出函数XP3ArchiveAttractFilter_v2即可使用。
加密DLL的def文件内容如下:
[code]
EXPORTS
XP3ArchiveAttractFilter_v2
[/code]
-----------------------------------我是PP的分隔线-----------------------------------
之后是解密:
[code]
//---------------------------------------------------------------------------
/*
通过 Releaser 使用 xp3enc.dll 可以对XP3文件包进行加密。
本C++源文件说明用于处理这类加密XP3文件的吉里吉里插件的编写方法。
如果你的程序从XP3压缩包启动,插件的文件扩展名需要设置为 tpm 。
吉里吉里如果发现扩展名为 tpm 的插件,则这个插件将在读取 startup.tjs 之前,
也就是打开第一个 XP3 文件之前被读取。
如果插件之间没有相互依赖等情况,则只要扩展名是 tpm ,实际上主文件名无论设
置为什么都没有关系。这里出于方便起见,假设这个文件为 xp3dec.tpm 。
和 xp3enc.dll 不同, xp3dec.tpm 是作为吉里吉里本体的插件工作。因此,必须
遵从吉里吉里插件的编写方法。此外,通过包含头文件tp_stub.h ,可以使用吉里
吉里本体的各种功能。
在 TVPSetXP3ArchiveExtractionFilter 中调用吉里吉里本体功能时请注意,虽然
TVPSetXP3ArchiveExtractionFilter 有可能同时从多个线程中被调用,但是可以通
过 tp_stub.h 调用的功能大部分只能在调用线程为主线程的时候使用。
关于加密方法的各种注意事项,请同时参考 xp3enc.dll 的样例代码 main.cpp 。
*/
//---------------------------------------------------------------------------
#include <windows.h>
#include "tp_stub.h"
// 请保证 tp_stub.h 在包含路径之中。
// 推荐使用与对应吉里吉里本体相同版本的 tp_stub.cpp 以及 tp_stub.h。
// (不过只要吉里吉里本体的接口没有变化,就可以继续使用旧版本的xp3dec.dll)
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void TVP_tTVPXP3ArchiveExtractionFilter_CONVENTION
TVPXP3ArchiveExtractionFilter(tTVPXP3ExtractionFilterInfo *info)
{
// TVPXP3ArchiveExtractionFilter 函数是会从吉里吉里本体调用的回调函数。
// 能得到的参数只有一个,就是对 tTVPXP3ExtractionFilterInfo 结构体的指针。
// TVPXP3ArchiveExtractionFilter 需要在后述的 V2Link 函数内使用
// 吉里吉里本体的 TVPSetXP3ArchiveExtractionFilter 函数设定。
// 这个样例只是纯粹的对 xp3enc.dll 样例代码加密的 XP3 文件包解密
// 将所有的数据以 FileHash 的最后一个字节作异或(XOR)运算
// 请注意,这个函数有可能在多个线程中被调用。
/*
tTVPXP3ExtractionFilterInfo 的成员如下
* SizeOfSelf : 结构体自身的大小
* Offset : "Buffer" 成员所指向的数据偏离这个文件头部的偏移值
* Buffer : 数据本体
* BufferSize : "Buffer" 成员所指向的数据的大小(字节单位)
* FileHash : 解密后文件内容的32位 Hash (散列)值
*/
// 检查结构体的大小
if(info->SizeOfSelf != sizeof(tTVPXP3ExtractionFilterInfo))
{
// 当结构体的大小错误,则最好投出异常
TVPThrowExceptionMessage(TJS_W("Incompatible tTVPXP3ExtractionFilterInfo size"));
// TVPThrowExceptionMessage 是用于投出异常的函数
// 本函数不会返回。
}
// 復号
tjs_uint i;
for(i = 0; i < info->BufferSize; i++)
((unsigned char *)info->Buffer)[i] ^= info->FileHash;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason,
void* lpReserved)
{
return 1;
}
//---------------------------------------------------------------------------
extern "C" HRESULT _stdcall V2Link(iTVPFunctionExporter *exporter)
{
// V2Link 是插件和吉里吉里本体链接时会被调用的函数
// 初始化Stub(必须编写)
TVPInitImportStub(exporter);
// 将 TVPSetXP3ArchiveExtractionFilter 函数指定给
// TVPXP3ArchiveExtractionFilter ,将其设定为回调函数
TVPSetXP3ArchiveExtractionFilter(TVPXP3ArchiveExtractionFilter);
return S_OK;
}
//---------------------------------------------------------------------------
extern "C" HRESULT _stdcall V2Unlink()
{
// V2Unlink 是插件和吉里吉里本体分离时调用的函数。
// 将 NULL 传递给 TVPSetXP3ArchiveExtractionFilter
// 解除回调函数的登记
TVPSetXP3ArchiveExtractionFilter(NULL);
// Stub使用完毕(必须编写)
TVPUninitImportStub();
return S_OK;
}
//---------------------------------------------------------------------------
[/code]
解密插件编译的时候需要使用吉里吉里的tp_stub.cpp和tp_stub.h。(请注意要编译tp_stub.cpp并和你的代码链接)
这个文件也需要编译成DLL,但为了让吉里吉里能够自动读取它,请把文件的后缀名改为.tpm。
[color=Red]如果需要tp_stub的下载请点[url=http://kcddp.keyfc.net/bbs/viewthread.php?tid=273]这里[/url][/color]
DLL需要导出的函数是V2Link和V2Unlink,这两个函数是插件与吉里吉里链接/解除链接时使用的函数。
def文件的内容如下:
[code]
EXPORTS
V2Link
V2Unlink
[/code]
更多的东西请各位参照说明,自己摸索。
2007-4-27 23:56
keakon
真强悍的帖……
先复制下来,快熄灯了,明天研究
感谢楼主~
2007-5-10 14:25
chris2002
樓主,這是否需要重新編寫吉里吉里的源碼呢?
2007-5-10 15:33
Miliardo
需要的是编写[插件]。
2007-7-1 22:59
keakon
通过 Releaser 使用 xp3enc.dll 可以对XP3文件包进行加密。
Releaser是krkrrel.exe吗?
似乎没找到krkrrel.exe导入xp3enc.dll的方法,是放在游戏文件夹里自动查找添加吗?
2007-7-2 00:07
keakon
知道了,原来不是放游戏目录,是krkrrel.exe的文件夹……
看样子要破解的话得反汇编xp3enc.tpm看算法了
[[i] 本帖最后由 keakon 于 2007-7-2 07:47 编辑 [/i]]
2007-7-9 04:53
Miliardo
[quote]原帖由 [i]keakon[/i] 于 2007-7-2 00:07 发表 [url=http://kcddp.keyfc.net/bbs/redirect.php?goto=findpost&pid=2149&ptid=272][img]http://kcddp.keyfc.net/bbs/images/common/back.gif[/img][/url]
知道了,原来不是放游戏目录,是krkrrel.exe的文件夹……
看样子要破解的话得反汇编xp3enc.tpm看算法了 [/quote]
这个理论上是可以的,实际上真正用心加密的开发者是不会把tpm暴露给别人的- v -
2007-8-1 07:12
chris2002
但不附上tpm是無法解密吧?
請問樓主能不能寫一個超強的加密分享一下呢?
或者直接將內核加密程度升級也行..:lol
[[i] 本帖最后由 chris2002 于 2007-8-1 07:14 编辑 [/i]]
2010-5-18 22:09
health901
求救啊,生成dll的时候无法导出函数,在工程源文件已经加入def文件
[code]LIBRARY xp3enc.dll
EXPORTS
XP3ArchiveAttractFilter_v2 @1 [/code]
不管用啊,解决方案生成的时候没有lib文件,把生成的dll放到krkrrel下,打包的时候不显示加密选项。
咱小白啊。。。
用的VC++ 2008 express
页:
[1]
Powered by Discuz! Archiver 5.5.0
© 2001-2006 Comsenz Inc.