Blog. Just Blog

Образ мышления: Assembler

То, что не удается запрограммировать на Ассемблере, приходится паять
Образ мышления: Assembler - RSS-канал Образ мышления: Assembler - Карта сайта

Как запретить Windows переходить в спящий режим

26.10.2010 | Категория: Образ мышления: Assembler | Автор: ManHunter
В некоторых случаях требуется, чтобы на время работы вашего приложения компьютер постоянно оставался в активном состоянии, то есть не включался скринсейвер, не отключался монитор, система не переходила в спящий режим. Для этого надо "убедить" Windows, что за клавиатурой сидит реальный пользователь и проявляет какую-то активность, в этом случае все счетчики времени бездействия будут сбрасываться. Для программной имитации действий пользователя используются две функции: mouse_event для симуляции работы с мышкой мышки и, соответственно, keybd_event для клавиатуры. Также можно использовать более универсальную функцию SendInput, она позволяет симулировать не только мышку и клавиатуру, но и хардварные события. Есть еще более суровые варианты, связанные с ковырянием в реестре, изменением профилей электропитания, но их я рассматривать не буду.

В прикладном приложении для имитации действий пользователя надо установить таймер, например, на секундный интервал, и в его функции-обработчике симулировать движение мыши. Нажатия кнопок мыши и клавиш на клавиатуре симулировать не надо, так как эти действия могут наложиться с действиями реального пользователя, а вот перемещение мышки на какое-нибудь незаметное расстояние будет в самый раз. Почитаем повнимательнее документацию к функции mouse_event. Координаты перемещения задаются в условных единицах - микки, которые высчитываются по формуле: 1 микки = (ширина или высота разрешения монитора) / 65535. Если не указан флаг MOUSEEVENTF_ABSOLUTE, то координаты считаются относительные, то есть от текущего положения курсора. Первоначальный вариант решения был в перемещении курсора на 1 микки от текущего положения курсора, а затем в возвращении его обратно. Но, к сожалению, на Windows XP этот способ все-таки двигал курсор (спасибо ezfalc0n за подсказку). Следующий вариант, вообще без движения, также сбрасывает счетчик времени бездействия системы, так что будем использовать именно его:
  1.         ; Симулировать событие от мышки, оставляя ее на месте
  2.         invoke  mouse_event,MOUSEEVENTF_MOVE,0,0,0,0
Вот и все решение. Теперь Windows будет бодрствовать ровно столько, сколько вам нужно. Можете убедиться в этом, запустив одновременно программу для определения времени бездействия системы и пример из приложения к статье. Вы увидите, что даже когда вы сами не прикасаетесь к мышке и клавиатуре, таймер бездействия системы (функция GetLastInputInfo) остается на нулевой отметке.

Читать статью целиком »
Просмотров: 13057 | Комментариев: 25

Экранная лупа на Ассемблере

15.10.2010 | Категория: Образ мышления: Assembler | Автор: ManHunter
Алгоритм реализации экранной лупы достаточно простой. Надо получить часть изображения рабочего стола и скопировать его с масштабированием в нужную область вашего приложения. Сделать это можно при помощи функции StretchBlt. Если посмотрите описание, то увидите, что для работы этой функции требуются следующие параметры: размеры результирующей области, размеры исходной области и контексты устройств (окон), в которых находятся области. А поскольку мы сейчас разрабатываем лупу, значит она должна увеличивать, то есть размеры исходного окна должны быть пропорционально меньше результирующего. Коэффициент пропорциональности и есть коэффициент увеличения лупы. При инициализации окна выполним предварительные расчеты:
  1.         ...
  2.         ; Получить контекст окна лупы
  3.         invoke  GetDlgItem,[hwnddlg],ID_ZOOM
  4.         mov     ebx,eax
  5.         invoke  GetDC,eax
  6.         mov     [wDC],eax
  7.  
  8.         ; Получить размеры окна лупы
  9.         invoke  GetClientRect,ebx,coord
  10.         mov     eax,[coord.right]
  11.         sub     eax,[coord.left]
  12.         mov     [dWidth],eax
  13.         mov     eax,[coord.bottom]
  14.         sub     eax,[coord.top]
  15.         mov     [dHeight],eax
  16.  
  17.         ; Получить контекст десктопа
  18.         invoke  GetDesktopWindow
  19.         mov     [hDesktop],eax
  20.         invoke  GetDC,eax
  21.         mov     [dDC],eax
  22.         ...
Как теперь запустить экранную лупу? Здесь есть два варианта: при получении сообщения от мыши и по таймеру. У каждого способа свои достоинства и недостатки. Если обрабатывать сообщения мыши, то требуется инжект вспомогательной dll во все процессы, а экран лупы будет обновляться только при движении мыши. Это существенно снизит нагрузку на систему, но если окно под курсором будет обновляться, а курсор останется неподвижным, то лупа получит только тот кадр, который был при последнем движении курсора. Обновление по таймеру создаст дополнительную нагрузку на систему, но при этом изображение в лупе будет в точности соответствовать текущему состоянию окна под курсором. Оба способа имеют место быть, каждый под свои задачи.

Читать статью целиком »
Просмотров: 6307 | Комментариев: 6

Защищенное поле для ввода пароля

23.08.2010 | Категория: Образ мышления: Assembler | Автор: ManHunter
Как-то задумался о том, можно ли защититься от программ, которые показывают пароли за "звездочками"? Ведь это могут быть не только безобидные программы для восстановления забытых паролей, но и "троянские кони", похищающие вашу приватную информацию. Немного поэкспериментировал, оказалось, что защититься можно. Сперва немного теоретической информации о том, каким образом открываются пароли. Первый способ: сначала нужному полю EDIT посылается сообщение EM_SETPASSWORDCHAR с нулевыми параметрами, в результате чего с него снимается атрибут ES_PASSWORD. После этого текст пароля можно прочитать как визуально, так и через GetWindowText, WM_GETTEXT и т.п. Второй способ, более "пробивной", это внедрение в исследуемый процесс своей DLL, после чего с ее помощью текст пароля читается через сообщение WM_GETTEXT. Это делается потому, что в целях безопасности информацию из поля, закрытого "звездочками", через GetWindowText или WM_GETTEXT можно получить только из контекста процесса, который владеет окном.

Чтобы защититься от программ первого типа, надо самостоятельно обрабатывать сообщение EM_SETPASSWORDCHAR и в обработчике подавлять его. Защититься от второго варианта сложнее, ведь если мы будем подавлять сообщение WM_GETTEXT, то мы и сами не сможем прочитать текст пароля. Значит надо каким-то образом различать "свои" сообщения WM_GETTEXT и "чужие". Признак "свой" можно сделать, например, указав в качестве длины буфера какое-нибудь заранее определенное уникальное значение, а затем в обработчике пропускать сообщения только с этим параметром. Установить собственный обработчик можно через субклассирование окна ввода, это мы уже разбирали в предыдущих статьях. Теперь от теории перейдем к практике.

Читать статью целиком »
Просмотров: 6158 | Комментариев: 10

Определение времени бездействия системы

05.08.2010 | Категория: Образ мышления: Assembler | Автор: ManHunter
Иногда приложениям требуется узнать время бездействия системы, то есть интервал времени, прошедший с момента когда пользователь последний раз пошевелил мышкой или нажал какую-нибудь кнопку на клавиатуре. Для определения время бездействия системы в системах Windows 2000 и старше используется функция API GetLastInputInfo. Она возвращает количество миллисекунд (тиков таймера), прошедшее от старта системы до момента последнего ввода. Время бездействия вычисляется как арифметическая разница между данными, возвращаемыми функцией GetTickCount и данными из GetLastInputInfo. В FASM, как обычно, ничего из нужных структур не определено, лезем в MSDN:
  1. section '.data' data readable writeable
  2.  
  3. struct  LASTINPUTINFO
  4.         cbSize   dd ?   ; Размер структуры
  5.         dwTime   dd ?   ; Время бездействия
  6. ends
  7.  
  8. lii     LASTINPUTINFO  
Получение времени бездействия системы:
  1.         ...
  2.         ; Получить время последнего ввода
  3.         mov     [lii.cbSize],sizeof.LASTINPUTINFO
  4.         invoke  GetLastInputInfo,lii
  5.  
  6.         ; Получить текущее время в миллисекундах
  7.         invoke  GetTickCount
  8.  
  9.         ; EAX - время бездействия системы в миллисекундах
  10.         sub     eax,[lii.dwTime]
  11.         ...
Это был самый простой способ, работающий на всех новых системах. В старых операционках типа Windows 9x функция GetLastInputInfo отсутствует, поэтому там придется использовать другой, более громоздкий способ с применением глобальных системных хуков.

Читать статью целиком »
Просмотров: 8359 | Комментариев: 11

Получение списка иконок в трее

18.07.2010 | Категория: Образ мышления: Assembler | Автор: ManHunter
Иногда приложению требуется получить список иконок, находящихся в трее, а также список приложений, которые их туда разместили. Это может быть нужно для обнаружения некоторых скрывающихся приложений, для эмуляции кликов на иконках, ну или просто для спортивного интереса. В любом случае для получения списка иконок надо сделать следующее: найти в трее панель с иконками, при помощи сообщения TB_BUTTONCOUNT получить количество иконок, а затем через отправку сообщения TB_GETBUTTON получить всю необходимую информацию по каждой иконке. Теперь рассмотрим все шаги подробнее.

Работать с вложенными окнами трея мы уже умеем, здесь практически то же самое, разница только в названиях классов дочерних окон.
  1. ; Сегмент данных
  2. section '.data' data readable writeable 
  3. ...
  4. class1  db 'Shell_TrayWnd',0    ; Название класса окна трея
  5. class2  db 'TrayNotifyWnd',0    ; Название класса панели уведомлений
  6. class3  db 'SysPager',0         ; Трей
  7. class4  db 'ToolbarWindow32',0  ; Панель с иконками
  8.  
  9. ToolbarHandle   dd ?            ; Хэндл окна с иконками
  10. ...
  11. ; Сегмент кода
  12. section '.code' code readable executable
  13.         ...
  14.         ; Найти окно трея
  15.         invoke  FindWindow,class1,NULL
  16.         or      eax,eax
  17.         jz      exit_process
  18.  
  19.         ; Найти панель уведомлений
  20.         invoke  FindWindowEx,eax,NULL,class2,NULL
  21.         or      eax,eax
  22.         jz      exit_process
  23.  
  24.         ; Найти трей
  25.         invoke  FindWindowEx,eax,NULL,class3,NULL
  26.         or      eax,eax
  27.         jz      exit_process
  28.  
  29.         ; Найти панель иконок в трее
  30.         invoke  FindWindowEx,eax,NULL,class4,NULL
  31.         or      eax,eax
  32.         jz      exit_process
  33.  
  34.         ; Сохранить хэндл окна с иконками
  35.         mov     [ToolbarHandle],eax
  36.         ...
Теперь у нас есть хэндл окна панели инструментов с иконками в трее. Получим количество иконок в панели.
  1.         ; Получить количество иконок в трее
  2.         invoke  SendMessage,eax,TB_BUTTONCOUNT,0,0
  3.         or      eax,eax
  4.         jz      exit_process
  5.  
  6.         ; Сохранить количество иконок в трее
  7.         mov     [IconsCount],eax
Количество иконок тоже есть. Осталось перебрать их в цикле и получить всю необходимую информацию. Для этого используется сообщение TB_GETBUTTON и структура TBBUTTON для получения результата. Однако, если сейчас попробовать послать окну панели сообщение TB_GETBUTTON, то в результате не получим ничего. Почему? Потому что память, в которую будут записываться данные, обязательно должна принадлежать процессу, который является владельцем окна трея (обычно это explorer.exe).

Читать статью целиком »
Просмотров: 9051 | Комментариев: 9

prev 01 ... 61 62 63 64 65 66 67 ... 74 next
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2025
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0045 сек.) / Память: 4.5 Mb
Наверх