Blog. Just Blog

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

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

Как получить имя файла, зная его Handle

29.01.2019 | Категория: Образ мышления: Assembler | Автор: ManHunter
В одной программе у меня появилась необходимость получить имя открытого файла, когда известен его хэндл. Полазив по этим вашим интернетам, я нашел немало решений этой задачи, в основном бездумно скопированных с одного сайта на другой. Пришлось разбираться и систематизировать все самому. Итак, самый простой и приятный способ, чтобы получить имя файла по его хэндлу - использовать функцию GetFinalPathNameByHandle.
  1.         ; Получить имя файла по его хэндлу
  2.         invoke GetFinalPathNameByHandle,[hFile],lpName,MAX_PATH,0
На вход подаем хэндл открытого файла, на выходе получаем полный путь к нему. Красота! Но, к сожалению, этот способ работает только на Windows Vista и более новых системах. Если вашему приложению требуется поддержка Windows XP, то придется проверять наличие этой функции в экспорте библиотеки kernel32. Для старых систем есть другой способ. Открытый файл проецируется в память с помощью функций CreateFileMapping и MapViewOfFile, затем с помощью функции GetMappedFileName можно узнать полный путь к спроецированному файлу:
  1.         ; Создать проекцию файла
  2.         invoke  CreateFileMapping,[hFile],NULL,PAGE_READONLY,0,1,NULL
  3.         mov     [hFileMap],eax
  4.         invoke  MapViewOfFile,[hFileMap],FILE_MAP_READ,0,0,1
  5.         mov     [pMem],eax
  6.  
  7.         ; Получить имя спроецированного файла
  8.         invoke  GetCurrentProcess
  9.         invoke  GetMappedFileName,eax,[pMem],lpName,MAX_PATH
  10.  
  11.         ; Прибраться за собой
  12.         invoke  UnmapViewOfFile,[pMem]
  13.         invoke  CloseHandle,[hFileMap]
Имя носителя в строке пути записывается в виде "\Device\HarddiskVolume1", для приведения его к более привычному виду надо пройтись по всем доступным буквам дисков, установленных в системе, каждую преобразовать в имя устройства и сравнить с именем устройства в пути к файлу. Для облегчения операции преобразования символических ссылок я нарисовал отдельную функцию. Способ с проецированием файла неплохой, но у него есть один существенный недостаток: проецирование не работает с файлами нулевой длины. Например, вы не сможете получить имя вновь созданного пустого файла, тогда как функция GetFinalPathNameByHandle прекрасно справляется с этой задачей.

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

Кодирование и декодирование чисел по алгоритму 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
Использования своего собственного порядка символов также позволяет добавить немного секурности вашему проекту, затрудняя перебор последовательных идентификаторов. Но вы должны понимать, что целиком надеяться на это ни в коем случае не стоит.

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

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

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

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

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

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

Как изменить цвет кнопок диалогового окна

17.11.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter
Когда-то давно в одной из статей я рассказывал, как менять цвета различных элементов диалоговых окон Windows. Наверняка вы обратили внимание, что элемент типа BUTTON, то есть кнопка, выбивается из общей схемы и на изменение цвета не реагирует должным образом. Решить эту проблему все-таки можно, но для этого придется самостоятельно отрисовывать все компоненты кнопки - фон, рамку и надпись. Зато такой способ открывает неограниченные возможности по кастомизации кнопок.

Первым делом в ресурсах или в функции создания кнопки через CreateWindow(Ex) надо дополнить стиль модифицируемой кнопки параметром BS_OWNERDRAW. С этого момента все функции по рисованию перекладываются на наше приложение. Для этого приложение должно обрабатывать сообщение WM_DRAWITEM. Окну-владельцу кнопки в параметре lParam этого сообщения передается указатель на структуру DRAWITEMSTRUCT, на основании которой мы и будем заниматься рисованием.
  1.         cmp     [msg],WM_DRAWITEM
  2.         je      color_button
  3.         ...
  4.         ...
  5. color_button:
  6.         ; Указатель на структуру DRAWITEMSTRUCT
  7.         mov     ebx,[lparam]
  8.  
  9.         ; Установить режим смешивания фоновых цветов
  10.         invoke  SetBkMode,[ebx+DRAWITEMSTRUCT.hDC],TRANSPARENT
  11.  
  12.         ; Кнопка активна?
  13.         test    [ebx+DRAWITEMSTRUCT.itemState],ODS_SELECTED
  14.         jz      @f
  15.  
  16.         invoke  GetSysColor,COLOR_ACTIVEBORDER
  17.         invoke  CreatePen,PS_SOLID,1,eax
  18.         invoke  SelectObject,[ebx+DRAWITEMSTRUCT.hDC],eax
  19.  
  20.         invoke  GetSysColor,COLOR_3DLIGHT
  21.         invoke  CreateSolidBrush,eax
  22.         invoke  SelectObject,[ebx+DRAWITEMSTRUCT.hDC],eax
  23.  
  24.         ; Прямоугольник с заливкой
  25.         invoke  Rectangle,[ebx+DRAWITEMSTRUCT.hDC],\
  26.                 [ebx+DRAWITEMSTRUCT.rcItem.left],\
  27.                 [ebx+DRAWITEMSTRUCT.rcItem.top],\
  28.                 [ebx+DRAWITEMSTRUCT.rcItem.right],\
  29.                 [ebx+DRAWITEMSTRUCT.rcItem.bottom]
  30.  
  31.         jmp     loc_text
  32. @@:
  33.         ; Установить цвет и стиль рамки
  34.         invoke  GetSysColor,COLOR_3DDKSHADOW
  35.         invoke  CreatePen,PS_SOLID,3,eax
  36.         invoke  SelectObject,[ebx+DRAWITEMSTRUCT.hDC],eax
  37.  
  38.         ; Установить цвет фона
  39.         invoke  GetSysColor,COLOR_HIGHLIGHT
  40.         invoke  CreateSolidBrush,eax
  41.         invoke  SelectObject,[ebx+DRAWITEMSTRUCT.hDC],eax
  42.  
  43.         ; Прямоугольник с заливкой
  44.         invoke  Rectangle,[ebx+DRAWITEMSTRUCT.hDC],\
  45.                 [ebx+DRAWITEMSTRUCT.rcItem.left],\
  46.                 [ebx+DRAWITEMSTRUCT.rcItem.top],\
  47.                 [ebx+DRAWITEMSTRUCT.rcItem.right],\
  48.                 [ebx+DRAWITEMSTRUCT.rcItem.bottom]
  49.  
  50. loc_text:
  51.         ; Длина надписи на кнопке
  52.         invoke  GetWindowTextLength,[ebx+DRAWITEMSTRUCT.hwndItem]
  53.         inc     eax
  54.         mov     [len],eax
  55.         invoke  GetWindowText,[ebx+DRAWITEMSTRUCT.hwndItem],buff,[len]
  56.  
  57.         ; Установить цвет текста
  58.         invoke  SetTextColor,[ebx+DRAWITEMSTRUCT.hDC],0x0000FFFF
  59.  
  60.         ; Для нажатой кнопки сдвинуть текст вниз-вправо
  61.         test    [ebx+DRAWITEMSTRUCT.itemState],ODS_SELECTED
  62.         jz      @f
  63.  
  64.         ; Установить цвет текста
  65.         invoke  SetTextColor,[ebx+DRAWITEMSTRUCT.hDC],0x000000FF
  66.  
  67.         add     [ebx+DRAWITEMSTRUCT.rcItem.left],2
  68.         add     [ebx+DRAWITEMSTRUCT.rcItem.top],2
  69. @@:
  70.         ; Надпись на кнопке
  71.         lea     esi,[ebx+DRAWITEMSTRUCT.rcItem]
  72.         invoke  DrawText,[ebx+DRAWITEMSTRUCT.hDC],buff,[len],esi,\
  73.                 DT_SINGLELINE+DT_VCENTER+DT_CENTER
В зависимости от состояния кнопки, нажата она или нет, меняется цвет фона, цвет текста и стиль рамки. Здесь рамка нарисована единым цветом и толщиной, но при необходимости можно заморочиться и нарисовать "трехмерные" границы с помощью функций MoveToEx и LineTo. Еще было бы правильным проверять, что цвета меняются именно для нужной кнопки, делается это проверкой элемента itemID в структуре DRAWITEMSTRUCT. В приведенном примере я это осознанно пропустил, чтобы не загромождать код.

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

Получение данных из консольного окна другого приложения

02.11.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter
Мы уже умеем перехватывать ввод и вывод консольных приложений, но этот способ работает только для тех процессов, которые мы сами запустили. Но иногда надо получать информацию из консольных приложений, которые уже были запущены в системе или могут быть запущены в дальнейшем, но не нами. А еще бывают консольные приложения, вывод которых невозможно перенаправить и, соответственно, невозможно получить описанным ранее способом. Для них также придется использовать способ из этой статьи.

Для начала как всегда несколько структур, которые изначально не описаны в FASM. Они нам понадобятся для работы с консольным окном:
  1. struct  COORD
  2.         X dw ?
  3.         Y dw ?
  4. ends
  5.  
  6. struct  SMALL_RECT
  7.         Left   dw ?
  8.         Top    dw ?
  9.         Right  dw ?
  10.         Bottom dw ?
  11. ends
  12.  
  13. struct CONSOLE_SCREEN_BUFFER_INFO
  14.         dwSize              COORD
  15.         dwCursorPosition    COORD
  16.         wAttributes         dw ?
  17.         srWindow            SMALL_RECT
  18.         dwMaximumWindowSize COORD
  19. ends
Теперь немного теории. Любое приложение, даже GUI, может создать собственную консоль или приаттачиться к уже существующей. Для аттача достаточно знать только идентификатор консольного процесса. После этого получаем стандартный хэндл вывода, используемый в этой консоли, параметры консольного окна (количество строк и столбцов), а потом единственной функцией ReadConsoleOutputCharacter забираем из консольного окна все содержимое.

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

Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2020
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0018 сек.) / Память: 4.75 Mb
Наверх