:: CertOpenStore()在Docker Windows上失败

我从在“networking服务”帐户和Docker Windows上运行的Windows服务调用:: CertOpenStore()。 但是“访问被拒绝”却失败了。

主机是Windows 10。

重现步骤:

  1. 创build一个Dockerfile。
  2. dockerbuild设-t样本。
  3. docker运行 – 名称示例-i –rm示例
  4. sc创buildDEMO_SERVICE binPath = C:\ tools \ CertOpenStoreExperimental.exe obj =“nt authority \ network service”
  5. networking启动DEMO_SERVICE
  6. 净停止DEMO_SERVICE
  7. TYPE result.txt

CertOpenStoreExperimental.exe的源代码如下:

// // Demo Service // #include <fstream> #include <iostream> #include <windows.h> #include <tchar.h> #include <assert.h> #include <stdarg.h> DWORD WINAPI HandlerEx( DWORD dwControl, DWORD dwEventType, PVOID pvEventData, PVOID pvContext); VOID WINAPI ServiceMain(DWORD dwArgc, PTSTR* pszArgv); VOID DebugPrint(LPTSTR szFormat, ...); /////////////////////////////////////////////////////////////////////////////// #define SERVICE_NAME (TEXT("Demo_Service")) #define DEBUG_BUFF_SIZE (1024) /////////////////////////////////////////////////////////////////////////////// SERVICE_TABLE_ENTRY ServiceTable[] = { { SERVICE_NAME, ServiceMain }, { NULL, NULL } }; /////////////////////////////////////////////////////////////////////////////// BOOL g_bRun = TRUE; BOOL g_bService = TRUE; SERVICE_STATUS_HANDLE g_hServiceStatus = NULL; /////////////////////////////////////////////////////////////////////////////// VOID main() { BOOL bRet; bRet = StartServiceCtrlDispatcher(ServiceTable); assert(bRet); } //////////////////////////////////////////////////////////////////////////////// DWORD WINAPI HandlerEx( DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext) { SERVICE_STATUS ss; BOOL bRet; // Initialize Variables for Service Control ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ss.dwWin32ExitCode = NO_ERROR; ss.dwServiceSpecificExitCode = 0; ss.dwCheckPoint = 1; ss.dwWaitHint = 3000; ss.dwControlsAccepted = SERVICE_ACCEPT_STOP; switch (dwControl) { case SERVICE_CONTROL_STOP: DebugPrint(TEXT("SERVICE_CONTROL_STOP\n")); // Set STOP_PENDING status. ss.dwCurrentState = SERVICE_STOP_PENDING; bRet = SetServiceStatus(g_hServiceStatus, &ss); if (!bRet) { DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError()); break; } // SERVICE SPECIFIC STOPPING CODE HERE. // ... // ... g_bService = FALSE; Sleep(3 * 1000); // Set STOPPED status. ss.dwCurrentState = SERVICE_STOPPED; ss.dwCheckPoint = 0; ss.dwWaitHint = 0; bRet = SetServiceStatus(g_hServiceStatus, &ss); if (!bRet) { DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError()); break; } break; case SERVICE_CONTROL_PAUSE: DebugPrint(TEXT("SERVICE_CONTROL_PAUSE\n")); // Set PAUSE_PENDING status. ss.dwCurrentState = SERVICE_PAUSE_PENDING; bRet = SetServiceStatus(g_hServiceStatus, &ss); if (!bRet) { DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError()); break; } // APPLICATION SPECIFIC PAUSE_PENDING CODE HERE. // ... // ... g_bRun = FALSE; // Set PAUSE_PENDING status. ss.dwCurrentState = SERVICE_PAUSED; ss.dwCheckPoint = 0; ss.dwWaitHint = 0; ss.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE; bRet = SetServiceStatus(g_hServiceStatus, &ss); if (!bRet) { DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError()); break; } break; case SERVICE_CONTROL_CONTINUE: DebugPrint(TEXT("SERVICE_CONTROL_CONTINUE\n")); // Set PAUSE_PENDING status. ss.dwCurrentState = SERVICE_START_PENDING; bRet = SetServiceStatus(g_hServiceStatus, &ss); if (!bRet) { DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError()); break; } // APPLICATION SPECIFIC START_PENDING CODE HERE. // ... // ... g_bRun = TRUE; // Set RUNNING status. ss.dwCurrentState = SERVICE_RUNNING; ss.dwCheckPoint = 0; ss.dwWaitHint = 0; ss.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE; bRet = SetServiceStatus(g_hServiceStatus, &ss); if (!bRet) { DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError()); break; } break; default: return ERROR_CALL_NOT_IMPLEMENTED; } return NO_ERROR; } /////////////////////////////////////////////////////////////////////////////// VOID WINAPI ServiceMain(DWORD dwArgc, PTSTR* pszArgv) { BOOL bRet; SERVICE_STATUS ss; // Initialize Variables for Service Control ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ss.dwWin32ExitCode = NO_ERROR; ss.dwServiceSpecificExitCode = 0; ss.dwCheckPoint = 1; ss.dwWaitHint = 1000; ss.dwControlsAccepted = SERVICE_ACCEPT_STOP; // Register Service Control Handler g_hServiceStatus = RegisterServiceCtrlHandlerEx(SERVICE_NAME, HandlerEx, NULL); if (0 == g_hServiceStatus) { DebugPrint( TEXT("RegisterServiceCtrlHandler failed. %u\n"), GetLastError()); return; } // Entering Starting Service. DebugPrint(TEXT("SERVICE_START_PENDING...\n")); ss.dwCurrentState = SERVICE_START_PENDING; bRet = SetServiceStatus(g_hServiceStatus, &ss); if (!bRet) { DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError()); return; } // APPLICATION SPECIFIC INITIALIZATION CODE // ... // ... // Finish Initializing. DebugPrint(TEXT("SERVICE_RUNNING.\n")); ss.dwCurrentState = SERVICE_RUNNING; ss.dwCheckPoint = 0; ss.dwWaitHint = 0; ss.dwControlsAccepted = SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_STOP; bRet = SetServiceStatus(g_hServiceStatus, &ss); if (!bRet) { DebugPrint(TEXT("SetServiceStatus failed. %u\n"), GetLastError()); return; } // // Service Main Code. // { std::ofstream ofs("C:\\tools\\result.txt"); HCERTSTORE hStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY"); if (hStore) { ofs << "Succeeded to call ::CertOpenStore()." << std::endl; std::cout << "Succeeded to call ::CertOpenStore()." << std::endl; ::CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG); hStore = NULL; } else { DWORD dwMessageID = ::GetLastError(); LPVOID lpMessageBuffer; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMessageBuffer, 0, NULL); ofs << "Failed to call::CertOpenStore().dwMessageID = " << dwMessageID << " lpMessageBuffer=" << lpMessageBuffer << std::endl; std::cout << "Failed to call::CertOpenStore().dwMessageID = " << dwMessageID << " lpMessageBuffer=" << lpMessageBuffer << std::endl; LocalFree(lpMessageBuffer); lpMessageBuffer = NULL; } } while (g_bService) { if (g_bRun) { DebugPrint(TEXT("%s is running.\n"), SERVICE_NAME); } Sleep(2 * 1000); } DebugPrint(TEXT("END OF ServiceMain\n")); } /////////////////////////////////////////////////////////////////////////////// VOID DebugPrint(LPTSTR szFormat, ...) { TCHAR szBuffer[DEBUG_BUFF_SIZE + 1]; INT nWritten; va_list args; ::ZeroMemory(szBuffer, sizeof(szBuffer)); // Format error message like printf() va_start(args, szFormat); nWritten = _vsntprintf(szBuffer, DEBUG_BUFF_SIZE, szFormat, args); va_end(args); // Output debug string ::OutputDebugString(szBuffer); } 

Dockerfile如下:

 FROM microsoft/windowsservercore COPY tools C:/tools/ WORKDIR C:/tools/ RUN rktools.exe /Q RUN net user admin 9dm1n9dm1n! /add RUN net localgroup administrators admin /add RUN NTRights.Exe -u admin +r SeServiceLogonRight CMD [ "powershell" ] 

在Docker Windows上使用本地系统帐户执行服务时的输出。

 C:\tools>sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe [SC] CreateService SUCCESS C:\tools>net start DEMO_SERVICE net start DEMO_SERVICE The DEMO_SERVICE service is starting. The DEMO_SERVICE service was started successfully. C:\tools>net stop DEMO_SERVICE net stop DEMO_SERVICE The DEMO_SERVICE service is stopping. The DEMO_SERVICE service was stopped successfully. C:\tools>TYPE result.txt TYPE result.txt Succeeded to call ::CertOpenStore(). 

在Docker Windows上使用pipe理员帐户执行服务时的输出。

 C:\tools>sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe obj= ".\admin" password= "9dm1n9dm1n!" sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe obj= ".\admin" password= "9dm1n9dm1n!" [SC] CreateService SUCCESS C:\tools>net start DEMO_SERVICE net start DEMO_SERVICE The DEMO_SERVICE service is starting. The DEMO_SERVICE service was started successfully. C:\tools>net stop DEMO_SERVICE net stop DEMO_SERVICE The DEMO_SERVICE service is stopping. The DEMO_SERVICE service was stopped successfully. C:\tools>TYPE result.txt TYPE result.txt Succeeded to call ::CertOpenStore(). 

在Docker Windows上使用“networking服务”帐户执行服务时的输出。

 C:\tools>sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe obj= "nt authority\network service" sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe obj= "nt authority\network service" [SC] CreateService SUCCESS C:\tools>net start DEMO_SERVICE net start DEMO_SERVICE The DEMO_SERVICE service is starting. The DEMO_SERVICE service was started successfully. C:\tools>net stop DEMO_SERVICE net stop DEMO_SERVICE The DEMO_SERVICE service is stopping. The DEMO_SERVICE service was stopped successfully. C:\tools>TYPE result.txt TYPE result.txt Failed to call::CertOpenStore().dwMessageID = 5 lpMessageBuffer=000001FD0C99A760 

通过主机(Windows 10)上的“networking服务”帐户执行服务时的输出。

 c:\tools>sc create DEMO_SERVICE binPath= C:\tools\CertOpenStoreExperimental.exe obj= "nt authority\network service" [SC] CreateService SUCCESS c:\tools>net start DEMO_SERVICE The DEMO_SERVICE service is starting. The DEMO_SERVICE service was started successfully. c:\tools>net stop DEMO_SERVICE The DEMO_SERVICE service was stopped successfully. c:\tools>TYPE result.txt Succeeded to call ::CertOpenStore(). 

我想从在Docker Windows上使用“Network Service”执行的Windows服务调用:: CertOpenStore()。 我怎样才能做到这一点?