Гость bronis Опубликовано 2 июля, 2011 Поделиться Опубликовано 2 июля, 2011 (изменено) local DLL = getAddress("USER32.DLL") -- Адрес DLL local Function = DLL+0x17809 -- USER32.TranslateMessage local Condition = 0x202 -- MSG==202 //WM_LBUTTONUP function debugger_onBreakpoint() -- выполнить если сработал бряк local pMSG = readInteger(ESP+0x4) -- поинтер на параметры функции local MSG = readInteger(pMSG+0x4) -- параметр функции - MSG s = string.format(">> 0x%08X: MSG = 0x%08X", EIP, MSG) -- форма записи в лог MSG if (EIP == Function) then -- проверяем если бряк сработал на нужной нам функции то if (MSG == Condition) then -- проверяем нужные нам параметры print(s) -- записываем в лог LuaEngine значение параметра MSG return 0 -- ставим бряк else -- в случае если условие не выполнено -- print(s) -- записываем в лог LuaEngine значение параметра MSG не прошедших условие return 1 -- продолжаем без бряка end end end debug_removeBreakpoint(Function) -- убераем старый бряк debug_setBreakpoint(Function, 4,bptExecute) -- ставим новый бряк Ищем интересующую нас функцию: - жмем Ctrl+Alt+S или заходим в View -> Enumerate DLL's and Symbols находясь при этом в коде программы чьи DLL нам нужны - ищем в списке нужную нам DLL(USER32), кликнув по треугольничку с лева разворачиваем список функций найденой нами DLL-ки - ищем в этом списке интересующую нас функцию(TranslateMessage) и жмем на нее двойным щелчком левой кнопкой мышки - жмем Ctrl+M или View -> Show module adresses ставим галочку для того чтобы адрес отображался в виде Модуль+Смещение ПС: Если адрес отображается не верно то поставьте галочку View -> Kernelmode symbols Кому лень искать то ее адрес USER32.DLL+17809, в Lua код записывать смещение надо в виде +0x17809. Заполняем данными Lua код: - Найденое смещение функции TranslateMessage вписываем в строку local DLL = getAddress("USER32.DLL") -- DLL содержащий нашу функцию local Function = DLL+0x17809 -- смещение функции относительно DLL - Вводим условие, например: local Condition = 0x202 // где 202 - код WM_LBUTTONUP Делаем условный бряк: - жмем Ctrl+L или Tools -> Lua Engine - вставляем Lua код в нижнее поле окна, и жмем кнопку Execute Читаем логи: - жмем Ctrl+L и в верхнем поле окна будет вестить лог в формате - >> 0x"Адрес": MSG = "Параметр" ПС: Прежде чем включить лог MSG непрошедших условие - советую убрать галочку с параметра в LuaEngine View -> Show on "print" Выключаем условный бряк: - Для того что бы выключить условие, снова открываем Lua Engine и прописываем туда function debugger_onBreakpoint() end Изменено 9 июля, 2020 пользователем imaginary Указано форматирование кода Lua Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 2 июля, 2011 Поделиться Опубликовано 2 июля, 2011 Актуально:local Function = getAddress("TranslateMessage")Для лучшей производительности лучше:1) cтроку:local Condition = 0x202 -- MSG==202 //WM_LBUTTONUPвынести из function debugger_onBreakpoint().2) строку :if (EIP == Function) thenзаменить на: if (EIP ~= Function) then return 1end3) Возможно лучше использовать объект от Stringlist вместо множественного построчного print(). Метод "strings_getText( твой Stringlist )" может сразу возвратить большую строку лога, которую уже можно обработать через printТакже помимо кодов сообщений можно логировать и адрес возврата по [esp+0]. А также другую информацию:BOOL TranslateMessage( const MSG* lpMsg // Указатель на структуру MSG, которая содержит информацию о сообщении извлеченную из очереди сообщений вызывающего потока при помощи использования функции GetMessage или PeekMessage.);typedef struct { HWND hwnd; // Дескриптор окна, оконная процедура которого принимает сообщение. UINT message; // Определяет код сообщения. Приложения могут использовать только младшее слово; старшее слово зарезервировано системой. WPARAM wParam; // Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message. LPARAM lParam; // Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message. DWORD time; // Определяет время, в которое сообщение было помещено в очередь. POINT pt; // Устанавливает позицию курсора, в экранных координатах, в момент, когда сообщение было помещено в очередь.} MSG, *PMSG; Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость bronis Опубликовано 2 июля, 2011 Поделиться Опубликовано 2 июля, 2011 MasterGH: Спасибо за замечания, исправил.local DLL = getAddress("USER32.DLL") -- local Function = getAddress("TranslateMessage")local Function = DLL+0x17809 -- USER32.TranslateMessagelocal Condition = 0x202 -- MSG==202 //WM_LBUTTONUPfunction debugger_onBreakpoint() -- выполнить если сработал бряк local pMSG = readInteger(ESP+0x4) -- поинтер на параметры функции local MSG = readInteger(pMSG+0x4) -- параметр функции - MSG loglist = createStringlist() -- создаем loglist strings_add(loglist,string.format(' • Call to %s from "%s" • ', getNameFromAddress(EIP), getNameFromAddress(readInteger(ESP)))) -- добавляем в loglist первую строку strings_add(loglist,string.format('>> hWnd = %X', readInteger(pMSG))) -- Дескриптор окна, оконная процедура которого принимает сообщение. strings_add(loglist,string.format('>> MSG = %X', MSG)) -- Определяет код сообщения. Приложения могут использовать только младшее слово; старшее слово зарезервировано системой. strings_add(loglist,string.format('>> wParam = %X', readInteger(pMSG+0x8))) -- Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message. strings_add(loglist,string.format('>> lParam = %08X', readInteger(pMSG+0xC))) -- Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message. strings_add(loglist,string.format('>> Time = %X', readInteger(pMSG+0x10))) -- Определяет время, в которое сообщение было помещено в очередь. strings_add(loglist,string.format('>> Point = %i x %i', readInteger(pMSG+0x14), readInteger(pMSG+0x18))) -- Устанавливает позицию курсора, в экранных координатах, в момент, когда сообщение было помещено в очередь. s = strings_getText(loglist) -- читаем loglist if (EIP ~= Function) then -- если бряк сработал не на нашей функции то return 1 -- продолжаем без бряка end if (MSG == Condition) then -- проверяем нужные нам параметры print(s) -- записываем в лог LuaEngine текст из loglist return 0 -- ставим бряк else -- в случае если условие не выполнено print(s) -- записываем в лог LuaEngine текст из loglist при не выполненом условии return 1 -- продолжаем без бряка endenddebug_removeBreakpoint(Function) -- убераем старый брякdebug_setBreakpoint(Function, 4,bptExecute) -- ставим новый брякПример логов: • Call to TranslateMessage from "notepad++.exe+9D41E" • >> hWnd = 3E068C>> MSG = 113>> wParam = 1>> lParam = 00000000>> Time = 66D51B9>> Point = 1216 x 889 • Call to TranslateMessage from "notepad++.exe+9D41E" • >> hWnd = 3E068C>> MSG = 202>> wParam = 0>> lParam = 00180060>> Time = 66D51B9>> Point = 1216 x 889Для отображения адресов в виде Функция+Смещение/Модуль+Смещение необходимо включить опцию в окне отладчика Ctrl+M или View -> Show module adresses.Для отображения только в виде Модуль+Смещение надо дополнительно включить View -> Kernelmode symbolsХотелось бы как нибудь конвертировать время >> Time = 66D51B9 в ЧЧ:ММ:СС:МС есть идеи?Еще не понятен 1 момент, пытался разделить lParam по 4 байта чтоб выглядело так >> lParam = 0018 0060Пытался это представить в таком виде strings_add(loglist,string.format('>> lParam = %04X %04X', readInteger(pMSG+0xC)), readInteger(pMSG+0xE))) но вместо этого он выдает больше 4 байт.Было бы не плохо добавить еще комент к дескриптору как в олли, в виде названия окнаК сожалению за не имением необходимых знаний и неудаче в поисках полной документации комант Lua для CE - я не могу реализовать данные идеи =( 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 3 июля, 2011 Поделиться Опубликовано 3 июля, 2011 Кое-что не совсем правильно. И немного не удобно в том, что нет выбора между остановкой просто на функции и остановкой по равенству кода сообщения... я потом поправлю, сейчас нет времени. И на будущее createStringlist() в твоём случае постоянно создаёт новый и новый список. Старый при этом не разрушается и происходит "утечка памяти". Достаточно создать список только один раз. Также лучше пользоваться просто print() я что-то "перенасоветовал". Когда я советовал я забыл, что ты ведёшь логи с остановками в Отладчике для пользователя. В этом случае проще использовать print() c длинной строкой (через string.fortmat)... Ладно, как уже писал, позже поправлю. Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость bronis Опубликовано 3 июля, 2011 Поделиться Опубликовано 3 июля, 2011 local DLL = getAddress("USER32.DLL") -- local Function = getAddress("TranslateMessage")local Function = DLL+0x17809 -- USER32.TranslateMessagelocal Condition = 0x202 -- MSG==202 //WM_LBUTTONUPlocal loglist = createStringlist() -- создаем loglistfunction debugger_onBreakpoint() -- выполнить если сработал бряк local pMSG = readInteger(ESP+0x4) -- поинтер на параметры функции local MSG = readInteger(pMSG+0x4) -- параметр функции - MSG strings_clear(loglist) -- чистим старые логи loglist strings_add(loglist,string.format(' • Call to %s from "%s" • ', getNameFromAddress(EIP), getNameFromAddress(readInteger(ESP)))) -- добавляем в loglist первую строку strings_add(loglist,string.format('>> hWnd = %X', readInteger(pMSG))) -- Дескриптор окна, оконная процедура которого принимает сообщение. strings_add(loglist,string.format('>> MSG = %X', MSG)) -- Определяет код сообщения. Приложения могут использовать только младшее слово; старшее слово зарезервировано системой. strings_add(loglist,string.format('>> wParam = %X', readInteger(pMSG+0x8))) -- Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message. strings_add(loglist,string.format('>> lParam = %08X', readInteger(pMSG+0xC))) -- Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message. strings_add(loglist,string.format('>> Time = %X', readInteger(pMSG+0x10))) -- Определяет время, в которое сообщение было помещено в очередь. strings_add(loglist,string.format('>> Point = %i x %i', readInteger(pMSG+0x14), readInteger(pMSG+0x18))) -- Устанавливает позицию курсора, в экранных координатах, в момент, когда сообщение было помещено в очередь. s = strings_getText(loglist) -- читаем loglist if (EIP ~= Function) then -- если бряк сработал не на нашей функции то return 1 -- продолжаем без бряка end if (MSG == Condition) then -- проверяем нужные нам параметры print(s) -- записываем в лог LuaEngine текст из loglist return 0 -- ставим бряк else -- в случае если условие не выполнено-- print(s) -- записываем в лог LuaEngine текст из loglist при не выполненом условии return 1 -- продолжаем без бряка endenddebug_removeBreakpoint(Function) -- убераем старый брякdebug_setBreakpoint(Function, 4,bptExecute) -- ставим новый брякВсе, теперь он будет использовать 1 лист на 1 екзекут кода в луа, а то переделывать обратно - получится столько принтов и стрингов что будет не красиво. Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 3 июля, 2011 Поделиться Опубликовано 3 июля, 2011 Вот изменённый вариант: Скрипт установки условного брейкпоинта на функции TranslateMessage. В параметрах сравнения участвует код сообщения "UINT message" Если сообщение равно сравниваемому, то отладчик прервётся и в поле лога выведет параметры структуры MSG BOOL TranslateMessage( const MSG* lpMsg // Указатель на структуру MSG, которая содержит информацию о сообщении извлеченную из очереди сообщений вызывающего потока при помощи использования функции GetMessage или PeekMessage. ); typedef struct { HWND hwnd; // Дескриптор окна, оконная процедура которого принимает сообщение. UINT message; // Определяет код сообщения. Приложения могут использовать только младшее слово; старшее слово зарезервировано системой. WPARAM wParam; // Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message. LPARAM lParam; // Определяет дополнительную информацию о сообщении. Точное значение зависит от значения члена структуры message. DWORD time; // Определяет время, в которое сообщение было помещено в очередь. POINT pt; // Устанавливает позицию курсора, в экранных координатах, в момент, когда сообщение было помещено в очередь. } MSG, *PMSG; Пример использования. Пример1. Установка условного брейкпоинта функции TranslateMessage в сравнении с параметром MSG: -- Сработает когда пользователь отпустит левую кнопку мышки WM_LBUTTONUP = 0x202 (другие коды сообщени ищите в Интернете) StartDebug_TranslateMessageCondition_onMSG(WM_LBUTTONUP) Пример2. Установика безусловного брейкпоинта с логировнием всех сообщений: StartDebug_TranslateMessage() Пример3. Если необходимо только прерваться на некоторой функции без сбора параметров: StartDebugSomeFunction(functionName) Пример4. Если необоходимо остановить отладку, то вызывать: StopDebug()]]--local mode = 0local addressesBreakPoint = {}local countAddressesBreakPoint = 0function AddBreakPointExecut(addressFunction) countAddressesBreakPoint = table.getn(addressesBreakPoint) countAddressesBreakPoint = countAddressesBreakPoint + 1 addressesBreakPoint[countAddressesBreakPoint] = addressFunction debug_setBreakpoint(addressFunction, 1, bptExecute)endfunction DeleteAllBreakPoint() for i=1, countAddressesBreakPoint do debug_removeBreakpoint(addressesBreakPoint[i]) end countAddressesBreakPoint = 0end-- Единая функция обработки сообщений о прерыванииfunction debugger_onBreakpoint() local withIn = false for i=1, countAddressesBreakPoint do if (EIP == addressesBreakPoint[i]) then withIn = true break end end if (not withIn) then return 1 end if ( (mode == 1) or (mode == 2) ) then local pMSG = readInteger(ESP+0x4) local MSG = readInteger(pMSG+0x4) if ((mode == 1) and (MSG ~= _iMSGBreak)) then return 1 end local s = string.format(" • Call to %s from \"%s\" •\n\r\n>> hWnd = %X\n\r\n>> MSG = %X\n\r\n>> wParam = %X\n\r\n>> lParam = %08X\n\r\n>> Time = %X\n\r\n>> Point = %i x %i\n\r\n", getNameFromAddress(EIP), getNameFromAddress(readInteger(ESP)), readInteger(pMSG), MSG, readInteger(pMSG+0x8), readInteger(pMSG+0xC), readInteger(pMSG+0x10), readInteger(pMSG+0x14), readInteger(pMSG+0x18)) if (mode == 1) then -- WM_LBUTTONUP print(s) -- записываем в лог LuaEngine текст из loglist return 0 -- ставим бряк else -- в случае если условие не выполнено print(s) -- записываем в лог LuaEngine текст из loglist при не выполненом условии return 1 -- продолжаем без бряка end end return 0endfunction StartDebug_TranslateMessageCondition_onMSG(iMSGBreak) DeleteAllBreakPoint() mode = 1 _iMSGBreak = iMSGBreak local addressFunction = getAddress("TranslateMessage") AddBreakPointExecut(addressFunction) print(string.format("Включен режим остановки на фунции TranslateMessage с условием: MSGBreak == %X",iMSGBreak))endfunction StartDebug_TranslateMessage() DeleteAllBreakPoint() mode = 2 local addressFunction = getAddress("TranslateMessage") AddBreakPointExecut(addressFunction) print("Включен режим остановки на фунции TranslateMessage без условий")endfunction StartDebugSomeFunction(functionName) mode = 0 local addressFunction = getAddress(functionName) AddBreakPointExecut(addressFunction)endfunction StopDebug() DeleteAllBreakPoint() _iMSGBreak = 0end--[[Я запустил функцию StartDebug_TranslateMessage() и StopDebug(), а остальные не запускал и поэтому могут быть ошибки, которых я не заметил.Если будет время сделаю форму с кнопками, полями ввода и т.п., а то через консоль неудобно. Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость bronis Опубликовано 3 июля, 2011 Поделиться Опубликовано 3 июля, 2011 Сложновато для переваривания, но удобно в применении ^_^/ Спасибо. Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 4 июля, 2011 Поделиться Опубликовано 4 июля, 2011 Хм, интересно. С помощью этого же приема можно принудительно отправить игру в оконный режим, путем перехвата функции DirectX - CreateDevice. Надо будет вечерком попробовать. Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterGH Опубликовано 4 июля, 2011 Поделиться Опубликовано 4 июля, 2011 Можно этим способом, а можно используя:generateAPIHookScript(address, addresstojumpto, addresstogetnewcalladdress OPT) Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения