- Статус
- Оффлайн
- Регистрация
- 13 Фев 2026
- Сообщения
- 682
- Реакции
- 18
Для любителей хардкорного кодинга и тех, кто презирает тяжелые либы. Попал в руки полный исходник чита для Divinity: Dragon Commander, написанный чисто на ассемблере (NASM). Это не очередная паста на C++, а суровая работа с регистрами, стеком и прямыми системными вызовами.
Что внутри:
Доступные фичи в билде:
Как собрать:
Для компиляции тебе понадобятся nasm.exe и golink.exe. Ниже скрипт для автоматизации процесса:
Технически решение очень изящное — минимум зависимостей, чистый WinAPI и DirectX. Если игра обновится, достаточно переснять паттерны в IDA и обновить их в секции .data.
Интересно глянуть, кто сейчас еще пишет такие вещи на ассемблере под старые DX9 хиты.
Что внутри:
- Полноценное меню в игре на D3DX9 (Insert для вызова).
- Система FindPattern для автоматического поиска оффсетов под текущую версию.
- Хуки на WindowProc и D3D EndFrame.
- Механика MemSwap для безопасного патчинга памяти.
- Готовый батник для сборки через GoLink.
Доступные фичи в билде:
- Бесконечное золото и очки исследований (Add Gold / Research Points).
- Мгновенный призыв дракона.
- Бессмертие дракона и бесконечная энергия.
- Стрельба без перегрева и Rapid Fire.
- Скиллы без отката (No Cooldown).
Код:
global DllMain
;kernel32.dll
extern CloseHandle
extern CreateThread
extern DisableThreadLibraryCalls
extern FreeLibrary
extern GetModuleHandleW
extern VirtualProtect
;user32.dll
extern GetClientRect
extern GetDpiForSystem
extern MessageBoxW
extern SetThreadDpiAwarenessContext
;d3dx9_43.dll
extern D3DXCreateFontW
struc RECT
.left resd 1
.top resd 1
.right resd 1
.bottom resd 1
endstruc
section .code
DllMain:
struc .stack
resd 1
.hInstDLL resd 1
.fdwReason resd 1
.lpvReserved resd 1
endstruc
cmp dword[esp+.fdwReason],1
jne .DLL_PROCESS_ATTACH
push [esp+.hInstDLL]
call [DisableThreadLibraryCalls]
push 0
push 0
push [esp+.hInstDLL+2*4]
push Init
push 0
push 0
call [CreateThread]
push eax
call [CloseHandle]
mov al,1
.DLL_PROCESS_ATTACH:
ret 3*4
Init:
struc .stack
resd 3
.hInstDLL resd 1
endstruc
push ebp
push esi
push -2 ;DPI_AWARENESS_CONTEXT_SYSTEM_AWARE
call [SetThreadDpiAwarenessContext]
push 0
call [GetModuleHandleW]
mov ebp,eax
mov esi,[ebp+0x3C] ;IMAGE_DOS_HEADER.e_lfanew
mov esi,[ebp+esi+0x50] ;IMAGE_NT_HEADERS.OptionalHeader+IMAGE_OPTIONAL_HEADER.SizeOfImage
push pAddGold1
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [AddGold1],eax
sub [bAddGold1+1],eax
push pAddGold2
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [AddGold2],eax
sub [bAddGold2+1],eax
push pAddResearchPoints
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [AddResearchPoints1],eax
sub [bAddResearchPoints+1],eax
push pInstantCallDragon
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [InstantCallDragon1],eax
push pDragonHealth1
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [DragonHealth1],eax
push pDragonHealth2
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [DragonHealth2],eax
push pDragonEnergy
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [DragonEnergy1],eax
push pWeaponNoOverheat
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [WeaponNoOverheat1],eax
push pWeaponRapidFire
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [WeaponRapidFire1],eax
push pSkillNoCoolDown
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [SkillNoCoolDown1],eax
push pWindow
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [Window1],eax
sub [bWindow+1],eax
push DX9Binding
call [GetModuleHandleW]
test eax,eax
je .NotFound
mov ebp,eax
mov esi,[ebp+0x3C] ;IMAGE_DOS_HEADER.e_lfanew
mov esi,[ebp+esi+0x50] ;IMAGE_NT_HEADERS.OptionalHeader+IMAGE_OPTIONAL_HEADER.SizeOfImage
push pD3DEndFrame
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [D3DEndFrame1],eax
sub [bD3DEndFrame+1],eax
push pD3DResetDevice
push esi
push ebp
call FindPattern
test eax,eax
je .NotFound
mov [D3DResetDevice1],eax
sub [bD3DResetDevice+1],eax
push bWindow.size
push bWindow
push [Window1]
call MemSwap
push bD3DEndFrame.size
push bD3DEndFrame
push [D3DEndFrame1]
call MemSwap
push bD3DResetDevice.size
push bD3DResetDevice
push [D3DResetDevice1]
call MemSwap
pop esi
pop ebp
ret 1*4
.NotFound:
push 0x10+0x1000 ;MB_ICONERROR+MB_SYSTEMMODAL
push MsgTitle
push MsgUnsupportedVersion
push 0
call [MessageBoxW]
pop esi
pop ebp
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
je .Found
add esi,1
cmp ecx,esi
je .NotFound
cmp bx,'??'
je .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
je .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
alignb 4
.stacksize equ $
resd 2
.Address resd 1
.Patch resd 1
.Size resd 1
endstruc
push ebx
sub esp,.stacksize
push esp
push 0x40 ;PAGE_EXECUTE_READWRITE
push [esp+.Size+2*4]
push [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
jne .Next
push esp
push [esp+.OldProtect+1*4]
push [esp+.Size+2*4]
push [esp+.Address+3*4]
call [VirtualProtect]
add esp,.stacksize
pop ebx
ret 3*4
WindowHook:
struc .stack
resd 2
.hWnd resd 1
.uMsg resd 1
.wParam resd 1
.lParam resd 1
endstruc
push ecx
cmp dword[ebp+.uMsg],0x100
jne .WM_KEYDOWN
cmp dword[ebp+.wParam],0x2D ;VK_INSERT
jne .Menu
test dword[ebp+.lParam],0x40000000
jne .Menu
cmp byte[Menu],0
sete [Menu]
.Menu:
cmp byte[Menu],0
jne .WM_KEYDOWN
cmp dword[ebp+.wParam],0x61 ;VK_NUMPAD1
jne .AddGold
test dword[ebp+.lParam],0x40000000
jne .AddGold
cmp byte[AddGold],0
sete [AddGold]
push bAddGold1.size
push bAddGold1
push [AddGold1]
call MemSwap
push bAddGold2.size
push bAddGold2
push [AddGold2]
call MemSwap
.AddGold:
cmp dword[ebp+.wParam],0x62 ;VK_NUMPAD2
jne .AddResearchPoints
test dword[ebp+.lParam],0x40000000
jne .AddResearchPoints
cmp byte[AddResearchPoints],0
sete [AddResearchPoints]
push bAddResearchPoints.size
push bAddResearchPoints
push [AddResearchPoints1]
call MemSwap
.AddResearchPoints:
cmp dword[ebp+.wParam],0x63 ;VK_NUMPAD3
jne .InstantCallDragon
test dword[ebp+.lParam],0x40000000
jne .InstantCallDragon
cmp byte[InstantCallDragon],0
sete [InstantCallDragon]
push bInstantCallDragon.size
push bInstantCallDragon
push [InstantCallDragon1]
call MemSwap
.InstantCallDragon:
cmp dword[ebp+.wParam],0x64 ;VK_NUMPAD4
jne .DragonHealth
test dword[ebp+.lParam],0x40000000
jne .DragonHealth
cmp byte[DragonHealth],0
sete [DragonHealth]
push bDragonHealth1.size
push bDragonHealth1
push [DragonHealth1]
call MemSwap
push bDragonHealth2.size
push bDragonHealth2
push [DragonHealth2]
call MemSwap
.DragonHealth:
cmp dword[ebp+.wParam],0x65 ;VK_NUMPAD5
jne .DragonEnergy
test dword[ebp+.lParam],0x40000000
jne .DragonEnergy
cmp byte[DragonEnergy],0
sete [DragonEnergy]
push bDragonEnergy.size
push bDragonEnergy
push [DragonEnergy1]
call MemSwap
.DragonEnergy:
cmp dword[ebp+.wParam],0x66 ;VK_NUMPAD6
jne .WeaponNoOverheat
test dword[ebp+.lParam],0x40000000
jne .WeaponNoOverheat
cmp byte[WeaponNoOverheat],0
sete [WeaponNoOverheat]
push bWeaponNoOverheat.size
push bWeaponNoOverheat
push [WeaponNoOverheat1]
call MemSwap
.WeaponNoOverheat:
cmp dword[ebp+.wParam],0x67 ;VK_NUMPAD7
jne .WeaponRapidFire
test dword[ebp+.lParam],0x40000000
jne .WeaponRapidFire
cmp byte[WeaponRapidFire],0
sete [WeaponRapidFire]
push bWeaponRapidFire.size
push bWeaponRapidFire
push [WeaponRapidFire1]
call MemSwap
.WeaponRapidFire:
cmp dword[ebp+.wParam],0x68 ;VK_NUMPAD8
jne .SkillNoCoolDown
test dword[ebp+.lParam],0x40000000
jne .SkillNoCoolDown
cmp byte[SkillNoCoolDown],0
sete [SkillNoCoolDown]
push bSkillNoCoolDown.size
push bSkillNoCoolDown
push [SkillNoCoolDown1]
call MemSwap
.SkillNoCoolDown:
.WM_KEYDOWN:
pop ecx
mov edi,[ebp+0xC] ;orig
test ecx,ecx ;orig
ret
MenuHook:
struc .stack
.Rect resb RECT_size
alignb 4
endstruc
push ebx
push ebp
push esi
push edi
sub esp,.stack_size
mov ebx,[eax+0x138] ;D3DDevice
cmp byte[Menu],0
jne .SkipDraw
cmp dword[hFont],0
jne .SkipFont
push Rect
push [ebx+0x44] ;hFocusWindow
call [GetClientRect]
test al,al
je .SkipDraw
call [GetDpiForSystem]
mov ecx,eax
mov eax,15
mul ecx
mov ecx,96 ;USER_DEFAULT_SCREEN_DPI
xor edx,edx
div ecx
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 eax
push ebx
call [D3DXCreateFontW]
test eax,eax
jne .SkipDraw
mov dword[Rect+RECT.top],3
mov eax,[Rect+RECT.right]
sub eax,160
mov [Rect+RECT.left],eax
sub dword[Rect+RECT.right],6
.SkipFont:
lea ebp,[esp+.Rect]
mov esi,[hFont]
mov edi,[esi] ;ID3DXFont
movdqu xmm0,[Rect]
movdqu [ebp],xmm0
push 0xFF1C9ADB ;blue
push 0x2 ;DT_RIGHT
push ebp
push MenuShow.size
push MenuShow
push 0
push esi
call [edi+60] ;DrawTextW
add [esp+.Rect+RECT.top],eax
mov eax,0xFF1C9ADB ;blue
mov ecx,0xFFFF0000 ;red
cmp byte[AddGold],0
cmovne eax,ecx
push eax
push 0
push ebp
push MenuAddGold.size
push MenuAddGold
push 0
push esi
call [edi+60] ;DrawTextW
add [esp+.Rect+RECT.top],eax
mov eax,0xFF1C9ADB ;blue
mov ecx,0xFFFF0000 ;red
cmp byte[AddResearchPoints],0
cmovne eax,ecx
push eax
push 0
push ebp
push MenuAddResearchPoints.size
push MenuAddResearchPoints
push 0
push esi
call [edi+60] ;DrawTextW
add [esp+.Rect+RECT.top],eax
mov eax,0xFF1C9ADB ;blue
mov ecx,0xFFFF0000 ;red
cmp byte[InstantCallDragon],0
cmovne eax,ecx
push eax
push 0
push ebp
push MenuInstantCallDragon.size
push MenuInstantCallDragon
push 0
push esi
call [edi+60] ;DrawTextW
add [esp+.Rect+RECT.top],eax
mov eax,0xFF1C9ADB ;blue
mov ecx,0xFFFF0000 ;red
cmp byte[DragonHealth],0
cmovne eax,ecx
push eax
push 0
push ebp
push MenuDragonHealth.size
push MenuDragonHealth
push 0
push esi
call [edi+60] ;DrawTextW
add [esp+.Rect+RECT.top],eax
mov eax,0xFF1C9ADB ;blue
mov ecx,0xFFFF0000 ;red
cmp byte[DragonEnergy],0
cmovne eax,ecx
push eax
push 0
push ebp
push MenuDragonEnergy.size
push MenuDragonEnergy
push 0
push esi
call [edi+60] ;DrawTextW
add [esp+.Rect+RECT.top],eax
mov eax,0xFF1C9ADB ;blue
mov ecx,0xFFFF0000 ;red
cmp byte[WeaponNoOverheat],0
cmovne eax,ecx
push eax
push 0
push ebp
push MenuWeaponNoOverheat.size
push MenuWeaponNoOverheat
push 0
push esi
call [edi+60] ;DrawTextW
add [esp+.Rect+RECT.top],eax
mov eax,0xFF1C9ADB ;blue
mov ecx,0xFFFF0000 ;red
cmp byte[WeaponRapidFire],0
cmovne eax,ecx
push eax
push 0
push ebp
push MenuWeaponRapidFire.size
push MenuWeaponRapidFire
push 0
push esi
call [edi+60] ;DrawTextW
add [esp+.Rect+RECT.top],eax
mov eax,0xFF1C9ADB ;blue
mov ecx,0xFFFF0000 ;red
cmp byte[SkillNoCoolDown],0
cmovne eax,ecx
push eax
push 0
push ebp
push MenuSkillNoCoolDown.size
push MenuSkillNoCoolDown
push 0
push esi
call [edi+60] ;DrawTextW
add [esp+.Rect+RECT.top],eax
add [esp+.Rect+RECT.top],eax
push 0xFF1C9ADB ;blue
push 0x2 ;DT_RIGHT
push ebp
push MenuAbout.size
push MenuAbout
push 0
push esi
call [edi+60] ;DrawTextW
.SkipDraw:
mov eax,ebx
add esp,.stack_size
pop edi
pop esi
pop ebp
pop ebx
ret
D3DResetDeviceHook:
push eax
push ecx
push edx
cmp dword[hFont],0
je .Skip
mov eax,[hFont]
mov ecx,[eax] ;ID3DXFont
push eax
call [ecx+8] ;Release
mov dword[hFont],0
.Skip:
pop edx
pop ecx
pop eax
mov edi,ecx ;orig
mov [esp+0x10+4],ebx ;orig
ret
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
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
pWindow db '8B7D0C85C974??8B55??8B01',0
bWindow db 0xE8
dd WindowHook-5
.size equ $-bWindow
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
MenuShow dw __utf16__'Insert menu',0
.size equ ($-MenuShow-2)/2
align 4,db 0
MenuAddGold dw __utf16__'Num1 add gold',0
.size equ ($-MenuAddGold-2)/2
align 4,db 0
MenuAddResearchPoints dw __utf16__'Num2 add research points',0
.size equ ($-MenuAddResearchPoints-2)/2
align 4,db 0
MenuInstantCallDragon dw __utf16__'Num3 instant call dragon',0
.size equ ($-MenuInstantCallDragon-2)/2
align 4,db 0
MenuDragonHealth dw __utf16__'Num4 dragon health',0
.size equ ($-MenuDragonHealth-2)/2
align 4,db 0
MenuDragonEnergy dw __utf16__'Num5 dragon energy',0
.size equ ($-MenuDragonEnergy-2)/2
align 4,db 0
MenuWeaponNoOverheat dw __utf16__'Num6 weapon no overheat',0
.size equ ($-MenuWeaponNoOverheat-2)/2
align 4,db 0
MenuWeaponRapidFire dw __utf16__'Num7 weapon rapid fire',0
.size equ ($-MenuWeaponRapidFire-2)/2
align 4,db 0
MenuSkillNoCoolDown dw __utf16__'Num8 skill no cooldown',0
.size equ ($-MenuSkillNoCoolDown-2)/2
align 4,db 0
MenuAbout dw __utf16__'by drunkdragon',0
.size equ ($-MenuAbout-2)/2
align 4,db 0
Font dw __utf16__'Arial',0
align 4,db 0
MsgTitle dw __utf16__'',0
align 4,db 0
MsgUnsupportedVersion dw __utf16__'Unsupported version!',0
align 4,db 0
DX9Binding dw __utf16__'DX9Binding.dll',0
section .bss
Menu resb 1
AddGold resb 1
AddResearchPoints resb 1
InstantCallDragon resb 1
DragonHealth resb 1
DragonEnergy resb 1
WeaponNoOverheat resb 1
WeaponRapidFire resb 1
SkillNoCoolDown resb 1
alignb 4
hFont resd 1
Rect resb RECT_size
AddGold1 resd 1
AddGold2 resd 1
AddResearchPoints1 resd 1
InstantCallDragon1 resd 1
DragonHealth1 resd 1
DragonHealth2 resd 1
DragonEnergy1 resd 1
WeaponNoOverheat1 resd 1
WeaponRapidFire1 resd 1
SkillNoCoolDown1 resd 1
Window1 resd 1
D3DEndFrame1 resd 1
D3DResetDevice1 resd 1
Как собрать:
Для компиляции тебе понадобятся nasm.exe и golink.exe. Ниже скрипт для автоматизации процесса:
Код:
@echo off
nasm.exe -f win32 "dragon commander hack.asm"
golink.exe /ni /nw /osversion 00060000 /version 00000000 /subsystemversion 00060000 /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
Технически решение очень изящное — минимум зависимостей, чистый WinAPI и DirectX. Если игра обновится, достаточно переснять паттерны в IDA и обновить их в секции .data.
Интересно глянуть, кто сейчас еще пишет такие вещи на ассемблере под старые DX9 хиты.