Blog. Just Blog

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

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

Как узнать, что программа запущена под Администратором

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

Первый способ наиболее универсальный и работает даже на старых операционных системах. Он заключается в том, что надо получить группы доступа для токена текущего процесса, а затем проверить, входит ли хоть одна из них в группу Администраторов локального компьютера. Вот пример реализации:
  1. ; Сегмент данных
  2. section '.data' data readable writeable
  3.  
  4. SECURITY_NT_AUTHORITY       = 5
  5. TOKEN_READ                  = 0x00020008
  6. SECURITY_BUILTIN_DOMAIN_RID = 0x00000020
  7. DOMAIN_ALIAS_RID_ADMINS     = 0x00000220
  8. TokenGroups                 = 0x00000002
  9.  
  10. BUFF_SIZE = 1024h ;  Размер буфера для групп доступа токена
  11.  
  12. NtAuthority     db 0,0,0,0,0,SECURITY_NT_AUTHORITY
  13.  
  14. hTokenHandle    dd ?
  15. dInfoSize       dd ?
  16. psidAdmins      dd ?
  17. hHeap           dd ?
  18. pTokenGroups    dd ?
  19.  
  20. ;---------------------------------------------
  21.  
  22. ; Сегмент кода
  23. section '.code' code readable executable
  24.         ...
  25.         ; Получить токен текущего процесса
  26.         invoke  GetCurrentProcess
  27.         invoke  OpenProcessToken,eax,TOKEN_READ,hTokenHandle
  28.  
  29.         ; Выделить память для массива групп
  30.         invoke  GetProcessHeap
  31.         mov     [hHeap],eax
  32.  
  33.         invoke  HeapAlloc,eax,HEAP_ZERO_MEMORY,BUFF_SIZE
  34.         mov     [pTokenGroups],eax
  35.  
  36.         ; Получить информацию о группах доступа токена
  37.         invoke  GetTokenInformation,[hTokenHandle],TokenGroups,\
  38.                 [pTokenGroups],dword BUFF_SIZE,dInfoSize
  39.  
  40.         ; Прибраться за собой
  41.         invoke  CloseHandle,[hTokenHandle]
  42.  
  43.         invoke  AllocateAndInitializeSid,NtAuthority,2,\
  44.                 SECURITY_BUILTIN_DOMAIN_RID,\
  45.                 DOMAIN_ALIAS_RID_ADMINS,0,0,0,0,0,0,psidAdmins
  46.  
  47.         ; Количество записей в структуре TOKEN_GROUPS
  48.         mov     esi,[pTokenGroups]
  49.         mov     ebx,dword [esi]
  50.         ; Указатель на массив SID_AND_ATTRIBUTES
  51.         add     esi,4
  52. @@:
  53.         ; Проверить соответствие SID
  54.         mov     eax,dword [esi]
  55.         invoke  EqualSid,[psidAdmins],eax
  56.         or      eax,eax
  57.         jnz     loc_admin
  58.  
  59.         ; Следующая группа
  60.         add     esi,8
  61.         dec     ebx
  62.         or      ebx,ebx
  63.         jnz     @b
  64.  
  65. loc_not_admin:
  66.         ; Пользователь не Администратор
  67.         ...
  68.  
  69. loc_admin:
  70.         ; Пользователь Администратор
  71.         ...
Обратите внимание, что никаких проверок на ошибки не выполняется, оставлен только рабочий код. Полный вариант вы можете посмотреть в приложении к статье.

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

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

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

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

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

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).

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

Построение карты памяти процесса

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

Для построения карты памяти процесса используется функция VirtualQueryEx и специальная структура MEMORY_BASIC_INFORMATION. В FASM она как обычно не определена, придется сделать это самостоятельно в сегменте данных:
  1. ; Структура для чтения памяти процесса
  2. struct  MEMORY_BASIC_INFORMATION
  3.         BaseAddress          dd ?
  4.         AllocationBase       dd ?
  5.         AllocationProtect    dd ?
  6.         RegionSize           dd ?
  7.         State                dd ?
  8.         Protect              dd ?
  9.         Type                 dd ?
  10. ends
  11.  
  12. ; Структура для чтения памяти процесса
  13. mbi             MEMORY_BASIC_INFORMATION
Для работы с памятью процесса при помощи функции VirtualQueryEx нам надо знать хэндл этого процесса. Для дочерних, которые мы запустили сами, все просто: это значение hProcess из структуры PROCESS_INFORMATION. Если процесс порожден не нами, то для получения его хэндла, зная ID процесса, надо воспользоваться функцией OpenProcess, обязательно с флагом PROCESS_QUERY_INFORMATION. Возможно, что перед этим потребуется повысить привилегии нашего процесса, активировав SeDebugPrivilege.

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

Проверка и обнаружение зависших приложений

27.10.2009 | Категория: Образ мышления: Assembler | Автор: ManHunter
Иногда для работы требуется определение зависших приложений, окна которых не отвечают на сообщения. Для этого есть два способа. Первый - официально документированный, через функцию SendMessageTimeOut. Особенность ее работы заключается в том, что после отправки сообщения окну она ждет ответ заданное время, и, если ответа от приложения не последовало, то возвращает FALSE. Вот пример использования функции. Нужные константы, как обычно, в FASM не определены, пришлось брать их из других источников.
  1.         ...
  2.         ; Определить таймаут 50 миллисекунд
  3.         TIMEOUT = 50
  4.         ; Определить константу SMTO_ABORTIFHUNG
  5.         SMTO_ABORTIFHUNG = 2
  6.         ; hwnd - хэндл проверяемого окна
  7.         invoke  SendMessageTimeout,[hwnd],NULL,0,0,SMTO_ABORTIFHUNG,TIMEOUT,NULL
  8.         ; Если вернулся 0, то приложение "висит"
  9.         or      eax,eax
  10.         jz      app_hung_up
  11.         ...
Минус использования этой функции в том, что при частой проверке большого количества окон зависших приложений, каждый раз будет отрабатываться таймаут для каждого такого окна, что суммарно может дать снижение производительности вашего приложения. Но повторюсь, Microsoft официально рекомендует к использованию именно эту функцию.

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

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