Blog. Just Blog

Быстрый поиск

Введите фрагмент названия статьи для поиска

Универсальное субклассирование окон на Ассемблере

05.12.2019 | Категория: Образ мышления: Assembler | Автор: ManHunter
Тема субклассирования окон уже не один раз поднималась в статьях на этом сайте. Теперь пришло время навести порядок и сделать наиболее удобное и универсальное решение для этой задачи. Воспользуемся функциями SetProp и GetProp, чтобы хранить адреса обработчиков прямо в свойствах окна без заведения дополнительных переменных.
  1. ;-------------------------------------------------------------------------
  2. ; Наименования свойств. Можно переименовать, если конфликтуют с другими 
  3. ; строками в программе
  4. ;-------------------------------------------------------------------------
  5. szOld   db 'OldWndProc', 0
  6. szNew   db 'NewWndProc', 0
  7.  
  8. ;-------------------------------------------------------------------------
  9. ; Функция субклассирования окна
  10. ;-------------------------------------------------------------------------
  11. ;  hWnd - хэндл окна для субклассирования
  12. ;  SubclassProc - адрес нового обработчика окна
  13. ;-------------------------------------------------------------------------
  14. proc SubclassWindow hWnd:DWORD,SubclassProc:DWORD
  15.         pusha
  16.  
  17.         ; Получить старый обработчик окна
  18.         invoke  GetWindowLong,[hWnd],GWL_WNDPROC
  19.         ; Сохранить его в свойствах окна
  20.         invoke  SetProp,[hWnd],szOld,eax
  21.         ; Сохранить в свойствах новый обработчик окна
  22.         invoke  SetProp,[hWnd],szNew,[SubclassProc]
  23.         ; Назначить окну универсальную функцию обработки
  24.         invoke  SetWindowLong,[hWnd],GWL_WNDPROC,CommonSubclassProc
  25.  
  26.         popa
  27.         ret
  28. endp
Использование функции простейшее. Обычно на этапе инициализации окна нужным элементам назначаются собственные обработчики:
  1.         ; Субклассировать поле ввода
  2.         invoke  GetDlgItem,[hwnddlg],ID_HEX
  3.         stdcall SubclassWindow,eax,EditWindowProc
  4.  
  5.         ; Субклассировать кнопку
  6.         invoke  GetDlgItem,[hwnddlg],ID_BTN
  7.         stdcall SubclassWindow,eax,ButtonProc
Нечасто, но может возникнуть ситуация, когда надо отменить субклассирование какого-либо элемента диалогового окна. Не проблема, есть и для этого своя функция.
  1. ;-------------------------------------------------------------------------
  2. ; Функция снятия субклассирования с окна
  3. ;-------------------------------------------------------------------------
  4. ;  hWnd - хэндл окна
  5. ;-------------------------------------------------------------------------
  6. proc UnSubclassWindow hWnd:DWORD
  7.         pusha
  8.  
  9.         ; Получить сохраненный обработчик окна
  10.         invoke  GetProp,[hWnd],szOld
  11.         or      eax,eax
  12.         ; Сохраненного обработчика нет
  13.         jz      .loc_ret
  14.         ; Назначить окну старую функцию обработки
  15.         invoke  SetWindowLong,[hWnd],GWL_WNDPROC,eax
  16.         ; Удалить сохраненные обработчики
  17.         invoke  RemoveProp,[hWnd],szOld
  18.         invoke  RemoveProp,[hWnd],szNew
  19. .loc_ret:
  20.         popa
  21.         ret
  22. endp
Здесь проверяется наличие сохраненного обработчика, если он есть, то обработчик окна восстанавливается на исходный, после чего сохраненные значения очищаются.

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

Преобразование символических ссылок в путь к файлу

08.02.2019 | Категория: Образ мышления: Assembler | Автор: ManHunter
"По следам наших публикаций". В одной из недавних статей я использовал код для преобразования символических ссылок на файл в привычный путь. Немного поразмыслив, я решил доработать его до полноценной универсальной функции, которая будет приводить любые "кривые" пути и символические ссылки к человекопонятному виду. Функция разворачивает переменные окружения, исправляет обратные слеши, а также обрабатывает символические ссылки вида "\SystemRoot\explorer.exe", "\Device\HarddiskVolume1\WINDOWS\win.ini", "\??\E:\asm\" и "file:///C:/Windows/explorer.exe". Поддерживаются файлы, каталоги и диски.
  1. ;------------------------------------------------------------
  2. ; Функция нормализации пути к файлу или каталогу
  3. ;------------------------------------------------------------
  4. ; Параметры:
  5. ;   lpPath - указатель на исходный путь
  6. ;   lpNorm - указатель на строку с нормализованным путем
  7. ; На выходе:
  8. ;   EAX = 1 - путь успешно нормализован
  9. ;   EAX = 0 - путь не найден
  10. ;------------------------------------------------------------
  11. proc normalize_path lpPath:DWORD,lpNorm:DWORD
  12.         _OBJ_CASE_INSENSITIVE         = 0x00000040
  13.         _FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020
  14.         _FILE_READ_DATA               = 1
  15.  
  16.         ; Тип запрашиваемой информации
  17.         _ObjectNameInformation = 1
  18.  
  19.         ; Структура для получения результата
  20.         struct _OBJECT_NAME_INFORMATION
  21.                 Length        dw ?
  22.                 MaximumLength dw ?
  23.                 Buffer        dd ?
  24.                 String        rw MAX_PATH-1
  25.         ends
  26.  
  27.         ; Структура для юникодной строки
  28.         struct _UNICODE_STRING
  29.                 Length        dw ?
  30.                 MaximumLength dw ?
  31.                 Buffer        dd ?
  32.         ends
  33.  
  34.         ; Структура для статуса выполнения операции
  35.         struct _IO_STATUS_BLOCK
  36.                 Status      dd ?
  37.                 Pointer     dd ?
  38.                 Information dd ?
  39.         ends
  40.  
  41.         ; Структура для атрибутов объекта
  42.         struct _OBJECT_ATTRIBUTES
  43.                 Length                   dd ?
  44.                 RootDirectory            dd ?
  45.                 ObjectName               dd ?
  46.                 Attributes               dd ?
  47.                 SecurityDescriptor       dd ?
  48.                 SecurityQualityOfService dd ?
  49.         ends
  50.  
  51.         locals
  52.                 hFile            dd ?
  53.                 tmp_name         rw MAX_PATH-1
  54.                 dDisk            dd ?
  55.                 szDisk           rw 4
  56.                 result           dd ?
  57.                 szTmp            rw MAX_PATH-1
  58.                 ObjectName       _UNICODE_STRING
  59.                 ObjectAttributes _OBJECT_ATTRIBUTES
  60.                 IoStatusBlock    _IO_STATUS_BLOCK
  61.                 dwSize           dd ?
  62.                 ObjectNameInfo   _OBJECT_NAME_INFORMATION
  63.         endl
  64.  
  65.         pusha
  66.  
  67.         mov     [result],0
  68.  
  69.         ; Преобразовать File URL в путь
  70.         lea     eax,[dwSize]
  71.         mov     dword [eax],MAX_PATH*2
  72.         lea     ebx,[szTmp]
  73.         invoke  PathCreateFromUrl,[lpPath],ebx,eax,0
  74.         or      eax,eax
  75.         jz      @f
  76.  
  77.         mov     ebx,[lpPath]
  78. @@:
  79.         ; Развернуть переменные окружения
  80.         lea     eax,[tmp_name]
  81.         invoke  ExpandEnvironmentStrings,ebx,eax,MAX_PATH*2
  82.  
  83.         ; Исправить обратные слеши
  84.         lea     ebx,[tmp_name]
  85.         mov     esi,ebx
  86.         mov     edi,ebx
  87. .loc_fix_slashes:
  88.         lodsw
  89.         cmp     ax,'/'
  90.         jne     @f
  91.         mov     ax,'\'
  92. @@:
  93.         stosw
  94.         or      ax,ax
  95.         jnz     .loc_fix_slashes
  96.  
  97.         ; Путь уже нормализован?
  98.         cmp     word [ebx+2],':'
  99.         jne     @f
  100.  
  101.         ; Больше ничего делать не требуется
  102.         invoke  lstrcpy,[lpNorm],ebx
  103.         mov     [result],1
  104.         jmp     .loc_ret
  105. @@:
  106.         lea     eax,[ObjectName]
  107.         invoke  RtlInitUnicodeString,eax,ebx
  108.  
  109.         push    _FILE_SYNCHRONOUS_IO_NONALERT
  110.         push    FILE_SHARE_READ+FILE_SHARE_WRITE+FILE_SHARE_DELETE
  111.         lea     eax,[IoStatusBlock]
  112.         push    eax
  113.         lea     ebx,[ObjectAttributes]
  114.         push    ebx
  115.         mov     [ebx+_OBJECT_ATTRIBUTES.Length],sizeof._OBJECT_ATTRIBUTES
  116.         lea     eax,[ObjectName]
  117.         mov     [ebx+_OBJECT_ATTRIBUTES.ObjectName],eax
  118.         mov     [ebx+_OBJECT_ATTRIBUTES.Attributes],_OBJ_CASE_INSENSITIVE
  119.         push    _FILE_READ_DATA+SYNCHRONIZE
  120.         lea     eax,[hFile]
  121.         push    eax
  122.         invoke  NtOpenFile
  123.         or      eax,eax
  124.         jz      @f
  125.  
  126.         ; Файл открыть не удалось
  127.         lea     ebx,[tmp_name]
  128.         invoke  lstrcpy,[lpNorm],ebx
  129.         jmp     .loc_ret
  130. @@:
  131.         lea     ebx,[dwSize]
  132.         ; Получить размер информации
  133.         invoke  NtQueryObject,[hFile],_ObjectNameInformation,NULL,0,ebx
  134.         ; Получить информацию об объекте
  135.         push    ebx
  136.         push    [dwSize]
  137.         lea     eax,[ObjectNameInfo]
  138.         push    eax
  139.         invoke  NtQueryObject,[hFile],_ObjectNameInformation
  140.         or      eax,eax
  141.         jz      @f
  142.  
  143.         ; Имя объекта получить не удалось
  144.         lea     ebx,[tmp_name]
  145.         invoke  lstrcpy,[lpNorm],ebx
  146.         invoke  NtClose,[hFile]
  147.         jmp     .loc_ret
  148. @@:
  149.         ; Сохранить полученное имя
  150.         lea     eax,[ObjectNameInfo]
  151.         lea     eax,[eax+_OBJECT_NAME_INFORMATION.String]
  152.         lea     ebx,[tmp_name]
  153.         invoke  lstrcpy,ebx,eax
  154.  
  155.         ; Закрыть открытый файл
  156.         invoke  NtClose,[hFile]
  157.  
  158.         ; Перебрать все диски, начиная с A:
  159.         mov     [dDisk],1
  160. .loc_find_drive:
  161.         invoke  GetLogicalDrives
  162. @@:
  163.         test    eax,[dDisk]
  164.         jnz     @f
  165.         shl     [dDisk],1
  166.         jnz     @b
  167.  
  168.         ; Диск определить не удалось
  169.         lea     ebx,[tmp_name]
  170.         invoke  lstrcpy,[lpNorm],ebx
  171.         jmp     .loc_ret
  172. @@:
  173.         lea     eax,[szDisk]
  174.         mov     dword [eax],0x003A0041 ; 'A:' в юникоде
  175.         mov     dword [eax+4],0
  176.         mov     ecx,[dDisk]
  177.         bsr     ecx,ecx
  178.         add     dword [eax],ecx
  179.  
  180.         ; Следующий диск
  181.         shl     [dDisk],1
  182.  
  183.         ; Преобразовать букву диска в строку типа \Device\HarddiskVolume1
  184.         lea     eax,[szDisk]
  185.         lea     ebx,[szTmp]
  186.         invoke  QueryDosDevice,eax,ebx,MAX_PATH*2
  187.         or      eax,eax
  188.         ; Диска нет, пропускаем
  189.         jz      @f
  190.         ; Сравнить начало пути со строкой устройства
  191.         mov     ecx,eax
  192.         lea     esi,[tmp_name]
  193.         mov     edi,ebx
  194.         repe    cmpsw
  195.         or      ecx,ecx
  196.         jnz     @f
  197.  
  198.         ; Только буква диска
  199.         lea     eax,[szDisk]
  200.         invoke  lstrcpy,[lpNorm],eax
  201.         mov     [result],1
  202.         jmp     .loc_ret
  203. @@:
  204.         cmp     ecx,1
  205.         jne     .loc_find_drive
  206.         ; Дополнительная проверка корректности пути
  207.         dec     esi
  208.         dec     esi
  209.         cmp     word [esi],'\'
  210.         jne     .loc_find_drive
  211.  
  212.         ; Диск + оставшийся путь к файлу
  213.         lea     eax,[szDisk]
  214.         invoke  lstrcpy,[lpNorm],eax
  215.         invoke  lstrcat,[lpNorm],esi
  216.         mov     [result],1
  217. .loc_ret:
  218.         popa
  219.  
  220.         mov     eax,[result]
  221.         ret
  222. endp
Параметры вызова: lpPath - указатель на юникодную строку с исходным путем, lpNorm - указатель на строку, куда будет записан нормализованный путь к файлу или каталогу. В регистре EAX возвращается результат выполнения операции: 1 - нормализация прошла успешно, 0 - что-то пошло не так, например, не найден объект, на который указывает символическая ссылка, или файл расположен на сетевом диске. В случае неудачи в lpNorm будет записан исходный путь, но с развернутыми переменными окружения и исправленными слешами, или вовсе без изменений, если никаких преобразований не выполнялось.

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

Кодирование и декодирование чисел по алгоритму Base58

22.01.2019 | Категория: Образ мышления: Assembler | Автор: ManHunter
Base58 - вариант кодирования чисел в виде буквенно-цифрового текста на основе цифр и символов латинского алфавита. Алфавит Base58, как можно догадаться из названия, содержит 58 символов. Base58 был разработан для передачи данных и уменьшения количества ошибок у пользователей, которые вручную вводят данные на основе распечатанного текста или фотографии, то есть без возможности машинного копирования и вставки. Так, к примеру, Base58 используется для кодирования идентификаторов кошельков Bitcoin, для создания коротких ссылок на фотохостингах и т.п. В отличие от кодирования Base64, позволяющего работать с неограниченными объемами двоичных данных, Base58 предназначен для кодирования только одиночных числовых значений.

Согласно спецификации, в алфавит Base58 не входят буквенно-цифровые символы, которые имеют сходное написание и могут неоднозначно восприниматься человеком (например, буква "О" и цифра "0"), а также символы, используемые при формировании URL. Вместе с тем, порядок следования символов в алфавите ничем не регламентирован, зависит только от сферы применения кодирования и может быть любым. Для этой статьи я выбрал следующий алфавит Base58:
  1. alpha db '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
  2. alpha_len=$-alpha
Использования своего собственного порядка символов также позволяет добавить немного секурности вашему проекту, затрудняя перебор последовательных идентификаторов. Но вы должны понимать, что целиком надеяться на это ни в коем случае не стоит.

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

Алгоритмы шифрования TEA и XTEA на Ассемблере

13.12.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter

Алгоритмы шифрования TEA и XTEA на Ассемблере

Tiny Encryption Algorithm (TEA) - один из видов блочных алгоритмов шифрования данных. Главными отличиями TEA являются высокая скорость работы, нетребовательность к памяти и простота реализации на различных языках программирования. Не обошлось и без недостатков в виде уязвимости к некоторым типам криптографических атак, но даже несмотря на это алгоритм завоевал широкую популярность в различных системах.

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

Как удалить BOM из файлов

24.12.2017 | Категория: Web-мастеру и не только | Автор: ManHunter
Маркер последовательности байтов, он же BOM - специальный символ Юникода, который вставляется в начало текстового файла для обозначения того, что в этом файле используется Юникод. Согласно спецификации, использование этого символа не является обязательным, однако оно широко распространено, что иногда приводит к проблемам при обработке данных.

Так, к примеру, однажды я столкнулся с ситуацией, когда от сторонней системы передавался файл в формате JSON, а я у себя должен был извлечь поступившие данные при помощи стандартной функции PHP json_decode. Файл передается и принимается успешно, на первый взгляд имеет абсолютно корректную структуру, правильно открывается в браузере и блокноте, но функция декодирования все равно возвращает ошибку, что данные некорректные. Сейчас я не смогу сказать, сколько времени потратил на выяснение причины ошибки, пока, наконец, не решил открыть файл при помощи HEX-редактора. Оказалось, что всему виной был маркер BOM, из-за которого функция json_decode не могла корректно раскодировать файл.

Для решения проблемы я быстренько нарисовал вот такую функцию в несколько строчек:
  1. // Функция удаления BOM из потока данных
  2. function remove_BOM($data) {
  3.     // Маркер UTF-8
  4.     if (substr($data,0,3)=="\xEF\xBB\xBF") {
  5.         return substr($data,3);
  6.     }
  7.     // Маркер UTF-16
  8.     elseif (substr($data,0,2)=="\xFF\xFE") {
  9.         return substr($data,2);
  10.     }
  11.     else {
  12.         return $data;
  13.     }
  14. }
При получении файла данные сперва обрабатывались при помощи этой функции и только после этого отправлялись на декодирование в json_decode.

Просмотров: 1141 | Комментариев: 1

prev 01 02 03 04 05 06 07
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2020
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.12 сек. / MySQL: 3 (0.0463 сек.) / Память: 5 Mb
Наверх