Working on a small app that has to be run as an Administrator. I need to check if the user is running it as an administrator, but as usual I just get lost in the Microsoft web site. Any help would be appreciated.
The following function returns a nonzero value, if the process runs with administrator rights:include \masm32\include\Advapi32.inc
includelib \masm32\lib\Advapi32.lib
...
TokenElevation EQU 20
...
IsElevated proc
LOCAL b:BOOL
LOCAL hToken:HANDLE
LOCAL Elevation:TOKEN_ELEVATION
LOCAL cbSize:DWORD
mov b,0
mov hToken,0
mov edx,rv(GetCurrentProcess)
.if rv(OpenProcessToken,edx,TOKEN_QUERY,&hToken )
mov cbSize,SIZEOF TOKEN_ELEVATION
.if rv(GetTokenInformation, hToken, TokenElevation, &Elevation, SIZEOF Elevation, &cbSize )
m2m b,Elevation.TokenIsElevated
.endif
.endif
.if hToken
invoke CloseHandle,hToken
.endif
mov eax,b
ret
IsElevated endp
EDIT: This code does not work for WinXp
You can set your program--thru the manifest--to force admin rights:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0"
processorArchitecture="X86"
name="YourAppName"
type="win32"/>
<description>Description of your application</description>
<!-- Identify the application security requirements. -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="requireAdministrator"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
hth,
farrier
Thanks for the help. :t
Quote from: qWord on October 08, 2012, 08:29:31 AM
The following function returns a nonzero value, if the process runs with administrator rights:include \masm32\include\Advapi32.inc
includelib \masm32\lib\Advapi32.lib
...
TokenElevation EQU 20
...
IsElevated proc
LOCAL b:BOOL
LOCAL hToken:HANDLE
LOCAL Elevation:TOKEN_ELEVATION
LOCAL cbSize:DWORD
mov b,0
mov hToken,0
mov edx,rv(GetCurrentProcess)
.if rv(OpenProcessToken,edx,TOKEN_QUERY,&hToken )
mov cbSize,SIZEOF TOKEN_ELEVATION
.if rv(GetTokenInformation, hToken, TokenElevation, &Elevation, SIZEOF Elevation, &cbSize )
m2m b,Elevation.TokenIsElevated
.endif
.endif
.if hToken
invoke CloseHandle,hToken
.endif
mov eax,b
ret
IsElevated endp
Hey qWord ....
How would be the best way to incorporate that into an app ?
I have an example of checking for multiple instances ....How would be the best way to add your proc ?
JJ,
bom dia.
As always, a very precise answer from you.
Thanks a lot.
Mic
Found this on my hard disk, have IsAdmin function inside, it's just a snippet of other program that I was working 4 years ago. Assemble as console.
Only tested on 32 bits, xp and win7.
The IsUserAnAdmin API function :
https://msdn.microsoft.com/en-us/library/windows/desktop/bb776463%28v=vs.85%29.aspx
A quick example :
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\shell32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\shell32.lib
.code
start:
invoke IsUserAnAdmin
invoke ExitProcess,eax
END start
test.bat :
@IsUserAnAdmin.exe
@IF %ERRORLEVEL% == 1 ( echo The user is an administrator. ) ELSE ( echo The user is not an administrator. )
End of client support: Windows Vista
But it works on Win7-64 ;)
Many thanks to everybody who helped me.
mineiro, voce e Mineiro ?
Minha esposa e de Almenara/MG
Last question...
INVOKE IsUserAnAdmin
Returns TRUE or FALSE
What's wrong with that function ?
So the whole check on the user is only one line.
Hi clamicun,
As Jochen stated, Vista is the last client operating system supporting this API but it works on Windows 7 :
https://msdn.microsoft.com/en-us/library/windows/desktop/bb776463%28v=vs.85%29.aspx
Quote from: Vortex on August 19, 2016, 03:22:55 AMbut it works on Windows 7 :
Not surprisingly, it works also on Windows 10. Microsoft doesn't risk a shitstorm...
This application gets the username with the API function GetUserName and compares it against the list of the members of the Administrators group :
include IsUserAdmin.inc
.data
WSTR LocalGroup,"Administrators"
ResumeHandle dd 0
_size dd 64
.data?
buffer dd ?
EntriesRead dd ?
TotalEntries dd ?
UserName db 128 dup(?)
.code
start:
invoke GetUserNameW,ADDR UserName,ADDR _size
invoke NetLocalGroupGetMembers,NULL,ADDR LocalGroup,\
3,ADDR buffer,MAX_PREFERRED_LENGTH,\
ADDR EntriesRead,ADDR TotalEntries,ADDR ResumeHandle
call IsUserAdministrator
push eax
invoke NetApiBufferFree,buffer
call ExitProcess
IsUserAdministrator PROC USES esi edi ebx
mov ebx,EntriesRead
mov esi,buffer
CompareUserName:
mov edi,LOCALGROUP_MEMBERS_INFO_3.lgrmi3_domainandname[esi]
mov edx,edi
sub edx,2
; Remove the slash symbol from the user name : COMPUTERNAME\User
FindSlash:
add edx,2
cmp BYTE PTR [edx],'\'
jne FindSlash
add edx,2
invoke ucCmp,edx,ADDR UserName
test eax,eax
jz @f
mov eax,1
ret
@@:
add esi,SIZEOF LOCALGROUP_MEMBERS_INFO_3
dec ebx
jnz CompareUserName
ret
IsUserAdministrator ENDP
END start
test.bat :
@IsUserAdmin.exe
@IF %ERRORLEVEL% == 1 ( echo The user is an administrator. ) ELSE ( echo The user is not an administrator. )
DON57,
There are numerous ways to check if Administrative Privileges (https://msdn.microsoft.com/en-us/library/windows/desktop/ms717801(v=vs.85).aspx) are required to run an application (manifests),...or, to check if the current user has been granted Administrative Privileges. Most programmers use the easiest method (for example: IsUserAnAdmin, MSDN (https://msdn.microsoft.com/en-us/library/windows/desktop/bb776463(v=vs.85).aspx), which was introduced in Windows XP). QWORD's post (above) uses the best method: OpenProcessToken function, MSDN (https://msdn.microsoft.com/en-us/library/windows/desktop/aa379295(v=vs.85).aspx), and, then, actually enumerate the current user's Privileges with GetTokenInformation, MSDN (https://msdn.microsoft.com/en-us/library/windows/desktop/aa446671(v=vs.85).aspx). I have used methods similar to Vortex's (above),...it is the normal approach, and, it is usually adequate for the circumstances,...but, it can be easily screwed up.
The problem is that the number of Privileges (https://msdn.microsoft.com/en-us/library/windows/desktop/aa379306(v=vs.85).aspx) has increased in the various Windows Operating System versions over the years,...and, some of them are quite powerful,...super-privileges (see below),...so, it's good to know exactly which Privileges are enabled.
...Also, with the introduction of the User Account Control (UAC) beginning with Windows Vista, there are an enormous number of default security settings possible that the average computer user doesn't understand (and Privileges are disabled by default). Here is an excellent article, describing the features of the User Account Control (UAC): Security: Inside Windows Vista User Account Control, Mark Russinovich, TechNet, June 2007 (https://technet.microsoft.com/en-us/magazine/cc138019.aspx)
This is from:
Windows Internals, Sixth Edition, by, Mark Russinovich, David A. Solomon, and, Alex Ionescu, 2012:
QuoteSuper Privileges:
Several privileges are so powerful that a user to which they are assigned is effectively a "super user" who has full control over a computer. These privileges can be used in an infinite number of ways to gain unauthorized access to otherwise off-limit resources and to perform unauthorized operations.
However, we'll focus on using the privilege to execute code that grants the user privileges not assigned to the user, with the knowledge that this capability can be leveraged to perform any operation on the local machine that the user desires. This section lists the privileges and discusses the ways that they can be exploited. Other privileges, such as Lock Pages In Physical Memory, can be exploited for denial-of-service attacks on a system, but these are not discussed. Note that on systems with UAC enabled, these privileges will be granted
only to applications running at high integrity level or higher, even if the account possesses them:
■■ Debug programs A user with this privilege can open any process on the system (except for a Protected Process) without regard to the security descriptor present on the process. The user could implement a program that opens the LSASS process, for example, copy executable code into its address space, and then inject a thread with the CreateRemoteThread Windows API to execute the injected code in a more-privileged security context. The code could grant the user additional privileges and group memberships.
■■ Take Ownership This privilege allows a holder to take ownership of any securable object (even protected processes and threads) by writing his own SID into the owner field of the object's security descriptor. Recall that an owner is always granted permission to read and modify the DACL of the security descriptor, so a process with this privilege could modify the DACL to grant itself full access to the object and then close and reopen the object with full access. This would allow the owner to see sensitive data and to even replace system files that execute as part of normal system operation, such as LSASS, with his own programs that grant a user elevated privileges.
■■ Restore Files and Directories A user assigned this privilege can replace any file on the system with her own. She could exploit this power by replacing system files as described in the preceding paragraph.
■■ Load and Unload Device Drivers A malicious user could use this privilege to load a device driver into the system. Device drivers are considered trusted parts of the operating system that can execute within it with System account credentials, so a driver could launch privileged programs that assign the user other rights.
■■ Create a Token Object This privilege can be used in the obvious way to generate tokens that represent arbitrary user accounts with arbitrary group membership and privilege assignment.
■■ Act As Part of Operating System LsaRegisterLogonProcess, the function a process calls to establish a trusted connection to LSASS, checks for this privilege. A malicious user with this privilege can establish a trusted-LSASS connection and then execute LsaLogonUser, a function used to create new logon sessions. LsaLogonUser requires a valid user name and password and accepts an optional list of SIDs that it adds to the initial token created for a new logon session. The user could therefore use her own user name and password to create a new logon session that includes the SIDs of more privileged groups or users in the resulting token.
Note that the use of an elevated privilege does not extend past the machine boundary to the network, because any interaction with another computer requires authentication with a domain controller and validation of domain passwords. Domain passwords are not stored on a computer either in plain text or encrypted form, so they are not accessible to malicious code.
Quote
mineiro, voce e Mineiro ?
Minha esposa e de Almenara/MG
Yes sir clamicun, I'm from São João Del Rei. City of mountains, churches, colonial houses, royal path, iron ore, defunct gold mines, milk, coffe... .
I met Almenara years ago, a good city. You probably listen she saying " uai " several times. :t
MSDN code example converted to asm :
; https://msdn.microsoft.com/en-us/library/aa376389.aspx
include IsUserAdmin.inc
.data
NtAuthority _SID_IDENTIFIER_AUTHORITY SECURITY_NT_AUTHORITY
.data?
AdminGroup dd ?
b dd ?
.code
start:
call main
invoke ExitProcess,eax
main PROC uses ebx
xor eax,eax
invoke AllocateAndInitializeSid,ADDR NtAuthority,2,\
SECURITY_BUILTIN_DOMAIN_RID,\
DOMAIN_ALIAS_RID_ADMINS,\
eax,eax,eax,eax,eax,eax,\
ADDR AdminGroup
test eax,eax
jnz @f
ret
@@:
mov b,eax
mov ebx,1
invoke CheckTokenMembership,0,\
AdminGroup,ADDR b
test eax,eax
jnz @f
xor ebx,ebx
@@:
invoke FreeSid,AdminGroup
mov eax,ebx
ret
main ENDP
END start
As I have'nt worked with compound structures all that much please enlighten me to what exactly "this" structure produces :
- we know _SID_IDENTIFIER_AUTHORITY = 6 bytes and SECURITY_NT_AUTHORITY = has a static value of 5
- I'am unsure what the resulting data structure then is - either: 7 bytes total ? //or// 5 x 6 byte array? //or// data initialized to 5 ?
- looking at the original MSDN post - is this really what they meant for us to create ?
RE:
NtAuthority _SID_IDENTIFIER_AUTHORITY SECURITY_NT_AUTHORITY
Then there's this - We check for token membership within the SID group created, however that might be a misnomer :
- The original code has a byte (bool) variable "b" that only contains the value "TRUE" or "1" in the case we are testing for,
so actually we're only testing to see if the calling thread with the related user rights may create a token within the AdminGroup
- Are we really only using "b" to for-fill the constraints of the calling convention for the API ?
- It's probably might also be dangerous to send ZERO instead of NULL - I'am just thinking of special cases where invoked
procedures check for zero / not zero - when converting example code to assembly in general
RE:
invoke CheckTokenMembership,0,AdminGroup,ADDR b
Microsoft:
A handle to an access token. The handle must have TOKEN_QUERY access to the token. The token must be an impersonation token.
If TokenHandle is NULL, CheckTokenMembership uses the impersonation token of the calling thread. If the thread is not impersonating, the function duplicates the thread's primary token to create an impersonation token
Please advice masters....
Quote- we know _SID_IDENTIFIER_AUTHORITY = 6 bytes and SECURITY_NT_AUTHORITY = has a static value of 5
- I'am unsure what the resulting data structure then is - either: 7 bytes total ? //or// 5 x 6 byte array? //or// data initialized to 5 ?
If you check windows.inc, you will see that the original structure does not have a leading underscore and it's composed only from 6 bytes.
windows.inc :
SID_IDENTIFIER_AUTHORITY STRUCT
Value BYTE 6 dup(?)
SID_IDENTIFIER_AUTHORITY ENDS
To avoid some error messages while assembling the code, I preferred to redefine the structure. Honestly, I didn't bother much finding another solution.
IsUserAdmin.inc :
_SID_IDENTIFIER_AUTHORITY STRUCT
v1 db ?
v2 db ?
v3 db ?
v4 db ?
v5 db ?
v6 db ?
_SID_IDENTIFIER_AUTHORITY ENDS
SECURITY_NT_AUTHORITY is an equate used to initialize the original structure
SID_IDENTIFIER_AUTHORITYwindows.inc :
SECURITY_NT_AUTHORITY equ {0,0,0,0,0,5}
Quote- The original code has a byte (bool) variable "b" that only contains the value "TRUE" or "1" in the case we are testing for,
so actually we're only testing to see if the calling thread with the related user rights may create a token within the AdminGroup
- Are we really only using "b" to for-fill the constraints of the calling convention for the API ?
The value of b depends on the value returned by the function
AllocateAndInitializeSid :
https://msdn.microsoft.com/en-us/library/aa376389.aspx
The usage of the parameter IsMember is mandatory, it's enforced by MS plus
CheckTokenMembership depends on the value of the element IsMember :
BOOL WINAPI CheckTokenMembership(
_In_opt_ HANDLE TokenHandle,
_In_ PSID SidToCheck,
_Out_ PBOOL IsMember
);
- It's probably might also be dangerous to send ZERO instead of NULL - I'am just thinking of special cases where invoked
procedures check for zero / not zero - when converting example code to assembly in general
If we omit the semantical discussions on the pair of
ZERO \
NULL , there is absolutely no any danger. Again disregarding any semantics, your
NULL value will be converted to
ZEROs in the machine language. Not absolutely the same but this case reminds the usage of Masm high level constructs for procedural coding to "avoid" the jmp instruction. Be a purist or a practical coder, you end up with the jmp instructions. That's only what the processor understands.
You can replace the following line :
invoke CheckTokenMembership,0,AdminGroup,ADDR b
with this one :
invoke CheckTokenMembership,NULL,AdminGroup,ADDR b
Disassembling the object module with Agner Fog's objconv tool, you get the same result :
push offset b
push dword ptr [AdminGroup]
push 0
call _CheckTokenMembership@12
If TokenHandle is NULL, CheckTokenMembership uses the impersonation token of the calling thread.
That's the trick of that API function. A practical way to specify the impersonation token avoiding all the effort to deal with the other process management functions.
IsNTAdmin is in advpack.dll, works on Windows 10! Pass it two dwords of nothing and it'll return a non-zero if the "Current User" is Admin, meaning if you didn't run that app as Admin, you're not one. XP will let it go through if the account isn't a "Regular user" (who did that?!) and under Vista+, will return a non-zero only *if* the program was run elevated. It's what I've been using.
GuruSR.
IsNTAdmin looks like an "undocumented" API function.
https://source.winehq.org/WineAPI/IsNTAdmin.html
A quick example :
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\advpack.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\advpack.lib
includelib \masm32\lib\masm32.lib
.data
msg1 db 'The user is not an admin.',0,0,0,0,0,0,0
db 'The user is an admin.',0
.code
start:
invoke IsNTAdmin,0,NULL
shl eax,5
add eax,OFFSET msg1
invoke StdOut,eax
invoke ExitProcess,0
END start
Quote from: GuruSR on October 06, 2016, 12:50:10 PM
IsNTAdmin is in advpack.dll, works on Windows 10!
On Win7-64, IsNTAdmin uses advapi32.dll, but the result is the same. Both IsUserAnAdmin and IsNTAdmin are wrappers for CheckTokenMembership:
include \Masm32\MasmBasic\Res\JBasic.inc ; OPT_64 1 ; put 0 for 32 bit, 1 for 64 bit assembly
Init
Print Str$("IsUserAnAdmin\t%i\n", rv(IsUserAnAdmin)) ; uses shell32.dll SHTestTokenMembership -> Uses CheckTokenMembership
Inkey Str$("IsNTAdmin\t%i\n", rvd(IsNTAdmin, 0, 0)) ; uses advapi32.dll CheckTokenMembership
EndOfCode(32- and 64-bit exe attached; building the source requires MasmBasic (http://masm32.com/board/index.php?topic=94.0))
Quote from: jj2007 on October 07, 2016, 07:46:35 AM
On Win7-64, IsNTAdmin uses advapi32.dll, but the result is the same. Both IsUserAnAdmin and IsNTAdmin are wrappers for CheckTokenMembership:
But, IsNTAdmin is the only one that goes down to I believe, Windows 2000, maybe just to XP. It has a wider range of OS's, as it's been listed as being available (Undocumented as well) since 2001, IsUserAnAdmin is newer and isn't in 2000, not sure about XP.
GuruSR.