2012-02-15 1 views
6

권한 상승이 필요한 로컬 COM 서버를 생성 했으므로 승격되지 않은 프로세스 내부에서 인스턴스화해야합니다.COM Elevation Vista/Windows 7에서 Moniker가 서버를 승격하지 못했습니다.

MSDN's article on the COM elevation moniker을 사용하여 지정된 요구 사항에 따라 서버 클래스를 구성했습니다. 서버가 HKLM 하이브에 성공적으로 등록되었습니다.

코드 샘플 : 그것은 CoGetObject(PWideChar(sMonikerName), @rBindOpts, IID, PInterface)에 관해서

procedure CoCreateInstanceAsAdmin(const Handle: HWND; 
     const ClassID, IID: TGuid; PInterface: PPointer); 
var 
    rBindOpts: TBindOpts3; 
    sMonikerName: WideString; 
    iRes: HRESULT; 
begin 
    ZeroMemory(@rBindOpts, Sizeof(TBindOpts3)); 
    rBindOpts.cbStruct := Sizeof(TBindOpts3); 
    rBindOpts.hwnd := Handle; 
    rBindOpts.dwClassContext := CLSCTX_LOCAL_SERVER; 
    sMonikerName := 'Elevation:Administrator!new:' + GUIDToString(ClassID); 
    iRes := CoGetObject(PWideChar(sMonikerName), @rBindOpts, IID, PInterface); 
    OleCheck(iRes); 
end; 

class function CoIMyServer.Create: IMyServer; 
begin 
    CoCreateInstanceAsAdmin(HInstance, CLASS_IMyServer, IMyServer, @Result); 
end; 

는 내가 UAC 화면을 얻을 관리자로 서버를 실행 확인합니다. 그러나 OleCheck(iRes)은 "요청한 작업에 권한 상승이 필요합니다"오류를 반환합니다.

that article 나는 "Over-The-Shoulder (OTS) Elevation"에 대해 읽었습니다.

승격되지 않은 프로세스에서 내 서버 인스턴스를 사용할 수있는 유일한 방법입니까? 그렇다면 서버에서 언제 CoInitializeSecurity을 호출해야합니까?


전체 등록 정보

HKLM\SOFTWARE\Wow6432Node\Classes\CLSID 
    {MyServer CLSID} 
     (Default) = IMyServer Object 
     LocalizedString = @C:\Program Files (x86)\MyServer\MyServer.exe,-15500 
    Elevation 
     Enabled = 0x000001 (1) 
    LocalServer32 
     (Default) = C:\PROGRA~2\MyServer\MYSERVER.EXE 
    ProgID 
     (Default) = uMyServer.IMyServer 
    TypeLib 
     (Default) = {TypeLib GUID} 
    Version 
     (Default) = 1.0 

HKLM\SOFTWARE\Wow6432Node\Classes\Interface 
    {GUID of IID_IMyServer} 
     (Default) = IMyServer 
    ProxyStubClsid32 
     (Default) = {Some GUID} 
    TypeLib 
     (Default) = {TypeLib GUID} 
     Version = 1.0 

위의 서버를 등록한 후 내 레지스트리에 존재하는 유일한 항목입니다. 내가 사용하려고 모두 동일한 AppID가 GUID으로

function GetSecurityDescriptor(const lpszSDDL: LPWSTR; out pSD: PSecurityDescriptor): Boolean; 
begin 
    Result := ConvertStringSecurityDescriptorToSecurityDescriptorW(lpszSDDL, SDDL_REVISION_1, 
    pSD, nil); 
end; 

function GetLaunchActPermissionsWithIL(out pSD: PSecurityDescriptor): Boolean; 
var 
    lpszSDDL: LPWSTR; 
begin 
    // Allow World Local Launch/Activation permissions. Label the SD for LOW IL Execute UP 
    lpszSDDL := 'O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)'; 
    Result := GetSecurityDescriptor(lpszSDDL, pSD); 
end; 

function GetAccessPermissionsForLUAServer(out pSD: PSecurityDescriptor): Boolean; 
var 
    lpszSDDL: LPWSTR; 
begin 
    // Local call permissions to IU, SY 
    lpszSDDL := 'O:BAG:BAD:(A;;0x3;;;IU)(A;;0x3;;;SY)'; 
    Result := GetSecurityDescriptor(lpszSDDL, pSD); 
end; 

function SetAccessPermissions(hAppKey: HKEY; pSD: PSECURITY_DESCRIPTOR): Boolean; 
var 
    dwLen: DWORD; 
    iRes: LONG; 
begin 
    dwLen := GetSecurityDescriptorLength(pSD); 
    iRes := RegSetValueExA(hAppKey, 'AccessPermission', 0, REG_BINARY, pSD, dwLen); 
    Result := iRes = ERROR_SUCCESS; 
end; 

function SetLaunchActPermissions(hAppKey: HKEY; pSD: PSECURITY_DESCRIPTOR): Boolean; 
var 
    dwLen: DWORD; 
    iRes: LONG; 
begin 
    dwLen := GetSecurityDescriptorLength(pSD); 
    iRes := RegSetValueExA(hAppKey, 'LaunchPermission', 0, REG_BINARY, pSD, dwLen); 
    Result := iRes = ERROR_SUCCESS; 
end; 

procedure Initialize; 
var 
    pSD: PSecurityDescriptor; 
    sSubKey: WideString; 
    hAppKey: HKEY; 
begin 
    sSubKey := 'AppID\{GUID}'; 
    RegOpenKeyW(HKEY_CLASSES_ROOT, PWideChar(sSubKey), hAppKey); 
    if GetAccessPermissionsForLUAServer(pSD) then 
    if not SetAccessPermissions(hAppKey, pSD) then 
     raise Exception.Create(Format('Access permissions aren''t set. System error: %d', 
     [GetLastError()])); 

    pSD := nil; 
    if GetLaunchActPermissionsWithIL(pSD) then 
    if not SetLaunchActPermissions(hAppKey, pSD) then 
     raise Exception.Create(Format('Launch permissions aren''t set. System error: %d', 
     [GetLastError()])); 
end; 

initialization 
    TAutoObjectFactory.Create(ComServer, TMyServer, Class_IMyServer, 
    ciMultiInstance, tmApartment); 
    Initialize; 

:


추가적인 세부 사항

성공은 암시 적으로 다음 코드를 사용하여 조언으로 점심 권한을 설정 + CoInitializeSecurity()를 호출하지 않고 시도 내 서버 인터페이스의 CLSID GUID와 새로 생성 된 GUID : 결과가 동일합니다. AccessPermissionLaunchPermission 값이 서버 등록 후 지정된 위치에 나타납니다.

또한 시도 :

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\MyServer.exe] 
@="MyServer" 
"AppID"="{My GUID}" 
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\{My GUID}] 
@="MyServer" 
"ROTFlags"=dword:00000001 
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{My GUID}] 
@="MyServer Object" 
"AppID"="{My GUID}" 
:

  • 64 비트 응용 프로그램으로 내가 수동으로 만든

추가 레지스트리 키/값을 서버에있는 건물 APPID 키

  • ROTFlags = 1 지정
  • +0

    정말로 'HKEY_CLASSES_ROOT'에 직접 쓰지 말아야합니다. 읽기에는 괜찮지 만 쓰기를 위해서는'HKEY_LOCAL_MACHINE \ Software \ Classes'를 사용해야합니다. MSDN은 그만큼 말한다. 그 외에도'CoInitializeSecurity()'를 어디에서 어떻게 호출합니까? –

    +0

    레지스트리 키에 대해 확인하십시오. 그것을 수정했습니다. "Over-The-Shoulder (OTS) Elevation"섹션에 따르면'CoInitializeSecurity()'는 암묵적으로 호출됩니다 ('SetAccessPermissions' 코드로 예제를 보시기 바랍니다). – AlexeyDaryin

    +0

    아직 명시 적으로 호출 해 보셨습니까? –

    답변

    7

    실수로 한 가지 실수는 RTL의 글로바 l HInstance 여기서 CoGetObject()HWND을 대신 인식합니다. HINSTANCE 핸들이 유효한 HWND 핸들이 아닙니다. 예를 들어 Handle 속성이 TFormHWND을 사용하거나 Elevation Moniker가 적합한 창을 선택하게하려면 0을 지정해야합니다.

    ERROR_ELEVATION_REQUIRED 반환 값은 COM 등록이 불완전한 것 같습니다.실제로 레지스트리에 저장되어있는 전체 등록 세부 정보를 표시하십시오 (코드가 저장하는 것으로 생각하는 것이 아니라 레지스트리가 실제로 저장하고있는 것).

    CoInitializeSecurity()은 서버 프로세스가 실행될 때 호출되어야합니다.

    +0

    레미, 고마워. 'HInstance' 변수로 문제를 해결했습니다. 첫 번째 게시물에 등록 세부 정보를 제공했습니다. – AlexeyDaryin

    +0

    64 비트 OS에서 실행중인 32 비트 COM 서버를 만들었습니다. 'Wow6432Node' 트리 아래에 등록되지 않도록 COM 서버의 64 비트 버전을 만들려고 했습니까? 그 외에도'ROTFlags' 값을 등록에 추가하려고 했습니까? 이 기사의 '상승 된 서버 및 ROT 등록'섹션을 참조하십시오. 마지막으로, 귀하의 클라이언트 응용 프로그램이 낮은 무결성 수준에서 실행되고 있습니까? 그렇다면 기사의 'COM 권한 및 필수 액세스 레이블'섹션과 'CoCreateInstance and Integrity Levels'섹션을 참조하십시오. –

    +0

    원본 게시물에 세부 정보를 추가했습니다. 모든 조언을 적용하려고했지만 결과는 바뀌지 않았습니다. 여전히 'ERROR_ELEVATION_REQUIRED'이 (가) 있습니다. – AlexeyDaryin

    관련 문제