// 前一段时间一个朋友让我帮忙写一个的程序演示CreateProcessAsUser的用法,我写完以后运行,
// 发现2K/XP/2003系统下居然默认把Administrator的SeTcbPrivilege权限去掉了, 而且SDK提供的API没有添加这个权限的功能,
// shit, 最后只好把功能写到了一个服务里. 颇为不爽
// 今天有了时间,整理了思路,准备绕一个弯子,把Administrator的SeTcbPribilege权限打开。
// 当然这样的系统含有一定的安全隐患,但是真的被人利用了其他未公开的Bugs,这个隐患又算得了什么呢。。。
//
// 代码很简单,有兴趣可以看看。运行这个程序你必须有管理员权限,如果要起作用需要重新登陆一次,唉,Windows。。。。
// 废话少说,goto code
//
// Coder Jozu
////////////////////////////////////////////////////////////////////
//
#ifndef UNICODE
#define UNICODE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <Ntsecapi.h>
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif
#ifdef _DEBUG
#define JASSERT(x) printf x
#else
#define JASSERT(x)
#endif
#define RET_OK 1
#define RET_ERR 2
#define RET_UKN 0
#define MAX_NAME_LEN 200
//////////////////////////////////////////////////////////////////////////
void
InitUnicodeString( OUT PLSA_UNICODE_STRING LsaUnicodeString, IN LPWSTR pwszString)
{
memset(LsaUnicodeString, 0, sizeof(LsaUnicodeString));
LsaUnicodeString->Length = wcslen(pwszString) * sizeof(WCHAR);
LsaUnicodeString->MaximumLength = LsaUnicodeString->Length + sizeof(UNICODE_NULL);
LsaUnicodeString->Buffer = pwszString;
}
//////////////////////////////////////////////////////////////////////////
LSA_HANDLE
WINAPI
OpenPolicy(DWORD DesiredAccess, LPWSTR ServerName)
{
LSA_HANDLE PolicyHandle = NULL;
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
LSA_UNICODE_STRING ServerNameString;
NTSTATUS Status;
memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
InitUnicodeString(&ServerNameString, ServerName);
Status = LsaOpenPolicy( &ServerNameString,
&ObjectAttributes,
DesiredAccess,
&PolicyHandle);
if(Status != STATUS_SUCCESS)
{
JASSERT(("OpenPolicy->LsaOpenPolicy error %X\n", Status));
}
return PolicyHandle;
}
//////////////////////////////////////////////////////////////////////////
BOOL
WINAPI
GetAccountSid(LPTSTR AccountName,
PSID *Sid)
{
PSID pSID = NULL;
DWORD cbSid = 0;
LPTSTR DomainName = NULL;
DWORD cbDomainName = 0;
SID_NAME_USE SIDNameUse;
BOOL bDone = FALSE;
__try
{
if(!LookupAccountName(NULL, // we only concertrate local machine.
AccountName,
pSID,
&cbSid,
DomainName,
&cbDomainName,
&SIDNameUse))
{
pSID = (PSID)malloc(cbSid);
DomainName = (LPTSTR)malloc(cbDomainName * sizeof(TCHAR));
if(!pSID || !DomainName)
{
JASSERT(("Not enough memory! failed...\n"));
__leave;
}
if(!LookupAccountName(NULL,
AccountName,
pSID,
&cbSid,
DomainName,
&cbDomainName,
&SIDNameUse))
{
JASSERT(("Not enough memory! failed...\n"));
__leave;
}
bDone = TRUE;
}
}
__finally
{
if(DomainName)
free(DomainName);
if(!bDone && pSID)
free(pSID);
}
if(bDone)
*Sid = pSID;
return bDone;
}
//////////////////////////////////////////////////////////////////////////
BOOL
WINAPI
AdjustUserPolicy(LSA_HANDLE PolicyHandle,
PSID pAccountSid,
LPWSTR lpwSePrivilege,
BOOL fRemove)
{
LSA_UNICODE_STRING SePrivilegeString;
NTSTATUS Status;
InitUnicodeString(&SePrivilegeString, lpwSePrivilege);
if(fRemove)
{
Status = LsaRemoveAccountRights(PolicyHandle,
pAccountSid,
FALSE,
&SePrivilegeString,
1);
}
else
{
Status = LsaAddAccountRights(PolicyHandle,
pAccountSid,
&SePrivilegeString,
1);
}
return (Status == STATUS_SUCCESS);
}
//////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv)
{
LSA_HANDLE PolicyHandle = NULL;
PSID pSid = NULL;
DWORD cbAccountName = MAX_NAME_LEN;
TCHAR AccountName[MAX_NAME_LEN];
TCHAR wComputerName[] = L"";
int nRet = RET_ERR;
__try
{
if(!GetUserName(AccountName, &cbAccountName))
{
printf("ft..... How long are your name?\n");
__leave;
}
PolicyHandle = OpenPolicy(POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, wComputerName);
if(!PolicyHandle)
{
printf("OpenPolicy return NULL\n");
__leave;
}
if(!GetAccountSid(AccountName, &pSid))
{
printf("GetAccountSid return false\n");
__leave;
}
if(!AdjustUserPolicy(PolicyHandle, pSid, SE_TCB_NAME, FALSE))
{
printf("AdjustUserPolicy return false\n");
__leave;
}
nRet = RET_OK;
}
__finally
{
if(pSid)
free(pSid);
if(PolicyHandle)
LsaClose(PolicyHandle);
}
return nRet;
}