성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <div style='font-family: 맑은 고딕, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>Appinit_Dlls로 구현한 환경 변수 설정 DLL</div><br /> <br /> 환경 변수(Environment variables) 값으로 프로그램의 동작을 제어하는 경우가 종종 있는데요. <br /> <br /> 윈도우 환경에서는 기본적으로 "사용자 계정 단위"와 "시스템 전역 단위"로 환경 변수를 설정해주는 UI를 제공합니다.<br /> <br /> <img alt='appinit_dll_env_set_1.png' src='/SysWebRes/bbs/appinit_dll_env_set_1.png' /><br /> <br /> 문제는, "사용자 계정 단위"는 상황에 따라서 고려할 사항들이 많아서 때론 부적합한 면이 있고, "시스템 전역 단위"는 자칫 원하는 응용 프로그램을 제외한 다른 프로그램에도 영향을 주기 때문에 문제가 됩니다. 영향을 주는 정도가 아니고, dll 로딩에 연관된 동작이라면 해당 모듈이 잠기는 상황까지 발생하기 때문에 차후의 업그레이드나 설치 제거를 위해서 컴퓨터를 재부팅해야 하는 점이 다소 심각하긴 합니다.<br /> <br /> 즉, 특정 응용 프로그램에만 "환경 변수"를 적용하게 하고 싶은데 - 예를 들어, COM+ dllhost.exe에만 설정하고 싶다거나 - 기존의 방법으로는 적당한 것이 없다는 것!<br /> <br /> <hr style='width: 50%' /><br /> <br /> 그래서, 고민을 한 결과 Appinit_Dlls 레지스트리를 이용하여 설정을 이용해 보는 것이 어떨까 하는 생각이 들었습니다. 코드도 무지 간단합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { wchar_t fileName[MAX_PATH]; if (GetModuleFileName(NULL, fileName, MAX_PATH) == 0) // Kernel32.dll { return FALSE; } wstring fileNamePart = GetFileNamePart(fileName); // 전체 파일 경로에서 파일명만을 소문자로 반환 (코드 생략) if (wcscmp(fileNamePart.c_str(), L"w3wp.exe") != 0) { return FALSE; } SetEnvironmentVariable(L"TEST", "1"); // Kernel32.dll <b style='COLOR: blue'>return FALSE;</b> } </pre> <br /> 모든 메서드가 Kernel32.dll에서 제공되므로 부작용도 없고, 결정적으로 마지막에 무조건 "FALSE"를 반환하기 때문에 말 그대로 환경 변수만 정확하게 설정하고 해당 exe 프로세스 공간에서 제거되어 모듈이 잠기는 현상까지도 걱정하지 않아도 됩니다. 간단하죠! ^^ "AppInit"이라는 목적에 정확하게 부합하는 DLL입니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 위의 구현이 한 가지 아쉬운 점이라면, 코드는 간단한 반면 실제 적용하는 과정이 다소 복잡하다는 것입니다. Appinit_Dlls 레지스트리에 등록된 DLL은 모든 프로세스에 올라온다는 점에 착안하여 악성 코드들의 심심치 않은 응용 대상이 된다는 것인데, 이 때문에 마이크로소프트는 Vista부터 기본적으로 Appinit_Dlls 기능을 비활성화 해놓고 있으며, Windows 7부터는 서명된 DLL만 활성화되도록 하는 옵션을 추가했습니다. (그런데, 서명된 DLL 사용의 기본값은 Windows 7에서 0, Windows Server 2008 R2에서 1입니다.)<br /> <br /> 이 때문에, 위와 같이 환경 변수만을 설정하는 정상적인 프로그램조차도 모든 윈도우 운영체제에 적용하려면 다음과 같은 사항들을 고려해야 합니다.<br /> <br /> <ul> <li>설치 시에, "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" 경로의 "Appinit_Dlls" 값에 자신이 만든 DLL 경로 등록</li> <li>설치 시에, "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" 경로의 "LoadAppInit_DLLs" 값을 숫자 1로 설정</li> <li>설치 시에, "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" 경로의 "RequireSignedAppInit_DLLs" 값을 숫자 0으로 설정</li> </ul> <br /> 그런데, 여기서 "RequireSignedAppInit_DLLs" 값을 0으로 설정해서 비활성화 하는 것은 왠지 방법이 아닌 것 같습니다. 왜냐하면 악성 코드들의 통로를 열어주는 것이 되므로 이 방법보다는 차라리 우리가 만든 DLL을 서명하는 것이 더 바람직합니다. (사실, 이 부분에 맞지 않는 부분이 있긴 합니다. 어차피 Appinit_Dlls 레지스트리 값에 "쓰기" 권한을 가진 악성 코드라면, 당연히 RequireSignedAppInit_DLLs도 0으로 설정할 것이기 때문입니다.)<br /> <br /> 이런저런 이유로 해당 DLL을 서명해 주는 것이 좋을 텐데... 익숙하게 알고 있던 ActiveX 서명과는 방법이 좀 다릅니다. 이에 대한 자세한 문서는 다음의 경로에서 구할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > AppInit DLLs in Windows 7 and Windows Server 2008 R2 ; <a target='_tab' href='https://learn.microsoft.com/en-us/windows/win32/win7appqual/appinit-dlls-in-windows-7-and-windows-server-2008-r2'>https://learn.microsoft.com/en-us/windows/win32/win7appqual/appinit-dlls-in-windows-7-and-windows-server-2008-r2</a> AppInit_Win7.docx ; <a target='_tab' href='http://download.microsoft.com/download/7/E/7/7E7662CF-CBEA-470B-A97E-CE7CE0D98DC2/AppInit_Win7.docx'>http://download.microsoft.com/download/7/E/7/7E7662CF-CBEA-470B-A97E-CE7CE0D98DC2/AppInit_Win7.docx</a> </pre> <br /> 대강 정리해 보면, 다음과 같은 순서로 진행해야 합니다.<br /> <br /> <ol> <li>DLL 빌드 시에 "/integritycheck" 옵션을 준다.</li> <li>교차 인증서(cross-certificate)를 같이 사용해서 서명한다.</li> </ol> <br /> 우선 1번은, Linker 옵션 설정 창에서 다음과 같이 설정해 주는 것으로 해결할 수 있습니다. (속성 페이지를 열은 김에, Debug/Release 모두 설정해 주는 것이 좋겠지요! ^^)<br /> <br /> <img alt='appinit_dll_env_set_2.png' src='/SysWebRes/bbs/appinit_dll_env_set_2.png' /><br /> <br /> 실수로 Debug에만 설정하고 나중에 배포할 때 Release로 빌드했다가 누락되는 경우가 있을 수도 있는데 배포된 PC에서 정상적으로 빌드된 경우인지 확인하려면 dumpbin을 이용하면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > C:\temp>dumpbin /headers test.dll Microsoft (R) COFF/PE Dumper Version 10.00.30319.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file test.dll PE signature found File Type: DLL FILE HEADER VALUES ...[생락]... OPTIONAL HEADER VALUES 10B magic # (PE32) ...[생략]... 2 subsystem (Windows GUI) 1C0 DLL characteristics Dynamic base <b style='COLOR: blue'>Check integrity</b> NX compatible 100000 size of stack reserve ...[생략]... </pre> <br /> "/integritycheck" 옵션이 적용된 경우라면, 위와 같이 "DLL characteristics"에서 "Check integrity" 항목을 발견할 수 있습니다.<br /> <br /> 그다음, 교차 인증서를 다운로드해야 하는데요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > Cross-Certificates for Kernel Mode Code Signing ; <a target='_tab' href='https://learn.microsoft.com/en-us/windows-hardware/drivers/install/cross-certificates-for-kernel-mode-code-signing'>https://learn.microsoft.com/en-us/windows-hardware/drivers/install/cross-certificates-for-kernel-mode-code-signing</a> </pre> <br /> 위의 경로에서 소프트웨어 코드 서명 인증서를 발급받은 인증 기관에 해당하는 교차 인증서를 다운로드합니다. 현재 아래의 인증기관에 대한 교차 인증서만을 제공해 주고 있는데요.<br /> <br /> <ul> <li>Baltimore CyberTrust Root</li> <li>Equifax Secure Certificate Authority</li> <li>GTE CyberTrust Global Root</li> <li>GlobalSign Root CA</li> <li>GeoTrust Global CA</li> <li>VeriSign Class 3 Public Primary Certification Authority</li> </ul> <br /> 의미인 즉, 위의 인증 기관 이외에서 발급받은 인증서로는 Appinit_Dlls 목적으로 사용될 DLL 서명용으로는 부적합하다는 것입니다.<br /> <br /> 이렇게 해서 교차인증서를 다운로드했으면 (여기서는 Verisign에 해당하는 "MSCV-VSClass3.cer" 파일을 다운로드했다고 가정하고.) 다음과 같은 인자와 함께 최종적으로 서명하는 것이 가능합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > Signtool sign /v <b style='COLOR: blue'>/ph</b> /ac MSCV-VSClass3.cer <b style='COLOR: blue'>/s my</b> /n sysnet.pe.kr /t http://timestamp.verisign.com/scripts/timestamp.dll test.dll </pre> <br /> 만약, Team Build에서 위의 과정을 추가하고 싶다면 "/s my" 옵션의 계정에 종속된 위치보다는 "LOCAL MACHINE"에 설정된 인증서를 지정하고 싶을 텐데요. 그런 경우에는 "/sm" 옵션으로 주면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > Signtool sign /v <b style='COLOR: blue'>/ph</b> /ac MSCV-VSClass3.cer <b style='COLOR: blue'>/sm</b> /n sysnet.pe.kr /t http://timestamp.verisign.com/scripts/timestamp.dll test.dll </pre> <br /> 만약, 위의 과정 중에 하나라도 부적합하다면 해당 DLL은 프로세스에 올라오지 않습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 참고로, "/integritycheck"만 있고 서명을 하지 않은 경우에는 모든 exe를 실행할 때마다 다음과 같은 오류 메시지가 발생합니다.<br /> <br /> <img alt='appinit_dll_env_set_3.png' src='/SysWebRes/bbs/appinit_dll_env_set_3.png' /><br /> <br /> <span style='BACKGROUND-COLOR: #ccffcc; FONT-STYLE: italic; MARGIN: 10px 0px 10px 10px; WIDTH: 800px; FONT-FAMILY: 맑은 고딕, Consolas, Verdana; COLOR: #005555'> "<br /> ... is either not designed to run on Windows or it contains an error. Try installing the program again using the original installation media or contract your system administrator or the software vendor for support.<br /> "<br /> </span><br /><br /> <br /> 다행히, 해당 응용 프로그램이 실행은 됩니다.<br /> <br /><br /><hr /><span style='color: Maroon'>[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1298
(왼쪽의 숫자를 입력해야 합니다.)