سؤال

اريد الانفصال EndScene من تطبيق DirectX 9 التعسفي لإنشاء تراكب صغير. على سبيل المثال ، يمكنك أن تأخذ تراكب الإطار المضاد للهرمون ، والذي يظهر في الألعاب عند تنشيطه.

أعرف الطرق التالية للقيام بذلك:

  1. إنشاء جديد d3d9.dll, ، ثم يتم نسخها إلى مسار الألعاب. نظرًا لأن المجلد الحالي يتم تفتيشه أولاً ، قبل الانتقال إلى System32 وما إلى ذلك ، يتم تحميل DLL المعدل ، وتنفيذ رمزتي الإضافية.

    الجانب السلبي: عليك أن تضعها هناك قبل أن تبدأ اللعبة.

    • نفس الطريقة الأولى ، ولكن استبدال DLL في System32 مباشرة.

    الجانب السلبي: لا يمكنك إضافة رمز محدد للعبة. لا يمكنك استبعاد التطبيقات حيث لا تريد تحميل DLL الخاص بك.

    • الحصول على إزاحة EndScene مباشرة من DLL باستخدام أدوات مثل Ida Pro 4.9 مجانًا. نظرًا لأن DLL يتم تحميله كما هو ، يمكنك فقط إضافة هذه الإزاحة إلى عنوان بدء DLL ، عندما يتم تعيينه إلى اللعبة ، للحصول على الإزاحة الفعلية ، ثم ربطه.

    الجانب السلبي: الإزاحة ليست هي نفسها في كل نظام.

    • ربط Direct3Dcreate9 للحصول على D3D9 ، ثم التثبيت d3d9-> createdevice للحصول على مؤشر الجهاز ، ثم التثبيت الجهاز-> endscene من خلال الجدول الافتراضي.

    الجانب السلبي: لا يمكن حقن DLL ، عندما تعمل العملية بالفعل. عليك أن تبدأ العملية مع CREATE_SUSPENDED العلم لتوصيل الأولي Direct3Dcreate9.

    • إنشاء جهاز جديد في نافذة جديدة ، بمجرد حقن DLL. ثم الحصول على EndScene إزاحة من هذا الجهاز وربطه ، مما يؤدي إلى خطاف للجهاز الذي تستخدمه اللعبة.

    الجانب السلبي: اعتبارًا من بعض المعلومات التي قرأتها ، قد يتداخل إنشاء جهاز ثانٍ مع الجهاز الحالي ، وقد يتخطى وضع النوافذ مقابل وضع ملء الشاشة وما إلى ذلك.

    • نفس الطريقة الثالثة. ومع ذلك ، سوف تقوم بفحص نمط للحصول على EndScene.

    الجانب السلبي: لا يبدو هذا موثوقا.

كيف يمكنني ربط EndScene من DLL محقن ، والتي قد يتم تحميلها عند تشغيل اللعبة بالفعل ، دون الحاجة إلى التعامل مع مختلف d3d9.dllعلى أنظمة أخرى ، وبأسلوب موثوق به؟ كيف تؤدي الفتحات على سبيل المثال أن تكون خطافات DirectX؟ يجب ألا ينطبق DLL على جميع الألعاب ، فقط على عمليات محددة حيث حقنها عبر CreateRemoteThread.

هل كانت مفيدة؟

المحلول

تقوم بتثبيت خطاف واسع النظام. (SetWindowshookex) مع هذا ، سيتم تحميلك في كل عملية.

الآن عندما يتم استدعاء الخطاف ، تبحث عن D3D9.dll محملة.

إذا تم تحميل أحدهم ، يمكنك إنشاء كائن D3D9 مؤقتًا ، وتمشي في VTABLE للحصول على عنوان طريقة Endscene.

ثم يمكنك تصحيح مكالمة endscene ، بطريقتك الخاصة. (استبدل التعليمات الأولى في endscene عن طريق مكالمة إلى طريقتك.

عند الانتهاء ، يجب عليك تصحيح المكالمة مرة أخرى ، للاتصال بطريقة Endscene الأصلية. ثم أعد تثبيت التصحيح الخاص بك.

هذه هي الطريقة التي تفعل بها الفجوات. ((وصلة)


يمكنك العثور على عنوان وظيفة من VTABLE من واجهة.

حتى تتمكن من القيام بما يلي (الكود الزائف):

IDirect3DDevice9* pTempDev = ...;
const int EndSceneIndex = 26 (?);

typedef HRESULT (IDirect3DDevice9::* EndSceneFunc)( void );

BYTE* pVtable = reinterpret_cast<void*>( pTempDev );
EndSceneFunc = pVtable + sizeof(void*) * EndSceneIndex;

لا يحتوي EndSceneFunc الآن على مؤشر إلى الوظيفة نفسها. يمكننا الآن إما تصحيح جميع مواقع الاتصال أو يمكننا تصحيح الوظيفة نفسها.

احذر من أن كل هذا يعتمد على معرفة تنفيذ com-interfaces في Windows. لكن هذا يعمل على جميع إصدارات Windows (إما 32 أو 64 ، وليس كلاهما في نفس الوقت).

نصائح أخرى

سؤال قديم قليلاً أعرفه - ولكن في حال كان أي شخص مهتمًا بالقيام بذلك باستخدام C#، إليك مثال على ربط API Direct3D 9 باستخدام C#. يستخدم هذا EasyHook مجموعة .NET مفتوحة المصدر تتيح لك "تثبيت السنانير" بأمان "من التعليمات البرمجية المدارة إلى وظائف غير مُدارة. (ملاحظة: يعتني EasyHook بجميع المشكلات المحيطة بحقن DLL - على سبيل المثال create_suspended و ACL's و 32 مقابل 64 بت وما إلى ذلك)

أستخدم نهج VTABLE مماثل كما ذكر كريستوفر عبر DLL C ++ صغير لتحديد ديناميكي وظائف IDIRECT3DDEVICE9 لربط. يتم ذلك عن طريق إنشاء مقبض نافذة مؤقتة ، وإنشاء idirect3device9 ، وإنشاء idirect3device9 داخل التجميع المحقن قبل ثم ربط الوظائف المطلوبة. يتيح هذا لتطبيقك توصيل هدف يتم تشغيله بالفعل (تحديث: لاحظ أن هذا ممكن بالكامل ضمن C# أيضًا - راجع التعليقات على الصفحة المرتبطة).

تحديث: هناك أيضًا إصدار محدث لـ ربط Direct3d 9 و 10 و 11 لا يزال يستخدم EasyHook ومع SharpDX بدلاً من slimdx

أعلم أن هذا السؤال قديم ، ولكن هذا يجب أن يعمل مع أي برنامج باستخدام DirectX9 ، فأنت تقوم بإنشاء مثيلك الخاص بشكل أساسي ، ثم الحصول على المؤشر إلى VTABLE ، ثم تقوم بربطه فقط. ستحتاج إلى الالتفاف 3.x راجع للشغل:

//Just some typedefs:
typedef HRESULT (WINAPI* oEndScene) (LPDIRECT3DDEVICE9 D3DDevice);
static oEndScene EndScene;

//Do this in a function or whatever
HMODULE hDLL=GetModuleHandleA("d3d9");
LPDIRECT3D9(__stdcall*pDirect3DCreate9)(UINT) = (LPDIRECT3D9(__stdcall*)(UINT))GetProcAddress( hDLL, "Direct3DCreate9");

LPDIRECT3D9 pD3D = pDirect3DCreate9(D3D_SDK_VERSION);

D3DDISPLAYMODE d3ddm;
HRESULT hRes = pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm );
D3DPRESENT_PARAMETERS d3dpp; 
ZeroMemory( &d3dpp, sizeof(d3dpp));
d3dpp.Windowed = true;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;

WNDCLASSEX wc = { sizeof(WNDCLASSEX),CS_CLASSDC,TempWndProc,0L,0L,GetModuleHandle(NULL),NULL,NULL,NULL,NULL,("1"),NULL};
RegisterClassEx(&wc);
HWND hWnd = CreateWindow(("1"),NULL,WS_OVERLAPPEDWINDOW,100,100,300,300,GetDesktopWindow(),NULL,wc.hInstance,NULL);

hRes = pD3D->CreateDevice( 
    D3DADAPTER_DEFAULT,
    D3DDEVTYPE_HAL,
    hWnd,
    D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_DISABLE_DRIVER_MANAGEMENT,
    &d3dpp, &ppReturnedDeviceInterface);

pD3D->Release();
DestroyWindow(hWnd);

if(pD3D == NULL){
    //printf ("WARNING: D3D FAILED");
    return false;
}
pInterface = (unsigned long*)*((unsigned long*)ppReturnedDeviceInterface);


EndScene = (oEndScene) (DWORD) pInterface[42];
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)EndScene, newEndScene);
DetourTransactionCommit();

ثم وظيفتك:

HRESULT WINAPI D3D9Hook::newEndScene(LPDIRECT3DDEVICE9 pDevice)
{   
    //Do your stuff here

    //Call the original (if you want)
    return EndScene(pDevice);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top