
Как узнать, что программа запущена под Администратором
Иногда требуется узнать, запущена ли ваша программа под учетной записью с правами Администратора, или же от обычного пользователя. Для чего это нужно? Например, некоторые операции с реестром или файлами требуют права Администратора. При попытке выполнить их обычному пользователю вернется ошибка ERROR_ACCESS_DENIED, но для более точного анализа ситуации надо будет проверить права доступа и уведомить об этом пользователя. Проверить, что программа запущена под Администратором, можно несколькими способами.Первый способ наиболее универсальный и работает даже на старых операционных системах. Он заключается в том, что надо получить группы доступа для токена текущего процесса, а затем проверить, входит ли хоть одна из них в группу Администраторов локального компьютера. Вот пример реализации:
Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- SECURITY_NT_AUTHORITY = 5
- TOKEN_READ = 0x00020008
- SECURITY_BUILTIN_DOMAIN_RID = 0x00000020
- DOMAIN_ALIAS_RID_ADMINS = 0x00000220
- TokenGroups = 0x00000002
- BUFF_SIZE = 1024h ; Размер буфера для групп доступа токена
- NtAuthority db 0,0,0,0,0,SECURITY_NT_AUTHORITY
- hTokenHandle dd ?
- dInfoSize dd ?
- psidAdmins dd ?
- hHeap dd ?
- pTokenGroups dd ?
- ;---------------------------------------------
- ; Сегмент кода
- section '.code' code readable executable
- ...
- ; Получить токен текущего процесса
- invoke GetCurrentProcess
- invoke OpenProcessToken,eax,TOKEN_READ,hTokenHandle
- ; Выделить память для массива групп
- invoke GetProcessHeap
- mov [hHeap],eax
- invoke HeapAlloc,eax,HEAP_ZERO_MEMORY,BUFF_SIZE
- mov [pTokenGroups],eax
- ; Получить информацию о группах доступа токена
- invoke GetTokenInformation,[hTokenHandle],TokenGroups,\
- [pTokenGroups],dword BUFF_SIZE,dInfoSize
- ; Прибраться за собой
- invoke CloseHandle,[hTokenHandle]
- invoke AllocateAndInitializeSid,NtAuthority,2,\
- SECURITY_BUILTIN_DOMAIN_RID,\
- DOMAIN_ALIAS_RID_ADMINS,0,0,0,0,0,0,psidAdmins
- ; Количество записей в структуре TOKEN_GROUPS
- mov esi,[pTokenGroups]
- mov ebx,dword [esi]
- ; Указатель на массив SID_AND_ATTRIBUTES
- add esi,4
- @@:
- ; Проверить соответствие SID
- mov eax,dword [esi]
- invoke EqualSid,[psidAdmins],eax
- or eax,eax
- jnz loc_admin
- ; Следующая группа
- add esi,8
- dec ebx
- or ebx,ebx
- jnz @b
- loc_not_admin:
- ; Пользователь не Администратор
- ...
- loc_admin:
- ; Пользователь Администратор
- ...
Второй вариант очень похож на предыдущий, но будет работать только на системах, начиная с Windows 2000. В нем используется функция CheckTokenMembership, которая и выполняет все громоздкие проверки.
Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- SECURITY_NT_AUTHORITY = 5
- SECURITY_BUILTIN_DOMAIN_RID = 0x00000020
- DOMAIN_ALIAS_RID_ADMINS = 0x00000220
- NtAuthority db 0,0,0,0,0,SECURITY_NT_AUTHORITY
- psidAdmins dd ?
- pbAdmin dd ?
- ;---------------------------------------------
- ; Сегмент кода
- section '.code' code readable executable
- ...
- invoke AllocateAndInitializeSid,NtAuthority,2,\
- SECURITY_BUILTIN_DOMAIN_RID,\
- DOMAIN_ALIAS_RID_ADMINS,0,0,0,0,0,0,psidAdmins
- invoke CheckTokenMembership,NULL,[psidAdmins],pbAdmin
- mov eax,[pbAdmin]
- ; Если EAX=1, то программа запущена под Администратором
- ...
Code (Assembler) : Убрать нумерацию
- ...
- invoke IsUserAdmin
- ; Если EAX=1, то программа запущена под Администратором
- ...
Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- struct USER_INFO_1
- usri1_name dd ?
- usri1_password dd ?
- usri1_password_age dd ?
- usri1_priv dd ?
- usri1_home_dir dd ?
- usri1_comment dd ?
- usri1_flags dd ?
- usri1_script_path dd ?
- ends
- dSize dd 100h
- szUname rb 100h
- info dd ?
- NERR_SUCCESS = 0
- USER_PRIV_ADMIN = 2
- ;---------------------------------------------
- ; Сегмент кода
- section '.code' code readable executable
- ...
- ; Получить логин текущего пользователя
- invoke GetUserName,szUname,dSize
- ; Получить информацию о пользователе
- invoke NetUserGetInfo,NULL,szUname,1,info
- cmp eax,NERR_SUCCESS
- jne loc_error
- ; Указатель на структуру USER_INFO_1
- mov eax,[info]
- ; Пользователь админ?
- cmp dword [eax+USER_INFO_1.usri1_priv],USER_PRIV_ADMIN
- je loc_admin
- loc_not_admin:
- ; Пользователь не Администратор
- ...
- loc_admin:
- ; Пользователь Администратор
- ...
Ну а в заключении еще один небольшой пример, не совсем относящийся к теме статьи, но очень близкий. Это проверка, загружена система в безопасном режиме или в нормальном.
Code (Assembler) : Убрать нумерацию
- ; Получить информацию о загрузке системы
- invoke GetSystemMetrics,SM_CLEANBOOT
- ; EAX=0 - нормальная загрузка
- ; EAX=1 - безопасный режим
- ; EAX=2 - безопасный режим с поддержкой сети
Просмотров: 10711 | Комментариев: 25

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье

ManHunter
(19.03.2025 в 16:41):
На фрилансе за денежку

mehomozg
(19.03.2025 в 16:36):
Можете,пожалуйста,сказать где мне найти версию этого кода для masm64?
Пытался переписать все эти варианты и каждый из них обламывался на различных перессылках данных в библиотеке.
Пытался переписать все эти варианты и каждый из них обламывался на различных перессылках данных в библиотеке.

rtfm
(06.06.2021 в 19:42):
Потребовалась консольная (cmd) определялка IsAdmin/IsElevated.
С некоторым удивлением узнал, что с однозначными вариантами - непросто (хотя бы, для xp-10, включая PE).
Лобовые (запись в защищенные объекты фc, реестр и т.п) и более элегантные (вроде fltmc) способы, без использования сторонних утилит, имеют тот недостаток, что их результат отличается от результата CheckTokenMembership, которым пользуются инсталляторы. Т.е. фактически привилегии есть, а скриптовая установка чего-либо может показать обломинго.
Использование же CheckTokenMembership (или его “обертки” IsUserAnAdmin) означает вызовы api из cmd (см. winapiexec и т.д.) или иное использование сторонних (не входящих в win) утилит.
Про менее типовые варианты (как вариант эмуляции - process explorer или process hacker -> run as limited user, coretechnologies\run with restricted rights и т.п.) говорить вообще сложно – кто в лес, кто по дрова.
Это не претензия к приведенным примерам (в них - api), просто иллюстрация к словам. i.postimg.cc/FHCX8cw5/4.png
С некоторым удивлением узнал, что с однозначными вариантами - непросто (хотя бы, для xp-10, включая PE).
Лобовые (запись в защищенные объекты фc, реестр и т.п) и более элегантные (вроде fltmc) способы, без использования сторонних утилит, имеют тот недостаток, что их результат отличается от результата CheckTokenMembership, которым пользуются инсталляторы. Т.е. фактически привилегии есть, а скриптовая установка чего-либо может показать обломинго.
Использование же CheckTokenMembership (или его “обертки” IsUserAnAdmin) означает вызовы api из cmd (см. winapiexec и т.д.) или иное использование сторонних (не входящих в win) утилит.
Про менее типовые варианты (как вариант эмуляции - process explorer или process hacker -> run as limited user, coretechnologies\run with restricted rights и т.п.) говорить вообще сложно – кто в лес, кто по дрова.
Это не претензия к приведенным примерам (в них - api), просто иллюстрация к словам. i.postimg.cc/FHCX8cw5/4.png

addhaloka
(26.02.2016 в 10:51):
Нашёл ещё вариант - с IsUserAnAdmin из shell32.dll:
section '.code' code readable executable
proc IsUserAnRoot
invoke GetModuleHandle,szSH32
invoke GetProcAddress,eax,2A8h ; по ординалу, вроде как нужно для старых осей (win2000): https://exelab.ru/f/index.php?...opic=10294#7
or eax,eax
jz @F
call eax
@@:
ret
szSH32 db 'shell32.dll',0
endp
start:
call IsUserAnRoot
; Пользователь админ?
or eax,eax
; далее, как в примере №3
section '.code' code readable executable
proc IsUserAnRoot
invoke GetModuleHandle,szSH32
invoke GetProcAddress,eax,2A8h ; по ординалу, вроде как нужно для старых осей (win2000): https://exelab.ru/f/index.php?...opic=10294#7
or eax,eax
jz @F
call eax
@@:
ret
szSH32 db 'shell32.dll',0
endp
start:
call IsUserAnRoot
; Пользователь админ?
or eax,eax
; далее, как в примере №3

ManHunter
(16.05.2015 в 19:15):
Общепринятая формулировка - "запустите программу под администратором". Никто и никогда не говорит типа "запустите процесс, чтобы он имел права администратора".

капитошка
(16.05.2015 в 14:49):
извините за то что придираюсь, немного не точные формулировки в названии поста и некоторых предложениях.
нужно точно указать что проверяется наличие прав администратора у запущенного процесса. иначе можно понять что проверяется не администратор ли тот от кого запущен процесс.
вот кстати творчество на основе способа №2.
proc IsUserAdmin
push 0
push esp
align 4
nop
nop
nop
call @F
db 1,2,0,0,0,0,0,SECURITY_NT_AUTHORITY
dd SECURITY_BUILTIN_DOMAIN_RID
dd DOMAIN_ALIAS_RID_ADMINS
@@: invoke CheckTokenMembership, 0
pop eax
ret
endp
нужно точно указать что проверяется наличие прав администратора у запущенного процесса. иначе можно понять что проверяется не администратор ли тот от кого запущен процесс.
вот кстати творчество на основе способа №2.
proc IsUserAdmin
push 0
push esp
align 4
nop
nop
nop
call @F
db 1,2,0,0,0,0,0,SECURITY_NT_AUTHORITY
dd SECURITY_BUILTIN_DOMAIN_RID
dd DOMAIN_ALIAS_RID_ADMINS
@@: invoke CheckTokenMembership, 0
pop eax
ret
endp

ManHunter
(16.11.2013 в 19:41):
Вряд ли получится, ограниченное приложение без дебажных прав в любом случае будет иметь минимальные права доступа.
А что касается Nt* функций, то не такие уж они и недокументированные, раз все ими пользуются. Я бы их назвал больше "неафишируемыми", чем недокументированными.
А что касается Nt* функций, то не такие уж они и недокументированные, раз все ими пользуются. Я бы их назвал больше "неафишируемыми", чем недокументированными.

_lucius_
(16.11.2013 в 18:20):
ManHunter, здравствуйте. Спасибо вам за ваш замечательный блог. Не подскажите как узнать права у чужого процесса, при условии что у нас самих прав нет и в связи с этим мы не можем открыть процесс с правами PROCESS_QUERY_INFORMATION. Эти права нужны для того чтобы получить хэндл токена (через OpenProcessToken), а затем узнать права через SHTestTokenMembership. Читал то что можно получить хэндл через ZwQuerySystemInformation/ZwDuplicateObject, но очень не хотелось бы использовать недокументированные функции.

X
(13.02.2012 в 18:56):
Супер! Работает!

ManHunter
(13.02.2012 в 17:37):
Всегда пожалуйста.
данные:
sei SHELLEXECUTEINFO
runas db 'runas',0
program db 'fasmw.exe',0
buff rb 200h
код:
mov [sei.cbSize],sizeof.SHELLEXECUTEINFO
mov [sei.lpVerb],runas
mov [sei.lpFile],program
invoke GetCurrentDirectory,200h,buff
mov [sei.lpDirectory],buff
mov [sei.nShow],SW_SHOW
invoke ShellExecuteEx,sei
и при запуске дочерней программы будет выдан запрос учетки пользователя
данные:
sei SHELLEXECUTEINFO
runas db 'runas',0
program db 'fasmw.exe',0
buff rb 200h
код:
mov [sei.cbSize],sizeof.SHELLEXECUTEINFO
mov [sei.lpVerb],runas
mov [sei.lpFile],program
invoke GetCurrentDirectory,200h,buff
mov [sei.lpDirectory],buff
mov [sei.nShow],SW_SHOW
invoke ShellExecuteEx,sei
и при запуске дочерней программы будет выдан запрос учетки пользователя

X
(13.02.2012 в 17:36):
Спасибо, я понял.

ManHunter
(13.02.2012 в 17:31):
Которое из написанного непонятно? Запрашиваешь у пользователя логин-пароль Администратора, передаешь их на runas.exe, PROFIT.
А из юзера свое приложение ты все равно не поднимешь до админа без применения всяких сплойтов, равно как и не запустишь процесс из своего так, чтобы он вдруг заимел админские права без знания логина-пароля админа. Иначе тогда зачем все эти ограничения прав придуманы? Все трояны бы тогда работали из любой ограниченной учетки.
А из юзера свое приложение ты все равно не поднимешь до админа без применения всяких сплойтов, равно как и не запустишь процесс из своего так, чтобы он вдруг заимел админские права без знания логина-пароля админа. Иначе тогда зачем все эти ограничения прав придуманы? Все трояны бы тогда работали из любой ограниченной учетки.

X
(13.02.2012 в 17:23):
Пользователь запускает мою программу как не Администратор. Моей программе необходимо запустить cmd.exe с правами Администратора. Я не знаю логин и пароль Администратора. Для запуска cmd.exe я использую WinAPI CreateProcess -> процесс cmd.exe запускается с ограниченными привилегиями. Пробую повысить привилегии своего запускающего процесса:
invoke LookupPrivilegeValue,NULL,SE_SECURITY_NAME,udtLUID
mov [tkp.PrivilegeCount],1
mov [tkp.Privileges.Attributes],SE_PRIVILEGE_ENABLED
mov eax,[udtLUID.lowPart]
mov [tkp.Privileges.pLuid.lowPart],eax
mov eax,[udtLUID.HighPart]
mov [tkp.Privileges.pLuid.HighPart],eax
invoke AdjustTokenPrivileges,[TTokenHd],0,tkp,0,0,0
Не помогает.
invoke LookupPrivilegeValue,NULL,SE_SECURITY_NAME,udtLUID
mov [tkp.PrivilegeCount],1
mov [tkp.Privileges.Attributes],SE_PRIVILEGE_ENABLED
mov eax,[udtLUID.lowPart]
mov [tkp.Privileges.pLuid.lowPart],eax
mov eax,[udtLUID.HighPart]
mov [tkp.Privileges.pLuid.HighPart],eax
invoke AdjustTokenPrivileges,[TTokenHd],0,tkp,0,0,0
Не помогает.

ManHunter
(13.02.2012 в 16:58):
google -> DialogBoxParam, CreateWindow - диалоговое окно с вводом пароля, логина, имени прабабушки и клички любимой собаки
google -> AdjustTokenPrivileges - повышение привилегий процесса
cmd -> runas.exe /?
Или ты чо, из юзерской учетки в своем процессе решил в админы выпрыгнуть? Тогда сразу можешь забыть.
google -> AdjustTokenPrivileges - повышение привилегий процесса
cmd -> runas.exe /?
Или ты чо, из юзерской учетки в своем процессе решил в админы выпрыгнуть? Тогда сразу можешь забыть.

X
(13.02.2012 в 16:41):
Я имел ввиду, как заставить пользователя ввести логин и пароль администратора или повысить привилегии процесса?

ManHunter
(13.02.2012 в 16:16):
google -> CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW и т.д.

X
(13.02.2012 в 16:14):
Если после проверки оказалось, что пользователь не администратор, как зная SID администратора (psidAdmins) запустить другой процесс с правами администратора?

ManHunter
(09.01.2012 в 21:02):
UAC у меня выключено, и система стоит на минимальном уровне уведомлений. А об UAC я думаю, что это натуральная херня, которую в MS придумали, чтобы хомячки с предустановленными системами не разносили всякую заразу и не жрали мозги техподдержке.

Stanis
(09.01.2012 в 11:23):
ManHunter, вопрос не совсем по теме, но все же
У вас UAC включено или выключенно? и что Вы думаете вообще о нём?
У вас UAC включено или выключенно? и что Вы думаете вообще о нём?

Andrew
(28.11.2011 в 13:46):
ManHunter, спасибо за ответ!

ManHunter
(28.11.2011 в 12:04):
OllyDbg и отлаживаю, для юзермода пока ничего лучше не придумали. И пока что обхожусь без отладочной информации :)

Andrew
(28.11.2011 в 12:01):
ManHunter, скажите пожалуйста (если это не секрет), чем вы отлаживаете ваши приложения? Я пользуюсь OllyDbg, но при размере PE модуля в 10 КБ и больше без отладочной информации запутаться в строчках кода легче легкого (из-за этого даже хотел перейти с FASM на NASM/YASM, но тем не менее отказался от этой идеи).

ManHunter
(21.11.2011 в 08:18):
4-й способ и под Гостем тоже показывает "Something wrong", я поэтому сразу написал, что способ очень ненадежный. Про UAC обязательно добавлю, спасибо.

Nutscracker
(21.11.2011 в 02:12):
Наверное, надо про UAC добавить.
На Win 7 с включенным UAC правильное «You are NOT admin» сообщают is_admin2.exe и is_admin3.exe.
А если запустить с правами NT AUTHORITY\система (как у процесса winlogon), то is_admin4.exe сообщит «Something wrong ;(».
На Win 7 с включенным UAC правильное «You are NOT admin» сообщают is_admin2.exe и is_admin3.exe.
А если запустить с правами NT AUTHORITY\система (как у процесса winlogon), то is_admin4.exe сообщит «Something wrong ;(».

Добавить комментарий
Заполните форму для добавления комментария

А и кстати первый и четвёртый исполняемые файлы у меня в любом случае печатают "You are ADMINISTRATOR"