Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

709 lines
16 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. injecter.cxx
  5. Abstract:
  6. Injecter
  7. Author:
  8. Larry Zhu (LZhu) December 1, 2001 Created
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. #pragma hdrstop
  15. #include "injecter.hxx"
  16. DWORD
  17. AdjustDebugPriv(
  18. VOID
  19. )
  20. {
  21. HANDLE hToken = NULL;
  22. DWORD dwErr = 0;
  23. TOKEN_PRIVILEGES newPrivs = {0};
  24. if (!OpenProcessToken(
  25. GetCurrentProcess(),
  26. TOKEN_ADJUST_PRIVILEGES,
  27. &hToken))
  28. {
  29. dwErr = GetLastError();
  30. goto Cleanup;
  31. }
  32. if (!LookupPrivilegeValue(
  33. NULL,
  34. SE_DEBUG_NAME,
  35. &newPrivs.Privileges[0].Luid
  36. ))
  37. {
  38. dwErr = GetLastError();
  39. goto Cleanup;
  40. }
  41. newPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  42. newPrivs.PrivilegeCount = 1;
  43. if (!AdjustTokenPrivileges(
  44. hToken,
  45. FALSE,
  46. &newPrivs,
  47. 0,
  48. NULL,
  49. NULL
  50. ))
  51. {
  52. dwErr = GetLastError();
  53. goto Cleanup;
  54. }
  55. Cleanup:
  56. if (hToken)
  57. {
  58. CloseHandle(hToken);
  59. }
  60. return dwErr;
  61. }
  62. static DWORD
  63. WorkerFunc(
  64. IN REMOTE_INFO* pInfo
  65. )
  66. {
  67. HINSTANCE hDll = NULL;
  68. PFuncRunIt_t pFuncRunit = NULL;
  69. DWORD dwErr = -1;
  70. hDll = pInfo->pFuncLoadLibrary(pInfo->szDllName);
  71. if (hDll != NULL)
  72. {
  73. pFuncRunit = (PFuncRunIt_t) pInfo->pFuncGetProcAddress(
  74. hDll,
  75. pInfo->szProcName
  76. );
  77. if (pFuncRunit != NULL)
  78. {
  79. dwErr = pFuncRunit(
  80. pInfo->cbParameters,
  81. pInfo->Parameters
  82. );
  83. }
  84. else
  85. {
  86. dwErr = -3;
  87. }
  88. //
  89. // ERROR_NO_MORE_USER_HANDLES unload repeatedly
  90. // ERROR_SERVER_HAS_OPEN_HANDLES no unload at all
  91. // others unload once
  92. //
  93. if (ERROR_SERVER_HAS_OPEN_HANDLES != dwErr)
  94. {
  95. pInfo->pFuncFreeLibrary(hDll);
  96. //
  97. // unload abandoned dll
  98. //
  99. if (ERROR_NO_MORE_USER_HANDLES == dwErr)
  100. {
  101. while (pInfo->pFuncFreeLibrary(hDll))
  102. {
  103. // repeat FreeLibrary unit it fails
  104. }
  105. }
  106. }
  107. }
  108. else
  109. {
  110. dwErr = -2;
  111. }
  112. return dwErr;
  113. }
  114. static VOID
  115. MarkerFunc(
  116. VOID
  117. )
  118. {
  119. // empty
  120. }
  121. DWORD
  122. InjectDllToProcess(
  123. IN HANDLE hProc,
  124. IN PCSTR pszDllFileName,
  125. IN ULONG cbParameters,
  126. IN VOID* pvParameters
  127. )
  128. {
  129. DWORD dwErr = ERROR_SUCCESS;
  130. VOID* pRemoteAlloc = NULL;
  131. HANDLE hRemoteThread = NULL;
  132. HINSTANCE hKernel32 = NULL;
  133. HINSTANCE hDll = NULL;
  134. REMOTE_INFO* pRemInfo = NULL;
  135. ULONG cbRemInfo = 0;
  136. ULONG ulFuncSize = 0;
  137. ULONG ulBytesToAlloc = 0;
  138. CHAR szDllPath[MAX_PATH] = {0};
  139. SIZE_T dwBytesWritten = 0;
  140. DWORD dwIgnored;
  141. ULONG cbPadding = sizeof(ULONG);
  142. cbRemInfo = sizeof(REMOTE_INFO) + cbParameters | sizeof(VOID*); // add a safe zone
  143. pRemInfo = (REMOTE_INFO*) new CHAR [cbRemInfo];
  144. if (!pRemInfo)
  145. {
  146. dwErr = ERROR_OUTOFMEMORY;
  147. }
  148. RtlZeroMemory(pRemInfo, cbRemInfo);
  149. pRemInfo->cbParameters = cbParameters;
  150. hKernel32 = LoadLibraryA("Kernel32");
  151. if (!hKernel32)
  152. {
  153. dwErr = GetLastError();
  154. goto Cleanup;
  155. }
  156. pRemInfo->pFuncLoadLibrary = (PFuncLoadLib_t) GetProcAddress(hKernel32, "LoadLibraryA");
  157. if (!pRemInfo->pFuncLoadLibrary)
  158. {
  159. dwErr = GetLastError();
  160. goto Cleanup;
  161. }
  162. pRemInfo->pFuncGetProcAddress = (PFuncGetProcAddr_t) GetProcAddress(hKernel32, "GetProcAddress");
  163. if (!pRemInfo->pFuncGetProcAddress)
  164. {
  165. dwErr = GetLastError();
  166. goto Cleanup;
  167. }
  168. pRemInfo->pFuncFreeLibrary = (PFuncFreeLib_t) GetProcAddress(hKernel32, "FreeLibrary");
  169. if (!pRemInfo->pFuncFreeLibrary)
  170. {
  171. dwErr = GetLastError();
  172. goto Cleanup;
  173. }
  174. if (0 == GetModuleFileNameA(NULL, szDllPath, sizeof (szDllPath)))
  175. {
  176. dwErr = GetLastError();
  177. goto Cleanup;
  178. }
  179. strcpy(strrchr (szDllPath, '\\') + 1, pszDllFileName);
  180. strncpy(pRemInfo->szDllName, szDllPath, sizeof(pRemInfo->szDllName));
  181. strncpy(pRemInfo->szProcName, REMOTE_DLL_ENTRY, sizeof(pRemInfo->szProcName));
  182. pRemInfo->cbParameters = cbParameters;
  183. memcpy(&pRemInfo->Parameters, pvParameters, pRemInfo->cbParameters);
  184. ulFuncSize = (ULONG) ((ULONG_PTR) MarkerFunc - (ULONG_PTR) WorkerFunc);
  185. cbPadding = sizeof(void*) - ulFuncSize % sizeof(void*);
  186. ulBytesToAlloc = ulFuncSize + cbPadding + cbRemInfo;
  187. DebugPrintf(SSPI_LOG, "InjectDllToProcess dllname %s, ulBytesToAlloc %#x, cbRemInfo %#x\n",
  188. pszDllFileName, ulBytesToAlloc, cbRemInfo);
  189. DebugPrintf(SSPI_LOG, "pInfo->pFuncLoadLibrary %p\n", pRemInfo->pFuncLoadLibrary);
  190. DebugPrintf(SSPI_LOG, "pInfo->pFuncGetProcAddress %p\n", pRemInfo->pFuncGetProcAddress);
  191. DebugPrintf(SSPI_LOG, "pInfo->pFuncFreeLibrary %p\n", pRemInfo->pFuncFreeLibrary);
  192. DebugPrintf(SSPI_LOG, "pInfo->szDllName %s\n", pRemInfo->szDllName);
  193. DebugPrintf(SSPI_LOG, "pInfo->szProcName %s\n", pRemInfo->szProcName);
  194. DebugPrintf(SSPI_LOG, "pInfo->cbParameters %#x, pInfo->Parameters %p\n",
  195. pRemInfo->cbParameters, pRemInfo->Parameters);
  196. DebugPrintHex(SSPI_LOG, "Parameters", pRemInfo->cbParameters, pRemInfo->Parameters);
  197. pRemoteAlloc = VirtualAllocEx(
  198. hProc,
  199. NULL,
  200. ulBytesToAlloc,
  201. MEM_COMMIT,
  202. PAGE_READWRITE
  203. );
  204. if (pRemoteAlloc == NULL)
  205. {
  206. dwErr = GetLastError();
  207. goto Cleanup;
  208. }
  209. if (!WriteProcessMemory(
  210. hProc,
  211. pRemoteAlloc,
  212. (PVOID) WorkerFunc,
  213. ulFuncSize + cbPadding,
  214. &dwBytesWritten
  215. ))
  216. {
  217. dwErr = GetLastError();
  218. goto Cleanup;
  219. }
  220. if (!WriteProcessMemory(
  221. hProc,
  222. ((UCHAR*) pRemoteAlloc) + ulFuncSize + cbPadding,
  223. pRemInfo,
  224. cbRemInfo,
  225. &dwBytesWritten
  226. ))
  227. {
  228. dwErr = GetLastError();
  229. goto Cleanup;
  230. }
  231. DebugPrintf(SSPI_LOG,
  232. "InjectDllToProcess pRemoteAlloc %p, pRemInfo %p\n",
  233. pRemoteAlloc, ((UCHAR*) pRemoteAlloc) + ulFuncSize + cbPadding);
  234. hRemoteThread = CreateRemoteThread(
  235. hProc,
  236. NULL,
  237. 0,
  238. (PTHREAD_START_ROUTINE) pRemoteAlloc, // start address
  239. ((UCHAR*) pRemoteAlloc) + ulFuncSize + cbPadding, // parameter
  240. 0, // creation flags
  241. &dwIgnored
  242. );
  243. if (!hRemoteThread)
  244. {
  245. dwErr = GetLastError();
  246. goto Cleanup;
  247. }
  248. //
  249. // run Init()
  250. //
  251. dwErr = WaitForSingleObject(hRemoteThread, INFINITE);
  252. if (dwErr != ERROR_SUCCESS)
  253. {
  254. DebugPrintf(SSPI_ERROR, "WaitForSingleObject failed with %#x\n", dwErr);
  255. dwErr = GetLastError();
  256. }
  257. Cleanup:
  258. if (hKernel32)
  259. {
  260. FreeLibrary(hKernel32);
  261. }
  262. if (hRemoteThread)
  263. {
  264. CloseHandle(hRemoteThread);
  265. }
  266. if (pRemoteAlloc)
  267. {
  268. VirtualFreeEx(hProc, pRemoteAlloc, 0, MEM_RELEASE);
  269. }
  270. if (pRemInfo)
  271. {
  272. delete [] pRemInfo;
  273. }
  274. return dwErr;
  275. }
  276. DWORD
  277. FindPid(
  278. IN PCSTR pszImageFileName
  279. )
  280. {
  281. NTSTATUS Status ;
  282. PSYSTEM_PROCESS_INFORMATION pSystemInfo = NULL;
  283. PSYSTEM_PROCESS_INFORMATION pWalk = NULL;
  284. ANSI_STRING AnsiProcessName = {0};
  285. UNICODE_STRING ProcessName = {0};
  286. DWORD ulPid = 0;
  287. DebugPrintf(SSPI_LOG, "FindPid looking for %s\n", pszImageFileName);
  288. pSystemInfo = new SYSTEM_PROCESS_INFORMATION[1024];
  289. if ( !pSystemInfo )
  290. {
  291. DebugPrintf(SSPI_ERROR, "FindPid out of memory\n");
  292. return ERROR_SUCCESS;
  293. }
  294. Status = NtQuerySystemInformation(
  295. SystemProcessInformation,
  296. pSystemInfo,
  297. sizeof( SYSTEM_PROCESS_INFORMATION ) * 1024,
  298. NULL
  299. );
  300. if ( !NT_SUCCESS( Status ) )
  301. {
  302. DebugPrintf(SSPI_ERROR, "NtQuerySystemInformation failed with %#x\n", Status);
  303. return ERROR_SUCCESS;
  304. }
  305. RtlInitAnsiString(&AnsiProcessName, pszImageFileName);
  306. Status = RtlAnsiStringToUnicodeString(&ProcessName, &AnsiProcessName, TRUE);
  307. if ( !NT_SUCCESS( Status ) )
  308. {
  309. DebugPrintf(SSPI_ERROR, "RtlAnsiStringToUnicodeString failed with %#x\n", Status);
  310. return ERROR_SUCCESS;
  311. }
  312. pWalk = pSystemInfo ;
  313. while ( RtlCompareUnicodeString( &pWalk->ImageName, &ProcessName, TRUE ) != 0 )
  314. {
  315. if ( pWalk->NextEntryOffset == 0 )
  316. {
  317. pWalk = NULL ;
  318. break;
  319. }
  320. pWalk = (PSYSTEM_PROCESS_INFORMATION) ((PUCHAR) pWalk + pWalk->NextEntryOffset );
  321. }
  322. if ( !pWalk )
  323. {
  324. delete [] pSystemInfo;
  325. return ERROR_SUCCESS;
  326. }
  327. ulPid = PtrToUlong( pWalk->UniqueProcessId );
  328. delete [] pSystemInfo;
  329. return ulPid;
  330. }
  331. void
  332. DisplayUsage(
  333. IN PCSTR pszApp,
  334. IN OPTIONAL PCSTR pszArgs
  335. )
  336. {
  337. DebugPrintf(SSPI_ERROR, "\n\nUsage: %s <injectee.dll> [-p<PID>|-n<process name>] %s\n\n\n", pszApp, pszArgs ? pszArgs : "");
  338. }
  339. DWORD
  340. Init(
  341. IN PCSTR pszFileName,
  342. IN ULONG argc,
  343. IN PCSTR* argv,
  344. IN PCSTR pszDllName,
  345. IN PCSTR pszRunItProcName,
  346. IN PCSTR pszInitProcName,
  347. OUT ULONG* pcbParameters,
  348. OUT VOID** ppvParameters
  349. )
  350. {
  351. DWORD dwErr = ERROR_SUCCESS;
  352. HINSTANCE hDll = NULL;
  353. PFuncRunIt_t pFuncRunIt = NULL;
  354. PFuncInit_t pFuncInit = NULL;
  355. BOOLEAN bUseDefaulInitHandler = FALSE;
  356. hDll = LoadLibraryA(pszDllName);
  357. if (!hDll)
  358. {
  359. dwErr = GetLastError();
  360. goto Cleanup;
  361. }
  362. pFuncRunIt = (PFuncRunIt_t) GetProcAddress(hDll, pszRunItProcName);
  363. if (!pFuncRunIt)
  364. {
  365. dwErr = GetLastError();
  366. goto Cleanup;
  367. }
  368. pFuncInit = (PFuncInit_t) GetProcAddress(hDll, pszInitProcName);
  369. if (!pFuncInit)
  370. {
  371. dwErr = GetLastError();
  372. DebugPrintf(SSPI_WARN, "Init failed to locate %s %#x\n", REMOTE_DLL_INIT, dwErr);
  373. if (dwErr == ERROR_PROC_NOT_FOUND)
  374. {
  375. bUseDefaulInitHandler = TRUE;
  376. }
  377. else
  378. {
  379. goto Cleanup;
  380. }
  381. }
  382. else
  383. {
  384. dwErr = pFuncInit(
  385. argc,
  386. argv,
  387. pcbParameters,
  388. ppvParameters
  389. );
  390. if (dwErr == ERROR_CONTINUE)
  391. {
  392. bUseDefaulInitHandler = TRUE;
  393. }
  394. else if (dwErr == ERROR_INVALID_PARAMETER)
  395. {
  396. DisplayUsage(pszFileName, (PSTR) (*ppvParameters));
  397. goto Cleanup;
  398. }
  399. else if (dwErr != ERROR_SUCCESS)
  400. {
  401. DebugPrintf(SSPI_ERROR, "Init faield with %#x\n", dwErr);
  402. goto Cleanup;
  403. }
  404. }
  405. if (bUseDefaulInitHandler)
  406. {
  407. dwErr = InitDefaultHandler(argc, argv, pcbParameters, ppvParameters);
  408. }
  409. else
  410. {
  411. dwErr = ERROR_SUCCESS;
  412. }
  413. Cleanup:
  414. if (hDll)
  415. {
  416. FreeLibrary(hDll);
  417. }
  418. return dwErr;
  419. }
  420. int
  421. InitDefaultHandler(
  422. IN ULONG argc,
  423. IN PCSTR* argv,
  424. OUT ULONG* pcbParameters,
  425. OUT VOID** ppvParameters
  426. )
  427. {
  428. DWORD dwErr = ERROR_SUCCESS;
  429. CHAR Parameters[REMOTE_PACKET_SIZE] = {0};
  430. ULONG cbBuffer = sizeof(Parameters);
  431. VOID* pvParameters = NULL;
  432. ULONG cbParameters = 0;
  433. DebugPrintf(SSPI_LOG, "InitDefaultHandler is used\n");
  434. *pcbParameters = 0;
  435. *ppvParameters = NULL;
  436. for (ULONG i = 0; i < (ULONG) argc; i++)
  437. {
  438. cbBuffer -= _snprintf(Parameters + sizeof(Parameters) - cbBuffer, cbBuffer, "%s", argv[i]);
  439. cbBuffer--; // add a null
  440. }
  441. cbBuffer--; // the last null of multi-sz string
  442. cbParameters = sizeof(Parameters) - cbBuffer;
  443. pvParameters = new CHAR[cbParameters];
  444. if (pvParameters)
  445. {
  446. memcpy(pvParameters, Parameters, cbParameters);
  447. *ppvParameters = pvParameters;
  448. pvParameters = NULL;
  449. *pcbParameters = cbParameters;
  450. }
  451. else
  452. {
  453. dwErr = ERROR_OUTOFMEMORY;
  454. goto Cleanup;
  455. }
  456. Cleanup:
  457. if (pvParameters)
  458. {
  459. delete [] pvParameters;
  460. }
  461. return dwErr;
  462. }
  463. int __cdecl
  464. main(
  465. IN int argc,
  466. IN CHAR* argv[]
  467. )
  468. {
  469. DWORD dwErr = ERROR_SUCCESS;
  470. DWORD dwIgnored;
  471. HANDLE hLsassProc = NULL;
  472. HANDLE hReceiveThread = NULL;
  473. ULONG ulPid = 0;
  474. VOID* pvParameters = NULL;
  475. ULONG cbParamerter = 0;
  476. ULONG ulStart = 2;
  477. PSTR pszProcess = "lsass.exe";
  478. if (argc >= 3)
  479. {
  480. if ((argv[2][0] == '-') || (argv[2][0] == '/'))
  481. {
  482. if (argv[2][1] == 'n')
  483. {
  484. ulStart++;
  485. pszProcess = argv[2] + 2 * sizeof(char);
  486. }
  487. else if (argv[2][1] == 'p')
  488. {
  489. ulStart++;
  490. ulPid = strtol(argv[2] + 2 * sizeof(char), NULL, 0);
  491. }
  492. }
  493. }
  494. #if 0
  495. /* allow the user to override settings with command line switches */
  496. for (i = 1; i < argc; i++)
  497. {
  498. if ((*argv[i] == '-') || (*argv[i] == '/'))
  499. {
  500. switch (tolower(*(argv[i]+1)))
  501. {
  502. case 'd':
  503. fEncode = 0;
  504. break;
  505. case 'e':
  506. fEncode = 1;
  507. break;
  508. case 'i':
  509. fFixedStyle = 0;
  510. break;
  511. case 'f':
  512. pszFileName = argv[i] + 2;
  513. break;
  514. case 'h':
  515. case '?':
  516. default:
  517. Usage(argv[0]);
  518. }
  519. }
  520. else
  521. Usage(argv[0]);
  522. }
  523. #endif 0
  524. if ((argc >= 2) && (ulPid == 0))
  525. {
  526. ulPid = FindPid(pszProcess);
  527. }
  528. if (!ulPid)
  529. {
  530. DisplayUsage(argv[0], NULL);
  531. DebugPrintf(SSPI_ERROR, "%s failed: pszProcess is \"%s\", ulPid is %#x\n", argv[0], pszProcess, ulPid);
  532. goto Cleanup;
  533. }
  534. DebugPrintf(SSPI_LOG, "%s is injecting %s with pid %#x(%d)\n", argv[0], pszProcess, ulPid, ulPid);
  535. dwErr = Init(argv[0],
  536. argc - ulStart,
  537. (PCSTR*) reinterpret_cast<PSTR*>(argv + ulStart),
  538. argv[1],
  539. REMOTE_DLL_ENTRY,
  540. REMOTE_DLL_INIT,
  541. &cbParamerter,
  542. &pvParameters);
  543. if (dwErr != ERROR_SUCCESS)
  544. {
  545. DebugPrintf(SSPI_ERROR, "Init failed with error %#x\n", dwErr);
  546. goto Cleanup;
  547. }
  548. dwErr = AdjustDebugPriv();
  549. if (dwErr != ERROR_SUCCESS)
  550. {
  551. DebugPrintf(SSPI_ERROR, "EnableDebugPriv failed with error %#x\n", dwErr);
  552. goto Cleanup;
  553. }
  554. hLsassProc = OpenProcess(MAXIMUM_ALLOWED, FALSE, ulPid);
  555. if (!hLsassProc)
  556. {
  557. DebugPrintf(SSPI_ERROR, "OpenProcess pid %#x failed with last error %#x\n", ulPid, GetLastError());
  558. goto Cleanup;
  559. }
  560. dwErr = InjectDllToProcess(
  561. hLsassProc,
  562. argv[1],
  563. cbParamerter,
  564. pvParameters
  565. );
  566. if (dwErr != ERROR_SUCCESS)
  567. {
  568. DebugPrintf(SSPI_ERROR, "InjectDllToProcess failed with status %#x, dwErr %#x\n", dwErr);
  569. goto Cleanup;
  570. }
  571. Cleanup:
  572. if (pvParameters)
  573. {
  574. delete [] pvParameters;
  575. }
  576. if (hLsassProc)
  577. {
  578. CloseHandle(hLsassProc);
  579. }
  580. if (hReceiveThread)
  581. {
  582. CloseHandle(hReceiveThread);
  583. }
  584. return ERROR_SUCCESS;
  585. }