Hacking Diablo II之D2HACKIT技术详解

Hacking Diablo II之D2HACKIT技术详解趁着圣诞又歇了几天,没博,倒是主动被动的看了不少片子。我发现我的观影口味挺杂,什么都看,还什么都能看的津津有味。这些片中,有肥皂剧型的“AllyMcBeal”(甜心俏佳人),柯恩兄弟的黑帮型的"Miller’sCrossing",闷骚型的“CountryLife”,一直想看的“北京乐与路”,还有成龙大叔的“神话”。前几天有博友留言希望我多谈点儿d2hackit,那我就随便说说。D2中的外挂,…

大家好,又见面了,我是你们的朋友全栈君。趁着圣诞又歇了几天,没博,倒是主动被动的看了不少片子。我发现我的观影口味挺杂,什么都看,还什么都能看的津津有味。这些片中,有肥皂剧型的“Ally McBeal”(甜心俏佳人),柯恩兄弟的黑帮型的”Miller’s Crossing”,闷骚型的“Country Life”,一直想看的“北京乐与路”,还有成龙大叔的“神话”。

前几天有博友留言希望我多谈点儿d2hackit,那我就随便说说。

D2中的外挂,比较有代表性的大致可以分为三类:以maphack为代表的辅助型,以帮助玩家更有效的玩游戏为目的;以D2JSP为代表的BOT型,用于在无人值守的状态下自动进行游戏;还有一类就是以d2hackit为代表的全能型,bot、pickit、dupe、pk hack、packet sniffer、trade hack、drop hack什么都能做,D2中dupe泛滥有一部分原因要归功于它,比较有代表性的基于d2hackit的插件外挂有09时期的pickit、PindleBot,和1.10时期的zPickit。

从结果上看,d2hackit无疑是成功的,然而从软件设计角度看,它当初的部分设计目标并没有达到。d2hackit的设计意图,是要实现一个外挂的开发平台,其他开发者只需用这个平台提供的基础设施,不必具备逆向工程,甚至汇编语言的能力就能够做出外挂。按照d2hackit原作者thohell的设想,d2hackit甚至不必局限于D2,而是一个通用的外挂开发平台,可以用于其他游戏。

降低外挂开发的难度这一点d2hackit是做到了,d2hackit插件泛滥就说明了它的成功。通用平台这一目标它显然没有达到,别说用于其它游戏,在09补丁上能用的插件,在1.10上都用不了,必须重新编译甚至修改源代码。

d2hackit的基本工作原理,跟我以前写的一篇
介绍外挂工作原理的文章里说的大致相同:d2hackit的加载、卸载,地址(旁路点、游戏内部函数和全局变量)的定位,以及旁路点被触发时的处理等几部份。不同的是d2hackit做为一个外挂平台,还需要加载它的插件,并在适当时刻(收、发数据包,进入、退出游戏等)通知插件。下面逐一分析。

1,d2hackit的加载和卸载。 d2hackit在本质上就是一个windows的DLL,因此任何能在游戏进程加载、卸载DLL的方法都适用于d2hackit。d2hackit 自带的loader用的是远程DLL注入的方法,另外d2hackit本身也可以做为d2loader的插件在游戏程序运行时自动加载。

2,地址的定位。d2hackit对地址的定位是比较有特色的,它除了支持基址+偏移量的通常做法,还支持指纹式的内存数据匹配搜索,也就是说它可以通过搜索特定模式的字节序列来定位内存地址。这样设计的意图是在游戏补丁升级时只需更新指纹数据就可以让d2hackit工作于新版本补丁(当然大家都知道这个目标没有达到)。指纹模式在配置文件中指定(d2hackit.ini),格式如下:

;
Name
=
Module
,
patchsize
,
offset
,
fingerprint
GamePacketReceivedIntercept

=
D2Client
.
dll
,
7
,
13
,
8B5C2410xxxxxxxxxxxx8D145B8B0495

上面这行指定了接收数据包的旁路点地址的匹配模式:在d2client.dll中搜索8B5C2410xxxxxxxxxxxx8D145B8B0495特征数据,每xx匹配任意1字节数据。7为patch长度,13为距离匹配地址的偏移。

3,旁路点的事件处理。以接收游戏数据包的处理为例。在安装了GamePacketReceivedIntercept旁路点以后,每当收到游戏内数据包时,d2hackit的相应旁路点处理例程就会先获取控制权。为了不破坏原先的寄存器内容,旁路点处理例程必须先保存必要的寄存器然后再做真正的处理。因此处理例程分为两部分,用汇编写的GamePacketReceivedInterceptSTUB函数和C函数GamePacketReceivedIntercept。

DWORD__fastcallGamePacketReceivedIntercept(BYTE
*
aPacket,DWORDaLength)
{


//
Passpackettoallclientswhowantstosnoop


LinkedItem
*
li
=
ClientModules.GetFirstItem();

while
(li)
{

PCISpCIS

=
ClientModules.GetCIS(li);

if
(pCIS
&&
pCIS
->
OnGamePacketBeforeReceived)
{

aLength

=
pCIS
->
OnGamePacketBeforeReceived(aPacket,aLength);

if
(
!
aLength)
break
;
}
li

=
ClientModules.GetNextItem(li);
}

return
aLength;
}

上面是d2hackit的收到数据包时的处理代码,很简单,就是遍历加载的插件模块,挨个调用插件模块中的
OnGamePacketBeforeReceived函数进行进一步的分析。
4,d2hackit插件模块。d2hackit的插件以d2h为后缀,其实也是普通的DLL。做为d2hackit的插件,d2h必须提供一些回调入口点(即DLL的导出函数),供d2hackit在必要的时刻调用。这些入口点有:

BOOLEXPORTOnClientStart
();

BOOLEXPORTOnClientStop

();

DWORDEXPORTOnGameTimerTick

();

BOOLEXPORTOnGameCommandLine

(
char**argv
,
intargc
);

DWORDEXPORTOnBnetPacketBeforeSent

(
BYTE*aPacket
,
DWORDaLen
);

DWORDEXPORTOnBnetPacketBeforeReceived

(
BYTE*aPacket
,
DWORDaLen
);

DWORDEXPORTOnRealmPacketBeforeSent

(
BYTE*aPacket
,
DWORDaLen
);

DWORDEXPORTOnRealmPacketBeforeReceived

(
BYTE*aPacket
,
DWORDaLen
);

DWORDEXPORTOnGamePacketBeforeSent

(
BYTE*aPacket
,
DWORDaLen
);

DWORDEXPORTOnGamePacketBeforeReceived

(
BYTE*aPacket
,
DWORDaLen
);

LPCSTREXPORTGetModuleAuthor

();

LPCSTREXPORTGetModuleWebsite

();

LPCSTREXPORTGetModuleEmail

();

LPCSTREXPORTGetModuleDescription

();

DWORDEXPORTGetModuleVersion

();

VOIDEXPORTOnGameJoin

(
THISGAMESTRUCT*thisgame
);

VOIDEXPORTOnGameLeave

(
THISGAMESTRUCT*thisgame
);

通过名字你就能猜出它们在什么时候会被d2hackit调用,比如说收到数据包时就是
OnGamePacketBeforeReceived


d2hackit插件的加载有两种方法,一种是在d2hackit.ini里设定随着d2hackit本身加载时自动加载,另一种可以由玩家在进入游戏后在聊天输入框中以特定的命令加载(d2hackit截获了聊天输入框的处理)。
5,d2hackit也给插件模块提供了一组接口(API),供插件模块使用。比如在OnGamePacketBeforeReceived函数中,插件可以直接修改数据包buffer的数据,但有的时候你需要向玩家显示分析结果或者向服务器发送一些定制数据包,这时候就得调用d2hackit提供的API。基本的API大概有这些:

DWORDEXPORTGameSendPacketToServer(LPBYTEbuf,DWORDlen);
DWORDEXPORTBnetSendPacketToServer(LPBYTEbuf,DWORDlen);
DWORDEXPORTRealmSendPacketToServer(LPBYTEbuf,DWORDlen);
BOOLEXPORTGameSendMessageToChat(LPSTRmsg);
DWORDEXPORTGameSendPacketToGame(LPBYTEbuf,DWORDlen);
BOOLEXPORTGameInsertPacketToGame(LPBYTEbuf,DWORDlen);
BOOLEXPORTGamePrintInfo(LPCSTRbuf);
BOOLEXPORTGamePrintError(LPCSTRbuf);
BOOLEXPORTGamePrintVerbose(LPCSTRbuf);
BOOLEXPORTGamePrintString(LPCSTRbuf);
DWORDEXPORTGameSendPacketToServer(LPBYTEbuf,DWORDlen);
PTHISGAMESTRUCTEXPORTGetThisgameStruct(

void
);
PSERVERINFOEXPORTGetServerInfo(DWORDdwVersion,LPCSTRszModule);
BOOLEXPORTGameSaveAndExit();

这样,d2hackit的插件通过处理特定的事件和调用d2hackit提供的API就可以实现它想要的功能,无须汇编和逆向工程知识。由于网络游戏的功能实现非常依赖于数据包,因此通过截获数据包的收发来分析、篡改、伪造数据包可以完成绝大部分外挂的功能。

6,d2hackit的升级。由于d2hackit利用游戏的特定函数和数据进行工作,每次D2升级补丁d2hackit本身也必须重定位这些地址。做一个可以用于1.11b补丁的d2hackit其实也主要就是这个工作。比起d2hackmap来,d2hackit用的的地址很少(10个),难度小多了。要定位的地址有:

Hacking Diablo II之D2HACKIT技术详解GamePacketReceivedIntercept=D2Client.dll,7,13,8B5C2410xxxxxxxxxxxx8D145B8B0495

GamePacketReceivedIntercept2=D2Client.dll,7,18,85C9894C24xx0F8FxxxxxxxxFF05xxxxxxxx5F5E5D

GamePacketSentIntercept=D2Net.dll,5,0,!10005

GamePlayerInfoIntercept=D2Client.dll,6,10,E8xxxxxxxxE8xxxxxxxx8935xxxxxxxx5EC3

pPlayerInfoStruct=D2Client.dll,0,12,E8xxxxxxxxE8xxxxxxxx8935xxxxxxxx5EC3

GamePrintStringLocation=D2Client.dll,0,0,81ECxxxxxxxx53558BE956578A45xx84C0

LoaderStruct=Game.exe,0,0,1d10abd1

GameKeyDownIntercept=D2Client.dll,5,5,8B770833D2xxxxxxxxxxxxC0668B41043BC6

GameSendPacketToGameLocation=d2net.dll,0,21,81EC0C010000538B1Dxxxxxxxx5556

GameSaveAndExit=D2client.dll,0,0,33c9e8xxxxxxxxc705xxxxxxxxxxxxxxxxe8xxxxxxxxc705

GameSendMessageToChat=bnclient.dll,0,15,C390909090909090909090909090908BD1

pGameInfoStruct=d2client.dll,0,0,#6FAA1C5A

Hacking Diablo II之D2HACKIT技术详解

第二个要做的工作是修改旁路点的入口代码,因为不同的d2补丁具体代码可能有变化,对寄存器的利用也有所不同。具体的说就是要改这几个函数:

Hacking Diablo II之D2HACKIT技术详解
void
GamePacketReceivedInterceptSTUB();
Hacking Diablo II之D2HACKIT技术详解

void
GamePacketReceivedIntercept2STUB();
Hacking Diablo II之D2HACKIT技术详解

void
BnetPacketReceivedSaveSTUB();
Hacking Diablo II之D2HACKIT技术详解

void
BnetPacketReceivedInterceptSTUB();
Hacking Diablo II之D2HACKIT技术详解

void
GamePacketSentInterceptSTUB();
Hacking Diablo II之D2HACKIT技术详解

void
BnetPacketSentInterceptSTUB();
Hacking Diablo II之D2HACKIT技术详解

void
GamePlayerInfoInterceptSTUB();

第三步是修正两个游戏内部的数据结构:

Hacking Diablo II之D2HACKIT技术详解
typedef
struct
playerinfostruct_t_110
Hacking Diablo II之D2HACKIT技术详解Hacking Diablo II之D2HACKIT技术详解


{

Hacking Diablo II之D2HACKIT技术详解BYTEUnitType;
//+0x00
Hacking Diablo II之D2HACKIT技术详解
DWORDCharacterClass;//+0x04
Hacking Diablo II之D2HACKIT技术详解
DWORDunknown1;//+0x08
Hacking Diablo II之D2HACKIT技术详解
DWORDPlayerID;//+0x0c
Hacking Diablo II之D2HACKIT技术详解
DWORDPlayerLocation;//+0x10(defineslocationsomehowinoroutoftownandmaybeotherlocations(0x05=intown,0x01=outoftown)
Hacking Diablo II之D2HACKIT技术详解
LPCSTRPlayerName;//+0x14pointertoLPSZplayername
Hacking Diablo II之D2HACKIT技术详解
BYTEAct;//+0x18
Hacking Diablo II之D2HACKIT技术详解
BYTEunknown2[0x73];//+0x19
Hacking Diablo II之D2HACKIT技术详解
WORDPlayerPositionX;//+0x8c
Hacking Diablo II之D2HACKIT技术详解
WORDPlayerPositionY;//+0x8e
Hacking Diablo II之D2HACKIT技术详解

Hacking Diablo II之D2HACKIT技术详解}

PLAYERINFOSTRUCT_110,
*
PPLAYERINFOSTRUCT_110;
Hacking Diablo II之D2HACKIT技术详解
Hacking Diablo II之D2HACKIT技术详解typedef

struct
gamestruct_t_110
Hacking Diablo II之D2HACKIT技术详解Hacking Diablo II之D2HACKIT技术详解


{

Hacking Diablo II之D2HACKIT技术详解
charUnknown1[0x1a];
Hacking Diablo II之D2HACKIT技术详解
charGameName[0x10];
Hacking Diablo II之D2HACKIT技术详解
charUnknown2[0x08];
Hacking Diablo II之D2HACKIT技术详解
charServerIP[0x10];
Hacking Diablo II之D2HACKIT技术详解
charUnknown3[0x46];
Hacking Diablo II之D2HACKIT技术详解
charAccountName[0x10];
Hacking Diablo II之D2HACKIT技术详解
charUnknown4[0x20];
Hacking Diablo II之D2HACKIT技术详解
charCharacterName[0x10];
Hacking Diablo II之D2HACKIT技术详解
charUnknown5[0x08];
Hacking Diablo II之D2HACKIT技术详解
charRealmName[0x10];
Hacking Diablo II之D2HACKIT技术详解
charUnknown6[0x147];
Hacking Diablo II之D2HACKIT技术详解
charRealmName2[0x10];
Hacking Diablo II之D2HACKIT技术详解
charUnknown7[0x08];
Hacking Diablo II之D2HACKIT技术详解
charGamePassword[0x10];
Hacking Diablo II之D2HACKIT技术详解
Hacking Diablo II之D2HACKIT技术详解}

GAMESTRUCT_110,
*
PGAMESTRUCT_110;
Hacking Diablo II之D2HACKIT技术详解
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/137079.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 数电课设 八路抢答器设计详解

    数电课设 八路抢答器设计详解设计一个八路竞赛抢答器,可同时供八名选手或八个代表队参加比赛,他们的选号分别是1、2、3、4、5、6、7、8,各用一个抢答按钮,按钮的编号与选手的编号相对应,分别是S1、S2、S3、S4、S5、S6、S7、S8。给节目主持人设置一个控制开关,用来控制系统的清零(编号显示码管灭灯)和抢答器的开始(开始倒计时)。抢答器具有数据锁存和显示的功能。抢答开始后,若有选手按动抢答按钮,编号立即锁存,并在LED数码管上显示出选手的编号,同时扬声器给出音响提示。此外,要封锁输入电路,禁止其他选手抢答,优先抢答选手的编号

    2022年10月20日
    5
  • 移动通信网络结构「建议收藏」

    移动通信网络结构「建议收藏」移动通信网络架构蜂窝网络架构蜂窝系统:(小区制系统)将所要覆盖的地区划分为若干个小区,每个小区的半径可视用户的发布密度在1-10km左右,在每个小区设立一个基站为本小区范围内用户服务;与之相对应的网络称为蜂窝式网络。特点:用户容量大、服务性能较好、频谱利用率较高、用户终端小巧且电池使用时间长,辐射小等。问题:频率复用牵扯到系统的复杂性、重选、切换、漫游、位置登记、更新和管理以及系统鉴权等。…

    2022年9月21日
    7
  • 初级程序员如何提升自己(程序员的成长之路)

    入职后如何快速成长到CTO入职后三个月试用期要做的事三法宝,处理同事关系核心两点,处理好领导关系每件事都是学习的机会主动加班,试用期加班是学习的好机会未通过试用期,如何应对?前三年需要学的技术工作后,千万不要停止学习项目经验如何累积?JAVA高级技术还需要学习哪些?架构师课程如何学习?工作中,快速学习新技术的捷径(重要的是形成体系,而不是钻到某个技术点)…

    2022年4月13日
    52
  • DropDownList_onpropertychange事件

    DropDownList_onpropertychange事件 functionshow_sub(v){//alert(v);varparam=””;param+=”PId=”+$(“#PId”).val();param+=”&type=”+$(“#HidType”).val();…

    2025年10月29日
    5
  • Linux如何通过命令查看日志文件的某几行(中间几行或最后几行)「建议收藏」

    Linux如何通过命令查看日志文件的某几行(中间几行或最后几行)

    2022年2月8日
    45
  • ubuntu16.04修改用户名和密码_网络设置的用户名和密码

    ubuntu16.04修改用户名和密码_网络设置的用户名和密码1、修改密码(1)进入Ubuntu,打开终端,输入:sudosu转为root用户;(2)输入:sudopasswduser(user是对应的用户名);(3)输入新密码,确认密码;(4)修改密码成功,重启,输入新密码进入Ubuntu;2、修改主机名(1)修改hostname文件输入:sudovim/etc/hostname,把旧主机名修改为新主机名;(2)修改hosts文件输入:sudovim/etc/hosts,把旧主机名修…

    2022年9月29日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号