前言
在逆向一个专杀, MFC Dialog的程序.
在CxxWinApp::InitInstance中看到, 在增加权限之前, 先判断自己是否有管理员权限.
这代码MS都给了, 不用去逆向了, 找了一段MS的例子.
MS的例子中, 给了如何判断当前程序有管理员权限, 如何判断本程序是服务.
经过比对, 逆向出来的判断管理员身份的函数,更有实用性. 可以用在其他工程里面.
MS的例子还要改改, 将报错代码拿掉, 换成错误码.
记录
逆向出来的函数
BOOL isAdministrator()
{
BOOL bRc = FALSE;
BOOL bTmp = FALSE;
SID_IDENTIFIER_AUTHORITY pIdentifierAuthority = { SECURITY_NT_AUTHORITY };
PSID pSid = NULL;
HANDLE TokenHandle = NULL;
DWORD ReturnLength;
UCHAR TokenInformation[1024];
PTOKEN_GROUPS Groups = (PTOKEN_GROUPS)TokenInformation;
DWORD dwIndex = 0;
bRc = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY/*8u*/, &TokenHandle);
if (bRc) {
bTmp = GetTokenInformation(TokenHandle, TokenGroups, &TokenInformation, sizeof(TokenInformation), &ReturnLength);
CloseHandle(TokenHandle);
if (bTmp) {
bRc = AllocateAndInitializeSid(
&pIdentifierAuthority,
2u,
SECURITY_BUILTIN_DOMAIN_RID/*0x20u*/,
DOMAIN_ALIAS_RID_ADMINS/*0x220u*/,
0,
0,
0,
0,
0,
0,
&pSid);
if (bRc) {
bTmp = FALSE;
if (TokenInformation > 0) {
for (dwIndex = 0; dwIndex < Groups->GroupCount; dwIndex++) {
if (EqualSid(pSid, Groups->Groups[dwIndex].Sid)) {
bTmp = TRUE;
break;
}
}
}
FreeSid(pSid);
bRc = bTmp;
}
} else {
bRc = FALSE;
}
}
return bRc;
}
MS的例子
/*-------------------------------------------------------------------------
*
* security.c
* Microsoft Windows Win32 Security Support Functions
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL$
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
/*
* Returns nonzero if the current user has administrative privileges,
* or zero if not.
*/
int pgwin32_is_admin(void) {
HANDLE AccessToken;
UCHAR InfoBuffer[1024];
PTOKEN_GROUPS Groups = (PTOKEN_GROUPS)InfoBuffer;
DWORD InfoBufferSize;
PSID AdministratorsSid;
PSID PowerUsersSid;
SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };
UINT x;
BOOL success;
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&AccessToken))
ereport(FATAL,
(errmsg_internal("Failed to open process token: %i",(int)GetLastError())));
if (!GetTokenInformation(AccessToken,TokenGroups,InfoBuffer,
1024, &InfoBufferSize))
ereport(FATAL,
(errmsg_internal("Failed to get token information: %i",(int)GetLastError())));
CloseHandle(AccessToken);
if(!AllocateAndInitializeSid(&NtAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
0,&AdministratorsSid))
ereport(FATAL,
(errmsg_internal("Failed to get SID for Administrators group: %i",(int)GetLastError())));
if (!AllocateAndInitializeSid(&NtAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
0, &PowerUsersSid))
ereport(FATAL,
(errmsg_internal("Failed to get SID for PowerUsers group: %i",(int)GetLastError())));
success = FALSE;
for (x=0; x<Groups->GroupCount; x++)
{
if( EqualSid(AdministratorsSid, Groups->Groups[x].Sid) ||
EqualSid(PowerUsersSid, Groups->Groups[x].Sid))
{
success = TRUE;
break;
}
}
FreeSid(AdministratorsSid);
FreeSid(PowerUsersSid);
return success;
}
/*
* We consider ourselves running as a service if one of the following is
* true:
*
* 1) We are running as Local System (only used by services)
* 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
* process token by the SCM when starting a service)
*
* Return values:
* 0 = Not service
* 1 = Service
* -1 = Error (can't ereport error, this is called too early)
*/
int pgwin32_is_service(void) {
static int _is_service = -1;
HANDLE AccessToken;
UCHAR InfoBuffer[1024];
PTOKEN_GROUPS Groups = (PTOKEN_GROUPS)InfoBuffer;
PTOKEN_USER User = (PTOKEN_USER)InfoBuffer;
DWORD InfoBufferSize;
PSID ServiceSid;
PSID LocalSystemSid;
SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };
UINT x;
/* Only check the first time */
if (_is_service != -1)
return _is_service;
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&AccessToken)) {
fprintf(stderr,"Failed to open process token: %i\n",(int)GetLastError());
return -1;
}
/* First check for local system */
if (!GetTokenInformation(AccessToken,TokenUser,InfoBuffer,1024,&InfoBufferSize)) {
fprintf(stderr,"Failed to get token information: %i\n",(int)GetLastError());
return -1;
}
if (!AllocateAndInitializeSid(&NtAuthority,1,
SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,
&LocalSystemSid)) {
fprintf(stderr,"Failed to get SID for local system account\n");
CloseHandle(AccessToken);
return -1;
}
if (EqualSid(LocalSystemSid, User->User.Sid)) {
CloseHandle(AccessToken);
FreeSid(LocalSystemSid);
_is_service = 1;
return _is_service;
}
FreeSid(LocalSystemSid);
/* Now check for group SID */
if (!GetTokenInformation(AccessToken,TokenGroups,InfoBuffer,1024,&InfoBufferSize)) {
fprintf(stderr,"Failed to get token information: %i\n",(int)GetLastError());
return -1;
}
if (!AllocateAndInitializeSid(&NtAuthority,1,
SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
&ServiceSid)) {
fprintf(stderr,"Failed to get SID for service group\n");
CloseHandle(AccessToken);
return -1;
}
for (x = 0; x < Groups->GroupCount; x++)
{
if (EqualSid(ServiceSid, Groups->Groups[x].Sid))
{
_is_service = 1;
break;
}
}
FreeSid(ServiceSid);
CloseHandle(AccessToken);
if (_is_service == -1)
_is_service = 0;
return _is_service;
}