日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Hacking Diablo II之外挂实战教程:去除D2JSP试用版显示的Trial Version信息

發布時間:2024/8/1 javascript 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hacking Diablo II之外挂实战教程:去除D2JSP试用版显示的Trial Version信息 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前幾天一個網友給我發消息請我幫他個忙。他的問題是,他正在使用的D2JSP是免費試用版,試用版在運行時會在游戲的所有游戲畫面中央顯示一行很大的“Trial Version”字樣(見下圖中的紅圈),很煩人,他想去掉這行字。我想正好用此做個教程解釋前面介紹過的hack工作原理,于是答應幫他看看。


我已經很久沒有開BOT了,最后一次使用D2JSP還是2003年1.09d時期的事。根據我以前的理解,D2JSP和其他hacks一樣,由兩部分組成,d2jsp.exe只是一個loader,負責把d2jsp.dll加載到游戲進程。而d2jsp.dll才是D2JSP的運行引擎-真正發揮作用的東西。因此“Trial Version”字符串肯定在d2jsp.dll中。最開始的想法是“Trial Version”可能會以一個常量字符串的形式保存在d2jsp.dll中,因此最容易想到的做法是用UltraEdit打開d2jsp.dll,尋找“Trial Version”,找到的話把它改為空字符串就OK了。然而打開后發現d2jsp.dll是加了殼的,這才想起自從D2 1.10以來D2JSP開始收費,采取了一些措施防止別人破解,加殼就是其中之一(當然還是被人破了)。在d2jsp.dll文件的前面幾行看到了aspack字串,看來加的是aspack殼。脫殼我很不在行,但是我知道有一些自動脫殼工具,針對aspack的脫殼工具也肯定有,不妨試試,于是到網上抓了個脫殼軟件-AspackDie。當然試驗的結果是失敗了。又想,不管怎樣,d2jsp.dll運行的時候它自己得脫殼吧,那我可以在它自己脫殼后在進程內存中找吧。于是加載D2JSP后用WinHex打開游戲進程,查找Trial Version,然而還是沒找到。看來可能用了即時脫殼技術,或者干脆Trial Version根本不是常量字符串,比如我知道如果在C/C++中這樣寫szVersion就不是常量字符串:

?

char?szVersion[]?=?{'T',?'r',?'i',?'a',?'l',?'?',?'V',?'e',?'r',?'s',?'i',?'o',?'n',?''};

然后怎么辦,繼續研究脫殼?不,其實我早就有了更好、更通用的解決方法,但是需要編程。現在看來簡單的思路行不通,還是寫程序算了。換個角度來看,不管字符串是什么,總得調用某個函數來輸出顯示吧,看上圖中的字樣,顯然是調用了Diablo II的內部函數顯示的,因此如果能截獲這個函數過濾掉"Trial Version"字符串就搞定了。而且這種方法不用修改D2JSP程序,對所有D2JSP版本都起作用,因此更通用。問題是它調用了D2X的哪個函數呢?我想起我的d2hackmap中也用到了類似的字符串顯示的功能,它們用的有可能是同一個!于是把d2hackmap的源代碼翻出來看了看,發現了d2win.dll中導出序號為10064(Diablo II中所有dll導出的函數都只有序號沒有名字)的函數做此用途,其函數聲明為:

?

void?__fastcall?D2WIN_DrawText(wchar_t?*str,?int?xpos,?int?ypos,?DWORD?color,?DWORD?unknown);

?然后用VC++ attach到游戲進程進行調試,想在D2WIN_DrawText設斷點監控,結果發現調試器剛attach上去D2JSP就會崩潰。看來它做了反調試處理,這也在意料之中。還是直接寫個DLL注入到游戲進程截獲D2WIN_DrawText來觀測得了,字符串可以用Win32 API OutputDebugString輸出然后用DbgView觀測:

?

void?__fastcall?MyD2WIN_DrawText(wchar_t?*str,?int?xpos,?int?ypos,?DWORD?color,?DWORD?unknown)

{
????
if?(str)?OutputDebugStringW(str);
}

結果發現“Trial Version”果然是通過D2WIN_DrawText輸出的,見下圖。


現在只要改變MyD2WIN_DrawText()的實現,判斷輸出字符串如果為"Trial Version"則跳過真正的D2WIN_DrawText()代碼就搞定了,代碼見后面的詳細源代碼分析。改變后的顯示結果如下圖,畫面上方的d2jsp v1.2.0字樣還在,Trial Version字樣已經沒了:


至此,給D2JSP打補丁的程序d2jsppatch.dll已經做好了,然而還有一個問題,就是d2jsppatch.dll如何加載呢?用D2JSP開的BOT一般是無人職守自動運行的,因此d2jsppatch.dll最好能夠隨著d2jsp.dll自動加載,否則每次都需要人工加載那就太麻煩了。那怎么做到隨d2jsp.dll自動加載呢?一個辦法是把d2jsp.dll改名為d2jsp2.dll,d2jsppatch.dll改名為d2jsp.dll,這樣d2jsp.exe每次加載d2jsp.dll時其實加載的是d2jsppatch.dll。d2jsppatch.dll加載起來后,在它的啟動代碼里再手工加載d2jsp2.dll(即原來的d2jsp.dll),這樣就達到了自動加載d2jsppatch.dll的目的。這種方法的缺點是它改變了D2JSP原有模塊之間的關系,可能會導致一些兼容性問題,比如d2jsp.exe可能會校驗d2jsp.dll檢查它是否被人改過,或者某個依賴于d2jsp.dll工作的程序可能會用LoadLibrary("d2jsp.dll")/GetProcAddress()獲取d2jsp.dll的到處函數,這時就會失敗。

伴隨d2jsp.dll自動加載的另外一種做法是把d2jsppatch.dll靜態綁定到d2jsp.dll或者d2jsp.dll會用到的某個DLL。由于d2jsp.dll加了殼,DLL文件的IAT(Import Address Table,即導入表)已經被破壞,最好是從d2jsp.dll會用到的DLL下手。我們知道D2JSP支持jscript腳本程序,它肯定會加載jscript腳本引擎js32.dll,所以我們可以把d2jsppatch.dll靜態綁定到js32.dll上去。熟悉Windows編程且喜歡玩API hooking的朋友可能知道微軟的Detours Library,其中附帶了一個程序setdll.exe可以把一個DLL靜態綁定到其他EXE或者DLL。在命令行運行:

?

setdll.exe?-d:d2jsppatch.dll?js32.dll

就把d2jsppatch.dll綁定到了js32.dll,如下圖。

以下是對d2jsppatch.dll源代碼的詳細分析,給感興趣的朋友參考。d2jsppatch.dll雖然是針對D2JSP的,但是它包含了一個hack的所有基本組成部分,而且功能很簡單,用它來了解hack的工作原理是很合適的。d2maphack、d2hackmap等hacks的工作原理和它完全一樣,不同的只是實現的功能。

1,d2jsppatch.dll的加載和卸載。DLL入口函數DllMain中一般用來做安裝(InstallPatch)、卸載(RemovePatch)旁路點(detour patch)。安裝、卸載工作可能導致程序崩潰(見以前的文章),放在DllMain中進行最合適,因為Windows保證在DllMain中的代碼執行時進程內的其他線程不會運行,見:http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx

?

BOOL?APIENTRY?DllMain(HANDLE?hModule,?DWORD?dwReason,?LPVOID?lpReserved)
{
????
if?(DLL_PROCESS_ATTACH?==?dwReason)
????
{
????????DisableThreadLibraryCalls((HMODULE)hModule);
????????
return?InstallPatch();
????}

????
else?if(DLL_PROCESS_DETACH?==?dwReason)
????
{
????????RemovePatch();
????}

????
return?TRUE;
}

?2,旁路點的安裝和卸載。安裝旁路點一般就是往旁路點處插入一個跳轉(call或jmp,5字節)指令,讓程序運行到此處時跳轉到自己的patch代碼。要注意程序代碼段的頁面屬性一般都是只讀的,安裝前先要把頁面屬性改成可讀寫,裝完后再恢復原來的頁面屬性。卸載旁路點就是把patch點原先的代碼寫回去,因此在安裝時要做一下備份。

?

void?WriteLocalBYTES(void*?pAddress,?void?*buf,?int?len)
{
????DWORD?oldprot?
=?0,?dummy;
????VirtualProtect(pAddress,?len,?PAGE_EXECUTE_READWRITE,?
&oldprot);
????WriteProcessMemory(GetCurrentProcess(),?pAddress,?buf,?len,?
&dummy);
????VirtualProtect(pAddress,?len,?oldprot,?
&dummy);
}


void?PatchCALL(DWORD?pOldCode,?DWORD?pNewCode,?DWORD?len)
{
????BYTE?buf1[
5];
????buf1[
0]?=?0xe8;?//?inst?call
????*(DWORD?*)(buf1+1)?=?pNewCode-(pOldCode+5);
????WriteLocalBYTES((
void*)pOldCode,?buf1,?len);
}


FARPROC?g_pDrawText;
BYTE?g_oldcode[
5];
BOOL?InstallPatch()
{
????HMODULE?hD2Win?
=?GetModuleHandle("d2win.dll");
????
if?(!hD2Win)?hD2Win?=?LoadLibrary("d2win.dll");
????
if?(hD2Win)
????
{
????????g_pDrawText?
=?GetProcAddress(hD2Win,?(LPCSTR)10064);
????????
if?(g_pDrawText)
????????
{
????????????memcpy(g_oldcode,?g_pDrawText,?
5);
????????????PatchCALL((DWORD)g_pDrawText,?(DWORD)D2WinDrawTextPatch_ASM,?
5);
????????????
return?TRUE;
????????}

????}

????
return?FALSE;
}


void?RemovePatch()
{
????
if?(g_pDrawText)
????????WriteLocalBYTES(g_pDrawText,?g_oldcode,?
5);
}

3,旁路點的patch代碼。patch代碼根據所要實現的功能的不同而不同,需要具體情況具體分析。一般來說邏輯稍微復雜些的patch代碼會由兩步分組成,一是用匯編寫的入口代碼,對寄存器和棧指針進行精細控制以免破壞原先的數據;二是用C/C++寫的邏輯實現代碼。匯編入口代碼調用C/C++的邏輯實現代碼。在此例中,D2WinDrawTextPatch_ASM為純(嵌入)匯編函數,第一行代碼運行前的寄存器內容和棧布局如注釋所示,D2WinDrawTextPatch有5個參數,由于是__fastcall,因此前兩個參數在ecx和edx中傳遞(VC的規定,C++ Builder可能有所不同),剩下三個從棧中傳入。由于C函數D2WinDrawTextPatch可能破壞ecx和edx里的內容,因此調用前必須保存它們的值,然后調用D2WinDrawTextPatch做真正的字符串過濾,注意D2WinDrawTextPatch也聲明為__fastcall,因此參數str為ecx。根據str是否為"Trial Version",D2WinDrawTextPatch返回TRUE或FALSE(返回值存放在eax中)。D2WinDrawTextPatch_ASM在D2WinDrawTextPatch返回后先恢復ecx和edx的原先內容,接著根據eax的值判斷是否應該執行真正的D2WinDrawText函數來顯示字符串。標號draw_text后面的代碼流程將跳到真正的D2WinDrawText去執行,由于旁路點把它的前兩個指令(共5個字節)改掉了(見下圖,上半部分為patch前的代碼,下半部分為patch后的代碼),在跳轉之前必須先執行這兩條指令。 BOOL?__fastcall?D2WinDrawTextPatch(wchar_t?*str)
{
????
return?str?&&?(*str?==?L'T'?&&?wcscmp(str,?L"Trial?Version")?==?0);
}


/*
*?[esp+0x10]?=?arg?5?-?unknown
*?[esp+0x0c]?=?arg?4?-?col
*?[esp+0x08]?=?arg?3?-?ypos
*?[esp+0x04]?=?return?address?of?caller?of?D2WIN_DrawText,?e.g.,?from?D2JSP
*?[esp+0x00]?=?return?address?of?D2WIN_DrawText
*?edx?=?arg?2,?xpos
*?ecx?=?arg?1,?text?string
*/

void?__declspec(naked)?D2WinDrawTextPatch_ASM()
{
????__asm
????
{
????????push?edx;?
//?arg?2?-?xpos
????????push?ecx;?//?arg?1?-?str
????????call?D2WinDrawTextPatch;
????????pop?ecx;
????????pop?edx;
????????test?eax,?eax;
????????jz?draw_text;
????????pop?eax;?
//?discard?return?address?of?caller?of?D2WIN_DrawText
????????ret?0x0c;?//?discard?three?arguments
draw_text:
????????pop?eax;?
//?return?address?of?D2WIN_DrawText

????????
//?original?code,?overwritten?by?detour?patch
????????push?ebx;
????????mov?ebx,?dword?ptr?[esp
+0x10];

????????jmp?eax;
????}

}


4,給靜態綁定用的空導出函數。在一般的hack中這一部分是不需要的。setdll.exe在做靜態綁定時需要把d2jsppatch.dll的一個導出函數(隨便一個,有一個就行)插入js32.dll的IAT中。

?

extern?"C"?__declspec(?dllexport?)?VOID?FakedInterface()
{
}

?5,做為一個行為良好、成熟的hack,在安裝旁路點前還應該檢測自己用到的旁路點有沒有已經被其他hack改掉了,否則就會導致其他hack不能正常工作甚至整個游戲崩潰。如果別人已經改掉了,自己要么額外處理要么只好主動退出。那么如果要patch很多點(像maphack、hackmap有上百個),怎么檢查這些點是否被改了呢?一個快速而且有效的做法是對這些點的內容預先計算一個校驗和,運行時每次安裝旁路點前再校驗一遍然后和預先計算的值比較。d2jsppatch.dll的功能很簡單,沒有做這部分處理,具體做法請參考d2hackmap 2.24的源代碼,也可以到這里下載:http://newd2event.net/index.php?id=hacks/Sting_Hackmap。

附:完整的d2jsppatch.dll源代碼,只有短短的100行不到。

#define?WIN32_LEAN_AND_MEAN
#include?
<windows.h>

//?helper?stuff
void?WriteLocalBYTES(void*?pAddress,?void?*buf,?int?len)
{
????DWORD?oldprot?
=?0,?dummy;
????VirtualProtect(pAddress,?len,?PAGE_EXECUTE_READWRITE,?
&oldprot);
????WriteProcessMemory(GetCurrentProcess(),?pAddress,?buf,?len,?
&dummy);
????VirtualProtect(pAddress,?len,?oldprot,?
&dummy);
}


void?PatchCALL(DWORD?pOldCode,?DWORD?pNewCode,?DWORD?len)
{
????BYTE?buf1[
5];
????buf1[
0]?=?0xe8;?//?inst?call
????*(DWORD?*)(buf1+1)?=?pNewCode-(pOldCode+5);
????WriteLocalBYTES((
void*)pOldCode,?buf1,?len);
}


//?patch?stuff
//BOOL?__fastcall?D2DrawTextPatch(wchar_t?*str,?int?xpos,?int?ypos,?DWORD?col,?DWORD?unknown)
BOOL?__fastcall?D2WinDrawTextPatch(wchar_t?*str)
{
????
return?str?&&?(*str?==?L'T'?&&?wcscmp(str,?L"Trial?Version")?==?0);
}


/*
*?[esp+0x10]?=?arg?5?-?unknown
*?[esp+0x0c]?=?arg?4?-?col
*?[esp+0x08]?=?arg?3?-?ypos
*?[esp+0x04]?=?return?address?of?caller?of?D2WIN_DrawText,?e.g.,?from?D2JSP
*?[esp+0x00]?=?return?address?of?D2WIN_DrawText
*?edx?=?arg?2,?xpos
*?ecx?=?arg?1,?text?string
*/

void?__declspec(naked)?D2WinDrawTextPatch_ASM()
{
????__asm
????
{
????????push?edx;?
//?arg?2?-?xpos
????????push?ecx;?//?arg?1?-?str
????????call?D2WinDrawTextPatch;
????????pop?ecx;
????????pop?edx;
????????test?eax,?eax;
????????jz?draw_text;
????????pop?eax;?
//?discard?return?address?of?caller?of?D2WIN_DrawText
????????ret?0x0c;?//?discard?three?arguments
draw_text:
????????pop?eax;?
//?return?address?of?D2WIN_DrawText

????????
//?original?code,?overwritten?by?detour?patch
????????push?ebx;
????????mov?ebx,?[esp
+0x10];

????????jmp?eax;
????}

}


FARPROC?g_pDrawText;
BYTE?g_oldcode[
5];
BOOL?InstallPatch()
{
????HMODULE?hD2Win?
=?GetModuleHandle("d2win.dll");
????
if?(!hD2Win)?hD2Win?=?LoadLibrary("d2win.dll");
????
if?(hD2Win)
????
{
????????g_pDrawText?
=?GetProcAddress(hD2Win,?(LPCSTR)10064);
????????
if?(g_pDrawText)
????????
{
????????????memcpy(g_oldcode,?g_pDrawText,?
5);
????????????PatchCALL((DWORD)g_pDrawText,?(DWORD)D2WinDrawTextPatch_ASM,?
5);
????????????
return?TRUE;
????????}

????}

????
return?FALSE;
}


void?RemovePatch()
{
????
if?(g_pDrawText)
????????WriteLocalBYTES(g_pDrawText,?g_oldcode,?
5);
}


BOOL?APIENTRY?DllMain(HANDLE?hModule,?DWORD?dwReason,?LPVOID?lpReserved)
{
????
if?(DLL_PROCESS_ATTACH?==?dwReason)
????
{
????????DisableThreadLibraryCalls((HMODULE)hModule);
????????
return?InstallPatch();
????}

????
else?if(DLL_PROCESS_DETACH?==?dwReason)
????
{
????????RemovePatch();
????}

????
return?TRUE;
}


//?faked?exported?function?used?to?bind?with?js32.dll
extern?"C"?__declspec(?dllexport?)?VOID?FakedInterface()
{
}


總結

以上是生活随笔為你收集整理的Hacking Diablo II之外挂实战教程:去除D2JSP试用版显示的Trial Version信息的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产情侣啪啪 | 波多野结衣一区二区三区中文字幕 | 黑人巨大精品一区二区在线 | 日韩一区二区不卡视频 | 中文字幕人妻一区二区三区 | 天天色影综合网 | 密臀av | 波多野结衣免费观看视频 | 国产欧美一区二区在线 | 一区二区不卡视频在线观看 | 成人涩涩 | 片黄在线观看 | 粉嫩av一区二区 | 国产美女久久 | 国产精品视频全国免费观看 | 久久婷婷国产麻豆91 | 亚洲字幕av一区二区三区四区 | 精品777 | 越南黄色一级片 | 欧美激情精品久久久久 | 青娱乐在线免费视频 | av一区二区三区在线 | 他揉捏她两乳不停呻吟动态图 | 日韩a级在线观看 | 日韩精品视频免费在线观看 | 欧美激情在线狂野欧美精品 | 99精品久久久久 | www日日| 国产成人在线视频网站 | 好吊妞视频在线 | 国产成人精品无码免费看在线 | 日韩大片av | 粉色视频免费观看 | 亚洲影院在线播放 | 91福利视频在线观看 | 色花堂在线 | 人人射人人 | 三级电影网址 | 国产视频1区2区3区 国产欧美一区二区精品性色99 | 欧美性爱精品一区 | 久久国产传媒 | 啪在线视频 | 男女免费网站 | 中文在线а√在线8 | 日本伦理一区二区三区 | 婷婷综合六月 | 污视频导航 | 黄色激情网站 | 99精品热| 在线v | 曰本毛片| 成人91免费视频 | 欧美野外猛男的大粗鳮 | 在线三区| 秋霞久久精品 | 免费成人深夜夜行p站 | 性欧美精品男男 | 精品国产乱码久久 | 黄色小毛片 | 日本性猛交 | 国产午夜毛片 | 天天操天天操天天操天天操天天操 | 国产在线一区视频 | 噜噜色图 | 成人av影院在线观看 | 午夜成人影视 | www精品国产 | 日日夜夜亚洲 | 久久久久成人精品无码 | 亚洲av成人精品日韩在线播放 | 未满十八岁禁止进入 | 国产日韩欧美视频在线观看 | 亚洲精品乱码久久久久久蜜桃不卡 | 99国产超薄肉色丝袜交足 | 三级a视频 | 日韩一区电影 | 天天综合久久 | 麻豆精品国产传媒mv男同 | 六月激情综合网 | 欧美视频免费 | 华人永久免费 | 美女高潮流白浆视频 | 麻豆日韩 | 热久久精品免费视频 | 黄色网免费看 | 久久久999 | 黄毛片在线观看 | 91精品99| 在线射| 日本在线中文 | 国产av无码国产av毛片 | 国产aⅴ精品一区二区果冻 台湾性生生活1 | 美女黄视频大全 | 99精品一区二区三区无码吞精 | 国产天堂av在线 | 日本中文字幕不卡 | 欧美成人a| 国产黄色激情视频 | 夜夜骑天天干 |