Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 7개 있습니다.)
(시리즈 글이 2개 있습니다.)
VC++: 143. ionescu007/lxss github repo에 공개된 lxssmanager.dll의 CLSID_LxssUserSession/IID_ILxssSession 사용법
; https://www.sysnet.pe.kr/2/0/12676

VC++: 144. 역공학을 통한 lxssmanager.dll의 ILxssSession 사용법 분석
; https://www.sysnet.pe.kr/2/0/12677




ionescu007/lxss github repo에 공개된 lxssmanager.dll의 CLSID_LxssUserSession/IID_ILxssSession 사용법

아래의 글을 쓸 때까지만 해도,

Wslhub.Sdk 사용으로 알아보는 CoInitializeSecurity 사용 제약
; https://www.sysnet.pe.kr/2/0/12665

lxssmanager.dll에서 제공하는 CLSID_LxssUserSession/IID_ILxssSession COM 개체가 공개된 건 줄 알았습니다. ^^; 하지만, 비공개였고 그나마 찾은 자료는 github의 개인 repo였습니다.

ionescu007/lxss
; https://github.com/ionescu007/lxss

lxss/inc/lxssmanager.h
; https://github.com/ionescu007/lxss/blob/master/inc/lxssmanager.h

lxss/lxlaunch/lxlaunch.cpp
; https://github.com/ionescu007/lxss/blob/master/lxlaunch/lxlaunch.cpp

wslbridge2/src/LxssUserSession.hpp
; https://github.com/Biswa96/wslbridge2/blob/master/src/LxssUserSession.hpp

저 repo의 저작자는 나름의 역공학을 통해 그 결과를 공유해 주고 있는데요, 해당 자료를 COM 방식으로 정리하면 다음과 같이 요약될 수 있습니다.

#pragma once

#include <initguid.h>

DEFINE_GUID(CLSID_LxssManager, 0x4F476546, 0xB412, 0x4579, 0xB6, 0x4C, 0x12, 0x3D, 0xF3, 0x31, 0xE3, 0xD6);

typedef struct _LXSS_STD_HANDLE
{
    ULONG Handle;
    BOOLEAN Pipe;
} LXSS_STD_HANDLE, * PLXSS_STD_HANDLE;

typedef struct _LXSS_CONSOLE_DATA_V2
{
    ULONG ConsoleHandle;
} LXSS_CONSOLE_DATA_V2, * PLXSS_CONSOLE_DATA_V2;

typedef struct _LXSS_CONSOLE_DATA
{
    ULONG InputHandle;
    ULONG OutputHandle;
    ULONG ControlHandle;
    USHORT Width;
    USHORT Height;
} LXSS_CONSOLE_DATA, * PLXSS_CONSOLE_DATA;

typedef struct _LXSS_STD_HANDLES
{
    LXSS_STD_HANDLE StdIn;
    LXSS_STD_HANDLE StdOut;
    LXSS_STD_HANDLE StdErr;
} LXSS_STD_HANDLES, * PLXSS_STD_HANDLES;

interface ILxInstance;

MIDL_INTERFACE("536A6BCF-FE04-41D9-B978-DCACA9A9B5B9") ILxssSession : IUnknown
{
    STDMETHOD(GetCurrentInstance)(ILxInstance** pInstanceOut);
    STDMETHOD(StartDefaultInstance)(_In_ const IID& InstanceIid, _Out_ PVOID* InstanceOut);
    STDMETHOD(SetState)(/* unknown */);
    STDMETHOD(QueryState)(/* unknown */);
    STDMETHOD(InitializeFileSystem)(/* unknown */);
    STDMETHOD(Destroy)(/* unknown */);
};

MIDL_INTERFACE("8f9e8123-58d4-484a-ac25-7ef7d5f7448f") ILxInstance : IUnknown
{
    STDMETHOD(GetConfiguration)(/* unknown */);
    STDMETHOD(GetId)(/* unknown */);
    STDMETHOD(QueryState)(/* unknown */);
    STDMETHOD(SetState)(/* unknown */);
    STDMETHOD(CreateLxProcess)(_In_ PCCH CommandLine,
        _In_ ULONG ArgumentCount,
        _In_ PCCH* Arguments,
        _In_ ULONG EnvironmentCount,
        _In_ PCCH* Environment,
        _In_ PCCH CurrentDirectory,
        _In_ ULONG Flags,
        _In_ PLXSS_STD_HANDLES StdHandles,
        _In_ PLXSS_CONSOLE_DATA ConsoleData,
        _In_ ULONG Uid,
        _Out_ PULONG ProcessHandle);
    STDMETHOD(RegisterAdssBusServer)(_In_ PCCH ServerName, _Out_ PULONG ServerHandle);
    STDMETHOD(ConnectAdssBusServer)(/* unknown */);
    STDMETHOD(Destroy)(/* unknown */);
    STDMETHOD(GetState)(/* unknown */);
    STDMETHOD(StartSelf)(/* unknown */);
    STDMETHOD(StopSelf)(/* unknown */);
    STDMETHOD(GetSuspendState)(/* unknown */);
};

보는 바와 같이 저작자도 ILxssSession의 GetCurrentInstance, StartDefaultInstance 2개 함수와 ILxInstance의 CreateLxProcess, RegisterAdssBusServer 2개 함수에 대해서만 그 signature를 파악해낸 정도입니다.

어쨌든 이 정도만을 바탕으로 다음과 같이 테스트를 해볼 수 있는데,

#include <Windows.h>
#include <stdio.h>
#include "lxssmanager.h"

HRESULT OleMain();

int main()
{
    HRESULT hr = CoInitializeEx(nullptr, 0);
    if (hr != S_OK)
    {
        return 1;
    }

    hr = OleMain();

    CoUninitialize();

    return hr;
}

HRESULT OleMain()
{
    HRESULT hr = S_FALSE;

    hr = CoInitializeSecurity(nullptr,
        -1,
        nullptr,
        nullptr,
        RPC_C_AUTHN_LEVEL_DEFAULT,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        nullptr,
        EOAC_STATIC_CLOAKING,
        nullptr);

    if (hr != S_OK)
    {
        return hr;
    }

    ILxssSession* pSession = nullptr;
    ILxInsanace* pInstance = nullptr;

    do
    {
        hr = CoCreateInstance(CLSID_LxssManager, nullptr, CLSCTX_LOCAL_SERVER, 
            __uuidof(ILxssSession), (PVOID*)&pSession);
        if (hr != S_OK)
        {
            break;
        }

        printf("pSession == %p\n", pSession);

        hr = pSession->GetCurrentInstance(&pInstance);
        printf("GetCurrentInstance hr == %d(0x%x)\n", hr, hr);

        // -2147024891 == 0x80070005 E_ACCESSDENIED (Access is denied.)
        // -2147024894 == 0x80070002 (The system cannot find the file specified.)
        // -2147024809 == 0x80070057 (The parameter is incorrect.)
        // -2147220734 == 0x80040302

        hr = pSession->StartDefaultInstance(__uuidof(ILxInstance), (PVOID *)&pInstance);
        printf("StartDefaultInstance hr == %d(0x%x)\n", hr, hr);

        if (hr != S_OK)
        {
            break;
        }

    } while (false);

    if (pSession != nullptr)
    {
        pSession->Release();
    }

    if (pInstance != nullptr)
    {
        pInstance->Release();
    }

    return hr;
}

그런데 실제로 실행을 해보면 GetCurrentInstance는 0x80070057(E_INVALIDARG)을 반환하고, StartDefaultInstance 호출은 Get으로 받아온 인스턴스가 유효하지 않은 탓도 있겠지만 아예 crash가 발생합니다.

Faulting application name: ConsoleApplication1.exe, version: 0.0.0.0, time stamp: 0x60c9fe1d
Faulting module name: ntdll.dll, version: 10.0.19041.1023, time stamp: 0x7977b9de
Exception code: 0xc0000005
Fault offset: 0x00000000000a3ef0
Faulting process id: 0x4300
Faulting application start time: 0x01d762b478547e8a
Faulting application path: C:\temp\ConsoleApplication1\x64\Debug\ConsoleApplication1.exe
Faulting module path: C:\WINDOWS\SYSTEM32\ntdll.dll
Report Id: 7e85962d-3fa7-4bea-bd46-992aeee231e9
Faulting package full name: 
Faulting package-relative application ID: 

아마도 그때 당시에는 잘 동작했을지 모르겠지만 지금의 Windows 10에서는 오류가 발생하고 있습니다. 아쉽군요. ^^

(2023-10-20 업데이트) 해당 github의 저자가 작성한 코드도 참고해 보세요.

lxss/lxlaunch/lxlaunch.cpp
; https://github.com/ionescu007/lxss/blob/master/lxlaunch/lxlaunch.cpp


(첨부 파일은 이 글의 예제 코드를 포함합니다.)




이걸 테스트하면서 알게 된 사실이 하나 있는데요, 전에 CoInitializeSecurity가 다른 DLL을 로드하면서 자동 호출이 된다고 했었는데요,

별도 DLL에 포함된 타입을 STAThread Main 메서드에서 사용하는 경우 CoInitializeSecurity 자동 호출
; https://www.sysnet.pe.kr/2/0/12666

이와 유사하게 C++ 프로그램에서도 CoInitializeSecurity가 자동 호출되는 경우가 있었습니다. 재현은 다음과 같이 할 수 있는데요,

HRESULT hr = CoInitializeEx(nullptr, 0);

PVOID* pVoid;
hr = CoCreateInstance(CLSID_ShellDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown,
    (void**)&pVoid);

if (hr != S_OK)
{
    return;
}

hr = CoInitializeSecurity(nullptr,
    -1,
    nullptr,
    nullptr,
    RPC_C_AUTHN_LEVEL_DEFAULT,
    RPC_C_IMP_LEVEL_IMPERSONATE,
    nullptr,
    EOAC_STATIC_CLOAKING,
    nullptr);

// hr == 0x80010119 : Security must be initialized before any interfaces are marshalled or unmarshalled. It cannot be changed once initialized.
//       RPC_E_TOO_LATE (-2147417831) 

확실하게 파고들지는 않았지만, 아마도 CoCreateInstance 내부에서 호출이 되는 것 같습니다. 즉, CoInitializeEx를 호출했다고 하면 COM을 사용하겠다는 의도이고 그럼 당연히 개체 생성을 했을 것이므로 CoCreateInstance를 호출했을 것입니다.

결국 COM Apartment 초기화가 된 스레드를 사용한 응용 프로그램이 있다면 높은 확률로 CoInitializeSecurity API가 호출되었을 것입니다.




C# - CoCreateInstance 관련 Inteop 오류 정리
; https://www.sysnet.pe.kr/2/0/12678

Wslhub.Sdk 사용으로 알아보는 CoInitializeSecurity 사용 제약
; https://www.sysnet.pe.kr/2/0/12665

별도 DLL에 포함된 타입을 STAThread Main 메서드에서 사용하는 경우 CoInitializeSecurity 자동 호출
; https://www.sysnet.pe.kr/2/0/12666

COM+ 서버 응용 프로그램을 이용해 CoInitializeSecurity 제약 해결
; https://www.sysnet.pe.kr/2/0/12667

ionescu007/lxss github repo에 공개된 lxssmanager.dll의 CLSID_LxssUserSession/IID_ILxssSession 사용법
; https://www.sysnet.pe.kr/2/0/12676

역공학을 통한 lxssmanager.dll의 ILxssSession 사용법 분석
; https://www.sysnet.pe.kr/2/0/12677

C# - DLL Surrogate를 이용한 Out-of-process COM 개체 제작
; https://www.sysnet.pe.kr/2/0/12668

DLL Surrogate를 이용한 Out-of-process COM 개체에서의 CoInitializeSecurity 문제
; https://www.sysnet.pe.kr/2/0/12670

CoInitializeSecurity의 전역 설정을 재정의하는 CoSetProxyBlanket 함수 사용법
; https://www.sysnet.pe.kr/2/0/12679




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 7/4/2024]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 91  92  93  94  95  96  97  [98]  99  100  101  102  103  104  105  ...
NoWriterDateCnt.TitleFile(s)
11481정성태4/10/201831973개발 환경 구성: 357. CUDA의 인덱싱 관련 용어 - blockIdx, threadIdx, blockDim, gridDim
11480정성태4/9/201821987.NET Framework: 736. C# - API를 사용해 Azure에 접근하는 방법 [2]파일 다운로드1
11479정성태4/9/201817682.NET Framework: 735. Azure - PowerShell로 Access control(IAM)에 새로운 계정 만드는 방법
11478정성태11/8/201919892디버깅 기술: 115. windbg - 덤프 파일로부터 PID와 환경변수 등의 정보를 구하는 방법 [1]
11477정성태4/8/201817382오류 유형: 460. windbg - sos 명령어 수행 시 c0000006 오류 발생
11476정성태4/8/201818895디버깅 기술: 114. windbg - !threads 출력 결과로부터 닷넷 관리 스레드(System.Threading.Thread) 객체를 구하는 방법
11475정성태3/28/201821155디버깅 기술: 113. windbg - Thread.Suspend 호출 시 응용 프로그램 hang 현상에 대한 덤프 분석
11474정성태3/27/201819296오류 유형: 459. xperf: error: TEST.Event: Invalid flags. (0x3ec).
11473정성태3/22/201824514.NET Framework: 734. C# - Thread.Suspend 호출 시 응용 프로그램 hang 현상파일 다운로드2
11472정성태3/22/201818464개발 환경 구성: 356. GTX 1070, GTX 960, GT 640M의 cudaGetDeviceProperties 출력 결과
11471정성태3/20/201821892VC++: 125. CUDA로 작성한 RGB2RGBA 성능 [1]파일 다운로드1
11470정성태3/20/201823872오류 유형: 458. Visual Studio - CUDA 프로젝트 빌드 시 오류 C1189, expression must have a constant value
11469정성태3/19/201816872오류 유형: 457. error MSB3103: Invalid Resx file. Could not load file or assembly 'System.Windows.Forms, ...' or one of its dependencies.
11468정성태3/19/201816451오류 유형: 456. 닷넷 응용 프로그램 실행 시 0x80131401 예외 발생
11467정성태3/19/201815988오류 유형: 455. Visual Studio Installer - 업데이트 실패
11466정성태3/18/201817074개발 환경 구성: 355. 한 대의 PC에서 2개 이상의 DirectX 게임을 실행하는 방법
11463정성태3/15/201819479.NET Framework: 733. 스레드 간의 read/write 시에도 lock이 필요 없는 경우파일 다운로드1
11462정성태3/14/201822318개발 환경 구성: 354. HTTPS 호출에 대한 TLS 설정 확인하는 방법 [1]
11461정성태3/13/201824922오류 유형: 454. 윈도우 업데이트 설치 오류 - 0x800705b4 [1]
11460정성태3/13/201817404디버깅 기술: 112. windbg - 닷넷 메모리 덤프에서 전역 객체의 내용을 조사하는 방법
11459정성태3/13/201818177오류 유형: 453. Debug Diagnostic Tool에서 mscordacwks.dll을 찾지 못하는 문제
11458정성태2/21/201819243오류 유형: 452. This share requires the obsolete SMB1 protocol, which is unsafe and could expose your system to attack. [1]
11457정성태2/17/201823947.NET Framework: 732. C# - Task.ContinueWith 설명 [1]파일 다운로드1
11456정성태2/17/201829663.NET Framework: 731. C# - await을 Task 타입이 아닌 사용자 정의 타입에 적용하는 방법 [7]파일 다운로드1
11455정성태2/17/201818576오류 유형: 451. ASP.NET Core - An error occurred during the compilation of a resource required to process this request.
11454정성태2/12/201827448기타: 71. 만료된 Office 제품 키를 변경하는 방법
... 91  92  93  94  95  96  97  [98]  99  100  101  102  103  104  105  ...