성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] The Windows Registry Adventure #1: ...
[정성태] systemd for Developers I ; https:/...
[정성태] 엄밀히 object 타입의 인스턴스가 다른 타입으로 형변환 가능...
[정성태] 아래의 글에서 나오는 "Windows Application Pa...
[정성태] The history of calling conventions,...
[정성태] Secure and Deploy .NET Windows Form...
[정성태] Get Started with Milvus Vector DB i...
[정성태] cyberark/PipeViewer - A tool that...
[정성태] WinForms in a 64-Bit world – our st...
[정성태] 예제에서 SELECT_SQL도 내부적으로는 SqlCommand/...
글쓰기
제목
이름
암호
전자우편
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'>C++ - OSR Driver Loader와 같은 Legacy 커널 드라이버 설치 프로그램 제작</h1> <p> OSR Driver Loader는,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Loading the Windows Kernel Driver ; <a target='tab' href='https://resources.infosecinstitute.com/loading-the-windows-kernel-driver/'>https://resources.infosecinstitute.com/loading-the-windows-kernel-driver/</a> </pre> <br /> GUI 환경을 제공해 편리하긴 해도 명령행으로 쓸 수 없다는 불편함이 있습니다. (혹시 명령행을 제공하나요? ^^)<br /> <br /> 사실 명령행이 크게 필요하지 않은 이유가 있긴 한데, 이미 <a target='tab' href='https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/sc-create'>sc.exe</a>를 이용해서 그런 역할을 수행할 수 있기 때문입니다. 이에 대해서는 다음의 글에서 코드를 통한 방법과 함께 자세하게 설명하고 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Loading the Windows Kernel Driver ; <a target='tab' href='https://resources.infosecinstitute.com/loading-the-windows-kernel-driver/'>https://resources.infosecinstitute.com/loading-the-windows-kernel-driver/</a> </pre> <br /> 예를 들어, 지난 글에 소개한 KernelMemoryIO 드라이버를 명령행으로 다음과 같이 등록할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > c:\temp> <span style='color: blue; font-weight: bold'>sc create "KernelMemoryIO" binPath= "D:\wdk\KernelMemoryIO\x64\Debug\KernelMemoryIO.sys" type= kernel start= demand</span> [SC] CreateService SUCCESS </pre> <br /> 사실 이 작업도 그리 복잡한 시스템 변경을 수행하진 않습니다. 단순히 다음과 같이 "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services" 경로에 적절한 정보를 설정하는 것에 불과합니다.<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\KernelMemoryIO] "Type"=dword:00000001 "Start"=dword:00000003 "ErrorControl"=dword:00000001 "ImagePath"=hex(2):5c,00,3f,00,3f,00,5c,00,44,00,3a,00,5c,00,77,00,64,00,6b,00,\ 5c,00,4b,00,65,00,72,00,6e,00,65,00,6c,00,4d,00,65,00,6d,00,6f,00,72,00,79,\ 00,49,00,4f,00,5c,00,78,00,36,00,34,00,5c,00,44,00,65,00,62,00,75,00,67,00,\ 5c,00,4b,00,65,00,72,00,6e,00,65,00,6c,00,4d,00,65,00,6d,00,6f,00,72,00,79,\ 00,49,00,4f,00,2e,00,73,00,79,00,73,00,00,00 </pre> <br /> 등록된 드라이버를 제거하는 방법은 sc.exe로 해도 되지만,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > c:\temp> <span style='color: blue; font-weight: bold'>sc delete "KernelMemoryIO"</span> [SC] DeleteService SUCCESS </pre> <br /> 마찬가지로 그냥 레지스트리 키(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\KernelMemoryIO)를 삭제해도 무방합니다. 게다가 커널 드라이버를 시작 및 중지하는 방법은 일반적인 NT 서비스를 다루는 방법과 동일합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [시작] c:\temp> <span style='color: blue; font-weight: bold'>net start KernelMemoryIO</span> The KernelMemoryIO service was started successfully. [중지] c:\temp> <span style='color: blue; font-weight: bold'>net stop KernelMemoryIO</span> The KernelMemoryIO service was stopped successfully. </pre> <br /> 당연하지만, 위의 모든 작업은 "관리자 권한"을 요구합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 명령행이 아닌, 직접 코드를 작성하는 것도 그리 어렵지 않습니다. <a target='tab' href='https://docs.microsoft.com/en-us/windows/win32/services/service-control-manager'>Service Control Manager</a>를 다루는 <a target='tab' href='https://docs.microsoft.com/en-us/windows/win32/services/service-functions'>Win32 API</a>만 적절하게 호출하면 되는데 아래는 그렇게 해서 만든 간단한 프로그램입니다.<br /> <br /> <pre style='height: 400px; margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > #include "stdafx.h" int InstallDriver(wchar_t *pDriverFilePath, wchar_t *pDriverName); int UninstallDriver(wchar_t *pDriverName); int StartDeviceDriver(wchar_t *pDriverName); int StopDeviceDriver(wchar_t *pDriverName); // HKLM\SYSTEM\CurrentControlSet\Services\[DriverName] // [install] // InstallDriver 1 "[경로]" "[DriverName]" // or // sc create "[DriverName]" binPath= "[경로]" type= kernel start= demand // // [uninstall] // InstallDriver 0 "[DriverName]" // // [start_service] // InstallDriver 2 "[DriverName]" // or // net start "[DriverName]" // or // sc start "[DriverName]" // // [stop_service] // InstallDriver 3 "[DriverName]" // or // net stop "[DriverName]" // or // sc stop "[DriverName]" int _tmain(int argc, _TCHAR* argv[]) { wchar_t *mode = nullptr; wchar_t driverFullPath[MAX_PATH]; wchar_t *driverName = nullptr; if (argc > 0) { mode = argv[1]; } if (mode == nullptr) { return 1; } if (argc == 4) { wchar_t currentPath[MAX_PATH]; ::GetCurrentDirectory(MAX_PATH, currentPath); ::PathCombine(driverFullPath, currentPath, argv[2]); driverName = argv[3]; } else if (argc == 3) { driverName = argv[2]; } if (driverName == nullptr) { return 1; } if (wcscmp(mode, L"1") == 0) { return InstallDriver(driverFullPath, driverName) == 0; } else if (wcscmp(mode, L"0") == 0) { return UninstallDriver(driverName) == 0; } else if (wcscmp(mode, L"2") == 0) { return StartDeviceDriver(driverName) == 0; } else if (wcscmp(mode, L"3") == 0) { return StopDeviceDriver(driverName) == 0; } return 0; } int StartDeviceDriver(wchar_t *pDriverName) { int result = 0; SC_HANDLE hSCManager = NULL; SC_HANDLE hService = NULL; do { hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (hSCManager == NULL) { wprintf(L"[StartDeviceDriver] hSCManager == NULL"); break; } hService = OpenService(hSCManager, pDriverName, SERVICE_START); if (hService == NULL) { wprintf(L"[StartDeviceDriver] hService == NULL"); break; } if (::StartService(hService, 0, NULL) == TRUE) { result = 1; } } while (false); if (hService != NULL) { CloseServiceHandle(hService); hService = NULL; } if (hSCManager != NULL) { CloseServiceHandle(hSCManager); hSCManager = NULL; } return result; } int StopDeviceDriver(wchar_t *pDriverName) { int result = 0; SC_HANDLE hSCManager = NULL; SC_HANDLE hService = NULL; DWORD dwResult; do { hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hSCManager == NULL) { wprintf(L"[StopDeviceDriver] hSCManager == NULL"); break; } hService = OpenService(hSCManager, pDriverName, SERVICE_STOP | SERVICE_QUERY_STATUS); if (hService == NULL) { wprintf(L"[StopDeviceDriver] hService == NULL"); break; } SERVICE_STATUS st; if (::ControlService(hService, SERVICE_CONTROL_STOP, &st) == TRUE) { result = 1; } else { dwResult = ::GetLastError(); wprintf(L"[StopDeviceDriver - %s] ControlService == FALSE, LastError = %d", pDriverName, dwResult); } } while (false); if (hService != NULL) { CloseServiceHandle(hService); hService = NULL; } if (hSCManager != NULL) { CloseServiceHandle(hSCManager); hSCManager = NULL; } return result; } int InstallDriver(wchar_t *pDriverFilePath, wchar_t *pDriverName) { int result = 0; SC_HANDLE hSCManager = NULL; SC_HANDLE hService = NULL; do { hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (hSCManager == NULL) { wprintf(L"[InstallDriver] hSCManager == NULL"); break; } /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\[DirverName] */ hService = CreateService(hSCManager, pDriverName, pDriverName, GENERIC_READ, SERVICE_KERNEL_DRIVER, /* service type */ SERVICE_DEMAND_START, /* start type */ SERVICE_ERROR_NORMAL, /* error control type */ pDriverFilePath, /* service's binary */ NULL, /* no load ordering group */ NULL, /* no tag identifier*/ NULL, /* no dependencies */ NULL, /* LocalSystem account*/ NULL /* no password */ ); if (hService == NULL) { DWORD dwResult = ::GetLastError(); wprintf(L"[InstallDriver] hService == NULL, LastError = %d", dwResult); break; } result = 1; } while (false); if (hService != NULL) { CloseServiceHandle(hService); hService = NULL; } if (hSCManager != NULL) { CloseServiceHandle(hSCManager); hSCManager = NULL; } return result; } int UninstallDriver(wchar_t *pDriverName) { int result = 0; SC_HANDLE hSCManager = NULL; SC_HANDLE hService = NULL; do { hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hSCManager == NULL) { wprintf(L"[UninstallDriver] hSCManager == NULL"); break; } hService = OpenService(hSCManager, pDriverName, DELETE); if (hService == NULL) { wprintf(L"[UninstallDriver] hService == NULL"); break; } if (::DeleteService(hService) == TRUE) { result = 1; } } while (false); if (hService != NULL) { CloseServiceHandle(hService); hService = NULL; } if (hSCManager != NULL) { CloseServiceHandle(hSCManager); hSCManager = NULL; } return result; } </pre> <br /> 위의 소스 코드를 빌드한 결과물로 KernelMemoryIO 드라이버를 설치/제거/시작/중지하는 방법은 다음과 같습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [설치] c:\temp> InstallDriver64.exe 1 "D:\MyGit\wdk\KernelMemoryIO\x64\Debug\KernelMemoryIO.sys" KernelMemoryIO [제거] c:\temp> InstallDriver64.exe 0 KernelMemoryIO [시작] c:\temp> InstallDriver64.exe 2 KernelMemoryIO [중지] c:\temp> InstallDriver64.exe 3 KernelMemoryIO </pre> <br /> <hr style='width: 50%' /><br /> <br /> 이 글에서 소개한 소스 코드는 다음의 github에 등록해 두었습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > DotNetSamples/Cpp/InstallDriver/ ; <a target='tab' href='https://github.com/stjeong/DotNetSamples/tree/master/Cpp/InstallDriver'>https://github.com/stjeong/DotNetSamples/tree/master/Cpp/InstallDriver</a> </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1436
(왼쪽의 숫자를 입력해야 합니다.)