20111229

Уроки и трейнеры.

Скоро допишу уроки по нормальному созданию rapidfire-hack'а (быстрая стрельба), может немножко в Direct3D залезу.

Трейнер, который я с вами курочу, в принципе, уже достаточно работоспособен для благополучного использования. Что ещё к нему прикрутим? Предложения - в комменты. :)

20111228

Нашёл ещё одну неплохую [доку] по изучению Ассемблера. На русском, да. :)

Апдейт: А [вот тут] лежит куча-куча всяких примеров кода.

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

20111226

Наш трейнер.

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

У меня тут вопрос один к вам возник: Может, стоит добавить в уроки музыку? Я обычно слушаю online-радио жанра trance - помогает сосредоточиться. Могу один урок записать с фоновой музыкой - если не будет особо мешать просмотру - так и оставлю. Мнения - в комментарии к записи.

20111225

Ломаем игры по заявкам читателей.

На этот раз ломаем закись азота (N2O) в игре Need For Speed: Carbon. Попутно узнаём ещё одну новую инструкцию по работе с дробными (float) числами. :)

[Ссылка] на урок.

FASM - добавляем горячие клавиши.

Записал очередной видеоурок, в котором вкратце рассказано о работе с горячими клавишами. Тыкнули кнопку, находясь в игре, - сработал трейнер. Удоообно! :)

Для реализации используем две новых WinAPI-функции - [SetTimer] и [GetAsyncKeyState].

Подробности - в [видео].

20111223

Уроки.

В ближайшее время будет готова пара уроков по нашему трейнеру. Параллельно постараюсь показать пару новых фич по взлому.

PS: А может быть, ещё и один новый инструмент освоим. ;)

Удобный редактор кода.

Для удобного чтения (и быстрого редактирования) исходного кода на всяких разных языках (в том числе и на ассемблере) рекомендую пользоваться [вот этим] текстовым редактором. Весит мало, бесплатен, удобен. :)

20111222

Поболтушечки.

Как вам блог-то, в целом? Интересно? Понятно более-менее? Я адекватен?

Я могу, конечно, его и просто так вести (структуризация и запись приобретённых знаний и умений - это круто!), но мне будет сильно приятнее знать, что стараюсь я не только для себя. :)

Вы пишите, периодически, всё ли у вас получается. Я ж готов помогать, ну! :D

Немного улучшаем внешний вид трейнера.

Помните процедуру диалогового окна нашего трейнера? Приведу её исходный код ещё раз, вот:


proc DialogProc hwnddlg,msg,wparam,lparam
     cmp     [msg],WM_CLOSE
     je      .wmclose
     cmp     [msg],WM_COMMAND
     je      .wmcommand
     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
  .finish:
     ret
endp
Давайте сделаем так, чтобы можно было окошко нашего трейнера таскать мышкой не только за синий заголовок, но и за любую часть окна. Добавляем несколько строчек:

 proc DialogProc hwnddlg,msg,wparam,lparam
     cmp     [msg],WM_CLOSE
     je      .wmclose
     cmp     [msg],WM_COMMAND
     je      .wmcommand
     cmp     [msg],WM_LBUTTONDOWN ;Если сообщение - клик левой кнопкой мыши
     je      .move ;Пытаемся его обработать
     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 ;Какая-то хитрая функция
  .finish:
     ret
endp
Синим цветом - добавленный код, зелёным - комментарии. Итак, происходит следующее. Как только мы кликаем по нашему окну левой кнопкой мыши (ЛКМ) - в процедуру обработки окна приходит сообщение - "Аааа! Нажали ЛКМ!! Что делать?!!". Вот теперь наша процедура как раз знает, что делать. :)
Функцией SendMessage мы обманываем глупую виндовс и говорим ей, что мы якобы не просто нажали ЛКМ, а нажали её на заголовке, о чём нам говорит цифра "2" в аргументах этой функции. По сути, функция эта умеет слать сообщения вручную - как если бы они к нам приходили извне. В аргументах функция требует указать, кому слать сообщение (указываем hwnddlg - хэндл нашего диалогового окна), само сообщение (WM_NCLBUTTONDOWN - нажатие ЛКМ. На самом деле - не совсем ЛКМ, а ЛКМ вне пределов клиентской области окна, но нам этого пока знать не обязательно) и место, какой части окна шлём, в аргументах. У нас этим аргументом является цифра "2", она обозначает заголовок окна.

Итак, как это выглядит? Мы зажали левую кнопку в окне, двигаем мышью - а окно двигается вместе с ней, как если бы мы таскали его за заголовок. Здорово? Здорово!

Но если вы смотрели предыдущие статьи и урок, то уже смело возражаете мне - "Как же так? Новая WinAPI-функция, а в секции импорта мы её не описали! Использовать не сможем! Безобразие!". Да, всё верно. Вот наша старая секция импорта:


section '.idata' import data readable writeable
  library kernel,'kernel32.DLL',\
 user,'user32.DLL'
  import kernel,\
GetModuleHandle,'GetModuleHandleA',\
ExitProcess,'ExitProcess',\
OpenProcess,'OpenProcess',\
WriteProcessMemory,'WriteProcessMemory'
  import user,\
DialogBoxParam,'DialogBoxParamA',\
EndDialog,'EndDialog',\
MessageBox,'MessageBoxA',\
FindWindow,'FindWindowA',\
GetWindowThreadProcessId,'GetWindowThreadProcessId'

А вот - новая:


section '.idata' import data readable writeable
  library kernel,'kernel32.DLL',\
          user,'user32.DLL'
  import kernel,\
         GetModuleHandle,'GetModuleHandleA',\
         ExitProcess,'ExitProcess',\
         OpenProcess,'OpenProcess',\
         WriteProcessMemory,'WriteProcessMemory'
  import user,\
         DialogBoxParam,'DialogBoxParamA',\
         EndDialog,'EndDialog',\
         MessageBox,'MessageBoxA',\
         FindWindow,'FindWindowA',\
         GetWindowThreadProcessId,'GetWindowThreadProcessId',\
         SendMessage,'SendMessageA'
Синим цветом добавлена новая функция. кстати, запятая и косая черта обозначает перенос строки - по функции на строку читается удобнее, мне кажется. :)

Не забудьте в имени функции поставить букву А - SendMessageA. Дело в том (опять я в подробности полез), что существует две версии этой (и других) функций - с буквой A и с буквой W. Обозначают эти буквы разные кодировки - ANSI и Unicode. Что это такое - выясняйте сами, т.к. это уже выходит за рамки тематики моего блога. Или просто не заморачивайтесь и используйте версии с А. :)


Ну и, в завершение, избавим наше диалоговое окно от заголовка, который теперь нам стал катастрофически не нужен. Идём в секцию ресурсов и меняем описание диалога вот на такое:

dialog demonstration,'Crimsonland +1 trainer by keng',70,70,190,175,WS_POPUP
Как видите, мы просто убрали часть флагов из последнего аргумента, который отвечает за внешний вид нашего окна.

Полный исходный код (синим цветом - изменения):


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
Poke dd _Poke
windowcap db 'Crimsonland',0
addr dd 0x004256BF
godmode_on db 0x90,0x90,0x90,0x90,0x90,0x90
godmode_off db 0xD9,0x9F,0xC4,0xE5,0x48,0x00

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

     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

  .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
section '.idata' import data readable writeable
  library kernel,'kernel32.DLL',\
          user,'user32.DLL'
  import kernel,\
         GetModuleHandle,'GetModuleHandleA',\
         ExitProcess,'ExitProcess',\
         OpenProcess,'OpenProcess',\
         WriteProcessMemory,'WriteProcessMemory'
  import user,\
         DialogBoxParam,'DialogBoxParamA',\
         EndDialog,'EndDialog',\
         MessageBox,'MessageBoxA',\
         FindWindow,'FindWindowA',\
         GetWindowThreadProcessId,'GetWindowThreadProcessId',\
         SendMessage,'SendMessageA'
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
Трейнер наш после этих телодвижений будет выглядеть вот так:






Третья часть про трейнеры!

На этот раз - видео. Вот [ссылка].
Заодно выкладываю [архив] с исходным кодом и скомпилированным трейнером.

Нагуглите и прочитайте обо всём, что не стало понятным из урока (в частности - про новые WinAPI-функции), спросите об оставшеимся тут, в комментариях на youtube или на [форуме], медитируйте, делайте зарядку и чистите зубы 2 раза в день. :)

Согласен, урок получился довольно скомканным - но у меня очень мало времени, простите. Работа, да и праздники, как-никак.

PS: Очень полезно будет загрузить скомпилированный трейнер в Olly (File -> Open) и посмотреть на его работу пошагово. Многое запросто может встать на свои места. Попробуйте, не бойтесь экспериментировать! Это же так весело и интересно. :)

20111221

Трейнеры, снова.

Я опять слегка загружен на работе, так что сегодня вечером постараюсь выложить следующее видео, а пока что ещё немного поканифолю вам, дорогие мои читатели, ваши светлые головы. Собственно, о чём сказать-то хочется? "Hello, world!", минимальную программу, умеющую говорить "Привет!" и радостно закрываться, мы более-менее написали и проанализировали. Скажу по секрету - для трейнера нам придётся написать нечто посолиднее. Давайте вспомним алгоритм работы простейшего трейнера, о котором я упомянул в [предыдущей] статье. Вот он:

1. Запуститься, показать своё окно
2. Ждать нажатия на кнопку от пользователя
3. Если пользователь всё-таки это сделал - включить (или выключить) какую-то из опций-читов
4. Корректно завершить работу после закрытия


Теперь неспеша (заварив себе ещё чашечку чая, да взяв тех французских булок™) разберём его, начиная с первого пункта. Нам нужно запуститься и показать окно трейнера. Простого MessageBox тут недостаточно, потому что оно закроется сразу после нажатия кнопки "ОК" и мы ничего с этим поделать не можем. Нужно что-то другое. К счастью, хитрые разработчики Microsoft это самое "другое" уже придумали - мы можем сделать окно! Да не просто окно, а диалоговое окно. Оно отличается от обычного окна тем, что очень хорошо умеет работать со всякими кнопочками и менюшками (а кнопочки у нас в трейнере ещё как будут), ну и чтобы создать его нужно написать меньше кода, чем для создания просто окна.


Вот что нам понадобится:


Для начала - исходный код и скомпилированное приложение, которые можно скачать по [этой ссылке]. Качаем, запускаем, читаем дальше и разбираемся.


1. Сразу после старта трейнера, получить handle (хэндл) нашего трейнера. Хэндл - суть идентификатор (номер) исполняемого файла, чтобы винда не перепутала его с какой-нибудь другой программой. Нужен он нам для того, чтобы сотворить от имени нашей программы окно (в нашем случае - диалоговое). Вот как это выглядит:



invoke GetModuleHandle,0
invoke DialogBoxParam,eax,37,HWND_DESKTOP,DialogProc,0
invoke ExitProcess,0

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

Дальше у нас идёт [DialogBoxParam], которая, собственно, создаёт диалоговое окно. Ей в аргументах нужно передать хэндл того, кто хранит процедуру работы этого окна (её опишем ниже), имя-идентификатор (в нашем случае - номер), описывающий внешний вид этого окна, хэндл того, кому окно будет принадлежать (в нашем случае - рабочему столу, Desktop), процедуру, описывающую поведение окна и параметры инициализации (забиваем на них, передавая ноль).

Круто? Круто! Но сложновато. Не паникуйте, эту штуку нам придётся написать один раз и забыть о ней - тут менять мы ничего не будем. Сейчас я напишу что-нибудь про третью строчку (которая просто завершает процесс трейнера), а потом вернёмся дальше ко второй - в частности, к процедуре поведения нашего диалогового окна. В-ж-ж-ж-ж-ж-ж!.. Вот, возвращаюсь. :)

Итак, хэндл получили, диалоговое окно вызывали, а когда оно завершило работу - завершаем вслед за ним и работу процесса. Всё просто. Но самое интересное - это процедура работы диалогового окна.

Если вы что-нибудь до этого слышали о программировании, то поймёте меня быстро. Всё поведение диалогового окна - один здоровый цикл. Это, по сути, участок кода, который быстро-быстро бормочет повторяет одно и то же и тем самым взаимодействует с системой. Взаимодействует он при помощи так называемых сообщений. Ну вот например:

-Нажали на крестик сверху-справа - диалоговое окно говорит - "Я ща закроюсь!11", послав сообщение о попытке закрытия. Винда ему отвечает - "Окей, валяй!". Оно берёт и закрывается. 
-Тыкнули в окне левой (или правой) кнопкой мыши - диалоговое окно и говорит - "Меня тыкают! Щекотно! Что делать?". И если мы опишем, что делать, оно что-нибудь сделает.

Удобно? Удобно. Делать нам нужно не много - проверять, не нажал ли пользователь какую-нибудь кнопку на клавиатуре, да уметь закрываться. Вот, собственно, простейшая процедура этого самого диалогового окна:



proc DialogProc hwnddlg,msg,wparam,lparam
        cmp     [msg],WM_CLOSE
        je      .wmclose
        xor     eax,eax
        jmp     .finish
  .wmclose:
        invoke  EndDialog,[hwnddlg],0
  .finish:
        ret
endp


Начнём с того, что процедура [DialogProc] описана в MSDN. Она принимает аж четыре аргумента - хэндл диалога, в котором крутится (ох уж эти хэндлы!), сообщения, которые ей шлёт созданный диалог и два дополнительных параметра, в которых иногда хранится дополнительная информация (каменты!) к приходящим сообщениям. По сути, эта процедура для диалога - она как мозги. Диалог только паникует и орёт, что с ним происходит, а процедура всё это выслушивает и что-то делает. В случае успеха - возвращает ноль, в случае неуспеха - 1. Теперь давайте построчно.


"proc DialogProc hwnddlg,msg,wparam,lparam" - начало процедуры, её имя и описание. Слово proc - сокращение от Procedure (англ. Процедура) - говорит нам о том, что мы пишем процедуру. Дальше - имя и параметры, которые она принимает.


cmp [msg],WM_CLOSE


Вот тут, значит, мы сравниваем входящее сообщение (от диалога) с WM_CLOSE - эта штуковина присылается при попытке этот самый диалог закрыть. Следующей строчкой:


je .wmclose


Мы говорим, переходить нам к завершению процедуры (и закрытию диалога), или же идти дальше. Напомню, je значит Jump if Equal (англ. Прыгнуть, если равно). ".wmclose" - это специальная метка, говорящая о том, где лежит код закрытия. Получается, что если сообщение будет равно WM_CLOSE - мы будем выполнять код, лежащий после метки ".wmclose".


Если же нет - переходим к следующим двум строчкам:



xor eax,eax
jmp .finish


Первой строчкой мы помещаем (то же самое, что и mov eax,0) в регистр еах нолик, говорящий о том, что всё хорошо, а дальше переходим на метку завершения работы процедуры (не диалога!). Причём в этом случае прыжок идёт безусловный - мы ничего ни с чем не сравниваем. Просто еах = 0 - и на выход!


Остаётся вот этот кусок:



.wmclose:
        invoke EndDialog,[hwnddlg],0
.finish:
        ret
endp


Начинается он с метки, на которую мы прыгаем в случае завершения работы диалога. И вызывается после неё ни что иное, как [EndDialog] - функция, которой передаёшь хэндл (!) завершаемого диалога и нолик, говорящий о том, что всё завершается хорошо и без ошибок.


Дальше идёт метка завершения работы процедуры (обработки сообщений диалога), которая просто возвращает управление созданному диалогу командой ret, а тот ждёт новых сообщений, которые, если приходят, опять нашей процедуре и скармливает.


Последнее - endp - обозначает конец описания процедуры. Служебная конструкция, типа. 




Вот и выходит, что диалог создаётся, у него есть простенький мозг - процедура, которая обрабатывает его сообщения. И обрабатывать она умеет (пока что) только одно - сообщение о выходе. А это Alt+F4 и крестик сверху-справа.


Ребята, в исходном коде, который приложен в начале статьи, есть ещё пара непонятных моментов. В самом начале исходника:


format PE GUI 4.0
Эта строчка указывает компилятору, что мы хотим от него получить именно EXE-файл под Windows и ничего другого. Про сам формат (PE - Portable Executable) мы всё выясним чуть позже, сейчас нам о нём следует знать только пару вещей, а именно, что он делится на секции. В нашей программе их будет аж три - секция кода и секция данных, которая будет делиться на данные для импорта и секцию ресурсов. Вот как это выглядит:


Сначала - секция кода. Мы об этом компилятору говорим вот такой строкой:


section '.text' code readable executable
Секция такая-то, а последние три слова говорят, что это код, который можно как читать, так и выполнять.


Идём дальше. Секция импорта (сразу напишу её содержимое):



section '.idata' import data readable writeable
  library kernel,'kernel32.DLL',\
 user,'user32.DLL'
  import kernel,\
GetModuleHandle,'GetModuleHandleA',\
ExitProcess,'ExitProcess'
  import user,\
DialogBoxParam,'DialogBoxParamA',\
EndDialog,'EndDialog'



В этой секции описываются те внешние библиотеки, которые программа должна подключить себе для корректной работы. Корректная работа заключается в доступе к тем самым WinAPI-функциям, да-да. Как видите, мы подключили две библиотеки ("kernel32.dll" и "user32.dll"), указали, какие функции хотим использовать, после чего просто вызывали их из кода.


Согласен, сложно. Запомните, что для доступа к нужным функциям нужно подключить библиотеки, в которых эти функции хранятся. И всё, больше заморачиваться не стоит.


Остаётся секция ресурсов. Вот она:



section '.rsrc' resource data readable
  directory RT_DIALOG,dialogs
  resource dialogs,\
  37,LANG_ENGLISH+SUBLANG_DEFAULT,demonstration
  dialog demonstration,' DialogBox Example ',70,70,190,175,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME
  enddialog


На ней мы подробно остановимся в следующей статье (и уроке), но кратенько скажу, что она хранит в себе описание самого диалогового окна и всех его элементов. Размеры окна, заголовок, внешний вид, всякие кнопочки и всё подобное хранится именно тут.


В секции ресурсов из нашего примера описывается одно-единственное диалоговое окно, у которого будет заголовок "DialogBox Example" и, в общем-то, сам системный заголовок (синяя блямба в верхней его части и кнопкой с крестиком справа).


Вот, как-то так. Надо вызубрить, что программа делится на секцию кода, которая может выполняться и на секцию данных, где лежит всё остальное.



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









20111220

Трейнеры.

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


Итак, привожу исходный код программы из первого урока. Вот он (после точки с запятой идёт комментарий):

; Исходный листинг hello.asm из примеров по flat assemblerinclude 'win32ax.inc' ; Подключаемая библиотека для работы с WinAPI-функциями

.code ; Начало секции кода
  start: ; Единственная метка - точка входа в программу
invoke MessageBox,HWND_DESKTOP,"Hi! I'm the example program!",invoke GetCommandLine,MB_OK ; Вызов информационного окна
invoke ExitProcess,0 ; Закрытие программы
.end start ; Закрывающая конструкция для входной метки



Давайте теперь разберём каждую строчку, начиная с первой. Итак:

1. Команда include (англ. подключить) - служит для подключения для внешней библиотеки, позволяющей нам использовать WinAPI-функции. Очень необходимая штука, без неё ничего работать не будет - просто запомните. :)

2. Штучка .code сообщает компилятору, что мы собрались писать код. Это - секция кода, подробнее будет в следующем уроке.

3. start: (англ. начало) и end start ("end" - англ. конец) - обозначают начало и конец единственной процедуры нашей программы. Процедур в программе может быть больше одной, так что мы явно просим компилятор начать именно отсюда.

4. На команде invoke (англ. вызвать), которую мы в нашей программе используем аж дважды, остановлюсь чуть подробнее. Если очень просто, то этой командой мы вызываем WinAPI-функцию, передав функции необходимые аргументы. Вот вам простой пример:

Лето, Сочи, жара +35, идём мы себе в гавайских шортах и сланцах по улице, а тут нас неожиданно одолевает жажда. Заворачиваем за угол и - о, чудо! - видим автомат по продаже кока-колы.
Подходим к автомату, трясём карманы - находим мелочь. Теперь - самое интересное. Чтобы купить бутылку, автомату нужно дать взятку денег - тут всё понятно. Так вот, автомат - это функция, а деньги - это аргументы этой функции. Бывает даже так, что функция после вызова присылает нам какой-то ответ. В случае автомата это будет или "Иди на фиг, денег мало" или "Вот Ваш напиток, Господин!". На языке ассемблера мы могли бы купить колы вот так:

invoke Автомат,35

Начинает проясняться, правда? :)

Ладно, возвратимся к нашей программе, в которой мы вызываем две функции. Первой мы показываем информационное окошко с каким-то текстом и кнопочкой "ОК", а второй просто завершаем работу. Подробнее про обе функции можно почитать вот тут:

[MessageBox]
[ExitProcess]


Потихоньку привыкаем читать документацию на английском, это правда очень сильно пригодится, поверьте мне. Если не получается сходу - воспользуйтесь помощью гугл-переводчика, сделайте его капельку счастливее. :)


Для тех, кто до сих пор не понял, что за слово такое - "компилятор" - объясняю: это программа, делающая из нашего исходного кода исполняемый EXE-файл. Подробнее пока знать ни к чему, ещё успеем.

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

В общих чертах, трейнер должен делать вот такое:

1. Запуститься, показать своё окно
2. Ждать нажатия на кнопку от пользователя
3. Если пользователь всё-таки это сделал - включить (или выключить) какую-то из опций-читов
4. Корректно завершить работу после закрытия

Как видите, всё довольно прозрачно. А подробности - в следующем уроке. :)

PS: Полный исходный код и скомпилированное приложение можно найти в папке \examples\hello из дистрибутива [flat assembler].

20111217

Видеоурок по стратегиям.

Пока что, думаю, заключительный - начнём уже трейнеры писать, наконец. :)

Делать мы будем не абы чо, а Map Hack (!) - грозу всея онлайн-комьюнити, штуковину, позволяющую брать и бессовестно подглядывать за вражьим игроком, делая себе нифига себе такое преимущество.

Метод достаточно идиотский - наткнулся на него случайно, может работать не во всех играх. А может и работать, я во всех играх ещё не проверил. :)


PS: !!!Не пытайтесь!!! играть с этой штукой онлайн - велик риск быть забаненным. А я в этом не виноват, потому что сейчас это написал.

[ссылка на урок]

20111216

Напоследок.

Завтра я сотворю следующее видео по ассемблеру и трейнерам, честно-честно. И по гонкам что-нибудь, если успею. Вспомнил, что от меня хотели speedhack - неприличной скорости ускорение. Точнее, показать, как оно делается. :D

ВНЕЗАПНО, видеоурок!

По стратегиям, который я всё-таки записал, самым невероятным образом. Расскажу - не поверят!. Итак, опираясь на недоперевод статьи из предыдущих постов - переходим к наглядной практике:

[ссылка на урок]

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

Если сложно и не ломается - да забейте вы на этот отладчик, попейте чаю, возьмите листочик с карандашом и порисуйте лучше. Ну, в смысле, как на ваш взгляд всё это должно работать. Тогда может и идея какая придёт в светлую голову, так-то!

И в очередной раз можно убедиться в исключительной полезности гугла и петабайт справочных материалов, по сети раскиданных. Встретили команду, но не знаете нафига она? Гугл! Забыли как правильно пишется какое-то слово? Гугл! Хотите научиться ломать игры? Г!.. Ан-нет, - keng. :)


20111215

Новогоднее настроение!


Вроде середина декабря, новый год скоро и вообще, а я, вместо пожирания мандаринок, сижу и готовлю материал для следующих уроков. Неплохой бонус к новогодним праздникам, мне кажется. :)

А чем вы заняты в такое радостное время?

Ещё немножко про трейнеры.

Пока я тут скучаю на работе - накидаю вам небольшой план по дальнейшим урокам касательно чёрной магии ассемблера:

Собственно, алгоритм работы сферического трейнера в вакууме не представляет из себя ничего хитрого. Трейнеру для счастья и комфорта нужно всего ничего - запустить своё окошко и что-нибудь там показать-рассказать и дать послушать, затем - ждать, пока пользователь что-нибудь сделает - тыкнет в кнопку мышкой или нажмёт на клаве кнопку. Если вдруг такое происходит - сделать, что приказано, а потом тихо закрыться.

Вот в пункте "сделать, что приказано" и будет происходить самое интересное, и имя ему - запись в память. Да, я серьёзно. Именно в этот момент нам и понадобятся все наши найденные адреса и всё остальное, так-то!

Как видите, алгоритм простой. Поэтому я объявляю конкурс бесплатно без смс скачать - попробуйте реализовать этот алгоритм сами. Само собой, на любимом языке, если такой у вас есть. Если вдруг удастся (или нет) - пилите исходник в архив и, вместе с описанием, суйте всё это в комменты к этой записи.

Ну как, круто я придумал? :)

Дырявая моя голова!11

Забыла выложить [ссылку] на Flat Assembler. (:
PS: Нам нужна версия для Windows, можете мне поверить.

Прошу любить и критиковать - первый видеоурок по ассемблеру!

Или мнёмся на пороге, приступая к работе. (:

[ссылка]

20111214

Обломинго, товарищи!

Ребята, у меня сейчас конец квартала на работе, так что я там практически живу. После нескольких очень спешных, но безуспешных попыток найти сейчас современную стратегию без навешанных на неё защит и прочих усложнителей нашей геймхакерской жизни, я сейчас постараюсь изложить нужный материал в виде статьи, чтобы вы хоть как-то не скучали, а потом перейдём к ассемблеру и трейнерам, т.к. там для уроков ничего искать не нужно и времени у меня (которого и так катастрофически ни на что нет) отнимать будет не много - следовательно, уроки будут выкладываться чаще.

Собственно, статья будет переводом одного зарубежного ресурса с моими небольшими дополнениями. Переводить (скорее даже - вольно пересказывать)  я буду основные моменты, т.к. в той статье использовались не совсем актуальные на данный момент инструменты, но суть способа передаётся отлично в любом случае. Итак:

-------------------------------------

Задача: Мгновенная постройка только для игрока.
Инструменты:

-Игра жанра RTS
-Сканер памяти (Cheat Engine)
-Отладчик (тоже Cheat Engine)
-Начальные навыки взлома игр - теория по DMA, инъекции кода

Теория:

Главное, что нужно понять в теории к этой теме - разницу между игрой человека и компьютера, проще говоря - бота. Посидев с чашкой любимого чая и парой бутербродов над раздумьями, мы приходим к мысли, что человеку необходимо видеть происходящее на экране, чтобы принимать решения. Т.е. вся информация (количество ресурсов, построенные здания, положение армии и так далее) не просто обрабатывается алгоритмами игры, но и выводится для человека на экран в привычном человеку виде.

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

Грубо говоря, для игрока всё видимое на экране - это дублирование внутриигровых значений, т.е. можно искать, скажем, ресурсы, а найти только адрес, значение которого выводит их на экран, но не будет истинным значением ресурсов. Как-то так. А вот у бота всё попроще - он сразу из памяти читает.

Практика:

Как вы все уже могли догадаться, первая половина взлома происходит достаточно просто:

1. Мы знаем, что постройка чего либо занимает определённое время. Начинаем строить какое-то здание, видим на экране отображение прогресса строительства - или полоску:

[|||||||||||||||||||||||||||||||=>75 %        ]

или просто здоровье здания\проценты в цифрах.

2. Возможных алгоритмов поиска будет аж три штуки. Вот они:
-Неизвестное значение, уменьшилось-уменьшилось-уменьшилось.
-Неизвестное значение, увеличилось-увеличилось-увеличилось.
-Неизвестное значение, изменилось-изменилось-изменилось.

Тип данных - а когда как, на самом деле. От целого 1 байт до с плавающей точкой.

3. Итак, ставим новое здание, пока строится - пробуем искать по описанным выше способам.

В конце концов находим адрес, вешаем на него брейкпоинт и смотрим отладчиком, какая инструкция туда пишет. Вот тут - очень важный момент:

Где-то рядом с этой инструкцией будет сравнение (человек \ бот) и затем - условный переход или call (вызов) функции. По сути, для бота алгоритм будет примерно таким:

-Проверить, не достроилось ли здание
-Если достроилось - сообщить об этом

А вот для человека - таким:

-Проверить, не достроилось ли здание
-Обновить экранное значение (полоску или проценты)
-Если достроилось - сообщить об этом

Вот после сравнения как раз и будет идти инструкция, нужно ли игре обновлять значение на экране. И бывает так, что эта штука - единственное, как можно отличить игрока-человека от бота.

Сама по себе инструкция постройки будет тоже простецкая, как-нибудь вот так:

cmp edi, ebx //сравниваем значение текущего прогресса с 100%
je done //если достроилось - выходим и сообщаем об этом игроку
sub edi, eax //достраиваем ещё кусочек

Т.е. мы просто берём и в инъекции вычитаем из edi его же значение - вуаля, всё будет строиться сразу же. Но перед этим нам необходимо будет проверить, человек ли строит, т.к. код-то один и тот же - ну, с парой отличий. :)

Так как игра в любом случае должна отличать игроков друг от друга, смотрим код выше и ищем все сравнения, ставим на них брейкпоинты и внимательно изучаем значения регистров - сравниваться может что угодно, от ника того, кто строит, до цвета и просто флажка вида "Свой - чужой". В нашей инъекции обязательно это используем для отсеивания ботов.

Как видите, всё достаточно просто. Самое полезное в этой теме - понимание теории про экранные значения, процесс поиска нужного нам адреса (просто так бывает и не догадаешься так искать) и (довольно часто) - новые способы сравнения игроков между собой. В остальном этот урок на 90% схож с темой one hit kill (убийство с одного выстрела), которую я показывал на примере Crimsonland.


PS: Я изо всех сил стараюсь выкроить время для нормальной записи урока и покажу всё это на примере - так информация воспримется лучше, но пока что буду обращать больше внимания на трейнеры и ассемблер, т.к. это правда займёт меньше времени. Спасибо всем, кто это прочитал, прочитает или даже поделится ссылкой с другом. Если захочется почитать оригинальную статью на английском, то её можно найти, к примеру, тут.


20111121

Следующий видеоурок.

Ребята, про что следующий урок записать?

Поломаем стратегии? Скажем, мгновенную постройку сделаем?

Или RPG (работа с инвентарём)?

Или может, запишем урок по крутому дизассемблеру (и отладчику) - Hex-Rays IDA Pro?

 

Предложения, в том числе и свои, - в комментарии. :)

20111110

RSS

Настроил для блога RSS-канал, теперь можно подписываться. Сообщите, пожалуйста, если что-то не так работает.

20111109

Материалы по Ассемблеру.

На хабрахабре обнаружился замечательный [пост], содержащий тучу информации для помощи в изучении этого не менее замечательного языка. Берём на вооружение! Что-то я уже в блоге упоминал, что-то - нет.

Дополнительная информация.

В [предыдущем] видеоуроке (если вы, конечно, уже успели его посмотреть и ужаснуться), взлом был не таким, как в остальных уроках. В чём он отличался? А в том, что Cheat Engine мы не использовали и никакие адреса, по сути, не искали. Использовали мы замечательный отладчик под названием [OllyDbg], абсолютно бесплатный для некоммерческого использования (его даже можно скачать по [этой ссылке]) и который мы будем использовать дальше. Не всё время (с Cheat Engine бы до конца разобраться, да?), но периодически будем.

В предыдущем уроке мы ломали игру под названием Call of Duty, построенную на движке Quake 3 Arena. Это - замечательный факт, потому что к движку этого самого третьего квейка прилагается исходный код в виде SDK - Software Developer's Kit, он же - Инструментарий Разработчика.

Мы тут же лезем на [FTP] ID Software и качаем SDK последней версии. Написан он на С++, но мы, не зная этого языка, используем логику и английский язык - нам нужна функция стрельбы, то есть всё, где есть слова "weapon" (оружие) и "fire" (стрельба). Находим нужный файл, открываем простым текстовым редактором и ищем в нём одноимённую функцию.

В этой функции (опять же, практически на чистом английском), мы узнаём, что при её выполнении играется анимация выстрела, вспышка и звук, а вот про отдачу там ни слова нет.

Понимая, что в нашей игре она всё-таки есть, мы надеемся что мудрые разработчики нужную нам функцию просто немного дописали и идём в Olly.

В отладчике мы открываем процесс нашей игры и ищем в нём все текстовые строчки, среди которых нам попадается та самая функция, к вызову которой мы и переходим. А сразу же после неё мы обнаруживаем шибко подозрительный условный переход. Меняем его на обратный - и voila - отдачи в игре нет.

 

Можно было бы и пойти другим путём, используя только Cheat Engine:

Ищем неизвестное значение типа float, постреляли (ствол оружия направлен вверх) - увеличилось, ствол опустился - уменьшилось и так далее. После этого смотрим, что пишет в этот адрес, и ищем нужный нам код. Обычно это или условный переход, или же call (вызов функции). Плюс этого способа в том, что сработает в любой игре, минус же - что искать адрес придётся долго, а ещё дольше - разбираться в коде.

Поначалу OllyDbg может выглядеть сильно сложным и непонятным, но вспомните себя при просмотре первых видеоуроков и поймёте разницу - достаточно немного практики, чтобы освоиться. :)

Видеоурок.

Записал [видео] на тему no recoil - отдачи при стрельбе. Смотрим, задаём вопросы - урок не совсем обычный. Чуть позже напишу более подробный пост.

20111107

Трейнеры.

Помните, ребята, когда-то давно, ещё в предыдущей версии блога, я устраивал опрос на тему "Какой же язык программирования выбрать для написания трейнеров?". Там были варианты вроде Visual Basic, C++, C# и так далее.

В конце концов я пришёл к тому, что раз уж алгоритм (то, как трейнер работает) трейнера всегда один и тот же, независимо от языка, то писать мы будем сразу на ассемблере. Почему? Потому что далеко не факт, что все мои читатели знакомы с программированием в принципе, а вместе с видеоуроками волей-неволей стали потихоньку изучать ассемблер - самый низкоуровневый язык, обладающий самыми большими возможностями. Что значит "низкоуровневый"? Примерно вот так:

 

Компьютер сам по себе умеет обращаться только с ноликами и единичками - двоичным кодом, используя для этого двоичную систему счисления (у нас же, людей, она десятичная, арабская, а в Cheat Engine мы используем ещё и шестнадцатиричную). Когда трава была зеленее, а компьютеры занимали половинку спортивного зала программировали их никак иначе, чем переключением туда-сюда тумблеров (из 0 в 1 и наоборот). Потом ОКАЗАЛОСЬ, что это не очень удобно, когда программы стали посложнее и придумали язык ассемблера - максимально приближённый к переключению тумблеров с точки зрения компьютера и при этом хоть как-нибудь, но понятный людям. Большинство команд - это мнемонические сокращения, как то:

 

mov - move (сдвиг)

jmp - jump (прыжок)

ret - return (возврат)

 

и так далее. Это, собственно, самый низкий уровень языка. Простое правило - чем ниже уровень - тем больше возможностей. Со временем начали упрощать и ассемблер, так появились языки более высокого уровня - FORTRAN, C, Pascal и их современники. Код на ассемблере выглядит довольно специфично и сам процесс довольно сильно отличается от такового на языках высокого уровня, а раз мы с самого начала взялись вникать в ассембер (пусть и немного), то продолжать будем на нём же. В крайнем случае, когда читатель поймёт, что код трейнера довольно простенький - он сможет выбрать себе язык по вкусу и написать трейнер на нём.

Новые видеоуроки!

Уже совсем скоро. Будем ломать стратегии. Пару новых фишек тоже узнаем.

20111103

Подписки на блог.

RSS пока не перенастроен, но я есть и в твиттере, так что можете фолловить. Туда автоматически скидываются оповещения о добавлении новых уроков на YouTube, а так же комментариев к ним. Я тоже пишу, но редко.

Телепорт!

Ссылочка. Сейчас убегаю на работу, так что подробности напишу позже. Смотрим, вникаем, задаём вопросы, если что-то не ясно.

Ещё раз выражаю благодарность Xipho с форума Gamehacklab[RU], т.к. решение проблемы, возникшей при записи урока, нашлось именно благодаря его подсказке. Иначе бы мне пришлось дальше перелопачивать кучу иностранных ресурсов в поисках ответа, а это затянуло бы выход урока.

В нём мы реализуем (при помощи родного отладчика и любимого ассемблера, конечно же) возможность телепортации главного героя с место на место, даже если игра сама по себе так не умеет. Красивая штука, впечатляющая, не в каждом трейнере такое встретишь - потому что не все так умеют. А вы теперь уметь будете. :)

Следующие видеоуроки посвящу опциям rapid fire (быстрая стрельба) и no recoil (без отдачи), затем поломаем немного стратегии и RPG (мгновенная постройка зданий, работа с инвентарём и т.д.), после чего, вооружённые навыками, потихоньку начнём трейнеры писать.

Трейнеры будем писать сразу же на ассемблеры, причина довольно простая:

Ассемблер - низкоуровневый язык (чем ниже уровень - тем больше возможностей), выглядит он довольно странно и сам по себе сильно отличается от ЯВУ - языков высокого уровня, таких как C++, C#, Delphi или Visual Basic, на которых программирует подавляющее большинство вменяемых людей. :)

Код на языке ассемблера достаточно долго писать (команды маленькие и короткие, но их много - язык очень подробный), но этот код очень быстро выполняется и программы получаются крайне компактными, а учитывая то, что алгоритм работы трейнера по сути всегда один и тот же (и я вам его покажу и подробно объясню), то мы напишем его один раз и будем постепенно дорабатывать, не забивая голову языками высокого уровня. Кто захочет - тот освоит и их, тут разницы принципиальной нет. В будущем нам ЯВУ тоже наверняка понадобятся. ;)

20111101

123

Повседневное.

Пока я сижу на работе, а дома качаю\устанавливаю\ломаю игры по заявкам читателей, параллельно занимаясь написанием статей и записью видеоуроков, стало интересно:

Ребята! И те, кто читает мой блог, и те, кто случайно набрёл на эту страничку в поисках трейнера или читов к игре N, а блог их заинтересовал. Как у вас там? Применяете полученные знания? Всё получается? Ну не верится мне, что ни у кого не возникает ни единого вопроса. Задавайте их в комментах! Тут, на ютубе, присылайте по электропочте, в конце концов.

Я не могу просто так взять, взмахнуть мышкой с клавиатурой и сделать так, чтобы у вас вдруг сразу всё стало получаться - находиться нужные адреса и указатели, отлаживаться в отладчике код, писаться код трейнеров. Это нужно повторять снова и снова, шаг за шагом. Теорию нужно изучать, игры - ломать, код - писать. Только так всё начнёт получаться. Это (сюрприз!) - залог успеха в любом деле.

Понятно, что меня может читать и полтора человека раз в неделю, так как блог я веду совсем недавно, но и они вряд ли могут быть гениями, чтобы у них не возникало вопросов. Стесняться меня (или других читателей) тоже не надо - если вы задаёте вопросы и чего-то не понимаете, то это говорит лишь о том, что вы стараетесь узнать что-то новое, а не ждёте готовенькое, и уж точно ни разу нет в этом ничего постыдного.

20111030

Переезд.

Практически закончил переезд на новый домен (спасибо Xipho и команде gamehacklab.ru), движок блога, по такому-то случаю, я тоже сменил. Этот не хуже, мне кажется.

Продолжаю делать урок про телепорт. Ждите.

20111028

Восьмой, восьмой видеоурок!

Идём по [ссылке] и наслаждаемся. Качество может быть плохим какое-то время - видео только что загружено и всё ещё на обработке.

Темы дальнейших уроков!

Что охватим после телепорта, м? Уже были предложения по стратегиям - бесконечные ресурсы - это банально, а вот мгновенная постройка зданий и юнитов - это уже веселее. Ещё могу показать создание так называемого мапхака (maphack) - чита, позволяющего видеть вражеских юнитов, когда те скрыты "туманом войны" (игравшие в стратегии поймут, просто так эту штуку трудновато объяснить).

Если хотите - могу перейти к теме созданию трейнеров, которая тоже довольно обширная. В общем, жду мнений в комментариях. :)

Ещё один вариант - взлом эмуляторов Sega, Dendy, Sony PlayStation и иже с ними. Никогда толком не залезал в них, думаю, было бы неплохо освоить.

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

О координатах.

Вообще говоря, тема работы с координатами (как по горизонтальной оси - X\Y, так и по вертикальной - Z) довольно обширная и там можно много чего придумать. Самые распостранённые техники - побыстрее прыгать \ повыше прыгать (для врагов, соответственно, наоборот, ибо нефиг), да телепорт с места на место по уровню. Вот вариантов исполнения - их много, очень много. Подробнее расскажу в видео - там показан только один из способов, самый простой.

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

В будущем планирую показать пару других инструментов для взлома. В частности, более мощный отладчик и более мощный дизассемблер. Кому-то может не нравиться отладчик в Cheat Engine, кому-то могут понадобиться более крутые возможности. Словом, покажу, а там уж сами решите - надо оно вам, или нет. Я более продвинутые инструменты использую, когда не могу разобраться в коде игры сразу, т.е. в запущенных случаях, которые случаются довольно редко, как видно из предыдущих видеоуроков.

Наконец-то!

Ребята, записал, записал видеоурок моей мечты - огромный, здоров... А, хотя ладно, оставим это.

Записал видеоурок, посвящённый повадкам супермена - суперпрыжкам, но внезапно осознал, что опаздываю на работу. Работа пересилила, так что сейчас я в офисе, а урок выложу вечером, часов в шесть по московскому. Ждите.

20111027

Опрос-опросничек: Ломаем любимые игры читателей!

Ребята, я тут вот что подумал!

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

1. Ваше имя или никнейм (чтобы можно было как-то обратиться).
2. Название игры. Лучше - на английском языке.
3. Опция, которую пытались сделать. Например - "Бессмертие, бесконечные очки\деньги\жизни, убийство с одного удара" и т.д.

Соберём пачечку сообщений и я буду периодически записывать небольшие уроки конкретно по этим "заявкам", с максимально подробными объяснениями. И человеку будет приятно и материал заодно повторим, поймём и усвоим ещё лучше. Ну как? В общем, жду. :)

20111024

Задержки с публикациями.

Товарищи читатели!

Искренне прошу прощения за то, что не успеваю вовремя выкладывать новые уроки - весь в работе, даже выходные на неё потратил. Выложу урок про superjump в как можно ближайшее время, а вам пока что предлагаю задать накопившиеся вопросы (или я так хорошо даю материал и вам всё понятно?) и предложить тему следующего видеурока\статьи - будем что-то новое ковырять, или ещё с координатами повозимся? У меня в планах показать создание телепорта, это тоже не так уж сложно, но немного кода написать придётся. Если есть идеи получше - пишите, я только за.

20111016

Продолжение видеоуроков!

Ребята, дико извиняюсь за отсутствие публикаций - забегался на работе. Следующий видеоурок будет примерно в середине недели, будем учиться высоко прыгать, как и обещано. :)

20110929

Статья про FPU.

Как и обещано, [ссылка]. :D

Вторая часть седьмого видеоурока - делаем спидхак для Crimsonland!

С разбегу - [ссылка]!

Во второй части я покажу, как делается взлом скорости ("быстро бегать") для замечательной аркады Crimsonland, попутно объясню значение пары новых ассемблерных команд, характерных только для данного типа взлома. А именно:

fld [eax] - загружает значение типа float (с плавающей точкой) в [математический сопроцессор] (он же FPU) для последующих операций над ним.
fstp [eax] - соответственно, выгружает результат обратно в регистр eax.

Как именно вся эта фигня работает нам знать не настолько важно. Нам будут встречаться конструкции вида:

fld [eax+1234]
fadd [edi] (то же, что и add)
fsub [esx] (то же, что и sub)
fstp [eax+1234]


Основная мысль заключается в том, что главный процессор не умеет работать с дробными числами (float), так что для этого существует процессор поменьше - сопроцессор, который умеет только это. Командой fld (float load) мы заставляем главный процессор скормить нужное нам число сопроцессору, дальше в нём происходят какие-то действия над числом (fadd, fsub и т.п.), после чего по команде fstp число грузится обратно в главный процессор. Очень похоже на code-injection, правда? :)

Наша задача - или вклиниться в действия над значением после его загрузки в сопроцессор (пример - на видео), или посмотреть, что происходит чуть раньше - скажем, какая разница в координатах прибавляется\убавляется, часто можно обнаружить некоторый множитель. Типа, идём шагом - координаты умножаются на единичку, бежим бегом - умножаются на пять (бежим впятеро быстрее, чем идём шагом). Механизм действий схож для большинства игр, т.к. практически все хранят координаты в типе float, но ньюансы встречаются - нет универсального решения.

Теорию про сопроцессор и сопутствующие ему команды я выложу тут.



20110925

Ещё немного чтива

Нашёл ещё один неплохой вводный курс по ассемблеру - [ссылка]. В нём используется flat assembler, он же fasm - один из синтаксисов этого языка. Надо сказать, что ассемблера существует достаточно дофига диалектов - есть fasm, masm, nasm, tasm, в общем - много вариантов. Между собой они различаются разными поддерживаемыми фичами и набором команд. Самый популярный - masm, или Macro Assembler производства Microsoft. Если будем писать что-то на ассемблере, то выберу я именно этот - под него пишется большинство статей и он обладает наиболее богатой документацией. :)

Не пугайтесь, что диалектов такая куча - мы не полезем в дебри, где они покажутся существенными, нам достаточно просто понимать код, который отладчик показывает, а это не так трудно.

20110924

Первая часть седьмого видеоурока, или знакомимся со структурами.

Итак!

Тянуть время дальше стало катастрофически лень, так что я быстренько сел и записал вводное видео. Простите, что так поздно, дела-дела. :)

В этом видео я постарался объяснить значение такой офигенно полезной штуки, как структура.
Это, если не обращаться к википедии и заумным книжкам, просто способ организовать какую-то информацию. Относительно игр нам надо просто понимать, что своя структура есть у каждого игрового объекта, для однотипных объектов она чаще всего одинаковая (структура "монстр" - у каждого монстра, "игрок" - у каждого игрока, "пуля" - у каждой пули и так далее), а при взломе помним самое главное - в памяти все значения конкретной структуры чаще всего хранятся рядышком, бывает что просто подряд. :D

Нам это может сильно помочь при поиске каких-то величин, которые на экране не отображаются и которые найти обычными способами довольно проблематично. Например, ломаем мы гоночки. В какой-то момент нам ВНЕЗАПНО очень захотелось найти массу нашей машины. Да-да, раз в игре есть хоть какая-то физика (а в современных играх для этого дела целые физические движки созданы) - то есть и масса и все основные законы. Все ведь помнят второй закон Ньютона из школьного курса физики? Если нет, то поясню: чем меньше будет масса нашей машины, тем быстрее она будет ускоряться. Так что на старте с машиной весом в 5 грамм мы всех уделаем. ^^

Проблема в том, что массу машины нигде на экране не написали (идиоты!), и вот тут-то мы и вспоминаем про то, что у каждой машины наверняка есть структура, а в этой структуре наверняка хранится и масса тоже. :)

Такие вот пироги. Смотрим, вникаем, запоминаем: [ссылка].


20110923

Следующие видеоуроки

Помните, что я указал в последнем видеоуроке? "Будем учиться быстро бегать и высоко прыгать". Это значит, что мы будем искать координаты игрока и работать с ними.

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

Частей планируется 2-3, первая - про необходимые понятия и теорию, вторая - про "быстро бегать", ну а третья, очевидно, - про "высоко прыгать". Как пройдём это всё и материал более-менее усвоится - покажу, как делается "Rapid fire hack" - это когда мы из какого-то медленно стреляющего оружия будем стрелять аки из шестиствольного пулемёта - в общем, быстро, очень быстро!

На этом основной курс "как научиться ломать игры" будет в общем-то окончен, так что дальше буду выкладывать какие-то конкретные фичи (как найти то или иное труднодоступное для обычного поиска значение, более простой метод поиска указателей и т.п.), может быть коснусь темы снятия игровых защит - да, бывает и так, в современных играх - почти повсеместно.

Параллельно приступим к написанию трейнеров. Эта тема довольно объёмная и абстрактная - зависит она в основном от умения программировать. Всё ещё думаю, как к ней грамотно подойти, но какой-никакой план уже есть. :)

20110921

Видеоуроки по С++

Делюсь очень хорошим курсом из 60 видеоуроков (с комментариями на английском языке) по С++. Достойная штука для тех, кто хочет начать изучать плюсы, рекомендую! (:

[ссылка]

20110916

Шестой видеоурок, так сказать! :D

А если серьёзно - просто видеопояснение к [предыдущей записи] о Code-Injection. Ломаем таймер матча в Mortal Combat 4, а ещё - узнаём две новых команды ассемблера (совсем простеньких):

inc \ dec [регистр] - англ. increment (увеличение) \ decrement (уменьшение) - увеличивает или уменьшает содержимое [регистра] на единичку. Пример:

mov edi, 5 //кладём в edi пятёрочку
dec edi      //делаем магию!!

В итоге в edi будет лежать четыре. :)


В следующих двух видеоуроках будем учиться высоко (очень высоко!) прыгать и не менее быстро бегать. Оставайтесь на линии, Ваш звонок очень важен для нас! :D

[ссылка на урок]


Code-Injection: Подробности

В [пятом уроке] (и в четвёртом тоже ^^) мы рассматривали такую технику, как Code-Injection, или, если буквально, "инъекция кода". Давайте остановимся на этой штуке ещё немного - больно уж часто она используется. Больше скажу - одна из самых распостранённых техник взлома. :)

Итак. Представим, что имеется у нас вот такой гипотетический код игры:

Адрес   |  Команда      |    Комментарий
---------------------------------------------------------------------------------
0000000: mov eax, 3     //помещаем в регистр eax число "3"
0000001: sub eax, 1      //вычитаем из еах единичку
0000002: cmp eax, 0    //сравниваем еах с нулём
0000003: je "exit"         //если еах = 0, то выходим из игры
0000004: add eax, 2    //иначе прибавляем к еах двойку
0000005:
0000006:
0000007:
0000008:
0000009:
---------------------------------------------------------------------------------

Скажем, нашли мы нужный адрес в Cheat Engine, включили отладчик дабы посмотреть - а с чего это у нас заканчиваются жизни (которые, как вы поняли, в еах находятся), отладчик нам выплёвывает адрес 0х00000001.

Если мы хотим, чтобы жизни просто не убавлялись, мы заменяем команду "sub eax, 1" nop'ами - командами, которые ничего не делают. Почему я написал во множественном числе? Всё просто - одна команда "nop" занимает один байт места, а вот "sub eax, 1" места занимает чуток побольше. Точные значения нас сейчас не волнуют (их можно посмотреть в отладчике), скажем, что это четыре байта. Поэтому вместо:

sub eax, 1

Мы должны будем написать четыре команды "nop", по одной на каждый байт:

nop
nop
nop
nop

Если не соблюдать это правило (количество байт кода всегда неизменно) - получите синий экран и придётся делать заново.

Идём дальше. В чём суть техники Code-Injection? Мы берём какую-то команду (в данном примере - ту, что вычитает у нас жизни) и заменяем её на команду jmp - прыжок или переход. Там выполняем какой-то код, затем возвращаемся обратно - в код игры. Смотрите:

Адрес   |  Команда      |    Комментарий
---------------------------------------------------------------------------------

0000000: mov eax, 3             //помещаем в регистр eax число "3"
0000001: jmp [0000006]      //переходим ("прыгаем") на адрес 0x0000006
0000002: cmp eax, 0            //сравниваем еах с нулём
0000003: je "exit"                 //если еах = 0, то выходим из игры
0000004: add eax, 2            //иначе прибавляем к еах двойку
0000005:
0000006: add eax, 10 //добавляем к еах десять
0000007: jmp [0000002] //прыгаем обратно - на адрес 0x0000002
0000008:
0000009:
---------------------------------------------------------------------------------
В результате этих действий мы заставили игру выполнить наш код (находящийся под адресам 0х0000006-0х0000007) а затем вернуться обратно и продолжить свой. Что нам это даёт? На самом деле - что угодно, всё зависит от фантазии и навыков программирования. Можно добавить жизней, можно патронов, можно всех врагов убить, можно любимой бабушке привет  передать - в общем, чего душа пожелает, а дальше игра послушно вернётся к своим делам. :)

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




20110915

Какой язык программирования выбрать?

Сижу вот, думаю, какой ЯП выбрать, записывая уроки по написанию трейнеров - маленьких таких программ, которые подключаются к процессу запущенной игры и изменяют её код и\или адреса, как мы это делали вручную в Cheat Engine. Выбор, в принципе, небольшой:

-Ассемблер. Самый низкоуровевый язык, на нём пишут все крутые чуваки из всяких там DEViATED, PizzaDOX и Razor1911. Для понимания с нуля - трудноват, кода будет довольно много, с другой стороны - мы же его используем при взломе (в отладчике), трейнеры будут очень маленького размера (максимум - 50-100 килобайт) и очень быстрые (но это не так критично).

-C\C++. Языки более высокого уровня - кода меньше, он во многом гораздо понятнее для неподготовленного человека, трейнеры будут уже чуть побольше, кода писать придётся меньше.

-Языки высокого уровня - C#\Basic\Java. Кода писать ещё меньше, но трейнеры будут уже довольно ощутимого размера (под пару-тройку мегабайт - запросто). Для понимания - ещё проще, чем предыдущие С и С++.

Я разместил опрос (слева от основных постов) - потыкайте кнопочки, а? И вам, и мне будет проще. Пару недель опрос повисит, а дальше буду на результаты смотреть.

Небольшой трюк при поиске адресов.

Бывает так, что нужный адрес ну вот никак не находится, хотя ищешь всё правильно. Что можно сделать в этом случае. Смотрим на картинку (кликаем, чтобы увеличить):

Видим несколько галочек, подчёркнутых красным. Поясню их значение:

Первые три ("Writable", "Executable" и "CopyOnWrite") влияют на диапазон адресов, в котором мы будем искать, каждая может находиться в трёх положениях (галочка поставлена, снята, "серая"). Нас интересует галочка "Writable" - то есть перезаписываемая память. Если галочка стоит, то в диапазон поиска попадут адреса, в значения которых можно изменить. Если нет - то те, что доступны только для чтения. Если же галочка "серая" - то без разницы, сканировать будем и то и другое. Это может помочь при поиске указателей (они чаще всего только для чтения).

Галочка пониже - "Fast scan" - "Быстрый поиск". С одной стороны, звучит круто - мол, искать программа будет быстрее. Но есть небольшое "но" - искать программа будет те адреса, что кратны циферке 32. Как, зачем и почему - нас не интересует, просто если галочку снять - поиск будет идти чуть медленнее (на современных компьютерах разница будет мизерная), но адресов сканироваться при этом будет больше.

Последняя, нижняя - "Pause the game while scanning" - как вы уже догадались, решает, останавливать ли процесс игры на время сканирования или нет. Полезно при отсутствии в игре "Паузы" - если ищем какую-нибудь полоску здоровья и хотим гарантированно приостановить игровой процесс, дабы никто в игре не помешал.