Пропатчить отладчик для МК КР1878ВЕ1

Использование и разработка софта (преимущественно на ПЦ)

Moderator: Shaos

User avatar
Lavr
Supreme God
Posts: 16676
Joined: 21 Oct 2009 08:08
Location: Россия

Пропатчить отладчик для МК КР1878ВЕ1

Post by Lavr »

Тут у меня проблема возникла, и помню по старым номерам журнала "Хакер",
что решение у неё есть, но вот как это делается - не помню... :(

Ситуация вот какая: предположим, что есть программа вот такого типа:

Image

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

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



PS. В журналах "Хакер" это, как я помню, решали для окон типа "Пароль", но мне
не это нужно, хотя принцип, как мне кажется, должен быть такой же...
iLavr
awaken
Novelist
Posts: 44
Joined: 24 Jan 2015 13:56
Location: 178.172.216.50

Post by awaken »

OllyDbg
но смотрите чтоб переписать не легче было)
User avatar
Lavr
Supreme God
Posts: 16676
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

awaken wrote:но смотрите чтоб переписать не легче было)
Да переписать не легче - это я упрощенный пример нашел.

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


PS. Посмотрел я, ехе-шник у меня типа PE, и как внедряются в такой файл примерно объясняется вот здесь:
http://2x2is11.blogspot.ru/2010/09/blog-post_13.html
http://www.ht-group.net/23/
iLavr
User avatar
Lavr
Supreme God
Posts: 16676
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Может быть, я выше неудачный абстрактный пример выбрал, но конкретно суть следующая...

Есть вот такой Виндавозный отладчик для микроконтроллера КР1878ВЕ1, работает он довольно-таки
неплохо, все примеры для микроконтроллера я проверяю на нём.

Image

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

Image

Если исправлять содержимое полей портов в этих окнах, то отладчик это воспринимает, как ввод с ВУ.
Можно было бы эмуляцию кнопок прицепить... а то отлаживать, видя лишь циферки, - кисло немного... :-?
iLavr
aav8
Maniac
Posts: 287
Joined: 05 Nov 2008 19:47
Location: 81.28.208.238

Post by aav8 »

Есть некоторое подозрение, что эти окошки не стандартные для Win,
т.е. информация в них отрисовывается самой программй.
Стандартные окна получают информацию из сообщений, которые можно перехватить.
Вполне возможно при вводе данных в эти окошки, они принимают
стандартные сообщения (нажатие/отжатие кнопок) - туда скорее
всего возможно что-то пихать свое.
... примерно так
User avatar
Lavr
Supreme God
Posts: 16676
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

aav8 wrote:Есть некоторое подозрение, что эти окошки не стандартные для Win,
т.е. информация в них отрисовывается самой программй.
Они стандартные - я этот момент проверил, иначе и не пытался бы пробовать эту задачу решить...
aav8 wrote:Стандартные окна получают информацию из сообщений, которые можно перехватить.
Я неплохо эту процедуру представляю, и даже писал похожие программы сам.
Но у меня какой был принцип: при старте моя собственная программа вызывает на загрузку
нужную программу и сама садится в трее.
После того, как нужная программа запущена, находится ID (ну или "хэндлер") родительского окна, ищутся
все дочерние окна и среди них находится нужное мне.
После этого моя программа по таймеру опрашивает нужное окно, может считать из него и записать в него.

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

Поэтому вот этот трюк, как раз - то, что мне надо:"получить информацию из сообщения, в это окно".
Он как раз мне и нужен - в тот момент, когда пришло сообщение, его бы и обработать, а не "слушать" окно по таймеру.
Но вот в этом моменте, я как раз и затрудняюсь... Не знаю, как это сделать... о чём здесь и вопрошаю...
iLavr
aav8
Maniac
Posts: 287
Joined: 05 Nov 2008 19:47
Location: 81.28.208.238

Post by aav8 »

надо прицепиться к обработчику сообщений окна (но это возможно только из dll).
User avatar
Lavr
Supreme God
Posts: 16676
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

aav8 wrote:надо прицепиться к обработчику сообщений окна (но это возможно только из dll).
Ну естественно, это *.dll, и программа, вызываюшая эту *.dll
...при старте моя собственная программа вызывает на загрузку
нужную программу и сама садится в трее.
Хотелось бы какой-то понятный пример. А *.dll такого типа я писАть умею...

Вот типичный пример: моя программа EWB32.exe активизирует сам WEWB32.EXE и запускает EWBHook.dll.
В меню EWB добавляется дополнительное меню Resulsts Analysis, при клике на котором, управление передается
моей программе, вычисляющей спектр Фурье.

Image
iLavr
User avatar
Lavr
Supreme God
Posts: 16676
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Я, честно говоря, писал все эти трюки более 5 лет назад и немножко подзабыл всё...

Но вот это - код EWBHook.dll :

Code: Select all

/******************************************************************************/
/*           Ловушка WH_GETMESSAGE на сообщение нашего пункта меню            */
/******************************************************************************/
#include <windows.h>
#include <string.h> // strcat & etc. - символьные функции ---
#include "EWBHook.h"
#pragma argsused
//------------------------------------------------------------------------------
//       Отслеживаем нажатие правой кнопки мыши в трее на нашем значке      ----
//                     и сообщение нашего пункта меню                       ----
//------------------------------------------------------------------------------
#define UP 1
#define DOWN 2

int result;
int iMouseDoun;               //--- Здесь хранится состояние правой кнопки -
int iMouseUp;

HWND hMyWin;
HWND hEWBWin;
MSG* psMessageHook;           //--- Для анализа сообшений от окна ---
MOUSEHOOKSTRUCT* psMouseHook; //--- Для анализа сообшений от мыши ---

//---------------------------------------------------------------------------
//---  соглашение __stdcall означает, что вызываемая функция сама удалит из стека свои аргументы
//---  Ключевое слово __declspec с атрибутом dllexport помечает функцию как экспортируемую,
//---  имя функции добавляется в таблицу экспорта dll.

//---------------------------------------------------------------------------
//------------- Ловушка сообщения - ловим здесь ID нашего menu --------------
LRESULT CALLBACK MessageHook(int nCode,WPARAM wParam,LPARAM lParam)
{
    //
    // Note that CallNextHookEx ignores the first parameter (hhook) so
    // it is acceptable (barely) to pass in a NULL instead (hhook)hgHook.
    //
  if(nCode<0) return CallNextHookEx(NULL,nCode,wParam,lParam);

      psMessageHook=(MSG*)(lParam);
  if((psMessageHook->hwnd)==hEWBWin) //--- если сообщение WEWB32 окна ---
    {
//  PostMessage(hMyWin,WM_USER+2001, -1, (long)psMessageHook->message); //---  test  ---
      if((psMessageHook->message)==WM_COMMAND) //--- если сообщение menu ---
        {
         if((psMessageHook->wParam)==0x00000500) //---  0x00000500 ? ---
           {
           PostMessage(hMyWin,WM_USER+2001, -1,(long)psMessageHook->wParam);
           return CallNextHookEx(NULL,nCode,wParam,lParam);
           }
        }
    }
 return CallNextHookEx(NULL,nCode,wParam,lParam);
}
//---------------------------------------------------------------------------
//----------- Ловушка мыши  -------------------------------------------------
LRESULT CALLBACK MouseHook(int nCode,WPARAM wParam,LPARAM lParam)
{//--- подпрограмма анализа:   message identifier, mouse coordinates;
 if(wParam==WM_RBUTTONDOWN)
   {
   if(!(iMouseDoun==DOWN))
        iMouseDoun=DOWN;
   }
 if(wParam==WM_RBUTTONUP)
   {
   if(iMouseDoun==DOWN)
      iMouseDoun=UP;
      psMouseHook=(MOUSEHOOKSTRUCT*)(lParam);
      //--- отсигналим нашему окну сообщением WM_USER+2000 - что пора!!! ---
      PostMessage(hMyWin,WM_USER+2000, -1,(long)psMouseHook->hwnd);
   }
 return 0;
}

//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
   if(reason==DLL_PROCESS_ATTACH) //---- Проецируем .dll на адр. простр-во ----
   {
     //--- узнаем хэндлер своего стартового окна ---
       hMyWin=FindWindow("HookWndClass","EWBHook");
      hEWBWin=FindWindow("ewb5","Electronics Workbench Professional Edition");
   if(hEWBWin==0) //--- узнаем хэндлер окна WEWB32, если оно есть...
      PostMessage(hMyWin, WM_DESTROY, NULL, NULL); //--- иначе выходим...----
   }
   return 1;
}
Как мне здесь прицепиться к обработчику сообщений окна или перехватить его?


PS. Посмотрел я, класс этого окна - типа RICHEDIT, функция GetWindowText из него содержимое
спокойно берет - значит окно стандартное, и вывод внего, скорее всего через функцию SetWindowText ,
которую и надо перехватить, видимо, при обращении с хэндлером искомого окна?
iLavr
aav8
Maniac
Posts: 287
Joined: 05 Nov 2008 19:47
Location: 81.28.208.238

Post by aav8 »

Как мне здесь прицепиться к обработчику сообщений окна или перехватить его?
SetWindowLong(GWL_WNDPROC,....)
Вроде примерно так вставляется обработчик сообщений окна
User avatar
Lavr
Supreme God
Posts: 16676
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

aav8 wrote:
Как мне здесь прицепиться к обработчику сообщений окна или перехватить его?
SetWindowLong(GWL_WNDPROC,....)
Вроде примерно так вставляется обработчик сообщений окна
Знаю эту функцию:
Функция SetWindowLong
Описание:
function SetWindowLong(Wnd: HWnd; Index: Integer; NewLong: Longint): Longint;

Заменяет для окна атpибут стpуктуpы класса окна новым значением.
Параметры:

Wnd: Идентификатоp окна.
Index: Одна из следующих констант: gwl_ExStyle, gwl_Style, gwl_WndProc или
положительное смещение в байтах для доступа к дополнительным четыpехбайтным
значениям. См. "Смещения поля окна, gwl_" .
NewLong: Значение замены.

Возвpащаемое значение: Пpедыдущее значение.
Но в данном случае что-то я затрудняюсь в её применении, да и в целесообразности.

Раз уж есть *.dll, которая Hook-нула сообщения, видимо, в ней надо отслеживать функцию
SetWindowText с хэндлером искомого окна класса RICHEDIT - я так понимаю... но, возможно,
могу и ошибаться...
iLavr
User avatar
Lavr
Supreme God
Posts: 16676
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Я, конечно, не великий писатель на VC, но эта программа и меня чутка удивила... :o

Впервые встречаю, что у основного окна программы в зависимости от запуска меняется класс...

Code: Select all

Afx:400000:b:1466:6:3cf7 
Afx:400000:b:1466:6:3587 
Четыре последние цифры при каждом запуске разные... :(
Так что ID окна пришлось искать перебором, сравнивая текст загоровка с текстом "DebugMCT".

Дальше было веселее, не знаю уж как они запускали свои Child windows, но функция GetWindow
с параметром GW_CHILD не находит ни одного CHILD... :lol:

Пришлось искать их через EnumChildWindows...

Ну и теперь - последнее, самое интересное...

Нашел я ID текстового окна класса RICHEDIT, куда выводится содержимое RAM:

Image

А функция GetWindowTextA его текст и не ухватывает! :o

Я аж удивился... проверял же! :o Запускаю обе свои утилиты для таких целей (см.рисунок)
Так одна из них текст окна - выхватывает, а вторая - и нет! :roll:

Видимо вторая тоже юзает GetWindowTextA, как я думал... а вот первая, похоже действует иначе... 8)

Ну и самое что неприятное, это окно класса RICHEDIT вроде поддерживает редакцию
содержимого, но само же отредактировнное и отменяет... :(
iLavr
User avatar
Lavr
Supreme God
Posts: 16676
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Lavr wrote:Нашел я ID текстового окна класса RICHEDIT, куда выводится содержимое RAM:
http://www.nedopc.org/nedopc/upload/debugMCTPIC.gif
А функция GetWindowTextA его текст и не ухватывает! :o
Shaos, когда ты нам приводишь статистику языков, глядя на нее никогда не поверишь,
что больше всего все программируют на Delphi... :lol:
А вот когда что-то ищешь в Интернете, везде сплошное Delphi... Delphi...
А у них всё в обёртках... :(

Но вспомнил я, как ухватывают текст из RICHEDIT:
Только одну константу я до этого не знал:
To get the selected text in a rich edit control, use the EM_GETSELTEXT message. The text is copied
to the specified character array. You must ensure that the array is large enough to hold the selected
text plus a terminating null character.
А так с RICHEDIT общаются через SendMessage(...), используя EM_SETSEL, EM_GETSEL и EM_REPLACESEL.
И я ими вполне успешно пользовался в 2-х проектах, выложенных на форуме, для добавления текста
в конец RICHEDIT.

Но Delphiйцы меня рассмешили:"из RICHEDIT можно скопировать текст лишь через
буфер обмена!
" :o
iLavr
User avatar
Lavr
Supreme God
Posts: 16676
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Первая неприятность... :(
GetWindowTextLength не может получить длину текста
поля редактирования текста в другом приложении.
А GetWindowTextLength - это по сути SendMessage(...) с параметром WM_GETTEXTLENGTH...

Остальные SendMessage(...) пока тоже не срабатывают... :(
Похоже, другое приложение им тоже не нравится...

Попробую поиграть с установкой фокуса в интересующее меня окно RAM.



PS. Но внутри DebugMCT они работают с окном RichEdit именно этими командами,
подсмотрел через Microsoft Spy++...


PРS. А вот насчет "фокуса в окне RAM", я, похоже, прав...
There are a few issues:
1. From MSDN: The EM_GETSELTEXT message retrieves the currently selected text in a rich edit control.
2. When you click on the button that textbox will loos its focus and therefore currently selected text = ""
.
iLavr
User avatar
Lavr
Supreme God
Posts: 16676
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Ухватил я, наконец, эти данные о портах из окна RAM : 8)

Image

Ну авторы настарались... :(
И окно всех параметров - модальное, отсюда не child по сути, а owner, поэтому искать
его неудобно...
И все окна такого типа - одинаковые по признакам: класс RICHEDIT, и владелец у всех -
модальное окно класса #32770.
Пришлось отличать искомое окно по размеру через GetWindowRect...

Но дальше всё правильно было: SetActiveWindow - активное основное окно,
SendMessage в найденное окно WM_SETFOCUS, после чего SendMessage ему WM_GETTEXT -
в буфер.

Хотел выделить строку и скопировать только её, но авторы еще и запретили копирование
из RICHEDIT-контрола, SendMessage с EM_GETSELTEXT не срабатывает...


Далее - план такой: ID найденного окна передаю *.dll, которая Hook-нет сообщения этому окну,
и как только в окне изменяются значения, я его содержимое - WM_GETTEXT и байты двух портов
разбираю побитно на "зажигание" светодиодов.
iLavr