성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
[정성태] 만드실 수 있습니다. 단지, Unity 엔진 내의 스크립트와 W...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>역공학을 통한 lxssmanager.dll의 ILxssSession 사용법 분석</h1> <p> 이전 글에서,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ionescu007/lxss github repo에 공개된 lxssmanager.dll의 CLSID_LxssUserSession/IID_ILxssSession 사용법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12676'>https://www.sysnet.pe.kr/2/0/12676</a> </pre> <br /> ILxssSession, ILxInstnace를 소개했는데요, 아쉽게도 동작은 하지 않았지만 어쨌든 4개의 함수 signature를 공개했다는 것이 중요합니다. 그럼, 혹시 우리도 알 수 있지 않을까요? ^^<br /> <br /> 일단, CoCreateInstance로 반환한 ILxssSession 인스턴스를,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > hr = CoCreateInstance(CLSID_LxssManager, nullptr, CLSCTX_LOCAL_SERVER, __uuidof(ILxssSession), (PVOID*)&pSession); // pSession == 00000267BD58AB98 </pre> <br /> 해당 주솟값을 참조해서 들어가면 vtable 위치를 알 수 있는데요,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [00000267BD58AB98] == 00007ff9ae572180 </pre> <br /> vtable의 항목에 대해 windbg에서 symbol을 확인할 수 있습니다. 아래는 vtable에 대해 정리한 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# - PDB 파일로부터 심벌(Symbol) 및 타입(Type) 정보 열거 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12114'>https://www.sysnet.pe.kr/2/0/12114</a> 00007ff9`ae572180 00007ff9ae571490 LxssManagerProxyStub!IUnknown_QueryInterface_Proxy: // @0 IUnknown::QueryInterface 00007ff9`ae572188 00007ff9ae571320 LxssManagerProxyStub!IUnknown_AddRef_Proxy: // @8 IUnknown::AddRef 00007ff9`ae572190 00007ff9ae5713d0 LxssManagerProxyStub!IUnknown_Release_Proxy: // @10 IUnknown::Release 00007ff9`ae572198 00007ff9ae571340 LxssManagerProxyStub!ObjectStublessClient3: // @18 GetCurrentInstance 00007ff9`ae5721a0 00007ff9ae5714c0 LxssManagerProxyStub!ObjectStublessClient4: // @20 StartDefaultInstance 00007ff9`ae5721a8 00007ff9ae571390 LxssManagerProxyStub!ObjectStublessClient5: // @28 SetState 00007ff9`ae5721b0 00007ff9ae5713e0 LxssManagerProxyStub!ObjectStublessClient6: // @30 QueryState 00007ff9`ae5721b8 00007ff9ae571370 LxssManagerProxyStub!ObjectStublessClient7: // @38 InitializeFileSystem 00007ff9`ae5721c0 00007ff9ae5713f0 LxssManagerProxyStub!ObjectStublessClient8: // @40 Destroy 00007ff9`ae5721c8 00007ff9ae571400 LxssManagerProxyStub!ObjectStublessClient9: 00007ff9`ae5721d0 00007ff9ae571430 LxssManagerProxyStub!ObjectStublessClient10: 00007ff9`ae5721d8 00007ff9ae571310 LxssManagerProxyStub!ObjectStublessClient11: 00007ff9`ae5721e0 00007ff9ae5712f0 LxssManagerProxyStub!ObjectStublessClient12: 00007ff9`ae5721e8 00007ff9ae571380 LxssManagerProxyStub!ObjectStublessClient13: 00007ff9`ae5721f0 00007ff9ae571300 LxssManagerProxyStub!ObjectStublessClient14: 00007ff9`ae5721f8 00007ff9ae571360 LxssManagerProxyStub!ObjectStublessClient15: 00007ff9`ae572200 00007ff9ae571470 LxssManagerProxyStub!ObjectStublessClient16: 00007ff9`ae572208 00007ff9ae571420 LxssManagerProxyStub!ObjectStublessClient17: 00007ff9`ae572210 00007ff9ae571350 LxssManagerProxyStub!ObjectStublessClient18: 00007ff9`ae572218 00007ff9ae5713b0 LxssManagerProxyStub!ObjectStublessClient19: </pre> <br /> 아쉽게도 ObjectStublessClient3부터 시작해 ObjectStublessClient19까지의 함수는 추적해 들어가는 경우 얻을 수 있는 정보가 없습니다. ^^; 솔직히 없다기보다는 INPROC COM 개체였다면 쉽게 분석을 들어갈 수 있었겠지만 DCOM 서버라서 RPC 호출이 엮어져서 분석이 매우 어렵습니다. <br /> <br /> 그럼 접근법을 달리해서 wslapi.dll에 있는 함수 호출을 분석해 들어가면 될 듯합니다. 이를 위해 적당한 API 하나를 골라야 하는데, 함수 인자가 1개인 WslIsDistributionRegistered가 후보로 좋을 듯합니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > WslIsDistributionRegistered function (wslapi.h) ; <a target='tab' href='https://learn.microsoft.com/en-us/windows/win32/api/wslapi/nf-wslapi-wslisdistributionregistered'>https://learn.microsoft.com/en-us/windows/win32/api/wslapi/nf-wslapi-wslisdistributionregistered</a> </pre> <br /> 사용은 이렇게 하고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > typedef BOOL(__stdcall* pIsDistroRegistered)(PCWSTR distroName); HMODULE dll = LoadLibraryExW(L"wslapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); pIsDistroRegistered IsDistroRegistered = (pIsDistroRegistered)GetProcAddress(dll, "WslIsDistributionRegistered"); <span style='color: blue; font-weight: bold'>BOOL result = IsDistroRegistered(L"Ubuntu20.04");</span> printf("IsDistroRegistered: %d\n", result); </pre> <br /> windbg로 IsDistroRegistered 호출부터 BP를 걸어 들어가면 됩니다. 한번 따라가볼까요? ^^<br /> <br /> <hr style='width: 50%' /><br /> <br /> 아래는 windbg에서 본 wslapi!WslIsDistributionRegistered 코드입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > struct _LX_DIST_INFO { wchar_t *pName; int *pValue; } <span style='color: blue; font-weight: bold'>wslapi!WslIsDistributionRegistered:</span> 00007ff9`b9ff23a0 48895c2418 mov qword ptr [rsp+18h],rbx 00007ff9`b9ff23a5 48894c2408 mov qword ptr [rsp+8],rcx ss:00000094`eacffae0={ConsoleApplication1!`string' (00007ff7`54dead00)} // rsp + 8 == 00000094`eacffae0 // [rsp + 8] == 00007ff754dead58 == L"Ubuntu20.04" 00007ff9`b9ff23aa 57 push rdi 00007ff9`b9ff23ab 4883ec30 sub rsp,30h // int parent_sp_2; // rsp+48h == 00000094`eacffae8 // void *ptr_2; // rsp+28h == 00000094`eacffac8 00007ff9`b9ff23af 33ff xor edi,edi 00007ff9`b9ff23b1 897c2448 mov dword ptr [rsp+48h],edi // parent_sp_2 = 0; // [rsp + 48] == (00007ff9)00000000 00007ff9`b9ff23b5 8d4f10 lea ecx,[rdi+10h] // rcx == 0x10 00007ff9`b9ff23b8 e8db360000 call wslapi!operator new (00007ff9`b9ff5a98) // 0x10바이트만큼 공간 확보 00007ff9`b9ff23bd 4885c0 test rax,rax // rax == 00000267`bd5a5820 // 00000267`bd5a5820 38 01 00 00 00 00 00 8...... // 00000267`bd5a5827 00 01 00 00 00 10 16 ....... 00007ff9`b9ff23c0 7413 je wslapi!WslIsDistributionRegistered+0x35 (00007ff9`b9ff23d5) 00007ff9`b9ff23c2 488d4c2440 lea rcx,[rsp+40h] // L"Ubuntu20.04" 00007ff9`b9ff23c7 488908 mov qword ptr [rax],rcx 00007ff9`b9ff23ca 488d4c2448 lea rcx,[rsp+48h] 00007ff9`b9ff23cf 48894808 mov qword ptr [rax+8],rcx // _LX_DIST_INFO pInfo = new(); // info->pName = [1st_arg]; // info->pValue = &parent_sp_2; 00007ff9`b9ff23d3 eb03 jmp wslapi!WslIsDistributionRegistered+0x38 (00007ff9`b9ff23d8) 00007ff9`b9ff23d5 488bc7 (mov rax,rdi) 00007ff9`b9ff23d8 4885c0 test rax,rax 00007ff9`b9ff23db 747b je wslapi!WslIsDistributionRegistered+0xb8 (00007ff9`b9ff2458) 00007ff9`b9ff23dd 48897c2428 mov qword ptr [rsp+28h],rdi // ptr_2 = nullptr; // rsp+28h == 00000094`eacffac8 <span style='color: blue; font-weight: bold'>00007ff9`b9ff23e2 4c8d0577050000 lea r8,[wslapi!<lambda_d62d766b87cfe9fe43d92b02b0dda941>::<lambda_invoker_cdecl> (00007ff9`b9ff2960)] 00007ff9`b9ff23e9 4c8bc8 mov r9,rax 00007ff9`b9ff23ec 897c2420 mov dword ptr [rsp+20h],edi // DWORD dwCreationFlags = 0 00007ff9`b9ff23f0 33d2 xor edx,edx 00007ff9`b9ff23f2 33c9 xor ecx,ecx 00007ff9`b9ff23f4 48ff15054f0000 call qword ptr [wslapi!_imp_CreateThread (00007ff9`b9ff7300)] // CreateThread(0, 0, [wslapi!<lambda_d62d766b87cfe9fe43d92b02b0dda941>::<lambda_invoker_cdecl>, pInfo, dwCreationFlags, ptr_2); </span>00007ff9`b9ff23fb 0f1f440000 nop dword ptr [rax+rax] 00007ff9`b9ff2400 488bd8 mov rbx,rax // rax == 1bc // !handle 1bc ==> Type Thread 00007ff9`b9ff2403 4885c0 test rax,rax 00007ff9`b9ff2406 7439 je wslapi!WslIsDistributionRegistered+0xa1 (00007ff9`b9ff2441) 00007ff9`b9ff2408 83caff or edx,0FFFFFFFFh 00007ff9`b9ff240b 488bc8 mov rcx,rax 00007ff9`b9ff240e 48ff15534f0000 call qword ptr [wslapi!_imp_WaitForSingleObject (00007ff9`b9ff7368)] // WaitForSingleObject(rax, 4294967295); 00007ff9`b9ff2415 0f1f440000 nop dword ptr [rax+rax] 00007ff9`b9ff241a 8b7c2448 mov edi,dword ptr [rsp+48h] 00007ff9`b9ff241e 4883fbff cmp rbx,0FFFFFFFFFFFFFFFFh 00007ff9`b9ff2422 740f je wslapi!WslIsDistributionRegistered+0x93 (00007ff9`b9ff2433) 00007ff9`b9ff2424 488bcb mov rcx,rbx 00007ff9`b9ff2427 48ff15f24d0000 call qword ptr [wslapi!_imp_CloseHandle (00007ff9`b9ff7220)] 00007ff9`b9ff242e 0f1f440000 nop dword ptr [rax+rax] 00007ff9`b9ff2433 488b5c2450 mov rbx,qword ptr [rsp+50h] 00007ff9`b9ff2438 8bc7 mov eax,edi 00007ff9`b9ff243a 4883c430 add rsp,30h 00007ff9`b9ff243e 5f pop rdi 00007ff9`b9ff243f c3 ret </pre> <br /> 코드를 보면, 다른 건 별로 의미가 없고 WslIsDistributionRegistered의 본래 기능은 CreateThread에 전달된 lambda_invoker_cdecl 함수에서 실제 동작을 하는 걸로 보입니다. lambda_invoker_cdecl은 다음의 코드로 이뤄집니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>wslapi!<lambda_d62d766b87cfe9fe43d92b02b0dda941>::<lambda_invoker_cdecl>:</span> // DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter); 00007ff9`b9ff2960 48895c2408 mov qword ptr [rsp+8],rbx 00007ff9`b9ff2965 57 push rdi 00007ff9`b9ff2966 4883ec40 sub rsp,40h // _LX_CERATE_INFO *pCerateInfo; // __int128* pField1; // [rsp + 28h] 00007ff9`b9ff296a 488b059f760000 mov rax,qword ptr [wslapi!_security_cookie (00007ff9`b9ffa010)] 00007ff9`b9ff2971 4833c4 xor rax,rsp 00007ff9`b9ff2974 4889442438 mov qword ptr [rsp+38h],rax 00007ff9`b9ff2979 488bf9 mov rdi,rcx // rdi = lpParameter 00007ff9`b9ff297c 488d542420 lea rdx,[rsp+20h] // rdx = 94eb3ff900 00007ff9`b9ff2981 488b09 mov rcx,qword ptr [rcx] // rcx == 94eacffae0, [94eacffae0] == 7ff754dead58 == L"Ubuntu20.04" 00007ff9`b9ff2984 33db xor ebx,ebx 00007ff9`b9ff2986 48895c2420 mov qword ptr [rsp+20h],rbx // pCerateInfo = nullptr; 00007ff9`b9ff298b 488b09 mov rcx,qword ptr [rcx] // rcx = [rcx] == 7ff754dead58 <span style='color: blue; font-weight: bold'>00007ff9`b9ff298e e889220000 call wslapi!WslSession::s_Create (00007ff9`b9ff4c1c) // WslSession::s_Create(L"Ubuntu20.04", ptr_1); // pCreateInfo에 pSession을 담아 반환</span> 00007ff9`b9ff2993 85c0 test eax,eax 00007ff9`b9ff2995 7919 jns wslapi!<lambda_d62d766b87cfe9fe43d92b02b0dda941>::<lambda_invoker_cdecl>+0x50 (00007ff9`b9ff29b0) // 00007ff9`b9ff29b0로 점프 ...[생략]... 00007ff9`b9ff29b0 488b4c2420 mov rcx,qword ptr [rsp+20h] // rcx = pCerateInfo; 00007ff9`b9ff29b5 488d542428 lea rdx,[rsp+28h] // rdx = &pField1; 00007ff9`b9ff29ba 0f57c0 xorps xmm0,xmm0 00007ff9`b9ff29bd 0f11442428 movups xmmword ptr [rsp+28h],xmm0 // pField1 = nullptr; <span style='color: blue; font-weight: bold'>00007ff9`b9ff29c2 e829250000 call wslapi!WslSession::_GetDistroId (00007ff9`b9ff4ef0) // WslSession::_GetDistroId(pCreateInfo, pField1);</span> 00007ff9`b9ff29c7 85c0 test eax,eax 00007ff9`b9ff29c9 7821 js wslapi!<lambda_d62d766b87cfe9fe43d92b02b0dda941>::<lambda_invoker_cdecl>+0x8c (00007ff9`b9ff29ec) 00007ff9`b9ff29cb 488b442428 mov rax,qword ptr [rsp+28h] 00007ff9`b9ff29d0 483b05514e0000 cmp rax,qword ptr [wslapi!GUID_NULL (00007ff9`b9ff7828)] 00007ff9`b9ff29d7 750e jne wslapi!<lambda_d62d766b87cfe9fe43d92b02b0dda941>::<lambda_invoker_cdecl>+0x87 (00007ff9`b9ff29e7) 00007ff9`b9ff29d9 488b442430 mov rax,qword ptr [rsp+30h] 00007ff9`b9ff29de 483b054b4e0000 cmp rax,qword ptr [wslapi!GUID_NULL+0x8 (00007ff9`b9ff7830)] 00007ff9`b9ff29e5 7405 je wslapi!<lambda_d62d766b87cfe9fe43d92b02b0dda941>::<lambda_invoker_cdecl>+0x8c (00007ff9`b9ff29ec) 00007ff9`b9ff29e7 bb01000000 mov ebx,1 00007ff9`b9ff29ec 488b4708 mov rax,qword ptr [rdi+8] 00007ff9`b9ff29f0 8918 mov dword ptr [rax],ebx 00007ff9`b9ff29f2 488d4c2420 lea rcx,[rsp+20h] 00007ff9`b9ff29f7 e8c4ecffff call wslapi!wistd::unique_ptr<WslSession,wistd::default_delete<WslSession> >::~unique_ptr<WslSession,wistd::default_delete<WslSession> > (00007ff9`b9ff16c0) 00007ff9`b9ff29fc 488bcf mov rcx,rdi 00007ff9`b9ff29ff e888300000 call wslapi!operator delete (00007ff9`b9ff5a8c) 00007ff9`b9ff2a04 33c0 xor eax,eax 00007ff9`b9ff2a06 488b4c2438 mov rcx,qword ptr [rsp+38h] 00007ff9`b9ff2a0b 4833cc xor rcx,rsp 00007ff9`b9ff2a0e e8cd340000 call wslapi!_security_check_cookie (00007ff9`b9ff5ee0) 00007ff9`b9ff2a13 488b5c2450 mov rbx,qword ptr [rsp+50h] 00007ff9`b9ff2a18 4883c440 add rsp,40h ...[생략]... </pre> <br /> 위의 호출에서 s_Create 함수를 먼저 들어가 보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > struct _LX_CREATE_UNK16 { wchar_t *pDistName; ILxssSession *pSession; } struct _LX_CERATE_INFO { _LX_CREATE_UNK16 f1; __int64 flag2; } <span style='color: blue; font-weight: bold'>wslapi!WslSession::s_Create: // WslSession::s_Create(L"Ubuntu20.04", ptr_1);</span> 00007ff9`b9ff4c1c 48895c2408 mov qword ptr [rsp+8],rbx ss:00000094`eb3ff8e0=0000000000000000 00007ff9`b9ff4c21 4889742418 mov qword ptr [rsp+18h],rsi 00007ff9`b9ff4c26 57 push rdi 00007ff9`b9ff4c27 4883ec20 sub rsp,20h 00007ff9`b9ff4c2b 488bfa mov rdi,rdx // rdi == ptr_1 == 94eb3ff900 00007ff9`b9ff4c2e 488bf1 mov rsi,rcx // rsi == "Ubuntu20.04" 00007ff9`b9ff4c31 488d15182a0000 lea rdx,[wslapi!std::nothrow (00007ff9`b9ff7650)] 00007ff9`b9ff4c38 b918000000 mov ecx,18h 00007ff9`b9ff4c3d e89a180000 call wslapi!operator new (00007ff9`b9ff64dc) // _LX_CERATE_INFO pCreateInfo = new [0x18] // 24bytes [267bd5a5660] 00007ff9`b9ff4c42 4885c0 test rax,rax 00007ff9`b9ff4c45 7410 je wslapi!WslSession::s_Create+0x3b (00007ff9`b9ff4c57) 00007ff9`b9ff4c47 0f57c0 xorps xmm0,xmm0 00007ff9`b9ff4c4a 33c9 xor ecx,ecx 00007ff9`b9ff4c4c 0f1100 movups xmmword ptr [rax],xmm0 // pCreateInfo->f1 = 0; 00007ff9`b9ff4c4f 48894810 mov qword ptr [rax+10h],rcx // pCreateInfo->flag2 = 0; 00007ff9`b9ff4c53 c6401001 mov byte ptr [rax+10h],1 // pCreateInfo->flag2 = 1; 00007ff9`b9ff4c57 488b1f mov rbx,qword ptr [rdi] // rbx == 부모가 준 ptr_1 스택 영역 (아마도 구조체) // rbx = 0 00007ff9`b9ff4c5a 488364243800 and qword ptr [rsp+38h],0 00007ff9`b9ff4c60 488907 mov qword ptr [rdi],rax // ptr_1 = pCreateInfo; 00007ff9`b9ff4c63 4885db test rbx,rbx 00007ff9`b9ff4c66 7464 je wslapi!WslSession::s_Create+0xb0 (00007ff9`b9ff4ccc) // rbx != null이므로 00007ff9`b9ff4ccc로 점프 ...[생략]... 00007ff9`b9ff4ccc 488d4c2438 lea rcx,[rsp+38h] // rcx = 94eb3ff8e8 00007ff9`b9ff4cd1 e8eac9ffff call wslapi!wistd::unique_ptr<WslSession,wistd::default_delete<WslSession> >::~unique_ptr<WslSession,wistd::default_delete<WslSession> > (00007ff9`b9ff16c0) 00007ff9`b9ff4cd6 488b0f mov rcx,qword ptr [rdi] // rcx = pCreateInfo 00007ff9`b9ff4cd9 4885c9 test rcx,rcx 00007ff9`b9ff4cdc 7520 jne wslapi!WslSession::s_Create+0xe2 (00007ff9`b9ff4cfe) // rcx != null이므로 00007ff9`b9ff4cfe로 점프 ...[생략]... 00007ff9`b9ff4cfe 488bd6 mov rdx,rsi <span style='color: blue; font-weight: bold'>00007ff9`b9ff4d01 e826000000 call wslapi!WslSession::_Initialize (00007ff9`b9ff4d2c) // wslapi!WslSession::_Initialize(pCreateInfo, "Ubuntu20.04"); // pCreateInfo에 pSession을 담아 반환</span> 00007ff9`b9ff4d06 8bd8 mov ebx,eax 00007ff9`b9ff4d08 85c0 test eax,eax 00007ff9`b9ff4d0a 7907 jns wslapi!WslSession::s_Create+0xf7 (00007ff9`b9ff4d13) ...[생략]... 00007ff9`b9ff4d13 33c0 xor eax,eax // 반환값 0 00007ff9`b9ff4d15 488b5c2430 mov rbx,qword ptr [rsp+30h] 00007ff9`b9ff4d1a 488b742440 mov rsi,qword ptr [rsp+40h] 00007ff9`b9ff4d1f 4883c420 add rsp,20h 00007ff9`b9ff4d23 5f pop rdi 00007ff9`b9ff4d24 c3 ret </pre> <br /> 실제 작업은 "WslSession::_Initialize" 함수에서 이뤄지는 것을 알 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > wslapi!WslSession::_Initialize: 00007ff9`b9ff4d2c 48895c2410 mov qword ptr [rsp+10h],rbx ss:00000094`eb3ff8b8=0000000000000000 00007ff9`b9ff4d31 48896c2418 mov qword ptr [rsp+18h],rbp 00007ff9`b9ff4d36 4889742420 mov qword ptr [rsp+20h],rsi 00007ff9`b9ff4d3b 57 push rdi 00007ff9`b9ff4d3c 4883ec60 sub rsp,60h 00007ff9`b9ff4d40 488d7910 lea rdi,[rcx+10h] 00007ff9`b9ff4d44 488bea mov rbp,rdx 00007ff9`b9ff4d47 488bf1 mov rsi,rcx 00007ff9`b9ff4d4a c60700 mov byte ptr [rdi],0 00007ff9`b9ff4d4d 33d2 xor edx,edx 00007ff9`b9ff4d4f 33c9 xor ecx,ecx <span style='color: blue; font-weight: bold'>00007ff9`b9ff4d51 48ff1538240000 call qword ptr [wslapi!_imp_CoInitializeEx (00007ff9`b9ff7190)] // CoInitializeEx(nullptr, 0);</span> 00007ff9`b9ff4d58 0f1f440000 nop dword ptr [rax+rax] 00007ff9`b9ff4d5d 85c0 test eax,eax 00007ff9`b9ff4d5f 0f8874010000 js wslapi!WslSession::_Initialize+0x1ad (00007ff9`b9ff4ed9) 00007ff9`b9ff4d65 488364244000 and qword ptr [rsp+40h],0 00007ff9`b9ff4d6b 4533c9 xor r9d,r9d 00007ff9`b9ff4d6e c744243820000000 mov dword ptr [rsp+38h],20h 00007ff9`b9ff4d76 4533c0 xor r8d,r8d 00007ff9`b9ff4d79 488364243000 and qword ptr [rsp+30h],0 00007ff9`b9ff4d7f 83caff or edx,0FFFFFFFFh 00007ff9`b9ff4d82 c744242803000000 mov dword ptr [rsp+28h],3 00007ff9`b9ff4d8a 33c9 xor ecx,ecx 00007ff9`b9ff4d8c 8364242000 and dword ptr [rsp+20h],0 <span style='color: blue; font-weight: bold'>00007ff9`b9ff4d91 48ff1500240000 call qword ptr [wslapi!_imp_CoInitializeSecurity (00007ff9`b9ff7198)] // CoInitializeSecurity(0, -1, 0, 0, RpcAuthnLevel.Default /* 0 */, RpcImpLevel.Impersonate /* 3 */, 0, EoAuthnCap.StaticCloaking /* 0x20 */, 0);</span> 00007ff9`b9ff4d98 0f1f440000 nop dword ptr [rax+rax] 00007ff9`b9ff4d9d ba00000080 mov edx,80000000h 00007ff9`b9ff4da2 8d0c10 lea ecx,[rax+rdx] 00007ff9`b9ff4da5 85ca test edx,ecx 00007ff9`b9ff4da7 750b jne wslapi!WslSession::_Initialize+0x88 (00007ff9`b9ff4db4) 00007ff9`b9ff4da9 3d19010180 cmp eax,80010119h 00007ff9`b9ff4dae 0f850e010000 jne wslapi!WslSession::_Initialize+0x196 (00007ff9`b9ff4ec2) // RCP_E_TOO_LATE 00007ff9`b9ff4db4 488d5e08 lea rbx,[rsi+8] // rbx == &pCreateInfo->f1.pSession; 00007ff9`b9ff4db8 488b0b mov rcx,qword ptr [rbx] // rcx = pCreateInfo->f1.pSession; // == 0 00007ff9`b9ff4dbb 48832300 and qword ptr [rbx],0 // pCreateInfo->f1.pSession = 0; 00007ff9`b9ff4dbf 4885c9 test rcx,rcx 00007ff9`b9ff4dc2 740d je wslapi!WslSession::_Initialize+0xa5 (00007ff9`b9ff4dd1) // 00007ff9`b9ff4dd1 점프 ...[생략]... 00007ff9`b9ff4dd1 33d2 xor edx,edx 00007ff9`b9ff4dd3 48895c2420 mov qword ptr [rsp+20h],rbx 00007ff9`b9ff4dd8 4c8d0db12c0000 lea r9,[wslapi!GUID_536a6bcf_fe04_41d9_b978_dcaca9a9b5b9 (00007ff9`b9ff7a90)] 00007ff9`b9ff4ddf 488d0d9a2c0000 lea rcx,[wslapi!`string'+0x4 (00007ff9`b9ff7a80)] 00007ff9`b9ff4de6 448d4204 lea r8d,[rdx+4] <span style='color: blue; font-weight: bold'>00007ff9`b9ff4dea 48ff15af230000 call qword ptr [wslapi!_imp_CoCreateInstance (00007ff9`b9ff71a0)] // CoCreateInstance(CLSID_LxssManager, nullptr, CLSCTX_LOCAL_SERVER, __uuidof(ILxssSession), &pCreateInfo->f1.pSession);</span> 00007ff9`b9ff4df1 0f1f440000 nop dword ptr [rax+rax] 00007ff9`b9ff4df6 8bd8 mov ebx,eax 00007ff9`b9ff4df8 b89e010780 mov eax,8007019Eh // The Windows Subsystem for Linux has not been enabled. 00007ff9`b9ff4dfd 81fb54010480 cmp ebx,80040154h // Class not registered - Retrieving the COM class factory for component with CLSID 00007ff9`b9ff4e03 0f44d8 cmove ebx,eax 00007ff9`b9ff4e06 85db test ebx,ebx 00007ff9`b9ff4e08 7907 jns wslapi!WslSession::_Initialize+0xe5 (00007ff9`b9ff4e11) [br=1] // 00007ff9`b9ff4e11로 점프 ...[생략]... 00007ff9`b9ff4e11 4983c8ff or r8,0FFFFFFFFFFFFFFFFh // r8 = ffffffffffffffff 00007ff9`b9ff4e15 488d4c2470 lea rcx,[rsp+70h] // 00000094`eb3ff8b0 (이 위치는 WslSession::_initialize 반환 주소 값을 담고 있는 그다음 부모의 rsp 마지막 기준 주소) 00007ff9`b9ff4e1a 488bd5 mov rdx,rbp // rdx == "Ubuntu20.08" 00007ff9`b9ff4e1d e8c20a0000 call wslapi!wil::make_unique_string_nothrow<wil::unique_any_t<wil::details::unique_storage<wil::details::resource_policy<unsigned short * __ptr64,void (__cdecl*)(void * __ptr64),&CoTaskMemFree,wistd::integral_constant<unsigned __int64,0>,unsigned short * __ptr64,unsigned short * __ptr64,0,std::nullptr_t> > > > (00007ff9`b9ff58e4) // [rsp+70h] 00000094`eb3ff8b0 == 00000267bd5a57e0 == "Ubuntu20.04" 00007ff9`b9ff4e22 488d542470 lea rdx,[rsp+70h] // rdx == "Ubuntu20.04" // rdx == 94eb3ff8b0, [rdx] == 00000267bd5a57e0 == "Ubuntu20.04" 00007ff9`b9ff4e27 488bce mov rcx,rsi // rcx == pCreateInfo 00007ff9`b9ff4e2a e8b5050000 call wslapi!wil::unique_any_t<wil::details::unique_storage<wil::details::resource_policy<unsigned short * __ptr64,void (__cdecl*)(void * __ptr64),&CoTaskMemFree,wistd::integral_constant<unsigned __int64,0>,unsigned short * __ptr64,unsigned short * __ptr64,0,std::nullptr_t> > >::operator= (00007ff9`b9ff53e4) // 호출 후, // rax == 267bd5a5660, pCreateInfo // [rsp+70h] = 0 00007ff9`b9ff4e2f 488b4c2470 mov rcx,qword ptr [rsp+70h] // rcx = 0 00007ff9`b9ff4e34 4885c9 test rcx,rcx 00007ff9`b9ff4e37 740c je wslapi!WslSession::_Initialize+0x119 (00007ff9`b9ff4e45) // 00007ff9`b9ff4e45로 점프 ...[생략]... 00007ff9`b9ff4e45 48833e00 cmp qword ptr [rsi],0 00007ff9`b9ff4e49 752c jne wslapi!WslSession::_Initialize+0x14b (00007ff9`b9ff4e77) // 00007ff9`b9ff4e77로 점프 ...[생략]... 00007ff9`b9ff4e77 488d442450 lea rax,[rsp+50h] // rax == 00000094`eb3ff890 fffffffffffffffe 00007ff9`b9ff4e7c 483bf8 cmp rdi,rax // rdi == 267bd5a5670, pCreateInfo->flag2 00007ff9`b9ff4e7f 741a je wslapi!WslSession::_Initialize+0x16f (00007ff9`b9ff4e9b) 00007ff9`b9ff4e81 8a07 mov al,byte ptr [rdi] // pCreateInfo->flag2 == 0 (1로 초기화했는데 언제 0으로???) 00007ff9`b9ff4e83 c60700 mov byte ptr [rdi],0 // 어쨌든 pCreateInfo->flag2 = 0으로 초기화 00007ff9`b9ff4e86 84c0 test al,al 00007ff9`b9ff4e88 740c je wslapi!WslSession::_Initialize+0x16a (00007ff9`b9ff4e96) // 00007ff9`b9ff4e96으로 점프 ...[생략]... 00007ff9`b9ff4e96 c60701 mov byte ptr [rdi],1 // 어쨌든 pCreateInfo->flag2 = 1로 초기화 00007ff9`b9ff4e99 eb0c jmp wslapi!WslSession::_Initialize+0x17b (00007ff9`b9ff4ea7) // 00007ff9`b9ff4ea7로 점프 ...[생략]... 00007ff9`b9ff4ea7 33db xor ebx,ebx 00007ff9`b9ff4ea9 4c8d5c2460 lea r11,[rsp+60h] 00007ff9`b9ff4eae 8bc3 mov eax,ebx // 리턴 값 0 00007ff9`b9ff4eb0 498b5b18 mov rbx,qword ptr [r11+18h] 00007ff9`b9ff4eb4 498b6b20 mov rbp,qword ptr [r11+20h] 00007ff9`b9ff4eb8 498b7328 mov rsi,qword ptr [r11+28h] 00007ff9`b9ff4ebc 498be3 mov rsp,r11 00007ff9`b9ff4ebf 5f pop rdi 00007ff9`b9ff4ec0 c3 ret </pre> <br /> 익숙한 함수 호출들을 볼 수 있는데요, 결국 하는 것은 ILxssSession 인스턴스를 구하는 것입니다. 위의 함수를 호출한 lambda_invoker_cdecl 측에서는 저렇게 ILxssSession 인스턴스를 구한 후 WslSession::_GetDistroId 함수를 호출하게 됩니다. 그리고 마침내 이 함수에서 ILxssSession 인터페이스의 (QueryState로 보이는) 7번째 함수의,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > MIDL_INTERFACE("536A6BCF-FE04-41D9-B978-DCACA9A9B5B9") ILxssSession : IUnknown { STDMETHOD(GetCurrentInstance)(ILxInstnace** pInstanceOut); STDMETHOD(StartDefaultInstance)(_In_ const IID& InstanceIid, _Out_ PVOID* InstanceOut); STDMETHOD(SetState)(/* unknown */); <span style='color: blue; font-weight: bold'>STDMETHOD(QueryState)(/* unknown */);</span> STDMETHOD(InitializeFileSystem)(/* unknown */); STDMETHOD(Destroy)(/* unknown */); }; </pre> <br /> 사용 코드가 나옵니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > wslapi!WslSession::_GetDistroId: 00007ff9`b9ff4ef0 4053 push rbx 00007ff9`b9ff4ef2 4883ec30 sub rsp,30h 00007ff9`b9ff4ef6 4c8b5108 mov r10,qword ptr [rcx+8] // r10 == pCreateInfo->f1.pSession; 00007ff9`b9ff4efa 4c8bca mov r9,rdx // r9 == pField1 // 94eb3ff908 00007ff9`b9ff4efd 488b11 mov rdx,qword ptr [rcx] // rdx == 267bd5a57e0 == "Ubuntu20.04" 00007ff9`b9ff4f00 4533c0 xor r8d,r8d // r8 = 0 00007ff9`b9ff4f03 498bca mov rcx,r10 // rcx = 267bd58ab98, [267bd58ab98] == pSession; 00007ff9`b9ff4f06 498b02 mov rax,qword ptr [r10] // rax = pSesion.vptr 00007ff9`b9ff4f09 488b4030 mov rax,qword ptr [rax+30h] // rax = pSession의 QueryState <span style='color: blue; font-weight: bold'>00007ff9`b9ff4f0d ff15ad250000 call qword ptr [wslapi!_guard_dispatch_icall_fptr (00007ff9`b9ff74c0)] // pSession->QueryState("Ubuntu20.04", 0, &pField1);</span> 00007ff9`b9ff4f13 8bd8 mov ebx,eax // 80070005 00007ff9`b9ff4f15 85c0 test eax,eax 00007ff9`b9ff4f17 791d jns wslapi!WslSession::_GetDistroId+0x46 (00007ff9`b9ff4f36) 00007ff9`b9ff4f19 488b4c2438 mov rcx,qword ptr [rsp+38h] 00007ff9`b9ff4f1e 4c8d05bb2a0000 lea r8,[wslapi!`string' (00007ff9`b9ff79e0)] 00007ff9`b9ff4f25 448bc8 mov r9d,eax 00007ff9`b9ff4f28 ba67000000 mov edx,67h 00007ff9`b9ff4f2d e836cbffff call wslapi!wil::details::in1diag3::Return_Hr (00007ff9`b9ff1a68) 00007ff9`b9ff4f32 8bc3 mov eax,ebx 00007ff9`b9ff4f34 eb02 jmp wslapi!WslSession::_GetDistroId+0x48 (00007ff9`b9ff4f38) 00007ff9`b9ff4f36 33c0 xor eax,eax 00007ff9`b9ff4f38 4883c430 add rsp,30h 00007ff9`b9ff4f3c 5b pop rbx 00007ff9`b9ff4f3d c3 ret </pre> <br /> 여기까지 보면 QueryState의 signature를 이렇게 정의할 수 있는데요,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > STDMETHOD(QueryState)(const wchar_t* distroName, int unknownField, __int64 *pField); </pre> <br /> 마지막 인자에 대한 힌트를 lambda_invoker_cdecl의 WslSession::_GetDistroId에서 QueryState를 호출한 이후 다행히 그것을 다루는 코드에서 찾아볼 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 00007ff9`b9ff29c2 e829250000 call wslapi!WslSession::_GetDistroId (00007ff9`b9ff4ef0) // WslSession::_GetDistroId(pCreateInfo, pField1); 00007ff9`b9ff29c7 85c0 test eax,eax 00007ff9`b9ff29c9 7821 js wslapi!<lambda_d62d766b87cfe9fe43d92b02b0dda941>::<lambda_invoker_cdecl>+0x8c (00007ff9`b9ff29ec) <span style='color: blue; font-weight: bold'>00007ff9`b9ff29cb 488b442428 mov rax,qword ptr [rsp+28h] 00007ff9`b9ff29d0 483b05514e0000 cmp rax,qword ptr [wslapi!GUID_NULL (00007ff9`b9ff7828)]</span> 00007ff9`b9ff29d7 750e jne wslapi!<lambda_d62d766b87cfe9fe43d92b02b0dda941>::<lambda_invoker_cdecl>+0x87 (00007ff9`b9ff29e7) 00007ff9`b9ff29d9 488b442430 mov rax,qword ptr [rsp+30h] 00007ff9`b9ff29de 483b054b4e0000 cmp rax,qword ptr [wslapi!GUID_NULL+0x8 (00007ff9`b9ff7830)] 00007ff9`b9ff29e5 7405 je wslapi!<lambda_d62d766b87cfe9fe43d92b02b0dda941>::<lambda_invoker_cdecl>+0x8c (00007ff9`b9ff29ec) 00007ff9`b9ff29e7 bb01000000 mov ebx,1 </pre> <br /> GUID_NULL이 나오죠. ^^ 따라서 이렇게 마무리할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > STDMETHOD(QueryState)(const wchar_t* distroName, int unknownField, _In_ _Out_ IID* pGuid); </pre> <br /> 아울러, 이 값이 GUID라는 것에서 이전에 사용한 StartDefaultInstance의 사용법이 잘못되었음을 인지하게 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > hr = pSession->StartDefaultInstance(<span style='color: blue; font-weight: bold'>__uuidof(ILxInstance)</span>, (PVOID *)&pInstance); printf("StartDefaultInstance hr == %d(0x%x)\n", hr, hr); </pre> <br /> __uuidof(ILxInstance)가 아마도 QueryState로부터 받아온 GUID 값으로 보입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > IID instanceId; hr = pSession->QueryState(L"Ubuntu20.04", 0, <span style='color: blue; font-weight: bold'>&instanceId</span>); hr = pSession->StartDefaultInstance(<span style='color: blue; font-weight: bold'>instanceId</span>, (PVOID *)&pInstance); </pre> <br /> (그래도 crash되는 것은 마찬가지입니다. 아마도 다른 인자가 있을 듯합니다.)<br /> <br /> <hr style='width: 50%' /><br /> <br /> 마지막으로, 이것을 이용해 다음과 같이 WslIsDistributionRegistered 함수를 QueryState로 다시 작성할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > #include <Windows.h> #include <stdio.h> #include "lxssmanager.h" HRESULT OleMain(); BOOL WslIsDistributionRegistered(ILxssSession* pSession, const wchar_t* distroName); int main() { HRESULT hr = CoInitializeEx(nullptr, 0); if (hr != S_OK) { return 1; } hr = OleMain(); CoUninitialize(); return (hr == S_OK) ? 0 : 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; do { hr = CoCreateInstance(CLSID_LxssManager, nullptr, CLSCTX_LOCAL_SERVER, __uuidof(ILxssSession), (PVOID*)&pSession); if (hr != S_OK) { break; } // -2147024891 == 0x80070005 E_ACCESSDENIED (Access is denied.) // -2147024894 == 0x80070002 (The system cannot find the file specified.) // -2147024809 == 0x80070057 E_INVALIDARG (The parameter is incorrect.) // -2147220734 == 0x80040302 printf("IsRegistered: %d\n", WslIsDistributionRegistered(pSession, L"Ubuntu20.04")); } while (false); if (pSession != nullptr) { pSession->Release(); } return hr; } <span style='color: blue; font-weight: bold'>BOOL WslIsDistributionRegistered(ILxssSession* pSession, const wchar_t* distroName) { IID iid; HRESULT hr = pSession->QueryState(distroName, 0, &iid); if (hr != S_OK) { return FALSE; } </span> /* OLECHAR* guidString; <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20231113-00/?p=109011'>StringFromCLSID</a>(iid, &guidString); printf("%ls\n", guidString); CoTaskMemFree(guidString); */ <span style='color: blue; font-weight: bold'> return TRUE; }</span> </pre> <br /> (<a target='tab' href='https://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=1803&boardid=331301885'>첨부 파일은 이 글의 예제 코드를 포함</a>합니다.)<br /> <br /> <hr style='width: 50%' /><br /> <br /> 그나저나, 이런 어려움은 언젠가 마이크로소프트 측에서 (c:\windows\system32\lxss\)lxssmanager.dll에 대한 Type Library를 배포하면 자연스럽게 해결될 것입니다. 그런데 이게 그다지 희망적이지가 않습니다. <br /> <br /> 왜냐하면, lxssmanager.dll에서 제공하는 COM 개체의 호스팅 서비스를 찾아보면 마이크로소프트가 이 부분을 얼마나 비공개로 두고 싶은지 느낄 수 있기 때문입니다. 심심한데 이것도 기록을 남겨 볼까요? ^^<br /> <br /> 우선 lxssmanager.dll의 export 함수에서,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ServiceMain SvchostPushServiceGlobals DllCanUnloadNow DllGetClassObject InprocRegister InprocUnregister DllCanUnloadNow DllGetClassObject </pre> <br /> svchost.exe로 호스팅되는 서비스 프로세스가 아닐까 예상을 하게 되는데요, 실제로 레지스트리에는 다음과 같은 서비스 정보가 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LxssManager] DependOnService: RPCSS staterepository Description: @%systemroot%\\system32\\lxss\\LxssManager.dll,-101 DisplayName: @%systemroot%\\system32\\lxss\\LxssManager.dll,-100 ErrorControl=0x00000001 Group: LxssManagerGroup ImagePath: %systemroot%\system32\svchost.exe -k netsvcs -p LaunchProtected: 0x00000002 ObjectName: LocalSystem RequiredPrivileges: SeChangeNotifyPrivilege SeDebugPrivilege SeImpersonatePrivilege SeAssignPrimaryTokenPrivilege SeLoadDriverPrivilege SeTcbPrivilege ServiceSidType: 0x00000001 Start: 0x00000003 Type: 0x00000020 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LxssManager\parameters] ServiceDll: %SystemRoot%\system32\lxss\LxssManager.dll ServiceDllUnloadOnStop: 0x00000001 </pre> <br /> "C:\Windows\System32\lxss\en-US\LxssManager.dll.mui" 리소스 파일의 Strings 테이블에 따라,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 100: LXSSMANAGER 101: The LXSS Manager service supports running native ELF binaries. The service provides the infrastructure necessary for ELF binaries to run on Windows. If the service is stopped or disabled, those binaries will no longer run. 102: LxssManagerUser </pre> <br /> DisplayName은 LXSSMANAGER이므로 서비스 관리자에서 해당 이름과 "Path to executable"을 보면 다음과 같이 잘 나와 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Path to executable: C:\WINDOWS\system32\svchost.exe -k netsvcs -p Status: Running </pre> <a name='lxss_svc'></a> <br /> 오호~~~ 그럼 분명히 실행 중이기 때문에 process explorer를 통해 lxssmanager.dll을 로딩한 프로세스를 검색할 수 있을 것입니다. <strike>그런데 애석하게도 검색이 안 됩니다. 할 수 없이,</strike> 또는, 작업 관리자를 이용해 프로세스 실행/중지를 반복하며 어떤 svchost.exe인지 애써 찾아보면 (근래의 Process Explorer로 DLL 정보는 볼 수 있는)<strike>Process Explorer에서조차 DLL 로딩 정보를 볼 수 없는</strike> <a target='tab' href='https://www.sysnet.pe.kr/2/0/13169'>특별한 (PPL) 프로세스</a>가 나옵니다.<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='lxssmanager_service_1.png' src='/SysWebRes/bbs/lxssmanager_service_1.png' /><br /> <br /> 찾긴 찾았지만, 관리자 권한의 windbg로 attach시켜도 권한이 없다는 오류 메시지(Could not attach to process 9840, Win32 error 0n5 Access is denied)와 함께 더 이상 할 수 있는 것이 아무것도 없습니다. ^^; <br /> <br /> 이 정도로 보안에 신경 쓴다는 것은, Type Library를 공개하지 않을 충분한 이유가 있는 걸로 보입니다. ^^;<br /><br /> (2023-10-20 업데이트) 발표 자료가 하나 있군요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > The linux kernel hidden inside windows 10 ; <a target='tab' href='https://www.slideshare.net/mark-smith/the-linux-kernel-hidden-inside-windows-10'>https://www.slideshare.net/mark-smith/the-linux-kernel-hidden-inside-windows-10</a> </pre> <br /> 위의 자료를 보면, GetConfiguration, GetId, QueryState, SetState, CreateLxProcess, RegisterAdssBusServer, ConnectAdssBusServer, GetState, StartSelf, StopSelf, GetSuspendState 등의 함수가 구현되었다고 합니다. 아쉽게도 인자 정보가 없군요. ^^ (참고로, Adss는 "Android Sub System"의 약어라고 합니다.) <hr style='width: 50%' /><br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# - CoCreateInstance 관련 Inteop 오류 정리 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12678'>https://www.sysnet.pe.kr/2/0/12678</a> Wslhub.Sdk 사용으로 알아보는 CoInitializeSecurity 사용 제약 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12665'>https://www.sysnet.pe.kr/2/0/12665</a> 별도 DLL에 포함된 타입을 STAThread Main 메서드에서 사용하는 경우 CoInitializeSecurity 자동 호출 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12666'>https://www.sysnet.pe.kr/2/0/12666</a> COM+ 서버 응용 프로그램을 이용해 CoInitializeSecurity 제약 해결 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12667'>https://www.sysnet.pe.kr/2/0/12667</a> ionescu007/lxss github repo에 공개된 lxssmanager.dll의 CLSID_LxssUserSession/IID_ILxssSession 사용법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12676'>https://www.sysnet.pe.kr/2/0/12676</a> 역공학을 통한 lxssmanager.dll의 ILxssSession 사용법 분석 ; https://www.sysnet.pe.kr/2/0/12677 C# - DLL Surrogate를 이용한 Out-of-process COM 개체 제작 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12668'>https://www.sysnet.pe.kr/2/0/12668</a> DLL Surrogate를 이용한 Out-of-process COM 개체에서의 CoInitializeSecurity 문제 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12670'>https://www.sysnet.pe.kr/2/0/12670</a> CoInitializeSecurity의 전역 설정을 재정의하는 CoSetProxyBlanket 함수 사용법 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12679'>https://www.sysnet.pe.kr/2/0/12679</a> </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1725
(왼쪽의 숫자를 입력해야 합니다.)