Source code of Windows XP (NT5)
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.

439 lines
14 KiB

  1. #include <pch.cxx>
  2. #pragma hdrstop
  3. #include <ole2.h>
  4. #include "trkwks.hxx"
  5. #include "dltadmin.hxx"
  6. typedef HINSTANCE (WINAPI *PFNLoadLibrary)(LPCTSTR);
  7. typedef HMODULE (WINAPI *PFNGetModuleHandle)(LPCTSTR);
  8. typedef BOOL (WINAPI *PFNFreeLibrary)(HINSTANCE);
  9. typedef LONG (WINAPI *PFNGetLastError)();
  10. typedef VOID (WINAPI *PFNDebugBreak)();
  11. typedef VOID (WINAPI *PFNOutputDebugStringW)( LPCTSTR );
  12. typedef BOOL (WINAPI *PFNCreateProcessW)(
  13. IN LPCWSTR lpApplicationName,
  14. IN LPWSTR lpCommandLine,
  15. IN LPSECURITY_ATTRIBUTES lpProcessAttributes,
  16. IN LPSECURITY_ATTRIBUTES lpThreadAttributes,
  17. IN BOOL bInheritHandles,
  18. IN DWORD dwCreationFlags,
  19. IN LPVOID lpEnvironment,
  20. IN LPCWSTR lpCurrentDirectory,
  21. IN LPSTARTUPINFOW lpStartupInfo,
  22. OUT LPPROCESS_INFORMATION lpProcessInformation
  23. );
  24. typedef struct
  25. {
  26. EProcessAction eAction;
  27. PFNGetModuleHandle pfnGetModuleHandleW;
  28. PFNFreeLibrary pfnFreeLibrary;
  29. PFNLoadLibrary pfnLoadLibraryW;
  30. PFNGetLastError pfnGetLastError;
  31. PFNDebugBreak pfnDebugBreak;
  32. PFNOutputDebugStringW pfnOutputDebugStringW;
  33. PFNCreateProcessW pfnCreateProcessW;
  34. WCHAR wsz[ 4*MAX_PATH + 1 ];
  35. WCHAR wszMessage[ 2*MAX_PATH + 1 ];
  36. } THREADFNSTRUCT;
  37. extern "C"
  38. {
  39. // Turn off stack-probing.
  40. #pragma check_stack (off)
  41. // Also turn off optimizations, to ensure that the compiler doesn't
  42. // consolidate any of this code with that from another function.
  43. #pragma optimize( "", off )
  44. static void BeforeThreadFunc (void)
  45. {
  46. // Prevent optimizations
  47. int i = rand();
  48. }
  49. static DWORD WINAPI
  50. RemoteThreadFunc( THREADFNSTRUCT *pStruct )
  51. {
  52. pStruct->pfnOutputDebugStringW( pStruct->wszMessage );
  53. if( FREE_LIBRARY == pStruct->eAction )
  54. {
  55. HINSTANCE hinst = NULL;
  56. hinst = pStruct->pfnGetModuleHandleW( pStruct->wsz );
  57. if( NULL == hinst )
  58. return( pStruct->pfnGetLastError() );
  59. if( !pStruct->pfnFreeLibrary( hinst ))
  60. return( pStruct->pfnGetLastError() );
  61. else
  62. return( ERROR_SUCCESS );
  63. }
  64. else if( LOAD_LIBRARY == pStruct->eAction )
  65. {
  66. if( NULL == pStruct->pfnLoadLibraryW( pStruct->wsz ))
  67. return( pStruct->pfnGetLastError() );
  68. else
  69. return( ERROR_SUCCESS );
  70. }
  71. else if( DEBUG_BREAK == pStruct->eAction )
  72. {
  73. pStruct->pfnDebugBreak();
  74. return( ERROR_SUCCESS );
  75. }
  76. else if( CREATE_PROCESS == pStruct->eAction )
  77. {
  78. if( !pStruct->pfnCreateProcessW( NULL, pStruct->wsz,
  79. NULL, NULL,
  80. FALSE, NORMAL_PRIORITY_CLASS,
  81. NULL, NULL, NULL, NULL ))
  82. {
  83. return GetLastError();
  84. }
  85. else
  86. return ERROR_SUCCESS;
  87. }
  88. else
  89. {
  90. pStruct->pfnOutputDebugStringW( L"Invalid action to RemoteThreadFunc" );
  91. return ERROR_INVALID_PARAMETER;
  92. }
  93. }
  94. static void AfterThreadFunc (void)
  95. {
  96. // Prevent optimziations
  97. int i = 2 * rand();
  98. }
  99. #pragma optimize ("", on ) // Restore to default
  100. #pragma check_stack // Restore to default
  101. }
  102. BOOL
  103. RemoteProcessAction( HANDLE hProcess,
  104. EProcessAction eAction,
  105. const WCHAR *pwsz )
  106. {
  107. int cbCodeSize = 0;
  108. const DWORD cbMemSize = cbCodeSize + sizeof(THREADFNSTRUCT) + 3;
  109. DWORD *pdwCodeRemote = NULL;
  110. THREADFNSTRUCT ThreadFnStruct;
  111. THREADFNSTRUCT *pRemoteThreadFnStruct = NULL;
  112. HANDLE hThread = NULL;
  113. DWORD dwThreadID = 0;
  114. BOOL fSuccess = FALSE;
  115. __try {
  116. // Determine the size of RemoteThreadFunc. Assume the functions
  117. // either in order or in reverse order.
  118. if( (LPBYTE) AfterThreadFunc > (LPBYTE) RemoteThreadFunc )
  119. cbCodeSize = (int)( (LPBYTE) AfterThreadFunc - (LPBYTE) RemoteThreadFunc );
  120. else if( (LPBYTE) BeforeThreadFunc > (LPBYTE) RemoteThreadFunc )
  121. cbCodeSize = (int)( (LPBYTE) BeforeThreadFunc - (LPBYTE) RemoteThreadFunc );
  122. else
  123. {
  124. printf( "Can't determine size of code to inject (%p, %p, %p)\n",
  125. BeforeThreadFunc, AfterThreadFunc, RemoteThreadFunc );
  126. __leave;
  127. }
  128. // Allocate memory in the remote process's address space large
  129. // enough to hold our RemoteThreadFunc function and a THREADFNSTRUCT structure.
  130. pdwCodeRemote = (DWORD*) VirtualAllocEx( hProcess, NULL, cbMemSize,
  131. MEM_COMMIT, PAGE_EXECUTE_READWRITE );
  132. if( NULL == pdwCodeRemote )
  133. {
  134. printf( "VirtualAllocEx failed: %d\n", GetLastError() );
  135. __leave;
  136. }
  137. // Write a copy of RemoteThreadFunc to the remote process.
  138. if( !WriteProcessMemory( hProcess, pdwCodeRemote,
  139. (LPVOID) RemoteThreadFunc,
  140. cbCodeSize, NULL ))
  141. {
  142. printf( "WriteProcessMemory failed: %d\n", GetLastError() );
  143. __leave;
  144. }
  145. // Write a copy of ThreadFnStruct to the remote process
  146. // (the structure MUST start on an even 32-bit bourdary).
  147. pRemoteThreadFnStruct = reinterpret_cast<THREADFNSTRUCT *>
  148. ( (BYTE*)pdwCodeRemote + ((cbCodeSize + 4) & ~3) );
  149. memset( &ThreadFnStruct, 0, sizeof(ThreadFnStruct) );
  150. ThreadFnStruct.eAction = eAction;
  151. //wcscpy( ThreadFnStruct.wszMessage, L"*** Remote thread from dltadmin.exe ***\n" );
  152. if( LOAD_LIBRARY == eAction )
  153. {
  154. wcscpy( ThreadFnStruct.wsz, pwsz );
  155. wsprintf( ThreadFnStruct.wszMessage,
  156. L"Received request from dltadmin to load \"%s\"\n",
  157. pwsz );
  158. ThreadFnStruct.pfnLoadLibraryW = (PFNLoadLibrary)
  159. GetProcAddress( GetModuleHandle( L"kernel32.dll" ),
  160. "LoadLibraryW" );
  161. if( NULL == ThreadFnStruct.pfnLoadLibraryW )
  162. {
  163. printf( "Couldn't load LoadLibraryW (%d)\n", GetLastError() );
  164. __leave;
  165. }
  166. }
  167. else if( FREE_LIBRARY == eAction )
  168. {
  169. wcscpy( ThreadFnStruct.wsz, pwsz );
  170. wsprintf( ThreadFnStruct.wszMessage,
  171. L"Received request from dltadmin to free \"%s\"\n",
  172. pwsz );
  173. ThreadFnStruct.pfnFreeLibrary = (PFNFreeLibrary)
  174. GetProcAddress( GetModuleHandleA("kernel32.dll"),
  175. "FreeLibrary" );
  176. if( NULL == ThreadFnStruct.pfnFreeLibrary )
  177. {
  178. printf( "Couldn't load FreeLibrary (%d)\n", GetLastError() );
  179. __leave;
  180. }
  181. ThreadFnStruct.pfnGetModuleHandleW = (PFNGetModuleHandle)
  182. GetProcAddress( GetModuleHandle(L"kernel32.dll"),
  183. "GetModuleHandleW" );
  184. if( NULL == ThreadFnStruct.pfnFreeLibrary )
  185. {
  186. printf( "Couldn't load FreeLibrary (%d)\n", GetLastError() );
  187. __leave;
  188. }
  189. }
  190. else if( CREATE_PROCESS == eAction )
  191. {
  192. wcscpy( ThreadFnStruct.wsz, pwsz );
  193. wsprintf( ThreadFnStruct.wszMessage,
  194. L"Received request from dltadmin to create \"%s\"\n",
  195. pwsz );
  196. ThreadFnStruct.pfnCreateProcessW = (PFNCreateProcessW)
  197. GetProcAddress( GetModuleHandleA("kernel32.dll"),
  198. "CreateProcessW" );
  199. if( NULL == ThreadFnStruct.pfnCreateProcessW )
  200. {
  201. printf( "Couldn't load CreateProcess (%d)\n", GetLastError() );
  202. __leave;
  203. }
  204. }
  205. else // DEBUG_BREAK
  206. {
  207. wsprintf( ThreadFnStruct.wszMessage,
  208. L"Received request from dltadmin to DebugBreak\n" );
  209. ThreadFnStruct.pfnDebugBreak = (PFNDebugBreak)
  210. GetProcAddress( GetModuleHandleA("kernel32.dll"),
  211. "DebugBreak" );
  212. if( NULL == ThreadFnStruct.pfnDebugBreak )
  213. {
  214. printf( "Couldn't load DebugBreak (%d)\n", GetLastError() );
  215. __leave;
  216. }
  217. }
  218. ThreadFnStruct.pfnGetLastError = (PFNGetLastError)
  219. GetProcAddress( GetModuleHandle( L"kernel32.dll" ),
  220. "GetLastError" );
  221. if( NULL == ThreadFnStruct.pfnGetLastError )
  222. {
  223. printf( "Couldn't load GetLastError (%d)\n", GetLastError() );
  224. __leave;
  225. }
  226. ThreadFnStruct.pfnOutputDebugStringW = (PFNOutputDebugStringW)
  227. GetProcAddress( GetModuleHandle( L"kernel32.dll" ),
  228. "OutputDebugStringW" );
  229. if( NULL == ThreadFnStruct.pfnOutputDebugStringW )
  230. {
  231. printf( "Couldn't load OutputDebugStringW (%d)\n", GetLastError() );
  232. __leave;
  233. }
  234. // Write the struct into the remote thread's memory block.
  235. if( !WriteProcessMemory( hProcess, pRemoteThreadFnStruct,
  236. &ThreadFnStruct, sizeof(THREADFNSTRUCT), NULL ))
  237. {
  238. printf( "Couldn't write ThreadFnStruct to remote thread: %d\n", GetLastError() );
  239. __leave;
  240. }
  241. hThread = CreateRemoteThread( hProcess, NULL, 0,
  242. (LPTHREAD_START_ROUTINE) pdwCodeRemote,
  243. pRemoteThreadFnStruct, 0, &dwThreadID );
  244. if( NULL == hThread )
  245. {
  246. printf( "Couldn't create remote thread: %d\n", GetLastError() );
  247. __leave;
  248. }
  249. DWORD dwWait = WaitForSingleObject( hThread, INFINITE );
  250. if( WAIT_OBJECT_0 != dwWait )
  251. printf( "Wait failed: %d, %d\n", dwWait, GetLastError() );
  252. } // __try
  253. __finally
  254. {
  255. if( NULL != hThread )
  256. {
  257. DWORD dwError;
  258. if( !AbnormalTermination() )
  259. {
  260. if( !GetExitCodeThread( hThread, &dwError ))
  261. printf( "Couldn't get remote thread exit code: %d\n", GetLastError() );
  262. else if( ERROR_MOD_NOT_FOUND == dwError )
  263. {
  264. if( LOAD_LIBRARY == eAction )
  265. wprintf( L"DLL \"%s\" not found\n", pwsz );
  266. else if( FREE_LIBRARY == eAction )
  267. wprintf( L"DLL \"%s\" not already loaded\n", pwsz );
  268. }
  269. else if( ERROR_SUCCESS != dwError )
  270. printf( "Failed: 0x%x\n", dwError );
  271. else
  272. fSuccess = TRUE;
  273. }
  274. CloseHandle(hThread);
  275. }
  276. if( NULL != pdwCodeRemote )
  277. {
  278. if( !VirtualFreeEx( hProcess, pdwCodeRemote, 0, MEM_RELEASE ))
  279. printf( "Couldn't free remote memory: 0x%x\n", GetLastError() );
  280. }
  281. } // __finally
  282. if( fSuccess )
  283. printf( "Succeeded\n" );
  284. return( fSuccess );
  285. }
  286. BOOL
  287. DltAdminProcessAction( EProcessAction eAction, ULONG cArgs, TCHAR * const rgptszArgs[], ULONG *pcEaten )
  288. {
  289. BOOL fSuccess = FALSE;
  290. *pcEaten = 0;
  291. if( 0 == cArgs
  292. ||
  293. 1 <= cArgs && IsHelpArgument(rgptszArgs[0]) )
  294. {
  295. *pcEaten = 1;
  296. if( LOAD_LIBRARY == eAction )
  297. {
  298. printf( "\nOption LoadLib\n"
  299. " Purpose: Load a dll into a process with LoadLibrary\n"
  300. " Usage: -LoadLib -p <process ID> <library name>\n"
  301. " E.g.: -LoadLib -p 182 shell32.dll\n" );
  302. }
  303. else if( FREE_LIBRARY == eAction )
  304. {
  305. printf( "\nOption FreeLib\n"
  306. " Purpose: Unload a dll from a process with FreeLibrary\n"
  307. " Usage: -FreeLib -p <process ID> <library name>\n"
  308. " E.g.: -FreeLib -p 182 shell32.dll\n" );
  309. }
  310. else
  311. {
  312. printf( "\nOption DebugBreak\n"
  313. " Purpose: Execute DebugBreak within a process\n"
  314. " Usage: -DebugBreak -p <process ID>\n"
  315. " E.g.: -DebugBreak -p 182\n" );
  316. }
  317. return( TRUE );
  318. }
  319. ULONG iArgs = 0;
  320. if( 2 > cArgs
  321. ||
  322. TEXT('-') != rgptszArgs[0][0]
  323. &&
  324. TEXT('/') != rgptszArgs[0][0]
  325. ||
  326. TEXT('P') != rgptszArgs[0][1]
  327. &&
  328. TEXT('p') != rgptszArgs[0][1] )
  329. {
  330. printf( "Argument error. Use -? for usage info.\n" );
  331. return( FALSE );
  332. }
  333. HANDLE hProcess = NULL;
  334. __try
  335. {
  336. DWORD dwProcessID = 0;
  337. _stscanf( rgptszArgs[1], TEXT("%d"), &dwProcessID );
  338. if( 0 == dwProcessID )
  339. {
  340. printf( "Failed to open system process\n" );
  341. __leave;
  342. }
  343. EnablePrivilege(SE_DEBUG_NAME);
  344. hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessID );
  345. if( NULL == hProcess )
  346. {
  347. printf( "Failed to open process %d (%lu)\n", dwProcessID, GetLastError() );
  348. __leave;
  349. }
  350. if( RemoteProcessAction( hProcess, eAction,
  351. DEBUG_BREAK == eAction ? NULL : rgptszArgs[2] ))
  352. fSuccess = TRUE;
  353. if( DEBUG_BREAK == eAction )
  354. *pcEaten = 2;
  355. else
  356. *pcEaten = 3;
  357. }
  358. __finally
  359. {
  360. if( NULL != hProcess )
  361. CloseHandle( hProcess );
  362. }
  363. return( fSuccess );
  364. }