gmz Опубликовано 3 августа, 2016 Поделиться Опубликовано 3 августа, 2016 Некоторые особенности: 1 PE32 DLL 4.5 кб 2 Функция поиска паттерна 3 Паттерны текст вида 4 Функция обмена патч байтами 5 Если версия не совпадает - MessageBoxW и FreeLibrary 6 Клавиши работают только в активном окне игры 7 Меню и клавиши используют поток игры 8 Рисовка на базе D3DXCreateFontW->DrawTextW 9 100% unicode NASM: https://www.nasm.us -> nasm-2.xx.xx-win64.zip -> nasm.exe Linker: http://www.godevtool.com/Golink.zip -> golink.exe Редактор: https://notepad-plus-plus.org Приступим... Создадим txt файл и переименуем в "dragon commander hack.asm" Открываем файл в notepad++ Добавим EntryPoint, структуры, импорт апи Скрытый текст global DllMain struc RECT .left resd 1 .top resd 1 .right resd 1 .bottom resd 1 endstruc ;kernel32.dll extern DisableThreadLibraryCalls extern CreateThread extern CloseHandle extern GetModuleHandleW extern VirtualProtect extern FreeLibrary ;user32.dll extern GetFocus extern GetAsyncKeyState extern GetClientRect extern MessageBoxW ;d3dx9_43.dll extern D3DXCreateFontW Создадим секцию кода Скрытый текст section .code Добавим функцию DllMain, resd 1 - для пропуска адреса возврата а ret 3*4 значит что у функции 3 параметра. Скрытый текст DllMain: struc .stack resd 1 .hInstDLL resd 1 .Reason resd 1 .Reserved resd 1 endstruc cmp dword[esp+.Reason],1 jnz .DLL_PROCESS_ATTACH push dword[esp+.hInstDLL] call [DisableThreadLibraryCalls] push 0 push 0 push dword[esp+.hInstDLL+2*4] push Init push 0x1000 push 0 call [CreateThread] push eax call [CloseHandle] mov al,1 .DLL_PROCESS_ATTACH: ret 3*4 Добавляем функцию инициализации, получаем базу/размер модулей из PE хидера, поиск патч опций, DX9Binding.dll там будем ставить хуки для менюхи. Скрытый текст Init: struc .stack resd 3 .hInstDLL resd 1 endstruc push esi push edi push 0 call [GetModuleHandleW] mov esi,eax mov edi,[esi+60] ;IMAGE_DOS_HEADER.e_lfanew mov edi,[esi+edi+80] ;IMAGE_NT_HEADERS32.OptionalHeader+IMAGE_OPTIONAL_HEADER32.SizeOfImage push pAddGold1 push edi push esi call FindPattern test eax,eax jz .NotFound mov [aAddGold1],eax sub [bAddGold1+1],eax push pAddGold2 push edi push esi call FindPattern test eax,eax jz .NotFound mov [aAddGold2],eax sub [bAddGold2+1],eax push pAddResearchPoints push edi push esi call FindPattern test eax,eax jz .NotFound mov [aAddResearchPoints],eax sub [bAddResearchPoints+1],eax push pInstantCallDragon push edi push esi call FindPattern test eax,eax jz .NotFound mov [aInstantCallDragon],eax push pDragonHealth1 push edi push esi call FindPattern test eax,eax jz .NotFound mov [aDragonHealth1],eax push pDragonHealth2 push edi push esi call FindPattern test eax,eax jz .NotFound mov [aDragonHealth2],eax push pDragonEnergy push edi push esi call FindPattern test eax,eax jz .NotFound mov [aDragonEnergy],eax push pWeaponNoOverheat push edi push esi call FindPattern test eax,eax jz .NotFound mov [aWeaponNoOverheat],eax push pWeaponRapidFire push edi push esi call FindPattern test eax,eax jz .NotFound mov [aWeaponRapidFire],eax push pSkillNoCoolDown push edi push esi call FindPattern test eax,eax jz .NotFound mov [aSkillNoCoolDown],eax push DX9BindingDLL call [GetModuleHandleW] test eax,eax jz .NotFound mov esi,eax mov edi,[esi+60] ;IMAGE_DOS_HEADER.e_lfanew mov edi,[esi+edi+80] ;IMAGE_NT_HEADERS32.OptionalHeader+IMAGE_OPTIONAL_HEADER32.SizeOfImage push pD3DEndFrame push edi push esi call FindPattern test eax,eax jz .NotFound mov [aD3DEndFrame],eax sub [bD3DEndFrame+1],eax push pD3DresetDevice push edi push esi call FindPattern test eax,eax jz .NotFound mov [aD3DresetDevice],eax sub [bD3DresetDevice+1],eax push bD3DEndFrame.size push bD3DEndFrame push dword[aD3DEndFrame] call MemSwap push bD3DresetDevice.size push bD3DresetDevice push dword[aD3DresetDevice] call MemSwap pop edi pop esi ret 1*4 .NotFound: push 0x10+0x10000 ;MB_ICONERROR+MB_SETFOREGROUND push MsgTitle push MsgVersionUnsupported push 0 call [MessageBoxW] pop edi pop esi jmp [FreeLibrary] Добавляем функцию поиска. Она не особо сложная, быстрая и может пропускать мусорные байты. Принимает паттерны текст вида. Скрытый текст FindPattern: struc .stack resd 4 .Buffer resd 1 .Size resd 1 .Pattern resd 1 endstruc push ebx push esi push edi mov eax,[esp+.Buffer] mov ecx,[esp+.Size] add ecx,eax mov edx,[esp+.Pattern] .Next: lea esi,[eax-1] lea edi,[edx-2] .Check: add edi,2 mov bx,[edi] test bl,bl jz .Found add esi,1 cmp ecx,esi jz .NotFound cmp bx,'??' jz .Check sub bx,'00' cmp bh,10 jb .Skip1 sub bh,7 .Skip1: cmp bl,10 jb .Skip2 sub bl,7 .Skip2: shl bl,4 add bl,bh cmp [esi],bl jz .Check add eax,1 jmp .Next .NotFound: xor eax,eax .Found: pop edi pop esi pop ebx ret 3*4 и функцию обмена байтами, позволяет не копировать оригинал код для откл опций. Скрытый текст MemSwap: struc .stack .OldProtect resd 1 .stacksize equ $-$$ resd 2 .Address resd 1 .Patch resd 1 .Size resd 1 endstruc push ebx sub esp,.stacksize lea eax,[esp+.OldProtect] push eax push 0x40 ;PAGE_EXECUTE_READWRITE push dword[esp+.Size+2*4] push dword[esp+.Address+3*4] call [VirtualProtect] mov eax,[esp+.Address] mov ecx,[esp+.Patch] mov edx,[esp+.Size] .Next: sub edx,1 mov bh,[eax+edx] mov bl,[ecx+edx] mov [eax+edx],bl mov [ecx+edx],bh jnz .Next lea eax,[esp+.OldProtect] push eax push dword[esp+.OldProtect+1*4] push dword[esp+.Size+2*4] push dword[esp+.Address+3*4] call [VirtualProtect] add esp,.stacksize pop ebx ret 3*4 Теперь создадим функцию меню. Скрытый текст MenuHook: struc .stack .D3D_Device resd 1 .Rect resb RECT_size alignb 4 endstruc push ebp push esi push edi sub esp,.stack_size Место где установили перехват - достает D3D_Device, нам он нужен для D3DXCreateFontW, сохраним его, а потом вернем игре. Скрытый текст mov eax,[eax+0x138] ;device mov [esp+.D3D_Device],eax Добавим код для проверки активности окна. Также код используется для получения hGameWnd, следовательно, после инжекта, меню нарисуется только после клика в окно игры. Скрытый текст call [GetFocus] cmp dword[hGameWnd],0 jnz .FirstClick mov [hGameWnd],eax jmp .SkipDraw .FirstClick: cmp [hGameWnd],eax jnz .SkipKeys Добавим кнопку скрыть/показать меню. cmp + setz = 0/1 aka откл/вкл Скрытый текст push 0x2D ;VK_INSERT call [GetAsyncKeyState] cmp [kMenu+1],ah jz .Menu mov [kMenu+1],ah test ah,ah jz .Menu cmp byte[kMenu],0 setz [kMenu] .Menu: cmp byte[kMenu],0 jnz .SkipDraw Добавляем все опции... Скрытый текст push 0x61 ;VK_NUMPAD1 call [GetAsyncKeyState] cmp [kAddGold+1],ah jz .AddGold mov [kAddGold+1],ah test ah,ah jz .AddGold cmp byte[kAddGold],0 setz [kAddGold] push bAddGold1.size push bAddGold1 push dword[aAddGold1] call MemSwap push bAddGold2.size push bAddGold2 push dword[aAddGold2] call MemSwap .AddGold: push 0x62 ;VK_NUMPAD2 call [GetAsyncKeyState] cmp [kAddResearchPoints+1],ah jz .AddResearchPoints mov [kAddResearchPoints+1],ah test ah,ah jz .AddResearchPoints cmp byte[kAddResearchPoints],0 setz [kAddResearchPoints] push bAddResearchPoints.size push bAddResearchPoints push dword[aAddResearchPoints] call MemSwap .AddResearchPoints: push 0x63 ;VK_NUMPAD3 call [GetAsyncKeyState] cmp [kInstantCallDragon+1],ah jz .InstantCallDragon mov [kInstantCallDragon+1],ah test ah,ah jz .InstantCallDragon cmp byte[kInstantCallDragon],0 setz [kInstantCallDragon] push bInstantCallDragon.size push bInstantCallDragon push dword[aInstantCallDragon] call MemSwap .InstantCallDragon: push 0x64 ;VK_NUMPAD4 call [GetAsyncKeyState] cmp [kDragonHealth+1],ah jz .DragonHealth mov [kDragonHealth+1],ah test ah,ah jz .DragonHealth cmp byte[kDragonHealth],0 setz [kDragonHealth] push bDragonHealth1.size push bDragonHealth1 push dword[aDragonHealth1] call MemSwap push bDragonHealth2.size push bDragonHealth2 push dword[aDragonHealth2] call MemSwap .DragonHealth: push 0x65 ;VK_NUMPAD5 call [GetAsyncKeyState] cmp [kDragonEnergy+1],ah jz .DragonEnergy mov [kDragonEnergy+1],ah test ah,ah jz .DragonEnergy cmp byte[kDragonEnergy],0 setz [kDragonEnergy] push bDragonEnergy.size push bDragonEnergy push dword[aDragonEnergy] call MemSwap .DragonEnergy: push 0x66 ;VK_NUMPAD6 call [GetAsyncKeyState] cmp [kWeaponNoOverheat+1],ah jz .WeaponNoOverheat mov [kWeaponNoOverheat+1],ah test ah,ah jz .WeaponNoOverheat cmp byte[kWeaponNoOverheat],0 setz [kWeaponNoOverheat] push bWeaponNoOverheat.size push bWeaponNoOverheat push dword[aWeaponNoOverheat] call MemSwap .WeaponNoOverheat: push 0x67 ;VK_NUMPAD7 call [GetAsyncKeyState] cmp [kWeaponRapidFire+1],ah jz .WeaponRapidFire mov [kWeaponRapidFire+1],ah test ah,ah jz .WeaponRapidFire cmp byte[kWeaponRapidFire],0 setz [kWeaponRapidFire] push bWeaponRapidFire.size push bWeaponRapidFire push dword[aWeaponRapidFire] call MemSwap .WeaponRapidFire: push 0x68 ;VK_NUMPAD8 call [GetAsyncKeyState] cmp [kSkillNoCoolDown+1],ah jz .SkillNoCoolDown mov [kSkillNoCoolDown+1],ah test ah,ah jz .SkillNoCoolDown cmp byte[kSkillNoCoolDown],0 setz [kSkillNoCoolDown] push bSkillNoCoolDown.size push bSkillNoCoolDown push dword[aSkillNoCoolDown] call MemSwap .SkillNoCoolDown: После опций, добавим код создания шрифта и получения размера видимой области окна, также передвинем меню в правый угол а для копирования Rect структуры - используем SSE2. Скрытый текст .SkipKeys: cmp byte[kMenu],0 jnz .SkipDraw cmp dword[hFont],0 jnz .SkipCreateFont push hFont push Font push 0 push 5 ;CLEARTYPE_QUALITY push 0 push 0 push 0 push 0 push 700 ;FW_BOLD push 0 push 15 push dword[esp+.D3D_Device+11*4] call [D3DXCreateFontW] push Rect push dword[hGameWnd] call [GetClientRect] add dword[Rect+RECT.top],3 mov eax,[Rect+RECT.right] sub eax,160 mov [Rect+RECT.left],eax sub dword[Rect+RECT.right],6 .SkipCreateFont: movdqu xmm0,[Rect] movdqu [esp+.Rect],xmm0 lea ebp,[esp+.Rect] mov esi,[hFont] mov edi,[esi] ;d3dx9core.h Для вывода текста опций - используем DrawTextW Скрытый текст push 0xFF1C9ADB ;blue push 0x2 ;DT_RIGHT push ebp push Menu.size push Menu push 0 push esi call [edi+60] ;DrawTextW add [esp+.Rect+RECT.top],eax mov eax,0xFF1C9ADB ;blue mov ecx,0xFFFF0000 ;red cmp [kAddGold],cl cmovnz eax,ecx push eax push 0 push ebp push AddGold.size push AddGold push 0 push esi call [edi+60] ;DrawTextW add [esp+.Rect+RECT.top],eax mov eax,0xFF1C9ADB ;blue mov ecx,0xFFFF0000 ;red cmp [kAddResearchPoints],cl cmovnz eax,ecx push eax push 0 push ebp push AddResearchPoints.size push AddResearchPoints push 0 push esi call [edi+60] ;DrawTextW add [esp+.Rect+RECT.top],eax mov eax,0xFF1C9ADB ;blue mov ecx,0xFFFF0000 ;red cmp [kInstantCallDragon],cl cmovnz eax,ecx push eax push 0 push ebp push InstantCallDragon.size push InstantCallDragon push 0 push esi call [edi+60] ;DrawTextW add [esp+.Rect+RECT.top],eax mov eax,0xFF1C9ADB ;blue mov ecx,0xFFFF0000 ;red cmp [kDragonHealth],cl cmovnz eax,ecx push eax push 0 push ebp push DragonHealth.size push DragonHealth push 0 push esi call [edi+60] ;DrawTextW add [esp+.Rect+RECT.top],eax mov eax,0xFF1C9ADB ;blue mov ecx,0xFFFF0000 ;red cmp [kDragonEnergy],cl cmovnz eax,ecx push eax push 0 push ebp push DragonEnergy.size push DragonEnergy push 0 push esi call [edi+60] ;DrawTextW add [esp+.Rect+RECT.top],eax mov eax,0xFF1C9ADB ;blue mov ecx,0xFFFF0000 ;red cmp [kWeaponNoOverheat],cl cmovnz eax,ecx push eax push 0 push ebp push WeaponNoOverheat.size push WeaponNoOverheat push 0 push esi call [edi+60] ;DrawTextW add [esp+.Rect+RECT.top],eax mov eax,0xFF1C9ADB ;blue mov ecx,0xFFFF0000 ;red cmp [kWeaponRapidFire],cl cmovnz eax,ecx push eax push 0 push ebp push WeaponRapidFire.size push WeaponRapidFire push 0 push esi call [edi+60] ;DrawTextW add [esp+.Rect+RECT.top],eax mov eax,0xFF1C9ADB ;blue mov ecx,0xFFFF0000 ;red cmp [kSkillNoCoolDown],cl cmovnz eax,ecx push eax push 0 push ebp push SkillNoCoolDown.size push SkillNoCoolDown push 0 push esi call [edi+60] ;DrawTextW add eax,8 add [esp+.Rect+RECT.top],eax push 0xFF1C9ADB ;blue push 0x2 ;DT_RIGHT push ebp push About.size push About push 0 push esi call [edi+60] ;DrawTextW Возвращаем игре D3D_Device, убираем стек буфер, восстанавливаем важные регистры и ставим ret для возврата на код игры Скрытый текст .SkipDraw: mov eax,[esp+.D3D_Device] add esp,.stack_size pop edi pop esi pop ebp ret Добавляем функцию освобождения ресурсов которые были созданы D3DXCreateFontW, если их не освободить - игра просто вылелит в момент изменения размера окна. Обнуление hFont нужно чтобы D3DXCreateFontW мог создать новый шрифт и для получения нового размера окна. Скрытый текст D3DresetDeviceHook: push eax push ecx push edx cmp dword[hFont],0 jz .Skip mov eax,[hFont] mov ecx,[eax] ;d3dx9core.h push eax call [ecx+8] ;ReleaseFont mov dword[hFont],0 .Skip: pop edx pop ecx pop eax mov edi,ecx ;orig mov [esp+0x10+4],ebx ;orig ret и остальные функции для обработки перехвата. там также находится "оригинал код" который был заменен на call Скрытый текст AddGoldHook1: mov [esp+0x20+4],eax ;orig mov dword[eax+0x3C],1000 mov eax,[eax+0x3C] ;orig ret AddGoldHook2: mov dword[ecx+edx*4+0x480],100000 mov ecx,[ecx+edx*4+0x480] ;orig ret AddResearchPointsHook: mov dword[eax+0x44],1000 mov edx,[eax+0x44] pop ecx ;ret push edx ;orig push ecx lea ecx,[esp+0x5C+4] ;orig ret Создадим секцию данных для: паттернов, патчей, строк Скрытый текст section .data pAddGold1 db '894424??8B403C50',0 bAddGold1 db 0xE8 dd AddGoldHook1-5 db 0x90,0x90 .size equ $-bAddGold1 pAddGold2 db '8B8C??????????8944????894C????39',0 bAddGold2 db 0xE8 dd AddGoldHook2-5 db 0x90,0x90 .size equ $-bAddGold2 pAddResearchPoints db '528D4C24??FF15????????6A06',0 bAddResearchPoints db 0xE8 dd AddResearchPointsHook-5 .size equ $-bAddResearchPoints pInstantCallDragon db '2BC8898E????????79',0 bInstantCallDragon db 0x29,0xC9 .size equ $-bInstantCallDragon pDragonHealth1 db '7D??8B4424348B0FD9',0 bDragonHealth1 db 0xEB .size equ $-bDragonHealth1 pDragonHealth2 db '7D06D805????????D835????????D95C????D944????D84D',0 bDragonHealth2 db 0x74 .size equ $-bDragonHealth2 pDragonEnergy db '7A06D947??D95F??8B',0 bDragonEnergy db 0x70 .size equ $-bDragonEnergy pWeaponNoOverheat db 'D987????????D887????????D99F????????D987',0 bWeaponNoOverheat db 0xD9,0xEE,0x90,0x90,0x90,0x90 .size equ $-bWeaponNoOverheat pWeaponRapidFire db 'E8????????3BF07C162B',0 bWeaponRapidFire db 0xB8,0x20,0x4E,0x00,0x00 .size equ $-bWeaponRapidFire pSkillNoCoolDown db '2BC8890E7906C7',0 bSkillNoCoolDown db 0x29,0xC9 .size equ $-bSkillNoCoolDown pD3DEndFrame db '8B80????????8B088B??????????50FFD28B',0 bD3DEndFrame db 0xE8 dd MenuHook-5 db 0x90 .size equ $-bD3DEndFrame pD3DresetDevice db '8BF9895C????39',0 bD3DresetDevice db 0xE8 dd D3DresetDeviceHook-5 db 0x90 .size equ $-bD3DresetDevice align 4,db 0 Menu dw __utf16__'Insert menu',0 .size equ ($-Menu-2)/2 align 4,db 0 AddGold dw __utf16__'Num1 add gold',0 .size equ ($-AddGold-2)/2 align 4,db 0 AddResearchPoints dw __utf16__'Num2 add research points',0 .size equ ($-AddResearchPoints-2)/2 align 4,db 0 InstantCallDragon dw __utf16__'Num3 instant call dragon',0 .size equ ($-InstantCallDragon-2)/2 align 4,db 0 DragonHealth dw __utf16__'Num4 dragon health',0 .size equ ($-DragonHealth-2)/2 align 4,db 0 DragonEnergy dw __utf16__'Num5 dragon energy',0 .size equ ($-DragonEnergy-2)/2 align 4,db 0 WeaponNoOverheat dw __utf16__'Num6 weapon no overheat',0 .size equ ($-WeaponNoOverheat-2)/2 align 4,db 0 WeaponRapidFire dw __utf16__'Num7 weapon rapid fire',0 .size equ ($-WeaponRapidFire-2)/2 align 4,db 0 SkillNoCoolDown dw __utf16__'Num8 skill no cooldown',0 .size equ ($-SkillNoCoolDown-2)/2 align 4,db 0 About dw __utf16__'by gmz',0 .size equ ($-About-2)/2 align 4,db 0 DX9BindingDLL dw __utf16__'DX9Binding.dll',0 align 4,db 0 Font dw __utf16__'Arial',0 align 4,db 0 MsgTitle dw __utf16__'',0 align 4,db 0 MsgVersionUnsupported dw __utf16__'Version unsupported!',0 Создадим секцию неинициализ. данных, которые не занимают место в длке Скрытый текст section .bss hGameWnd resd 1 hFont resd 1 Rect resb RECT_size aAddGold1 resd 1 aAddGold2 resd 1 aAddResearchPoints resd 1 aInstantCallDragon resd 1 aDragonHealth1 resd 1 aDragonHealth2 resd 1 aDragonEnergy resd 1 aWeaponNoOverheat resd 1 aWeaponRapidFire resd 1 aSkillNoCoolDown resd 1 aD3DEndFrame resd 1 aD3DresetDevice resd 1 kMenu resb 2 kAddGold resb 2 kAddResearchPoints resb 2 kInstantCallDragon resb 2 kDragonHealth resb 2 kDragonEnergy resb 2 kWeaponNoOverheat resb 2 kWeaponRapidFire resb 2 kSkillNoCoolDown resb 2 Сборка: Скрытый текст @echo off ..\nasm.exe -f win32 "dragon commander hack.asm" ..\golink.exe /ni /nw /osversion 00060001 /version 00000000 /subsystemversion 00060001 /stacksize 0x10000 /stackinit 0x1000 /heapsize 0x10000 /heapinit 0x1000 /largeaddressaware /nxcompat /dynamicbase /base 0x10000000 /dll /entry DllMain "dragon commander hack.obj" kernel32.dll user32.dll d3dx9_43.dll if exist *.obj del *.obj pause ps справка по опциям линкера на оф сайте. 6 Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения