상당히 많은 시간을 날렸네요.. ㅜㅜ

이전 내용하고 비슷한데요..
이전에 서비스계정에 이름은 있고, 암호는 없는 사용자를 처리할 때는

HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Lsa
의 limitblankpassworduse 값을 1로 변경하면서 마무리 지었습니다.
윈도우즈 XP프로와, 서버계열에서는 아주 잘되던데..

윈도우즈 XP 홈에서는 저기까지는 잘되는데 나머지 난관이 발생하더군요..
사용자 계정 자체에 서비스로 로그온할 수 있는 보안 권한을 상승 시켜주어야 했습니다.

계정과 암호 (비어있을 경우) 정상적인데도 불구하고 서비스가 시작되지 않더군요.
서비스 관리자를 열어서 다시 서비스의 로그온 정보에서 암호를 지워주고 시작을
누르면 계정을 "서비스로 로그온 권한을 상승하였습니다." 라는 메시지가 나오면서
시작이 잘되더군요.

문제는 이걸 프로그램적으로 자동화 시켜야한다는게 문제였는데.. ^^;


#include <Ntsecapi.h>
#define TARGET_SYSTEM_NAME L"."
LSA_HANDLE GetPolicyHandle()
{
 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
 WCHAR SystemName[] = TARGET_SYSTEM_NAME;
 USHORT SystemNameLength;
 LSA_UNICODE_STRING lusSystemName;
 NTSTATUS ntsResult;
 LSA_HANDLE lsahPolicyHandle;
 
 // Object attributes are reserved, so initialize to zeros.
 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
 
 //Initialize an LSA_UNICODE_STRING to the server name.
 SystemNameLength = wcslen(SystemName);
 lusSystemName.Buffer = SystemName;
 lusSystemName.Length = SystemNameLength * sizeof(WCHAR);
 lusSystemName.MaximumLength = (SystemNameLength+1) * sizeof(WCHAR);
 
 // Get a handle to the Policy object.
 ntsResult = LsaOpenPolicy(
        &lusSystemName,    //Name of the target system.
        &ObjectAttributes, //Object attributes.
        POLICY_ALL_ACCESS, //Desired access permissions.
        &lsahPolicyHandle  //Receives the policy handle.
  );
 
 if (ntsResult != ERROR_SUCCESS)
  return NULL;
 return lsahPolicyHandle;
}

BOOL InitLsaString(PLSA_UNICODE_STRING pLsaString, LPCWSTR pwszString)
{
  DWORD dwLen = 0;

  if (NULL == pLsaString)
      return FALSE;

  if (NULL != pwszString)
  {
      dwLen = wcslen(pwszString);
      if (dwLen > 0x7ffe)   // String is too large
          return FALSE;
  }

  // Store the string.
  pLsaString->Buffer = (WCHAR *)pwszString;
  pLsaString->Length =  (USHORT)dwLen * sizeof(WCHAR);
  pLsaString->MaximumLength= (USHORT)(dwLen+1) * sizeof(WCHAR);

  return TRUE;
}

BOOL GetUserSID(PSID sid, const char* username)
{
    DWORD SidBufSz;
    char DomainNameBuf[256] = {0};
    DWORD DomainNameBufSz;
    SID_NAME_USE SNU;
    DomainNameBufSz = 256;

    if(!LookupAccountName(NULL, username, sid, &SidBufSz, DomainNameBuf, &DomainNameBufSz, &SNU))
        return FALSE;
 return TRUE;
}

BOOL AddPrivileges(PSID AccountSID, LSA_HANDLE PolicyHandle)
{
 LSA_UNICODE_STRING lucPrivilege;
 NTSTATUS ntsResult;
 
 // Create an LSA_UNICODE_STRING for the privilege names.
 if (!InitLsaString(&lucPrivilege, L"SeServiceLogonRight"))
  return FALSE;
 
 ntsResult = LsaAddAccountRights(
  PolicyHandle,  // An open policy handle.
  AccountSID,    // The target SID.
  &lucPrivilege, // The privileges.
  1              // Number of privileges.
  );               

 if (ntsResult == ERROR_SUCCESS)
  return TRUE;
 else
  return FALSE;
}

사용법은 아래와 같습니다.
 LSA_HANDLE Policy = GetPolicyHandle();
 BYTE buffer[1024] = {0};
 PSID sid = (PSID)buffer;
 if(GetUserSID(sid, "까마귀"))
  AddPrivileges(sid, Policy);

위와 같은 방법으로 사용자 계정에다가 직접 SeServiceLogonRight 권한을 넣어
주는 방법으로 해결했습니다.

자료가 없어서 헤딩좀 했는데.. 도움이 되시기를...

+ Recent posts