Author Topic: API call to check if program is being run as Administrator  (Read 8808 times)

mineiro

  • Member
  • ***
  • Posts: 450
Re: API call to check if program is being run as Administrator
« Reply #15 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
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

Vortex

  • Member
  • *****
  • Posts: 1987
Re: API call to check if program is being run as Administrator
« Reply #16 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

Raistlin

  • Member
  • ***
  • Posts: 494
Re: API call to check if program is being run as Administrator
« Reply #17 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....
Are you pondering what I'm pondering? It's time to take over the world ! - let's use ASSEMBLY...

Vortex

  • Member
  • *****
  • Posts: 1987
Re: API call to check if program is being run as Administrator
« Reply #18 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.

GuruSR

  • Member
  • **
  • Posts: 116
  • Assembler (6500, 68k, Intel), C(all), VB6, no .Net
Re: API call to check if program is being run as Administrator
« Reply #19 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.
Learned 68k Motorola Asm instruction set in 30 minutes on the way to an Amiga Developer's Forum meeting.
Following week wrote a kernel level memory pool manager in 68k assembler for fun.

Vortex

  • Member
  • *****
  • Posts: 1987
Re: API call to check if program is being run as Administrator
« Reply #20 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

jj2007

  • Member
  • *****
  • Posts: 9633
  • Assembler is fun ;-)
    • MasmBasic
Re: API call to check if program is being run as Administrator
« Reply #21 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)

GuruSR

  • Member
  • **
  • Posts: 116
  • Assembler (6500, 68k, Intel), C(all), VB6, no .Net
Re: API call to check if program is being run as Administrator
« Reply #22 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.
Learned 68k Motorola Asm instruction set in 30 minutes on the way to an Amiga Developer's Forum meeting.
Following week wrote a kernel level memory pool manager in 68k assembler for fun.