The MASM Forum

General => The Campus => Topic started by: Don57 on October 08, 2012, 07:37:55 AM

Title: API call to check if program is being run as Administrator
Post by: Don57 on October 08, 2012, 07:37:55 AM
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.
Title: Re: API call to check if program is being run as Administrator
Post by: qWord on October 08, 2012, 08:29:31 AM
The following function returns a nonzero value, if the process runs with administrator rights:
Code: [Select]
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
Title: Re: API call to check if program is being run as Administrator
Post by: farrier on October 08, 2012, 09:26:55 AM

You can set your program--thru the manifest--to force admin rights:

Code: [Select]
<?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
Title: Re: API call to check if program is being run as Administrator
Post by: Don57 on October 08, 2012, 09:49:56 AM
Thanks for the help.  :t
Title: Re: API call to check if program is being run as Administrator
Post by: hfheatherfox07 on October 11, 2012, 06:17:38 AM
The following function returns a nonzero value, if the process runs with administrator rights:
Code: [Select]
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 ?
Title: Re: API call to check if program is being run as Administrator
Post by: clamicun on August 17, 2016, 10:06:19 PM
JJ,
bom dia.
As always, a very precise answer from you.
Thanks a lot.
Mic
Title: Re: API call to check if program is being run as Administrator
Post by: mineiro on August 17, 2016, 11:27:48 PM
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.
Title: Re: API call to check if program is being run as Administrator
Post by: Vortex on August 18, 2016, 03:40:53 AM
The IsUserAnAdmin API function :

https://msdn.microsoft.com/en-us/library/windows/desktop/bb776463%28v=vs.85%29.aspx

A quick example :

Code: [Select]
.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 :

Code: [Select]
@IsUserAnAdmin.exe

@IF %ERRORLEVEL% == 1 ( echo The user is an administrator. ) ELSE ( echo The user is not an administrator. )
Title: Re: API call to check if program is being run as Administrator
Post by: jj2007 on August 18, 2016, 05:06:59 AM
End of client support: Windows Vista

But it works on Win7-64 ;)
Title: Re: API call to check if program is being run as Administrator
Post by: clamicun on August 18, 2016, 10:49:54 PM
Many thanks to everybody who helped me.

mineiro, voce e Mineiro ?
Minha esposa e de Almenara/MG
Title: Re: API call to check if program is being run as Administrator
Post by: clamicun on August 18, 2016, 11:48:32 PM
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.
Title: Re: API call to check if program is being run as Administrator
Post by: Vortex on August 19, 2016, 03:22:55 AM
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

Title: Re: API call to check if program is being run as Administrator
Post by: jj2007 on August 19, 2016, 03:36:23 AM
but it works on Windows 7 :

Not surprisingly, it works also on Windows 10. Microsoft doesn't risk a shitstorm...
Title: Re: API call to check if program is being run as Administrator
Post by: Vortex on August 19, 2016, 04:35:54 AM
This application gets the username with the API function GetUserName and compares it against the list of the members of the Administrators group :

Code: [Select]
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 :

Code: [Select]
@IsUserAdmin.exe

@IF %ERRORLEVEL% == 1 ( echo The user is an administrator. ) ELSE ( echo The user is not an administrator. )
Title: Re: API call to check if program is being run as Administrator
Post by: Zen on August 19, 2016, 04:47:04 AM
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
Quote
Super 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.
Title: Re: API call to check if program is being run as Administrator
Post by: mineiro on August 19, 2016, 06:04:37 AM
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
Title: Re: API call to check if program is being run as Administrator
Post by: Vortex on August 26, 2016, 06:25:16 AM
MSDN code example converted to asm :

Code: [Select]
; 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
Title: Re: API call to check if program is being run as Administrator
Post by: Raistlin on August 29, 2016, 04:24:29 PM
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:
Code: [Select]
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:
Code: [Select]
invoke  CheckTokenMembership,0,AdminGroup,ADDR b
Microsoft:
Code: [Select]
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....
Title: Re: API call to check if program is being run as Administrator
Post by: Vortex on August 29, 2016, 07:06:43 PM
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 :

Code: [Select]
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 :

Code: [Select]
_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_AUTHORITY

windows.inc :

Code: [Select]
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 :

Code: [Select]
BOOL WINAPI CheckTokenMembership(
  _In_opt_ HANDLE TokenHandle,
  _In_     PSID   SidToCheck,
  _Out_    PBOOL  IsMember
);

Code: [Select]
- 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 :

Code: [Select]
invoke  CheckTokenMembership,0,AdminGroup,ADDR b
with this one :

Code: [Select]
invoke  CheckTokenMembership,NULL,AdminGroup,ADDR b
Disassembling the object module with Agner Fog's objconv tool, you get the same result :

Code: [Select]
push    offset b
push    dword ptr [AdminGroup]
push    0
call    _CheckTokenMembership@12

Code: [Select]
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.
Title: Re: API call to check if program is being run as Administrator
Post by: GuruSR on October 06, 2016, 12:50:10 PM
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.
Title: Re: API call to check if program is being run as Administrator
Post by: Vortex on October 07, 2016, 04:41:07 AM
IsNTAdmin looks like an "undocumented" API function.

https://source.winehq.org/WineAPI/IsNTAdmin.html

A quick example :

Code: [Select]
.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
Title: Re: API call to check if program is being run as Administrator
Post by: jj2007 on October 07, 2016, 07:46:35 AM
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))
Title: Re: API call to check if program is being run as Administrator
Post by: GuruSR on October 07, 2016, 03:26:02 PM
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.