首页
社区
课程
招聘
[原创]某游戏皮肤修改工具的逆向与实现
发表于: 2014-10-7 21:10 28426

[原创]某游戏皮肤修改工具的逆向与实现

2014-10-7 21:10
28426
收藏
免费 4
支持
分享
最新回复 (60)
雪    币: 116
活跃值: (26)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
26
这种注入方式确实很久之前就有了。但是我一直不知道。第一次看到这种注入方式,所以觉得特别新奇。。。
2014-10-9 16:36
0
雪    币: 55
活跃值: (519)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
27
话说你那个模糊匹配的代码能不能发出来,好早以前我也有一段这个代码。现在弄丢了,找了一下午都没找到,还以为是ldasm里面的代码。。。
可以话站内信发给我。
2014-10-9 17:39
0
雪    币: 457
活跃值: (218)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
28
楼主 ~~~~~~~
2014-10-10 11:03
0
雪    币: 53
活跃值: (528)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
29
szBuffer[0] = 0x9C;
    szBuffer[1] = 0x60;
    szBuffer[2] = 0xE8;
    *(DWORD*)(szBuffer+3) = 0x104;
    RtlCopyMemory(szBuffer + 7,g_szPath,MAX_PATH);

    bP = &szBuffer[0x104+7];
    *bP = 0xB8;
    *(DWORD*)(bP+1) = (DWORD)LoadLibraryA;
    *(bP+5) = 0xFF;
    *(bP+6) = 0xD0;
    *(bP+7) = 0x61;
    *(bP+8) = 0x9d;
    *(bP+9) = 0x68;
    *(DWORD*)(bP+10) = ThreadContext.Eip;
    *(bP+14) = 0xc3;

LZ,这段代码 LoadLibraryA 的参数没有 push
2014-10-10 11:15
0
雪    币: 116
活跃值: (26)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
30
[QUOTE=暗月之魂;1322631]szBuffer[0] = 0x9C;
    szBuffer[1] = 0x60;
    szBuffer[2] = 0xE8;
    *(DWORD*)(szBuffer+3) = 0x104;
    RtlCopyMemory(szBuffer + 7,g_szPath,MAX...[/QUOTE]

不需要push可以达到同样的目的。
2014-10-10 11:35
0
雪    币: 116
活跃值: (26)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
31
你去逆向下我的那个dll。我是直接copy原作者的,匹配代码有点问题。如果没思路再短信我吧。到时我把代码发邮件给你。
2014-10-10 11:37
0
雪    币: 55
活跃值: (519)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
32
好的,谢谢,我先看看。
2014-10-10 13:19
0
雪    币: 5211
活跃值: (3457)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
33
我在想 Mon是怎么进去的?
2014-10-10 14:10
0
雪    币: 5211
活跃值: (3457)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
34
tp何在~   不过文章受益匪浅。谢谢了。
2014-10-10 14:11
0
雪    币: 1243
活跃值: (347)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
35
LZ,我仔细看了一遍,但是还在测试,这个seat应该是位置(字面意思:座位号),即在5V5的模式中,看看这个这个位置上是不是自己,是自己则替换皮肤,别人的就不换(if条件改一下全换。。。)
2014-10-10 15:11
0
雪    币: 55
活跃值: (519)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
36
看了下,似乎不仅仅是'?'这个char可以当做通配符吧。只要是由ascii码转换成int值后小于0的字符都可以用在中间作通配符...
不太明白为什么要第一次搜到特征码后没有马上返回结果。还要继续把0x1000大小的内存搜完才返回?还是我逆错了。。

^.^看错了。是在找到后的第二次while循环的头部跳出的。谢谢了。已经分析完了。代码的确有点问题,这样搜索的效率不是很高。
推荐改成Sunday算法进行内存搜索。不过还是希望lz可以把代码给大家共享一下。相信lz代码会比我写的代码可读性更高
2014-10-10 15:58
0
雪    币: 53
活跃值: (528)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
37
纳尼。。。。
2014-10-10 18:24
0
雪    币: 178
活跃值: (125)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
38
感谢分享
2014-10-10 21:22
0
雪    币: 55
活跃值: (519)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
39

是的,这是经常用MASM等工具进行编程的人惯用的(不良的?)一种代码写法,图个方便:

call @F          ;        此句等同与压栈,因为会保存下一个地址为返回地址,而下一个地址正好是个字符串,那么就等于push 字符串地址
db 'dll path',0      
@@:
call LoadLibrary
2014-10-10 21:43
0
雪    币: 509
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
40
牛B
2014-10-27 16:02
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
41
大神,我也在学习有关这个游戏的东西,这个真心牛啊。
2014-11-3 13:55
0
雪    币: 22
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
42
改造型第一步是用GetCommandLine獲取參數
啟動時會給一行參數例如
"8390" "LoL.exe" "Air\LOLClient.exe" "124.108.140.83 5105 lsdRQl1DdNsRYBe9mNy4YA== PlayerID"

目的就是為了取得 PlayerID,這在後面 Load Screen 那裡要用到

修改造型主要HOOK在兩個地方

//================================================================================

第一個 是 HOOK00(int this, int a2, char a3, char a4, int a5, int a6)

int ecx, int [ebp+8], char [ebp+C], char [ebp+10], int [ebp+14], int [ebp+18]

請對照 HOOK00_1(int par1, void *lp, int flag, int par2)

par1 = a5, lp = a6, a3 = flag, par2 = a4

有用的其實只有a6,其他都是多餘的。

要檢查的話只要檢查 a3 = 3, a4 = 7, a6 = 0x65 這個情況,a2 = 0

FF ?? 09 8B ?? ?? ?? FF ?? 05 ?? ?? FF ?? 01

0032B19E - 8D 46 11              - lea eax,[esi+11]
0032B1A1 - 50                    - push eax
0032B1A2 - 8D 4C 24 44           - lea ecx,[esp+44]
0032B1A6 - E8 F58CE3FF           - call 00163EA0
0032B1AB - C7 44 24 68 00000000  - mov [esp+68],00000000 : [00905A4D]
0032B1B3 - 8D 54 24 40           - lea edx,[esp+40]
[COLOR="Red"]0032B1B7 - FF 76 09              - push [esi+09] skinID
0032B1BA - 8B 4F 34              - mov ecx,[edi+34]
0032B1BD - 52                    - push edx
0032B1BE - FF 76 05              - push [esi+05]
0032B1C1 - 8B 01                 - mov eax,[ecx]
[COLOR="red"]0032B1C3 - FF 76 01              - push [esi+01] PlayerID
0032B1C6 - FF 50 28              - call dword ptr [eax+28]
0032B1C9 - 8D 4C 24 40           - lea ecx,[esp+40]
0032B1CD - E8 2E8DE3FF           - call 00163F00
0032B1D2 - EB 35                 - jmp 0032B209

class LoadingScreenHeroSkin
{
public:
	char a6;	//0x00	esi
	int PlayerID;	//0x01	esi+1
	int Unknown_5;	//0x05	esi+5
	char skinID;	//0x09	esi+9
	PAD(0x7);	//0x0A	esi+10
	PAD(0x5);	//0x11	esi+17 英雄名稱 ex:Ezreal
	PAD(0x20);	//0x16	esi+22
	int Unknown_54;	//0x36	esi+54
};

檢查 PlayerID 是否一樣,一樣就改 skinID 就可以換造型。

由於是5V5所以有10個client端,上面的 LoadingScreenHeroSkin 會跑10次。

需要自行計算自己的角色是在第幾個位置,從0~9計算出 MySeat 和 GameSeat

建議取名 clientID 不是 GameSeat

//================================================================================

第二個 是 void _stdcall HOOKHERO(DWORD _ebx)

LeagueofLegends 4.18 這裡改用ECX傳遞給ESI了,用 IDA 找 Creating Hero...

50 8D 44 24 78 64 A3 00 00 00 00 8B ?? 83

00186EBC - 50                    - push eax
00186EBD - 8D 44 24 78           - lea eax,[esp+78]
00186EC1 - 64 A3 00000000        - mov fs:[00000000],eax
[COLOR="Red"]00186EC7 - 8B F1                 - mov esi,ecx
00186EC9 - 83 3D 4C0C4E01 00     - cmp dword ptr [014E0C4C],00
00186ED0 - 0F84 7E040000         - je 00187354
00186ED6 - 68 4C290901           - push 0109294C [COLOR="Red"]Creating Hero...
00186EDB - 6A 00                 - push 00
00186EDD - 6A 01                 - push 01
00186EDF - 6A 03                 - push 03
00186EE1 - E8 9A3F0700           - call 001FAE80

class Creating_Hero
{
public:
	DWORD ECXtoESI		//0x00	esi
	PAD(0x1);		//0x04	esi+4
	int ObjID;		//0x05	esi+5
	int clientID;		//0x09	esi+9
	short NodeID;		//0x0D	esi+13
	short Team;		//0x0F	esi+15 等於1紫方100 等於0藍方200
	char Unknown_17;	//0x11	esi+17
	int skinID;		//0x12	esi+18 造型編號
	char *Name;		//0x16	esi+22 召喚師名稱
	PAD(0x76);		//0x20	esi+23 召喚師名稱字元長度
	char Skin;		//0x96	esi+150 英雄名稱 ex:Ezreal
	PAD(0x27);		//0x97	esi+151 英雄名稱字元長度
	float Unknown_190;	//0xBE	esi+190
	float Unknown_194;	//0xC2	esi+194
	int Unknown_198;	//0xC6	esi+198
	short Unknown_202;	//0xCA	esi+202
};

使用第一個 HOOK00 算出來的 GameSeat 和 clientID 比對後,修改 skinID 即可
2014-11-3 16:28
0
雪    币: 136
活跃值: (105)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
43
hehe 又见某人发帖了啊  龙....
2014-11-3 22:02
0
雪    币: 116
活跃值: (26)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
44
赞,这位朋友用心了。
分析的挺透彻。
我当初只分析了软件,没分析游戏,变量名是按照自己的想法取得。实在惭愧
2014-11-3 22:34
0
雪    币: 116
活跃值: (26)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
45
要说牛逼也是写这个软件的才牛逼。我只是从他的成品里学习了一点点思路。
2014-11-3 22:36
0
雪    币: 84
活跃值: (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
46
学习中。谢谢楼主!
2014-11-10 17:27
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
47
不知楼主是否可以留下QQ
2014-11-10 18:10
0
雪    币: 612
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
48
这种方式有点早 不过还是值得学习的
2014-11-11 12:55
0
雪    币: 118
活跃值: (72)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
49
探究过程很好。很有学习意义
2014-11-11 22:56
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
50
收藏一下
2014-11-12 09:31
0
游客
登录 | 注册 方可回帖
返回
//