20111227

Работа с указателями, или дописываем наш трейнер.

Ещё один небольшой, но ответственный и важный шажок в создании трейнера - работа с указателями. В [видео] кратко пересказана суть этого явления, а так же живой пример вместе с пошаговой отладкой в OllyDbg. Смотрим, задаём вопросы. Извините, что сбиваюсь - хотелось спать. :)

Полный исходный код трейнера (жирным синим шрифтом - новое) из этого урока на Flat Assembler:



format PE GUI 4.0
entry start
include 'c:\fasm\include\win32a.inc'
section '.data' data readable writable
error_message   db 'Error! :(',0
caption         db 'Fasm Trainer',0
pid             dd 0
 ;Необходимо для вызова процедуры чтения указателя через invoke
Poke            dd _Poke 
ReadPointer     dd _ReadPointer
windowcap       db 'Minesweeper',0
addr            dd 0x004256BF
godmode_on      db 0x90,0x90,0x90,0x90,0x90,0x90
godmode_off     db 0xD9,0x9F,0xC4,0xE5,0x48,0x00 
;Новые переменные  
 ;Базовый адрес указателя 
pointer_base    dd 0xFFD9AA38  
buffer          dd ? ;Буфер для чтения байт из памяти 
phandle         dd ? ;Переменная для хранения хэндла процесса


section '.text' code readable executable
start:
        invoke  GetModuleHandle,0
        invoke  DialogBoxParam,eax,37,HWND_DESKTOP,DialogProc,0
        invoke  ExitProcess,0
proc DialogProc hwnddlg,msg,wparam,lparam
     cmp        [msg],WM_CLOSE
     je         .wmclose
     cmp        [msg],WM_COMMAND
     je         .wmcommand
     cmp        [msg],WM_LBUTTONDOWN
     je         .move
     cmp        [msg],WM_INITDIALOG
     je         .init
     cmp        [msg],WM_TIMER
     je         .timer
     xor        eax,eax
     jmp        .finish
  .wmcommand:
     cmp        [wparam],BN_CLICKED shl 16 + 1
     je         .poke
     cmp        [wparam],BN_CLICKED shl 16 + 2
     je         .wmclose
  .poke:
     invoke     Poke,[addr],godmode_on,6
     jmp        .finish
  .wmclose:
     ;invoke     Poke,[addr],godmode_off,6
     invoke     EndDialog,[hwnddlg],0
  .move:
     invoke     SendMessage,[hwnddlg],WM_NCLBUTTONDOWN,2,0
     ret
  .init:
     invoke     SetTimer,[hwnddlg],0,100,0
     ret
  .timer:
     invoke     GetAsyncKeyState,VK_F11
     cmp        eax,0
     je         .finish
     invoke     ReadPointer,[pointer_base] ;Читаем указатель  
.finish:
     ret
endp
proc _Poke,memadd,memval,bytes
     invoke     FindWindow, 0, windowcap
     cmp        eax,0
     je         .error
     invoke     GetWindowThreadProcessId,eax,pid
     cmp        [pid],0
     je         .error
     invoke     OpenProcess,PROCESS_ALL_ACCESS,0,[pid]
     cmp        eax,0
     je         .error
     invoke     WriteProcessMemory,eax,[memadd],[memval],[bytes],0
     cmp        eax,0
     je         .error
     ret
.error:
     invoke     MessageBox,HWND_DESKTOP,error_message,caption,MB_OK
     ret
endp
proc _ReadPointer,address ;Процедура чтения указателя      
invoke     FindWindow,0,windowcap      
cmp        eax,0      
je         .error      
invoke     GetWindowThreadProcessId,eax,pid      
cmp        [pid],0      
je         .error      
invoke     OpenProcess,PROCESS_ALL_ACCESS,0,[pid]      
;Сохраняем хэндл процесса после его открытия     
cmp        eax,0     mov        [phandle],eax 
je         .error          
;Читаем содержимое базового адреса указателя в буфер
invoke     ReadProcessMemory,[phandle],[address],buffer,4,0       
cmp        eax,0      
je         .error     
 ;Прибавляем к содержимому буфера первое смещение
add        [buffer],0x18       
;Читаем полученный адрес
invoke     ReadProcessMemory,[phandle],[buffer],buffer,4,0  
 cmp        eax,0      
je         .error     
 ;Прибавляем второе смещение     
add        [buffer],0x20 
;Читаем полученный адрес
invoke     ReadProcessMemory,[phandle],[buffer],buffer,4,0       
cmp        eax,0      
je         .error           
ret 
.error:      
invoke     MessageBox,HWND_DESKTOP,error_message,caption,MB_OK      
ret  
endp
section '.idata' import data readable writeable
  library kernel,'kernel32.DLL',\
          user,'user32.DLL'
  import kernel,\
         GetModuleHandle,'GetModuleHandleA',\
         ExitProcess,'ExitProcess',\
         OpenProcess,'OpenProcess',\
         WriteProcessMemory,'WriteProcessMemory',\
;Объявляем новую функцию для работы с ней
         ReadProcessMemory,'ReadProcessMemory'

  import user,\
         DialogBoxParam,'DialogBoxParamA',\
         EndDialog,'EndDialog',\
         MessageBox,'MessageBoxA',\
         FindWindow,'FindWindowA',\
         GetWindowThreadProcessId,'GetWindowThreadProcessId',\
         SendMessage,'SendMessageA',\
         SetTimer,'SetTimer',\
         GetAsyncKeyState,'GetAsyncKeyState'
section '.rsrc' resource data readable
  directory RT_DIALOG,dialogs
  resource dialogs,37,LANG_ENGLISH+SUBLANG_DEFAULT,demonstration
  dialog demonstration,'Crimsonland +1 trainer by keng',70,70,190,175,WS_POPUP
         dialogitem 'STATIC','Press OK for toggle godmone on. Visit me at: www.gamehacklab.ru',-1,0,0,163,188,SS_LEFT + WS_VISIBLE+  SS_CENTER
         dialogitem 'BUTTON','OK',1,85,150,45,15,WS_VISIBLE
         dialogitem 'BUTTON','Cancel',2,135,150,45,15,WS_VISIBLE
  enddialog

PS: Как вы уже могли догадаться, квадратные скобки означают содержимое переменной, а их отсутствие - адрес этой переменной. :)

Комментариев нет:

Отправить комментарий

Не люблю мат и низкий уровень грамотности. Чем конкретнее поставите свой вопрос и чем лучше он будет выглядеть - тем большая вероятность на мой ответ. :)