Blog. Just Blog

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

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

Диалог открытия файлов и юзабилити Windows

02.11.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter
При всех удобствах Windows некоторые моменты меня очень сильно раздражают. Особенно поведение системы при вызове диалогов открытия файлов. Сперва немного предыстории. При работе с файлами через функцию GetOpenFileName или GetSaveFileName в структуре OPENFILENAME есть возможность указать путь, который должен открыться по умолчанию. Если это значение не задано, то система сама где-то запоминает папку, в которой последний раз был удачно открыт файл (то есть окно выбора файла было закрыто через кнопку "Ok"). Где именно хранится эта информация - я пока не выяснил, да и не особо надо. Второй вариант. Предположим, что некоторая программа самостоятельно запоминает путь к папке, в которой последний раз ею выполнялись какие-то действия с файлами. Это может быть, например, текстовый редактор, просмотрщик графики и т.п., не суть. Главное, что задумка очень хорошая и правильная. При следующем запуске или вызове диалога выбора файла в соответствующее поле OPENFILENAME будет подставлен сохраненный путь и пользователь продолжит работу с того места, где он в прошлый раз остановился. Что-то типа такого:
  1.         ...
  2.         invoke  GetModuleHandle,0
  3.         mov     [ofn.hInstance],eax
  4.         mov     [ofn.lStructSize], sizeof.OPENFILENAME
  5.         mov     [ofn.hwndOwner],0
  6.         mov     [ofn.nMaxFile],MAX_PATH
  7.         mov     [ofn.lpstrFile],buff
  8.         ; Открывать с последней сохраненной папки
  9.         mov     [ofn.lpstrInitialDir],saved_dir
  10.         mov     [ofn.Flags],OFN_EXPLORER+OFN_FILEMUSTEXIST
  11.         invoke  GetOpenFileName,ofn
  12.         ...
Неадекватное, на мой взгляд, поведение системы заключается в следующем. Вполне может возникнуть ситуация, что какая-то часть из сохраненного или запрошенного пути пропала. Например, я в просмотрщике рассортировал папку с фотографиями, в графическом редакторе подправил несколько файлов, а затем в файловом менеджере перенес всю папку с фотографиями в другое место на диске. В этом случае при попытке вернуться к просмотру в просмотрщике, повторно вызвать диалог открытия или сохранения файла в графическом редакторе, при любом раскладе в качестве дефолтного пути будет открыта какая-нибудь херня типа Библиотеки, Моих документов или вообще папки, куда установлена программа. Закономерности я тут тоже не уловил, видимо принятие решения остается за Windows и зависит от уровня осадков в Зимбабве. В итоге пользователю приходится снова топать весь путь из библиотеки до места работы.

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

Новый алгоритм получения Google PageRank

11.10.2011 | Категория: Web-мастеру и не только | Автор: ManHunter
Буквально на днях Google поменял алгоритм, по которому генерировалась ссылка для получения показателей Google PageRank. В результате этого отвалились многие сервисы, вспомогательные программы, сторонние тулбары, счетчики и еще бессчетное количество сеошного барахла. Мне было бы глубоко фиолетово на их проблемы, но у меня на сайте тоже используется система автоматического съема значений Google PR. Поэтому пришлось быстренько адаптироваться к новым условиям. Я установил себе гугловский тулбар, быстренько выпотрошил его и получил алгоритм генерации ссылки для получения Google PageRank. Вот как он выглядит на JavaScript:
  1. <script type="text/javascript">
  2.  
  3. // Программисты Google явно с юмором :)
  4. var HASH_SEED "Mining PageRank is AGAINST GOOGLE'S TERMS OF SERVICE. "+
  5.                  "Yes, I'm talking to you, scammer.";
  6.  
  7. // Расчет хэша строки запроса
  8. awesomeHash = function(a) {
  9.     var 16909125;
  10.     for (0a.lengthc++) {
  11.         b ^= HASH_SEED.charCodeAt(HASH_SEED.length) ^ a.charCodeAt(c);
  12.         b >>> 23 << 9;
  13.     }    
  14.     return '8'+hexEncodeU32(b);
  15. };
  16.  
  17. // Перевод числа в HEX-значение
  18. hexEncodeU32 = function(a) {
  19.     var toHex8(>>> 24);
  20.     b += toHex8(>>> 16 255);
  21.     b += toHex8(>>> 255);
  22.     return toHex8(255)
  23. };
  24. toHex8 = function(a) {
  25.     return (16 "0""") + a.toString(16)
  26. };
  27.  
  28. // Функция получения ссылки для запроса Google PR
  29. getPageRankLink = function(a) {
  30.     return 'http://toolbarqueries.google.ru/tbr?features=Rank'+
  31.            '&client=navclient-auto-ff&ch='+awesomeHash(a)+'&q=info:'+
  32.            encodeURIComponent(a);
  33. }
  34. </script>
Функция вызывается следующим образом. На входе подается ссылка на страницу, для которой требуется рассчитать Google PageRank, на выходе получаем ссылку, по которой можно узнать результат.
  1. <script type="text/javascript">
  2.  
  3. // Пример использования
  4. st='http://www.manhunter.ru/'
  5. alert(getPageRankLink(st));
  6.  
  7. </script>
Результат запроса к гугловскому серверу возвращается в виде строки, например, "Rank_1:1:2". Последняя цифра и есть искомое значение рейтинга страницы. Алгоритм можно без особого труда перевести на другие языки программирования.

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

Расчет CRC8 на Ассемблере

25.09.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter
Контрольная сумма CRC8 применяется в основном для коротких сетевых пакетов и в микроконтроллерах. Из-за большой вероятности появления коллизий, использовать ее можно или для контроля целостности небольших объемах данных (оптимально - до 15 байт информации), или в случаях, когда возможность появления искажений исходных данных крайне мала. Алгоритм расчета CRC8 реализуется очень просто, работает очень быстро, из-за чего до сих пор находит свое применение. Первый вариант - прямой расчет.
  1. ;-----------------------------------------------------------------------
  2. ; Функция вычисления хеша CRC8
  3. ; by ManHunter / PCL
  4. ; http://www.manhunter.ru
  5. ;-----------------------------------------------------------------------
  6. ; Параметры:
  7. ;       lpData - указатель на строку
  8. ;       dSize  - длина строки
  9. ; На выходе:
  10. ;       AL = полученный хеш
  11. ;-----------------------------------------------------------------------
  12. proc    CRC8 lpData:DWORD, dSize:DWORD
  13.         push    ebx ecx edx esi edi
  14.  
  15.         CRC8_POLYNOM = 31h
  16.  
  17.         ; Инициализация
  18.         mov     al,0FFh
  19.  
  20.         ; Длина строки
  21.         cmp     [dSize],0
  22.         je      .loc_ret
  23.  
  24.         ; Указатель на начало строки
  25.         xor     ecx,ecx
  26. @@:
  27.         ; Получить символ из строки
  28.         mov     ebx,[lpData]
  29.         xor     al,byte [ebx+ecx]
  30.  
  31.         xor     esi,esi
  32. .loc_cycle:
  33.         test    al,80h
  34.         jz      .loc_1
  35.  
  36.         shl     al,1
  37.         xor     al,CRC8_POLYNOM
  38.         jmp     .loc_next
  39. .loc_1:
  40.         shl     al,1
  41. .loc_next:
  42.         inc     esi
  43.         cmp     esi,8
  44.         jb      .loc_cycle
  45.  
  46.         ; Следующий символ
  47.         inc     ecx
  48.         cmp     ecx,[dSize]
  49.         jb      @b
  50.  
  51. .loc_ret:
  52.         and     eax,0FFh
  53.  
  54.         pop     edi esi edx ecx ebx
  55.         ret
  56. endp
Этот вариант компактный, но не самый быстрый по скорости вычисления. Более скоростной алгоритм расчета CRC8 - с использованием заранее подготовленной таблицы.

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

Принудительное завершение процесса

20.08.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter
Рано или поздно в программистской практике возникает задача по управлению процессами, в частности их принудительного завершения. Для дочерних процессов, порожденных собственным приложением, обычно хватает вызова TerminateProcess, но в некоторых случаях требуется принудительно завершить чужой процесс. Зная идентификатор процесса сделать это не составит большого труда. Открываем процесс функцией OpenProcess с правами PROCESS_TERMINATE, а затем, в случае успеха, отдаем полученный хэндл функции TerminateProcess. Вроде бы все просто, но не тут-то было. При попытке открыть некоторые процессы, как правило системные, возвращается ошибка ERROR_ACCESS_DENIED. Это связано с тем, что дескрипторы безопасности системных процессов блокируют такой доступ для всех пользователей, включая Администраторов. Чтобы обойти запрет, требуется поднять привилегии нашего процесса, а именно получить привилегию отладчика SE_DEBUG_NAME. Как повышать привилегии процесса в системе я уже писал. Напомню только, что необходимые структуры и константы в FASM отсутствуют и их придется определить самостоятельно.
  1. ; Константы для работы привилегиями
  2. TOKEN_ADJUST_PRIVILEGES = 20h
  3. TOKEN_QUERY             = 8h
  4. SE_PRIVILEGE_ENABLED    = 2h
  5.  
  6. ; Структуры для работы привилегиями
  7. struct LUID
  8.     lowPart             dd ?
  9.     HighPart            dd ?
  10. ends
  11.  
  12. struct LUID_AND_ATTRIBUTES
  13.     pLuid               LUID
  14.     Attributes          dd ?
  15. ends
  16.  
  17. struct _TOKEN_PRIVILEGES
  18.     PrivilegeCount      dd ?
  19.     Privileges          LUID_AND_ATTRIBUTES
  20. ends
Когда данные подготовлены, можно поднять привилегии нашего процесса. Этот код вам уже должен быть знаком и трудностей не вызовет.
  1.         invoke  GetCurrentProcess
  2.         invoke  OpenProcessToken,eax,TOKEN_ADJUST_PRIVILEGES+TOKEN_QUERY,TTokenHd
  3.  
  4.         ; Получить привилегии процесса
  5.         invoke  LookupPrivilegeValue,NULL,SE_DEBUG_NAME,udtLUID
  6.  
  7.         ; Повысить привилегии процесса
  8.         mov     [tkp.PrivilegeCount],1
  9.         mov     [tkp.Privileges.Attributes],SE_PRIVILEGE_ENABLED
  10.         mov     eax,[udtLUID.lowPart]
  11.         mov     [tkp.Privileges.pLuid.lowPart],eax
  12.         mov     eax,[udtLUID.HighPart]
  13.         mov     [tkp.Privileges.pLuid.HighPart],eax
  14.         invoke  AdjustTokenPrivileges,[TTokenHd],0,tkp,0,0,0
Все, теперь у нас есть доступ ко всем процессам, включая сервисы и системные приложения. Конечно, есть особые программы типа антивирусов и фаерволов, которые на уровне ядра системы защищаются от манипуляций с их процессами, с ними такой трюк не сработает.

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

Запись в архивы RAR, ZIP и ARJ без помощи архиватора

09.08.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter
Решил вспомнить свою юность, когда я занимался разработкой "самоходного программного обеспечения". Одной из особенностей моих творений было распространение не только через исполняемые файлы, но и через архивы различных форматов. Технология внедрения в архивные файлы не нова, она использовалась в разных вирусах еще со времен MS-DOS. Так как готовых решений на тот момент у меня не было, приходилось доходить до всего самому. Никакого вредоносного кода на этом сайте не появится, а вот некоторыми своими наработками по внедрению в архивы я с удовольствием поделюсь. Поскольку полноценно продублировать алгоритмы сжатия архиваторов в столь малом размере файла не представляется возможным, внедряться в архивы мы будем по методу "Store". Это означает, что файл в архив добавлен с опцией "без сжатия". Внутренние форматы различных архивных файлов, естественно, различаются, но у всех обязательно присутствуют служебные заголовки, используемые архиваторами, и, собственно, сами упакованные данные.

Самый простой для внедрения - формат RAR, используемый одноименным архиватором. Подробную спецификацию формата RAR можно почитать здесь.
  1. ;---------------------------------------------
  2. ; RAR Header
  3. ;---------------------------------------------
  4. rhcrc   dw      ?     ; --> Low-word CRC32 of fields in header
  5. rhtype  db      ?     ; Header type: 0x74
  6. rhflag  dw      ?     ; Bit flags
  7. rhsize  dw      ?     ; File header full size
  8. rcsize  dd      ?     ; Compressed file size
  9. rosize  dd      ?     ; Uncompressed file size
  10. rhoss   db      ?     ; Target OS version
  11. rfcrc   dd      ?     ; --> File CRC32
  12. rdtm    dd      ?     ; File Time/Date
  13. runp    db      ?     ; Archive version to extract
  14. rmeth   db      ?     ; Packing method (store)
  15. rnsize  dw      ?     ; File name size
  16. rfattr  dd      ?     ; File attributes
  17. rfname  rb      (?)   ; File name
Мнемокода "(?)" в FASM нет, просто таким образом я обозначил текстовую строку для записи имени файла неопределенной длины. В реальном проекте будет достаточно MAX_PATH или вообще фиксированного размера.
  1. ; "Хвост" архива - признак окончания данных
  2. tail    db      0C4h,03Dh,07Bh,00h,040h,07h,00h
  3. tail_length     = $-tail
Однако надо знать, что не во все RAR-архивы можно безопасно внедряться. Обязательно надо проверять флаговые биты в основном заголовке архива и пропускать заблокированные, многотомные, непрерывные архивы и архивы с цифровой подписью. Все эти проверки вы сможете сделать самостоятельно, здесь я их описывать не буду.

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

01 ... 59 60 61 62 63 64 65 ... 75
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2025
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.09 сек. / MySQL: 3 (0.0186 сек.) / Память: 4.5 Mb
Наверх