spshell.cpp 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052
  1. #include "precompile.h"
  2. #include "app.h"
  3. #include "osutil.h"
  4. #include "sp_dbg_export.h"
  5. #ifdef _WIN32
  6. #include <DbgHelp.h>
  7. #include <TlHelp32.h>
  8. #include <shellapi.h>
  9. #else
  10. #include <unistd.h>
  11. #endif //_WIN32
  12. #include "fileutil.h"
  13. #include "iniutil.h"
  14. #include "getopt.h"
  15. #include "toolkit.h"
  16. #include "SimpleString.h"
  17. #include "SpBase.h"
  18. #ifdef _WIN32
  19. #include <io.h>
  20. #endif //_WIN32
  21. #include <locale.h>
  22. #include <winpr/library.h>
  23. #include <winpr/environment.h>
  24. #include <winpr/registry.h>
  25. #include <winpr/sysinfo.h>
  26. using namespace std;
  27. #define DRIVER_NAME "HelloDDK"
  28. #define DRIVER_PATH "InterceptDll.sys"
  29. #define SET_EVENT \
  30. CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
  31. #define GET_SHARE_ADD \
  32. CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
  33. HANDLE g_hEvent = NULL;
  34. bool g_bMD5Exist = false;
  35. bool g_bWow64 = false;
  36. CSimpleStringA g_strMD5ListPath;
  37. static void SetEnvPath()
  38. {
  39. char path[MAX_PATH];
  40. char *buf;
  41. DWORD size;
  42. const char *var = "PATH";
  43. // set current path
  44. GetModuleFileNameA(NULL, path, MAX_PATH);
  45. *strrchr(path, SPLIT_SLASH) = 0;
  46. *strrchr(path, SPLIT_SLASH) = 0;
  47. SetCurrentDirectoryA(path);
  48. // append dep sub dir to %PATH%
  49. strcat(path, SPLIT_SLASH_STR "dep");
  50. size = GetEnvironmentVariableA(var, NULL, 0);
  51. buf = (char*)malloc(size+MAX_PATH*3);
  52. size = GetEnvironmentVariableA(var, buf, size);
  53. strcpy(buf+size, ENV_SEP_STR);
  54. strcat(buf+size, path);
  55. *strrchr(path, SPLIT_SLASH) = 0;
  56. strcat(path, SPLIT_SLASH_STR "bin");
  57. strcat(buf+size, ENV_SEP_STR);
  58. strcat(buf+size, path);
  59. *strrchr(path, SPLIT_SLASH) = 0;
  60. strcat(path, SPLIT_SLASH_STR "dev");
  61. strcat(buf+size, ENV_SEP_STR);
  62. strcat(buf+size, path);
  63. *strrchr(path, SPLIT_SLASH) = 0;
  64. strcat(path, SPLIT_SLASH_STR "imdep");
  65. strcat(buf + size, ENV_SEP_STR);
  66. strcat(buf + size, path);
  67. SetEnvironmentVariableA(var, buf);
  68. free(buf);
  69. SetEnvironmentVariableA("ModuleName", "SpShell");
  70. }
  71. #ifdef _WIN32
  72. // 获取设置内存使用率,4G
  73. static void SetWorkingSet()
  74. {
  75. SIZE_T dwMinSize, dwMaxSize;
  76. HANDLE hCurrProcess = GetCurrentProcess();
  77. GetProcessWorkingSetSize(hCurrProcess, &dwMinSize, &dwMaxSize);
  78. if (dwMaxSize < (2 << 20))
  79. dwMaxSize = 2 << 20;
  80. SetProcessWorkingSetSize(hCurrProcess, dwMinSize, dwMaxSize);
  81. }
  82. static LONG WINAPI SuppressError(struct _EXCEPTION_POINTERS* ExceptionInfo)
  83. {
  84. char tmp[MAX_PATH];
  85. HANDLE hDumpFile;
  86. wsprintfA(tmp, ".\\expt.spshell.%d.%d.dmp", GetCurrentThreadId(), GetCurrentProcessId());
  87. hDumpFile = CreateFileA( tmp, GENERIC_READ | GENERIC_WRITE,
  88. 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  89. if( ( hDumpFile != NULL ) && ( hDumpFile != INVALID_HANDLE_VALUE ) )
  90. {
  91. MINIDUMP_EXCEPTION_INFORMATION mdei;
  92. MINIDUMP_TYPE mdt;
  93. mdei.ThreadId = GetCurrentThreadId();
  94. mdei.ExceptionPointers = ExceptionInfo;
  95. mdei.ClientPointers = FALSE;
  96. mdt = MiniDumpNormal;
  97. MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
  98. hDumpFile, mdt, (ExceptionInfo != 0) ? &mdei : 0, 0, 0 );
  99. CloseHandle( hDumpFile );
  100. }
  101. char szCmd[256];
  102. sprintf_s(szCmd, 256, "TASKKILL /f /im sphost.exe");
  103. system(szCmd);
  104. ExitProcess(Error_Exception); // exit process to suppress reporting exception
  105. return EXCEPTION_EXECUTE_HANDLER;
  106. }
  107. static void DisableSetUnhandledExceptionFilter()
  108. {
  109. void* addr = (void*)GetProcAddress(LoadLibrary("kernel32.dll"), "SetUnhandledExceptionFilter");
  110. if (addr) {
  111. DWORD dwOldFlag, dwTempFlag;
  112. unsigned char code[] = {0x33, 0xC0, 0xC2, 0x04, 0x00}; // xor eax,eax; ret 4;
  113. //VirtualProtect(addr, sizeof(code), PAGE_READWRITE, &dwOldFlag);
  114. VirtualProtectEx(GetCurrentProcess(), addr, sizeof(code), PAGE_EXECUTE_READWRITE, &dwOldFlag);
  115. WriteProcessMemory(GetCurrentProcess(), addr, code, sizeof(code), NULL);
  116. VirtualProtect(addr, sizeof(code), dwOldFlag, &dwTempFlag);
  117. }
  118. }
  119. __declspec(dllimport) bool DisableCharmbar();
  120. __declspec(dllimport) bool EnableCharmbar();
  121. static HANDLE create_process(const char *app)
  122. {
  123. //BOOL bRet;
  124. STARTUPINFOA si = { sizeof(STARTUPINFOA) };
  125. si.wShowWindow = SW_SHOWMAXIMIZED;
  126. si.dwFlags = STARTF_USESHOWWINDOW;
  127. PROCESS_INFORMATION pi;
  128. DWORD dwSessionId;
  129. HANDLE hUserTokenDup, hThisToken;
  130. HANDLE hProcess = NULL;
  131. dwSessionId = WTSGetActiveConsoleSessionId();
  132. if (OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hThisToken)) {
  133. LUID luid;
  134. TOKEN_PRIVILEGES tp;
  135. LPVOID pEnv = NULL;
  136. LookupPrivilegeValueA(NULL, SE_DEBUG_NAME, &luid);
  137. tp.PrivilegeCount = 1;
  138. tp.Privileges[0].Luid = luid;
  139. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  140. DuplicateTokenEx(hThisToken, MAXIMUM_ALLOWED, NULL,
  141. SecurityIdentification, TokenPrimary, &hUserTokenDup);
  142. SetTokenInformation(hUserTokenDup,
  143. TokenSessionId, (void*)&dwSessionId, sizeof(DWORD));
  144. AdjustTokenPrivileges(hUserTokenDup, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
  145. (PTOKEN_PRIVILEGES)NULL, NULL);
  146. //CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE);
  147. if (CreateProcessAsUserA(hUserTokenDup, NULL,
  148. (LPSTR)app,
  149. NULL, NULL, FALSE, 0, pEnv, NULL, &si, &pi))
  150. {
  151. CloseHandle(pi.hThread);
  152. hProcess = pi.hProcess;
  153. }
  154. else
  155. sp_dbg_warn("create process failed! Error : ", GetLastError());
  156. //if (pEnv)
  157. //DestroyEnvironmentBlock(pEnv);
  158. CloseHandle(hUserTokenDup);
  159. CloseHandle(hThisToken);
  160. }
  161. else {
  162. sp_dbg_warn("open process token failed! Error : ", GetLastError());
  163. }
  164. return hProcess;
  165. }
  166. static void AutoHideTaskBar(bool bHide)
  167. {
  168. APPBARDATA apBar;
  169. memset(&apBar, 0, sizeof(apBar));
  170. apBar.cbSize = sizeof(apBar);
  171. apBar.lParam = bHide ? ABS_AUTOHIDE : ABS_ALWAYSONTOP;
  172. apBar.hWnd = FindWindow("Shell_TrayWnd", NULL);
  173. if (apBar.hWnd != NULL)
  174. {
  175. SHAppBarMessage(ABM_SETSTATE, &apBar);
  176. }
  177. }
  178. static bool AddRegIntValue(HKEY hKey, const char *szSubKey, const char *szKeyName, DWORD dwValue, bool bWin64)
  179. {
  180. HKEY hSubKey;
  181. LONG nRet = ::RegCreateKeyEx(hKey,
  182. szSubKey,
  183. 0,
  184. NULL,
  185. 0,
  186. bWin64 ? (KEY_ALL_ACCESS | KEY_WOW64_64KEY) : (KEY_ALL_ACCESS | KEY_WOW64_32KEY),
  187. NULL,
  188. &hSubKey,
  189. NULL);
  190. if (nRet != ERROR_SUCCESS)
  191. return false;
  192. nRet = RegSetValueExA(hSubKey, szKeyName, 0, REG_DWORD, (BYTE*)&dwValue, sizeof(DWORD));
  193. RegCloseKey(hSubKey);
  194. return (nRet == ERROR_SUCCESS);
  195. }
  196. static bool AddFirewallRules()
  197. {
  198. char szBinDir[MAX_PATH] = {};
  199. GetModuleFileNameA(NULL, szBinDir, MAX_PATH);
  200. *strrchr(szBinDir, SPLIT_SLASH) = 0;
  201. int nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpShell\"\"", NULL, SW_HIDE);
  202. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpShell\"\"", NULL, SW_HIDE);
  203. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpHost\"\"", NULL, SW_HIDE);
  204. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpGuardian\"\"", NULL, SW_HIDE);
  205. char szParam[1024] = {};
  206. sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpShell\"\" dir=out program=\"\"%s\\spshell.exe\"\" action=allow\"", szBinDir);
  207. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
  208. sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpHost\"\" dir=out program=\"\"%s\\sphost.exe\"\" action=allow\"", szBinDir);
  209. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
  210. sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpGuardian\"\" dir=out program=\"\"%s\\guardian.exe\"\" action=allow\"", szBinDir);
  211. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
  212. return nRet > 32;
  213. }
  214. int AddFireAddFirewallRulesThread(void* param)
  215. {
  216. if (!AddFirewallRules())
  217. {
  218. sp_dbg_fatal("设置Windows防火墙策略失败!!!");
  219. Sleep(10000);
  220. return -1;
  221. }
  222. else
  223. sp_dbg_info("设置Windows防火墙策略成功!!!");
  224. return 0;
  225. }
  226. static void AddFirewallRulesEx()
  227. {
  228. CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)& AddFireAddFirewallRulesThread, NULL, 0, NULL));
  229. }
  230. static bool DisableWindowsCharmBar(bool bX64)
  231. {
  232. if (!bX64)
  233. {
  234. if (DisableCharmbar())
  235. {
  236. sp_dbg_info("disable windows 8 charmbar succ");
  237. return true;
  238. }
  239. else
  240. {
  241. sp_dbg_error("disable windows 8 charmbar fail: %x", GetLastError());
  242. return false;
  243. }
  244. }
  245. else
  246. {
  247. // 由于64位Windows Hook需要64位进程和64位dll,需要独立启动MetroWatcher64注入
  248. char path[MAX_PATH] = {};
  249. GetModuleFileNameA(NULL, path, MAX_PATH);
  250. *strrchr(path, SPLIT_SLASH) = 0;
  251. char app[MAX_PATH] = {};
  252. sprintf(app, "%s\\MetroWatcher64.exe %d", path, GetCurrentProcessId());
  253. if (create_process(app) != NULL)
  254. {
  255. sp_dbg_info("disable windows 8 (64bit) charmbar succ");
  256. return true;
  257. }
  258. else
  259. {
  260. sp_dbg_error("disable windows 8 (64bit) charmbar fail: %x", GetLastError());
  261. return false;
  262. }
  263. }
  264. }
  265. #endif //_WIN32
  266. /*!
  267. * at Linux, judge whether current process runs as root privilege.
  268. * @return : True only if run as admin or root
  269. */
  270. static bool IsProcessRunAsAdmin()
  271. {
  272. BOOL bAdmin = FALSE;
  273. #ifdef _WIN32
  274. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  275. PSID AdministratorsGroup = NULL;
  276. sp_dbg_info("start AllocateAndInitializeSid");
  277. if (AllocateAndInitializeSid(
  278. &NtAuthority,
  279. 2,
  280. SECURITY_BUILTIN_DOMAIN_RID,
  281. DOMAIN_ALIAS_RID_ADMINS,
  282. 0, 0, 0, 0, 0, 0,
  283. &AdministratorsGroup)) {
  284. sp_dbg_info("start CheckTokenMembership");
  285. CheckTokenMembership(NULL, AdministratorsGroup, &bAdmin);
  286. sp_dbg_info("start FreeSid");
  287. FreeSid(AdministratorsGroup);
  288. }
  289. #else
  290. if (geteuid() == 0) {
  291. bAdmin = TRUE;
  292. } else {
  293. sp_dbg_warn("current process is not run as root privilege, euid:%u, uid:%d", geteuid(), getuid());
  294. }
  295. #endif //_WIN32
  296. return bAdmin == TRUE;
  297. }
  298. const char *GetMachineType()
  299. {
  300. auto env = sp_get_env();
  301. if (env == NULL)
  302. {
  303. sp_dbg_error("sp_get_env return null");
  304. return NULL;
  305. }
  306. return env->cfg->root_ini->machine_type;
  307. }
  308. const char *GetCenterSettingNameBySite(const char *pszSite)
  309. {
  310. if ((stricmp(pszSite, "CMB.LIB") == 0) // 行内大堂
  311. || (stricmp(pszSite, "CMB.SSB") == 0))//
  312. {
  313. return "CenterSetting.LAN.ini";
  314. }
  315. else if ((stricmp(pszSite, "CMB.LSS") == 0) //
  316. || (stricmp(pszSite, "CMB.FLB") == 0) //
  317. || (stricmp(pszSite, "CMB.OSB") == 0) //
  318. || (stricmp(pszSite, "CMB.SMM") == 0)) //
  319. {
  320. return "CenterSetting.DMZ.ini";
  321. }
  322. else
  323. {
  324. return "CenterSetting.DMZ.ini";
  325. }
  326. }
  327. const char *GetWebSiteFromConfig()
  328. {
  329. auto env = sp_get_env();
  330. if (env == NULL)
  331. {
  332. sp_dbg_error("sp_get_env return null");
  333. return NULL;
  334. }
  335. auto pszCenterSettingName = GetCenterSettingNameBySite(env->cfg->root_ini->site);
  336. char szCfgFile[256] = {};
  337. sprintf_s(szCfgFile, sizeof(szCfgFile), "%s\\%s", env->dir->cfg_path, pszCenterSettingName);
  338. // 判断对应集中配置文件是否存在,不存在则重命名CenterSetting.ini
  339. if (!ExistsFileA(szCfgFile))
  340. {
  341. char szBackupCfgFile[256] = {};
  342. sprintf_s(szBackupCfgFile, sizeof(szCfgFile), "%s\\CenterSetting.ini", env->dir->cfg_path);
  343. // default CenterSetting config file has been removed ? I can see it in depository [3/19/2020 7:47 Gifur]
  344. if (ExistsFileA(szBackupCfgFile))
  345. {
  346. rename(szBackupCfgFile, szCfgFile);
  347. }
  348. }
  349. // get machine type
  350. auto pMachineType = env->cfg->root_ini->machine_type;
  351. char szKeyName[256] = {};
  352. sprintf(szKeyName, "IEBrowser.%s.URL", pMachineType);
  353. auto pWebSite = inifile_read_str(szCfgFile, "HealthManager", szKeyName, NULL);
  354. if (pWebSite == NULL || strlen(pWebSite)==0)
  355. {
  356. sp_dbg_error("read %s from %s return null", szKeyName, pszCenterSettingName);
  357. return NULL;
  358. }
  359. // http://99.1.100.217/RVC.Web/default.aspx http://99.1.100.217/RVC.Web/default2.aspx
  360. // get root url
  361. auto p = strchr(pWebSite + 7, '/');
  362. if (p != NULL)
  363. *p = 0;
  364. p = strchr(pWebSite + 7, ':');
  365. if (p == NULL)
  366. strcat(pWebSite, ":80");
  367. return pWebSite;
  368. }
  369. #ifdef _WIN32
  370. static bool WebcamMicrophoneAuthorize(bool bWin64)
  371. {
  372. const char *pWetSite = GetWebSiteFromConfig();
  373. TCHAR szSubKey[1024] = { 0 };
  374. sprintf(szSubKey, "Software\\AppDataLow\\Software\\Microsoft\\Silverlight\\Permissions\\%s", pWetSite);
  375. if (!AddRegIntValue(HKEY_CURRENT_USER, szSubKey, "WebcamAndMicrophone", 0x00000011, bWin64))
  376. {
  377. sp_dbg_error("创建SL摄像机麦克风权限注册表项失败!");
  378. return false;
  379. }
  380. sp_dbg_info("add silverlight webcam and microphone permission succeed");
  381. return true;
  382. }
  383. #endif //_WIN32
  384. static bool SpTerminateProcess(HANDLE hProc, DWORD dwProcID)
  385. {
  386. if (!TerminateProcess(hProc, -1))
  387. {
  388. #ifdef _WIN32
  389. char szCmd[256];
  390. int nRet = 0;
  391. sp_dbg_debug("terminate process %d fail: 0x%X, retry with taskkill", dwProcID, GetLastError());
  392. sprintf_s(szCmd, 256, "TASKKILL /PID %d /F", dwProcID);
  393. WinExec(szCmd, SW_HIDE);
  394. return nRet != -1;
  395. #else
  396. return false;
  397. #endif //_WIN32
  398. }
  399. return true;
  400. }
  401. // replace it with osutil from libtoolkit [3/18/2020 19:01 Gifur]
  402. /*
  403. static bool DetectDuplicateInstance(char **pNames, int nNum)
  404. {
  405. sp_dbg_info("start GetCurrentProcessId");
  406. DWORD dwCurProcID = GetCurrentProcessId();
  407. sp_dbg_info("start CreateToolhelp32Snapshot");
  408. HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  409. if (hSnapshot)
  410. {
  411. PROCESSENTRY32 pe = {};
  412. pe.dwSize = sizeof(pe);
  413. sp_dbg_info("start Process32First");
  414. if (Process32First(hSnapshot, &pe))
  415. {
  416. do
  417. {
  418. for (int i = 0; i < nNum; i++)
  419. {
  420. if (stricmp(&pe.szExeFile[0], pNames[i]) == 0 && pe.th32ProcessID != dwCurProcID)
  421. {
  422. sp_dbg_info("start OpenProcess");
  423. HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
  424. if (hProc == NULL)
  425. {
  426. sp_dbg_error("find duplicated process: %s, id: %d", pNames[i], pe.th32ProcessID);
  427. CloseHandle(hSnapshot);
  428. return false;
  429. }
  430. if (!SpTerminateProcess(hProc, pe.th32ProcessID))
  431. {
  432. sp_dbg_error("terminate duplicated process %s fail, id: %d, error: %d", pNames[i], pe.th32ProcessID, GetLastError());
  433. CloseHandle(hSnapshot);
  434. return false;
  435. }
  436. sp_dbg_info("terminate duplicated process: %s, id: %d", pNames[i], pe.th32ProcessID);
  437. }
  438. }
  439. } while (Process32Next(hSnapshot, &pe));
  440. }
  441. CloseHandle(hSnapshot);
  442. }
  443. return true;
  444. }
  445. */
  446. #ifdef _WIN32
  447. static bool LoadInterceptDllDriver(char* lpszDriverName,char* lpszDriverPath)
  448. {
  449. /************************ 加载DLL监控驱动的代码*******************************
  450. ① 调用OpenSCManager,打开SCM管理器.如果返回NULL,则返回失败,否则继续
  451. ② 调用CreateService,创建服务,创建成功则转步骤 ⑥
  452. ③ 用GetLastError的得到错误返回值
  453. ④ 返回值为ERROR_IO_PENDING,说明服务已经创建过,用OpenService打开此服务.
  454. ⑤ 返回值为其他值, 创建武服务失败,返回失败.
  455. ⑥ 调用StartService开启服务
  456. ⑦ 成功返回
  457. ************************************************************************/
  458. CSimpleStringA strDriverPath;
  459. TCHAR szPath[MAX_PATH] = {0};
  460. GetModuleFileNameA(NULL, szPath, MAX_PATH);
  461. *strrchr(szPath, SPLIT_SLASH) = 0;
  462. strDriverPath = szPath;
  463. if (g_bWow64)
  464. {
  465. strDriverPath += SPLIT_SLASH_STR "InterceptDll_64.sys";
  466. }
  467. else
  468. {
  469. strDriverPath += SPLIT_SLASH_STR "InterceptDll_32.sys";
  470. }
  471. sp_dbg_info("strDriverPath[%s]",strDriverPath);
  472. bool bRet = false;
  473. SC_HANDLE hServiceMgr=NULL;
  474. SC_HANDLE hServiceDDK=NULL;
  475. hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  476. if(hServiceMgr == NULL)
  477. {
  478. sp_dbg_fatal("OpenSCManager() Failed %d!", GetLastError());
  479. bRet = false;
  480. goto BeforeLeave;
  481. }
  482. else
  483. {
  484. sp_dbg_info("OpenSCManager() ok");
  485. }
  486. hServiceDDK = CreateService(hServiceMgr,
  487. lpszDriverName, // 驱动程序的在注册表中的名字
  488. lpszDriverName, // 注册表驱动程序的 DisplayName 值
  489. SERVICE_ALL_ACCESS, // 加载驱动程序的访问权限
  490. SERVICE_KERNEL_DRIVER, // 表示加载的服务是驱动程序
  491. SERVICE_DEMAND_START, // 注册表驱动程序的 Start 值
  492. SERVICE_ERROR_IGNORE, // 注册表驱动程序的 ErrorControl 值
  493. //szDriverImagePath, // 注册表驱动程序的 ImagePath 值
  494. strDriverPath.GetData(),
  495. //"C:\\Run\\version\\1.10.0.0\\bin\\InterceptDll.sys",
  496. NULL,
  497. NULL,
  498. NULL,
  499. NULL,
  500. NULL);
  501. DWORD dwRtn;
  502. if(hServiceDDK == NULL) // 判断服务是否失败
  503. {
  504. dwRtn = GetLastError();
  505. if(dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS)
  506. {
  507. sp_dbg_fatal("CreateService() Faild %d !", dwRtn);
  508. bRet = false;
  509. goto BeforeLeave;
  510. }
  511. else
  512. {
  513. sp_dbg_info("CreateService() Faild Service is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS!");
  514. }
  515. // 驱动程序已经加载,只需要打开
  516. hServiceDDK = OpenService(hServiceMgr, lpszDriverName, SERVICE_ALL_ACCESS);
  517. if(hServiceDDK == NULL)
  518. {
  519. // 如果打开服务也失败,则意味错误
  520. dwRtn = GetLastError();
  521. sp_dbg_fatal("OpenService() Faild %d!", dwRtn);
  522. bRet = false;
  523. goto BeforeLeave;
  524. }
  525. else
  526. {
  527. sp_dbg_info("OpenService() ok!");
  528. }
  529. }
  530. else
  531. {
  532. sp_dbg_info("CrateService() ok !");
  533. }
  534. bRet= StartService(hServiceDDK, NULL, NULL);
  535. if(!bRet)
  536. {
  537. DWORD dwRtn = GetLastError();
  538. if(dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING)
  539. {
  540. sp_dbg_fatal("StartService() Faild %d !", dwRtn);
  541. bRet = false;
  542. goto BeforeLeave;
  543. }
  544. else
  545. {
  546. if(dwRtn == ERROR_IO_PENDING)
  547. {
  548. // 设备被挂住
  549. sp_dbg_fatal("StartService() Faild ERROR_IO_PENDING!");
  550. bRet = false;
  551. goto BeforeLeave;
  552. }
  553. else
  554. {
  555. // 服务已经开启
  556. sp_dbg_fatal("StartService() Faild ERROR_SERVICE_ALREADY_RUNNING!");
  557. bRet = true;
  558. goto BeforeLeave;
  559. }
  560. }
  561. }
  562. else
  563. {
  564. sp_dbg_info("StartService() ok!");
  565. }
  566. bRet = true;
  567. BeforeLeave:
  568. if(hServiceDDK)
  569. {
  570. CloseServiceHandle(hServiceDDK); // 服务句柄
  571. }
  572. if(hServiceMgr)
  573. {
  574. CloseServiceHandle(hServiceMgr); // SCM句柄
  575. }
  576. return bRet;
  577. }
  578. static bool UnloadInterceptDllDriver(char* szSvrName)
  579. {
  580. /************************* 卸载NT驱动的代码******************************
  581. ① 调用OpenSCManager,打开SCM管理器,如果返回NULL,则返回失败,否则继续.
  582. ② 调用OpenService.如果返回NULL,则返回失败,否则继续
  583. ③ 调用DeleteService卸载此项服务.
  584. ④ 成功返回.
  585. ************************************************************************/
  586. bool bRet = false;
  587. SC_HANDLE hServiceMgr=NULL;// SCM管理器的句柄
  588. SC_HANDLE hServiceDDK=NULL;// NT驱动程序的服务句柄
  589. SERVICE_STATUS SvrSta;
  590. sp_dbg_info("start OpenSCManager");
  591. hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  592. if( hServiceMgr == NULL )
  593. {
  594. sp_dbg_info("OpenSCManager() Failed %d!", GetLastError());
  595. bRet = false;
  596. goto BeforeLeave;
  597. }
  598. else
  599. {
  600. sp_dbg_info("OpenSCManager() ok !");
  601. }
  602. hServiceDDK = OpenService(hServiceMgr, szSvrName, SERVICE_ALL_ACCESS);
  603. if(hServiceDDK == NULL)
  604. {
  605. sp_dbg_info("OpenService() Failed %d!", GetLastError());
  606. bRet = false;
  607. goto BeforeLeave;
  608. }
  609. else
  610. {
  611. sp_dbg_info("OpenService() ok !");
  612. }
  613. // 停止驱动程序,如果停止失败,只有重新启动才能,再动态加载。
  614. if(!ControlService(hServiceDDK, SERVICE_CONTROL_STOP , &SvrSta ))
  615. {
  616. sp_dbg_info("ControlService() Failed %d!", GetLastError());
  617. }
  618. else
  619. {
  620. sp_dbg_info("ControlService() ok !");
  621. }
  622. if(!DeleteService(hServiceDDK))
  623. {
  624. sp_dbg_info("DeleteSrevice() Failed %d!", GetLastError());
  625. }
  626. else
  627. {
  628. sp_dbg_info("DelServer:DeleteSrevice() ok !");
  629. }
  630. bRet = true;
  631. BeforeLeave:
  632. if(hServiceDDK)
  633. {
  634. CloseServiceHandle(hServiceDDK); // 服务句柄
  635. }
  636. if(hServiceMgr)
  637. {
  638. CloseServiceHandle(hServiceMgr); // SCM 句柄
  639. }
  640. return bRet;
  641. }
  642. #endif //_WIN32
  643. void DisplayUsage()
  644. {
  645. char szHelp[1024] = { '\0' };
  646. sprintf_s(szHelp, 1024, "\n"
  647. "Usage spshell [--entity <entityName>] [--guardian] [--test] [--debug] [--ipc <pipe|tcp>]\n"
  648. " --entity {entityName} -- 启动指定的实体\n"
  649. " --guardian -- 以后台监控形式运行程序\n"
  650. " --test -- 以测试模式运行程序\n"
  651. " --debug -- 以Debug的模式运行程序\n"
  652. " --kill -- 直接杀死程序相关进程\n"
  653. " --ipc <pipe,tcp> -- pipe: 实体间以管道的方式通信;tcp: 实体间以socket的方式通信\n"
  654. );
  655. //sp_dbg_info(szHelp);
  656. #ifdef _WIN32
  657. MessageBoxA(NULL, szHelp, "Spshell Usage Tip", MB_OK);
  658. #else
  659. printf(szHelp);
  660. #endif //_WIN32
  661. }
  662. const char* GetFullVersionString(bool logFlag = false)
  663. {
  664. static char szVersion[128] = {'\0'};
  665. if (strlen(szVersion) == 0) {
  666. CVersion spbase_version;
  667. GetLibVersion(spbase_version);
  668. sprintf_s(szVersion, 128, "spbase version: %s(build date: %s)%s"
  669. "libtoolkit version: %s",
  670. spbase_version.ToString().GetData(), GetLibBuildDate(), logFlag ? " " : "\n",
  671. toolkit_version_string());
  672. }
  673. return szVersion;
  674. }
  675. sp_cfg_start_args_t* DealWithArgs(int argc, char** argv)
  676. {
  677. int allocedEntitiyLen = 0;
  678. sp_cfg_start_args_t* args = MALLOC_T(sp_cfg_start_args_t);
  679. assert(args);
  680. memset(args, 0, sizeof(sp_cfg_start_args_t));
  681. static struct option spshell_options[] = {
  682. {"entity", required_argument, 0, 'E' },
  683. {"guardian", no_argument, 0, 'G'},
  684. {"test", no_argument, 0, 'T'},
  685. {"debug", no_argument, 0, 'D'},
  686. {"ipc", required_argument, 0, 'I'},
  687. {"shutdown", no_argument, 0, 'S'},
  688. {"kill", no_argument, 0, 'K'},
  689. {"help", no_argument, 0, 'H'},
  690. {"version", no_argument, 0, 'V'},
  691. {0, 0, 0, 0}
  692. };
  693. int spshell_index = 0;
  694. int c;
  695. while ((c = getopt_long(argc, argv, "E:GTDI:?", spshell_options, &spshell_index)) != EOF) {
  696. switch (c) {
  697. case 'E':
  698. {
  699. //sp_dbg_info("start specified entity: %s", optarg);
  700. if (optarg != NULL) {
  701. const int len = strlen(optarg);
  702. if (args->start_entities == NULL || len + strlen(args->start_entities) + 2 /*;\0*/ >= allocedEntitiyLen) {
  703. if (args->start_entities == NULL) {
  704. assert(allocedEntitiyLen == 0);
  705. allocedEntitiyLen = 128;
  706. args->start_entities = CALLOC_T(allocedEntitiyLen, char);
  707. if (NULL == args->start_entities) {
  708. exit(-1);
  709. }
  710. }
  711. else {
  712. assert(allocedEntitiyLen != 0);
  713. const int newLen = allocedEntitiyLen + len + 32;
  714. char* newAlloc = CALLOC_T(newLen, char);
  715. if (NULL == newAlloc) {
  716. exit(-1);
  717. }
  718. memset(newAlloc, '\0', sizeof(char) * newLen);
  719. strcpy_s(newAlloc, newLen, args->start_entities);
  720. FREE(args->start_entities);
  721. args->start_entities = newAlloc;
  722. allocedEntitiyLen = newLen;
  723. }
  724. }
  725. strcat(args->start_entities, optarg);
  726. strcat(args->start_entities, ";");
  727. }
  728. }
  729. break;
  730. case 'G':
  731. //sp_dbg_info("run spshell as guardian mode!");
  732. args->guardian_mode = 1;
  733. break;
  734. case 'D':
  735. //sp_dbg_info("run spshell as debug mode!");
  736. args->debug_mode = 1;
  737. break;
  738. case 'T':
  739. //sp_dbg_info("run spshell as test mode!");
  740. args->test_mode = 1;
  741. break;
  742. case 'I':
  743. //sp_dbg_info("run spshell with specified ipc method: %s", optarg);
  744. if (optarg) {
  745. if (strnicmp(optarg, "tcp", strlen("tcp")) == 0)
  746. args->ipc_type = 1;
  747. }
  748. break;
  749. case 'K':
  750. {
  751. //sp_dbg_info("terminate spshell!");
  752. char* relate_processes[] = {
  753. #ifdef _WIN32
  754. "spshell.exe", "sphost.exe", "guardian.exe"
  755. #else
  756. "spshell", "sphost", "guardian"
  757. #endif //_WIN32
  758. };
  759. osutil_terminate_related_process(relate_processes, sizeof(relate_processes) / sizeof(relate_processes[0]));
  760. exit(0);
  761. }
  762. break;
  763. case 'V':
  764. {
  765. #ifdef _WIN32
  766. MessageBoxA(NULL, GetFullVersionString(), "Spshell", MB_OK);
  767. #else
  768. printf("%s\n", GetFullVersionString());
  769. #endif //_WIN32
  770. exit(0);
  771. }
  772. break;
  773. case 'H':
  774. case '?':
  775. default:
  776. DisplayUsage();
  777. exit(0);
  778. break;
  779. }
  780. }
  781. if (optind < argc) {
  782. //sp_dbg_warn("non-option ARGV-elements: ");
  783. while (optind < argc) {
  784. //sp_dbg_warn("\t%s", argv[optind++]);
  785. }
  786. }
  787. if (args && args->start_entities != 0) {
  788. args->start_entities[strlen(args->start_entities) - 1] = '\0';
  789. }
  790. return args;
  791. }
  792. int main(int argc, char** argv)
  793. {
  794. sp_cfg_start_args_t* args = DealWithArgs(argc, argv);
  795. WLog_initRVC("SpShell");
  796. #ifdef _WIN32
  797. _CrtSetDebugFillThreshold(0);
  798. #endif //_WIN32
  799. sp_dbg_init("SpShell");
  800. sp_dbg_info("===================SpShell start=====================");
  801. if (argc > 1) {
  802. char cmdline[1024] = { '\0' };
  803. for (int i = 0; i < argc; ++i) {
  804. sprintf_s(cmdline, 1024, "%s %s", cmdline, argv[i]);
  805. }
  806. sp_dbg_info(cmdline);
  807. }
  808. sp_dbg_info(GetFullVersionString(true));
  809. char proc1[64] = { '\0' };
  810. char proc2[64] = { '\0' };
  811. #ifdef _WIN32
  812. strcpy(proc1, "SpShell.exe");
  813. strcpy(proc2, "SpHost.exe");
  814. #else
  815. strcpy(proc1, "spshell");
  816. strcpy(proc2, "sphost");
  817. #endif //_WIN32
  818. char* arrProcName[] = { proc1, proc2 };
  819. //DetectDuplicateInstance
  820. if(!osutil_detect_unique_app(&arrProcName[0], sizeof(arrProcName) / sizeof(arrProcName[0])))
  821. {
  822. sp_dbg_fatal("detect duplicate spshell/sphost process, abort cur boot !!!");
  823. Sleep(10000);
  824. sp_dbg_term();
  825. return -200;
  826. }
  827. if (!IsProcessRunAsAdmin())
  828. {
  829. #ifdef _WIN32
  830. MessageBox(NULL, "Need run with Administrator privilege!", "Error", MB_OK);
  831. #else
  832. sp_dbg_fatal("current process need run with administrator or root privilege !!!");
  833. #endif //_WIN32
  834. Sleep(10000);
  835. sp_dbg_term();
  836. return -201;
  837. } else {
  838. sp_dbg_info("current process has been run with administrator or root privilege.");
  839. }
  840. #ifdef _WIN32
  841. // 设置防火墙注册表配置
  842. AddFirewallRulesEx();
  843. // 自动隐藏状态栏
  844. //AutoHideTaskBar(true);
  845. #endif //_WIN32
  846. #ifdef _WIN32
  847. setlocale(LC_ALL, "chs");
  848. #else
  849. if (NULL == setlocale(LC_ALL, "zh_CN.UTF-8")) {
  850. //zh_CN.UTF-8 zh_CN.GBK
  851. sp_dbg_error("setlocale failed: %s", strerror(errno));
  852. }
  853. sp_dbg_info("测试中文字符:%s", "招商银行");
  854. #endif //_WIN32
  855. SetEnvPath();
  856. #ifdef _WIN32
  857. SetWorkingSet();
  858. SetUnhandledExceptionFilter(&SuppressError);
  859. DisableSetUnhandledExceptionFilter();
  860. #endif //_WIN32
  861. sp_dbg_info("basic config success");
  862. #ifdef _WIN32
  863. // 检测是否Win8及64位
  864. OSVERSIONINFO ver = {};
  865. ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  866. GetVersionEx(&ver);
  867. bool bWin8 = (ver.dwMajorVersion >= 7 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 2));
  868. SYSTEM_INFO sysInfo = {};
  869. GetNativeSystemInfo(&sysInfo);
  870. bool bX64 = (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64);
  871. sp_dbg_info("OS version: %s %d.%d.%d ", bX64 ? "windows 64" : "windows 32", ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber);
  872. // 关闭WebBrowser渲染模式
  873. //DisableWebBrowserRenderMode(bX64);
  874. // 屏蔽CharmBar
  875. if (bWin8 && !DisableWindowsCharmBar(bX64))
  876. {
  877. Sleep(10000);
  878. return -300;
  879. }
  880. //#ifndef _DEBUG
  881. SetErrorMode(SEM_FAILCRITICALERRORS);
  882. //#endif
  883. #endif //_WIN32
  884. auto rc = app_init(args);
  885. FREE(args);
  886. if (rc == 0)
  887. {
  888. #ifdef _WIN32
  889. WebcamMicrophoneAuthorize(bX64);
  890. #endif //_WIN32
  891. rc = app_run();
  892. app_term();
  893. }
  894. else
  895. {
  896. sp_dbg_error("======================================================");
  897. sp_dbg_error("!!!!!! Startup failed, get more detail information from dbg/spshell !!!!!!");
  898. sp_dbg_error("======================================================");
  899. Sleep(10000);
  900. }
  901. #ifdef _WIN32
  902. if (bWin8 && !bX64) {
  903. EnableCharmbar();
  904. }
  905. // 显示状态栏
  906. //AutoHideTaskBar(false);
  907. #endif //_WIN32
  908. sp_dbg_term();
  909. return rc;
  910. }
  911. #ifdef _WIN32
  912. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  913. {
  914. return main(__argc, __argv);
  915. }
  916. #endif //_WIN32