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

비밀번호

댓글 작성자
 




... 76  77  78  79  80  81  82  83  [84]  85  86  87  88  89  90  ...
NoWriterDateCnt.TitleFile(s)
11831정성태3/4/201916742오류 유형: 523. Visual Studio 2019 - 새 창으로 뜬 윈도우를 닫을 때 비정상 종료
11830정성태2/26/201916432오류 유형: 522. 이벤트 로그 - Error opening event log file State. Log will not be processed. Return code from OpenEventLog is 87.
11829정성태2/26/201918164개발 환경 구성: 430. 마이크로소프트의 CoreCLR 프로파일러 예제 빌드 방법 - 리눅스 환경 [1]
11828정성태2/26/201926052개발 환경 구성: 429. Component Services 관리자의 RuntimeBroker 설정이 2개 있는 경우 [8]
11827정성태2/26/201919011오류 유형: 521. Visual Studio - Could not start the 'rsync' command on the remote host, please install it using your system package manager.
11826정성태2/26/201919199오류 유형: 520. 우분투에 .NET Core SDK 설치 시 패키지 의존성 오류
11825정성태2/25/201924385개발 환경 구성: 428. Visual Studio 2019 - CMake를 이용한 리눅스 빌드 환경 설정 [1]
11824정성태2/25/201918831오류 유형: 519. The SNMP Service encountered an error while accessing the registry key SYSTEM\CurrentControlSet\Services\SNMP\Parameters\TrapConfiguration. [1]
11823정성태2/21/201920600오류 유형: 518. IIS 관리 콘솔이 뜨지 않는 문제
11822정성태2/20/201918829오류 유형: 517. docker에 설치한 MongoDB 서버로 연결이 안 되는 경우
11821정성태2/20/201919606오류 유형: 516. Visual Studio 2019 - This extension uses deprecated APIs and is at risk of not functioning in a future VS update. [1]
11820정성태2/20/201922649오류 유형: 515. 윈도우 10 1809 업데이트 후 "User Profiles Service" 1534 경고 발생
11819정성태2/20/201921945Windows: 158. 컴퓨터와 사용자의 SID(security identifier) 확인 방법
11818정성태2/20/201919981VS.NET IDE: 131. Visual Studio 2019 Preview의 닷넷 프로젝트 빌드가 20초 이상 걸리는 경우 [2]
11817정성태2/17/201916364오류 유형: 514. WinDbg Preview 실행 오류 - Error : DbgX.dll : WindowsDebugger.WindowsDebuggerException: Could not load dbgeng.dll
11816정성태2/17/201919768Windows: 157. 윈도우 스토어 앱(Microsoft Store App)을 명령행에서 직접 실행하는 방법
11815정성태2/14/201918002오류 유형: 513. Visual Studio 2019 - VSIX 설치 시 "The extension cannot be installed to this product due to prerequisites that cannot be resolved." 오류 발생
11814정성태2/12/201916838오류 유형: 512. VM(가상 머신)의 NT 서비스들이 자동 시작되지 않는 문제
11813정성태2/12/201918269.NET Framework: 809. C# - ("Save File Dialog" 등의) 대화 창에 확장 속성을 보이는 방법
11812정성태2/11/201915527오류 유형: 511. Windows Server 2003 VM 부팅 후 로그인 시점에 0xC0000005 BSOD 발생
11811정성태2/11/201920672오류 유형: 510. 서버 운영체제에 NVIDIA GeForce Experience 실행 시 wlanapi.dll 누락 문제
11810정성태2/11/201918452.NET Framework: 808. .NET Profiler - GAC 모듈에서 GAC 비-등록 모듈을 참조하는 경우의 문제
11809정성태2/11/201920524.NET Framework: 807. ClrMD를 이용해 메모리 덤프 파일로부터 특정 인스턴스를 참조하고 있는 소유자 확인
11808정성태2/8/201921856디버깅 기술: 123. windbg - 닷넷 응용 프로그램의 메모리 누수 분석
11807정성태1/29/201919763Windows: 156. 가상 디스크의 용량을 복구 파티션으로 인해 늘리지 못하는 경우 [4]
11806정성태1/29/201919460디버깅 기술: 122. windbg - 덤프 파일로부터 PID와 환경 변수 등의 정보를 구하는 방법
... 76  77  78  79  80  81  82  83  [84]  85  86  87  88  89  90  ...