तैयार कार्यक्रमों की कार्यक्षमता का
विस्तार करने के विषय की निरंतरता में
, मैं पहले से संकलित कार्यक्रम के तर्क को बदलने के लिए एक और तरीके के बारे में बात करना चाहूंगा, जिसे निष्पादन योग्य फ़ाइल में स्वयं परिवर्तन करने की आवश्यकता नहीं है। संयुक्त राज्य अमेरिका में अपने संशोधन को वितरित करते समय यह काम आ सकता है, जहां निष्पादन योग्य फ़ाइल के साथ सीधे हस्तक्षेप की कड़ी निंदा की जाती है। यह एक छोटे से प्रॉक्सी dll (केवल kil4 किलोबाइट) बनाने के बारे में होगा, उदाहरण के लिए ddraw.dll का उपयोग करके एप्लिकेशन द्वारा उपयोग की गई लाइब्रेरी को बदलने के लिए।
चलिए शुरू करते हैं
सभी काम विजुअल स्टूडियो 2010 में किए जाएंगे। सबसे पहले, हम निर्यात कार्यों के लिए लक्ष्य पुस्तकालय की जांच करते हैं। ऐसा करने के लिए, डंपबिन उपयोगिता (VS2010 \ VC \ bin निर्देशिका में) का उपयोग करें:
vcvars32 dumpbin /EXPORTS c:\windows\system32\ddraw.dll
नतीजतन, हम प्राप्त करते हैं:
ordinal hint RVA name 1 0 00002E69 AcquireDDThreadLock 2 1 000327FA CompleteCreateSysmemSurface 3 2 00032FAE D3DParseUnknownCommand 4 3 00033EEF DDGetAttachedSurfaceLcl 5 4 000325D7 DDInternalLock 6 5 0003258C DDInternalUnlock 7 6 000363FC DSoundHelp 8 7 0000859D DirectDrawCreate 9 8 00037851 DirectDrawCreateClipper 10 9 0000EBC6 DirectDrawCreateEx 11 A 000338C9 DirectDrawEnumerateA 12 B 00033368 DirectDrawEnumerateExA 13 C 00032CB2 DirectDrawEnumerateExW 14 D 0003333B DirectDrawEnumerateW 15 E 000387C1 DllCanUnloadNow 16 F 00038607 DllGetClassObject 17 10 00032675 GetDDSurfaceLocal 18 11 0003A5F9 GetOLEThunkData 19 12 0000E927 GetSurfaceFromDC 20 13 00027CC4 RegisterSpecialCase 21 14 00002EA8 ReleaseDDThreadLock 22 15 000421A6 SetAppCompatData
इसके आधार पर, हम पहले से ही अपना प्रॉक्सी dll बना सकते हैं। चूंकि हमें WinAPI के अलावा किसी और चीज की आवश्यकता नहीं है, इसलिए, एक ताजा win32 लाइब्रेरी प्रोजेक्ट में, पहली बात यह है कि RTL को
/NODEFAULTLIB
को चालू करके और प्रवेश बिंदु
DllMain
निर्दिष्ट करके बंद कर दें। यह बहुत मात्रा में जीत जाएगा। अगला, DEF फ़ाइल में, हम निम्नलिखित रूप में निर्यात किए गए कार्यों को निर्दिष्ट करते हैं:
LIBRARY "ddraw" EXPORTS AcquireDDThreadLock = FakeAcquireDDThreadLock @1 CheckFullscreen = FakeCheckFullscreen @2 CompleteCreateSysmemSurface = FakeCompleteCreateSysmemSurface @3 D3DParseUnknownCommand = FakeD3DParseUnknownCommand @4 ...
चूँकि हमें यह सुनिश्चित करने की आवश्यकता है कि हमारे "नकली" फ़ंक्शंस बस नियंत्रण को उनके मूल में स्थानांतरित करते हैं, सी ++ में उनमें से प्रत्येक की घोषणा इस तरह दिखाई देगी:
__declspec(naked) void FakeAcquireDDThreadLock() { _asm { jmp [ddraw.AcquireDDThreadLock] } }
__declspec(naked)
का उपयोग करके हम संकलक को मानक प्रोलॉग और उपसंहार कोड उत्पन्न करने के लिए मजबूर नहीं करते हैं
__declspec(naked)
स्टैक
__declspec(naked)
। नतीजतन, स्टैक पर डेटा पहले से ही एक उपयुक्त रूप में संग्रहीत किया जाता है, और हम बस स्टैक के मापदंडों को बार-बार पारित किए बिना एक ही
jmp
कमांड के साथ मूल फ़ंक्शन का नियंत्रण स्थानांतरित कर सकते हैं।
संक्रमण के लिए पता हटाए गए ढांचे से लिया गया है, जो इस तरह दिखता है:
struct ddraw_dll { HMODULE dll; FARPROC AcquireDDThreadLock; FARPROC CheckFullscreen; FARPROC CompleteCreateSysmemSurface; FARPROC D3DParseUnknownCommand;
यह संरचना हमारे प्रॉक्सी dll को लोड करने के समय DllMain में आबाद है। सबसे पहले, हम मूल पुस्तकालय को लोड करते हैं, फिर, बदले में, हमें सभी निर्यात किए गए कार्यों के पते मिलते हैं। कोड कुछ इस तरह दिखेगा:
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { char path[MAX_PATH]; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: CopyMemory(path+GetSystemDirectory(path,MAX_PATH-10), "\\ddraw.dll",11); ddraw.dll = LoadLibrary(path); if (ddraw.dll == false) { MessageBox(0, "Cannot load original ddraw.dll library", APP_NAME, MB_ICONERROR); ExitProcess(0); } ddraw.AcquireDDThreadLock = GetProcAddress(ddraw.dll, "AcquireDDThreadLock"); ddraw.CheckFullscreen = GetProcAddress(ddraw.dll, "CheckFullscreen"); ddraw.CompleteCreateSysmemSurface = GetProcAddress(ddraw.dll, "CompleteCreateSysmemSurface"); ddraw.D3DParseUnknownCommand = GetProcAddress(ddraw.dll, "D3DParseUnknownCommand");
नतीजतन, हमें एक कॉम्पैक्ट डीएल मिला जो बस प्रक्रिया के साथ हस्तक्षेप किए बिना, सभी कॉल को खुद से गुजरता है। एक समान परिणाम एक
स्वचालित समाधान का उपयोग करके प्राप्त किया जा सकता है, लेकिन कोड इतना सुंदर नहीं होगा।
DirectDraw गेम्स के लिए विंडो मोड
हमें एक साफ प्रॉक्सी dll मिलने के बाद, जो लक्ष्य एप्लिकेशन के साथ सफलतापूर्वक काम करता है, हम आवश्यक संशोधनों के साथ आगे बढ़ सकते हैं। अपने पुस्तकालय को लोड करने के समय, हम कोड के आवश्यक अनुभागों को पहले से ही मेमोरी में पैच कर सकते हैं, अन्य पुस्तकालयों से कॉल के लिए हुक सेट कर सकते हैं, और उन कार्यों के तर्क को भी बदल सकते हैं जो हम अपने dll में प्रॉक्सी करते हैं। हमारे मामले में, DirectDrawCreate फ़ंक्शन को बदलना सबसे तर्कसंगत होगा, ताकि यह एक अप्रत्यक्ष संरचना को उन तरीकों के स्पूफ़ पते के साथ लौटाए, जिनके व्यवहार को हम अंतिम लक्ष्य को प्राप्त करने के लिए बदलना चाहेंगे।
हालाँकि, यह प्रदर्शन कार्य के लिए बहुत अधिक काम है, और इसलिए हम केवल पिछले लेख से wndmode.dll लाइब्रेरी की सेवाओं का उपयोग करते हैं, जो पहले से ही सभी आवश्यक को लागू करता है, बस इसे प्रक्रिया के पते स्थान में लोड करें।
चलो
DllMain
में इसे ठीक करते हैं,
case DLL_PROCESS_ATTACH
एक लाइन जोड़कर
case DLL_PROCESS_ATTACH
:
LoadLibrary("wndmode.dll");
आपके स्वाद में अन्य परिवर्तन :)
Wndmode.dll पुस्तकालय
यह लाइब्रेरी सभी डायरेक्टड्रॉल कॉल को इंटरसेप्ट करने, पैरामीटर बदलने के लिए ज़िम्मेदार है, ताकि प्रोग्राम एक विंडो में चले, और उसके बाद ही मूल डायरेक्टड्र फ़ंक्शन पर नियंत्रण स्थानांतरित हो।
Wndmode.dll अपने आप में d3dhook.dll लाइब्रेरी का अत्यधिक संशोधित संस्करण है, जहाँ इसे लागू किया गया है:
- डी 3 डी विंडवर कार्यक्रम से पूर्ण स्वतंत्रता
- सेटिंग्स wndmode.ini फ़ाइल के [WINDOWMODE] अनुभाग से भरी हुई हैं
- डिफ़ॉल्ट सेटिंग्स जिन्न संगतता के लिए प्रतिस्थापित
- जोड़ा गया बॉर्डर पैरामीटर जो विंडो के चारों ओर फ्रेम को चालू / बंद करता है
- यदि गेम रिज़ॉल्यूशन सिस्टम रिज़ॉल्यूशन के बराबर है, तो फ़्रेम स्वचालित रूप से हटा दिया जाता है
यही है, wndmode.dll का उपयोग करके हम लगभग किसी भी DirectDraw गेम को विंडो गेम बनाने का प्रयास कर सकते हैं।
निम्नलिखित सेटिंग्स wndmode.ini में निहित हो सकती हैं:
[WINDOWMODE] UseWindowMode=1 UseGDI=0 UseDirect3D=0 UseDirectInput=0 UseDirectDraw=1 UseDDrawColorEmulate=1 UseDDrawFlipBlt=0 UseDDrawColorConvert=1 UseDDrawPrimaryBlt=1 UseDDrawAutoBlt=0 UseDDrawEmulate=0 UseDDrawPrimaryLost=0 UseCursorMsg=0 UseCursorSet=0 UseCursorGet=0 UseSpeedHack=0 SpeedHackMultiple=10 UseBackgroundResize=0 UseForegroundControl=0 UseFGCGetActiveWindow=0 UseFGCGetForegroundWindow=0 UseFGCFixedWindowPosition=0 EnableExtraKey=0 ShowFps=0 UseCursorClip=0 UseBackgroundPriority=0 DDrawBltWait=-1 Border=1
अधिकांश विकल्प
डी 3 डी विंडवर के समान हैं। ऊंचाई और चौड़ाई पैरामीटर हटा दिए गए थे, जिसने खिड़की का आकार तय किया था, और इसके बजाय सीमा पैरामीटर जोड़ा गया था (खिड़की के फ्रेम या नहीं प्रदर्शित करने के लिए) और स्वचालित फ्रेम छिपाना लागू किया गया था यदि गेम का रिज़ॉल्यूशन सिस्टम रिज़ॉल्यूशन से मेल खाता है। प्रत्येक गेम के लिए उपयुक्त सेटिंग्स अलग-अलग होंगी, उन्हें मैन्युअल रूप से चुनना होगा।
डाउनलोड
स्रोत कोड: bitbucket.org परबायनेरिज़: wndmode.zip (340 kb)
डेमो: एज ऑफ़ एम्पायर्स: द राइज़ ऑफ़ रोम
खेल के साथ निर्देशिका में हमारे ddraw.dll, wndmode.dll और wndmode.ini को कॉपी करें, खेल शुरू करें। ड्रम रोल ...
