68 10270000 // push 2710 // Передаём параметр метода: 10000 мсек
ff15 bcd04500 // call dword ptr ds:[<&kernel32.Sleep>] // вызов метода
c3 // retn // возврат
Как подключить отладчик к запускаемому вручную процессу и не проворонить простыню кода?
Есть процесс (игра), которую нужно поковырять отладчиком.
Есть отладчики - OlyDbg 2 и IDA (с удовольствием освою более удобные альтернативы, если таковые будут предложены).
Идеальный вариант: Запускается отладчик, указывается путь к exe-файлу, отладчик перехватывает обращение к файлу и аттачится к процессу.
Для OlyDBG 1.xx нашёл плагин Catcha! - с 2.х не работает. Для IDA ничего не нашёл.
Появилась идея: написать программку, которая будет ждать появление процесса, после чего фризить его. Дальше вручную я подключусь отладчиком, и отпущу фриз.
Вопросы:
1) Нагуглил методы SuspendThread и ResumThread - копаю в верную сторону?
2) Все работы с чужими данными требуеют некие "права доступа", н.п. THREAD_SUSPEND_RESUME для вызова этих методов. Как их получить, как оповестить систему о том, что они у меня есть, и нужно ли это вообще делать при запуске от имени администратора?
Для чего нужно аттачиться к процессу и почему нельзя запустить его из дебагера:
Потому что приложение (игра) запускается в полноэкранном режиме и не имеет ключей командной строки или настроек, позволяющих запустить её в оконном режиме. Запускается через DirectX Windower (или аналог). Если можно запустить из-под отладчика его и автоматически перебросить отладку на запускаемые им процессы - будет здорово, расскажите как. Пока же придумываю различные способы извращения.
Надеюсь на вашу помощь. Заранее спасибо!
Нагуглил - как это делается в винде. Оказалось, что дергается метод Sleep из Kernell.dll.
Открыл exe'шник в отладчике IDA. Перешёл к таблице импортов. К великому счастью обнаружил там Sleep. Щёлкнул два раза по нему, чтобы перейти к объявлению. Перешёл к списку вызовов ('X'). Из доброй сотни выбрал первый попавшийся. Скопировал, как вызывается (ассёмблера я не знаю). Затем перебрался в OlyDbg. Нашёл (визуально) свободное место (простыню забитую 00), написал там код метода:
Код:
Код:
58 // pop eax // сохранил адрес возврата - дальше юзается стек
>>>Сюда добил эти 5 байт<<<
50 // push eax // закинул адрес обратно
>>>Сюда добил эти 5 байт<<<
50 // push eax // закинул адрес обратно
Собственно усё. Процесс запускается, тут же засыпает на 10 секунд. Я за это время успеваю к нему приаттачиться и с комфортом дебажу. Вот такие пироги. ^-^
P.S. Ах да, потом я это всё очень не интеллектуально переносил ручками в WinHEX и правил по байтикам (ну, ладно - копипастил). Вроде бы, ни IDA, ни OlyDBG не позволяют править на лету код и тут же его сохранять в EXE (если ошибаюсь - поправьте, а то надоело возиться, ещё и переводя виртуальные адреса в физические (благо всё в пределах одной страницы, а индексация простая - индекс страницы, смещение внутри).
Потому что приложение (игра) запускается в полноэкранном режиме и не имеет ключей командной строки или настроек, позволяющих запустить её в оконном режиме
Неправда. Что за игра(версия, локализация)?
Родное разрешение - 640х480. Родная цветовая палитра - 256 цветов.
Если вручную вбить флаги при формировании окна, получим чёрное окно. Если перевести экран в 256 цветов, также получим чёрное окно.
Всё, понял, в чём трабл.
Я не знаю, во всех ли это случаях работает, но некоторые программы (именно игры) можно запустить в окошке, вместо полного экрана, задав в ярлыке ключ -window и размер желаемого окна. Пример:
Код:
"D:\games\foo.exe" -800x600 -window
Код:
CPU Disasm
Address Hex dump Command Comments
0042A4CB |> \55 PUSH EBP ; /lParam => NULL
0042A4CC |. 56 PUSH ESI ; |hInst
0042A4CD |. 55 PUSH EBP ; |hMenu => NULL
0042A4CE |. 55 PUSH EBP ; |hParent => NULL
0042A4CF |. 68 E0010000 PUSH 1E0 ; |Height = 480.
0042A4D4 |. 68 80020000 PUSH 280 ; |Width = 640.
0042A4D9 |. 55 PUSH EBP ; |Y => 0
0042A4DA |. 55 PUSH EBP ; |X => 0
0042A4DB |. 68 00000890 PUSH 90080000 ; |Style = WS_POPUP|WS_SYSMENU|WS_VISIBLE
0042A4E0 |. 68 60F04500 PUSH 0045F060 ; |WindowName = "Battle of the Youstrass"
0042A4E5 |. 68 48F04500 PUSH 0045F048 ; |ClassName = "Battle of the Youstrass"
0042A4EA |. 6A 00 PUSH 0 ; |ExtStyle = 0
0042A4EC |. 8935 8CA84700 MOV DWORD PTR DS:[47A88C],ESI ; |
0042A4F2 |. FF15 2CD24500 CALL DWORD PTR DS:[<&USER32.CreateWindow ; \USER32.CreateWindowExA
Address Hex dump Command Comments
0042A4CB |> \55 PUSH EBP ; /lParam => NULL
0042A4CC |. 56 PUSH ESI ; |hInst
0042A4CD |. 55 PUSH EBP ; |hMenu => NULL
0042A4CE |. 55 PUSH EBP ; |hParent => NULL
0042A4CF |. 68 E0010000 PUSH 1E0 ; |Height = 480.
0042A4D4 |. 68 80020000 PUSH 280 ; |Width = 640.
0042A4D9 |. 55 PUSH EBP ; |Y => 0
0042A4DA |. 55 PUSH EBP ; |X => 0
0042A4DB |. 68 00000890 PUSH 90080000 ; |Style = WS_POPUP|WS_SYSMENU|WS_VISIBLE
0042A4E0 |. 68 60F04500 PUSH 0045F060 ; |WindowName = "Battle of the Youstrass"
0042A4E5 |. 68 48F04500 PUSH 0045F048 ; |ClassName = "Battle of the Youstrass"
0042A4EA |. 6A 00 PUSH 0 ; |ExtStyle = 0
0042A4EC |. 8935 8CA84700 MOV DWORD PTR DS:[47A88C],ESI ; |
0042A4F2 |. FF15 2CD24500 CALL DWORD PTR DS:[<&USER32.CreateWindow ; \USER32.CreateWindowExA