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.

1206 lines
24 KiB

  1. //
  2. // systemsecurity.cpp
  3. //
  4. // Copyright (c) Microsoft Corp, 1998
  5. //
  6. // This file contains source code for logging as Local System
  7. //
  8. // History:
  9. //
  10. // Todds 8/15/98 Created
  11. // Modified by Rohanp 4/26/2002
  12. //
  13. //
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <windows.h>
  18. #include <winbase.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <wincrypt.h>
  22. #include <userenv.h>
  23. #include <lm.h>
  24. #include <psapi.h>
  25. #define MyAlloc(cb) HeapAlloc(GetProcessHeap(), 0, cb)
  26. #define MyFree(pv) HeapFree(GetProcessHeap(), 0, pv)
  27. #define WSZ_BYTECOUNT(s) (2 * wcslen(s) + 2)
  28. #define MAX_BLOBS 20
  29. #define MAX_PROCESSES 200
  30. #define MAX_SD 2048
  31. #define BLOB_INCREMENT 0x4001 // 1 page + 1 byte...
  32. DWORD
  33. GetSystemProcessId(LPWSTR ProcessNameToFind,
  34. DWORD * ProcessId);
  35. //
  36. // SetSidOnAcl
  37. //
  38. BOOL
  39. SetSidOnAcl(
  40. PSID pSid,
  41. PACL pAclSource,
  42. PACL *pAclDestination,
  43. DWORD AccessMask,
  44. BYTE AceFlags,
  45. BOOL bAddSid
  46. )
  47. {
  48. DWORD dwNewAclSize = 0, dwErr = 0;
  49. LPVOID pAce = NULL;
  50. DWORD AceCounter = 0;
  51. BOOL bSuccess = FALSE; // assume this function will fail
  52. ACL_SIZE_INFORMATION AclInfo;
  53. //
  54. // If we were given a NULL Acl, just provide a NULL Acl
  55. //
  56. if(pAclSource == NULL)
  57. {
  58. *pAclDestination = NULL;
  59. return TRUE;
  60. }
  61. if(!IsValidSid(pSid))
  62. {
  63. return FALSE;
  64. }
  65. if(!GetAclInformation(
  66. pAclSource,
  67. &AclInfo,
  68. sizeof(ACL_SIZE_INFORMATION),
  69. AclSizeInformation
  70. ))
  71. {
  72. return FALSE;
  73. }
  74. //
  75. // compute size for new Acl, based on addition or subtraction of Ace
  76. //
  77. if(bAddSid)
  78. {
  79. dwNewAclSize=AclInfo.AclBytesInUse +
  80. sizeof(ACCESS_ALLOWED_ACE) +
  81. GetLengthSid(pSid) -
  82. sizeof(DWORD) ;
  83. }
  84. else
  85. {
  86. dwNewAclSize=AclInfo.AclBytesInUse -
  87. sizeof(ACCESS_ALLOWED_ACE) -
  88. GetLengthSid(pSid) +
  89. sizeof(DWORD) ;
  90. }
  91. *pAclDestination = (PACL)MyAlloc(dwNewAclSize);
  92. if(*pAclDestination == NULL)
  93. {
  94. return FALSE;
  95. }
  96. //
  97. // initialize new Acl
  98. //
  99. if(!InitializeAcl(
  100. *pAclDestination,
  101. dwNewAclSize,
  102. ACL_REVISION
  103. ))
  104. {
  105. dwErr = GetLastError();
  106. goto ret;
  107. }
  108. //
  109. // if appropriate, add ace representing pSid
  110. //
  111. if(bAddSid)
  112. {
  113. PACCESS_ALLOWED_ACE pNewAce = NULL;
  114. if(!AddAccessAllowedAce(
  115. *pAclDestination,
  116. ACL_REVISION,
  117. AccessMask,
  118. pSid
  119. ))
  120. {
  121. dwErr = GetLastError();
  122. goto ret;
  123. }
  124. //
  125. // get pointer to ace we just added, so we can change the AceFlags
  126. //
  127. if(!GetAce(
  128. *pAclDestination,
  129. 0, // this is the first ace in the Acl
  130. (void**) &pNewAce
  131. ))
  132. {
  133. dwErr = GetLastError();
  134. goto ret;
  135. }
  136. pNewAce->Header.AceFlags = AceFlags;
  137. }
  138. //
  139. // copy existing aces to new Acl
  140. //
  141. for(AceCounter = 0 ; AceCounter < AclInfo.AceCount ; AceCounter++)
  142. {
  143. //
  144. // fetch existing ace
  145. //
  146. if(!GetAce(pAclSource, AceCounter, &pAce))
  147. {
  148. dwErr = GetLastError();
  149. goto ret;
  150. }
  151. //
  152. // check to see if we are removing the Ace
  153. //
  154. if(!bAddSid)
  155. {
  156. //
  157. // we only care about ACCESS_ALLOWED aces
  158. //
  159. if((((PACE_HEADER)pAce)->AceType) == ACCESS_ALLOWED_ACE_TYPE)
  160. {
  161. PSID pTempSid=(PSID)&((PACCESS_ALLOWED_ACE)pAce)->SidStart;
  162. //
  163. // if the Sid matches, skip adding this Sid
  164. //
  165. if(EqualSid(pSid, pTempSid)) continue;
  166. }
  167. }
  168. //
  169. // append ace to Acl
  170. //
  171. if(!AddAce(
  172. *pAclDestination,
  173. ACL_REVISION,
  174. 0xFFFF, // maintain Ace order //MAXDWORD
  175. pAce,
  176. ((PACE_HEADER)pAce)->AceSize
  177. ))
  178. {
  179. dwErr = GetLastError();
  180. goto ret;
  181. }
  182. }
  183. bSuccess=TRUE; // indicate success
  184. ret:
  185. //
  186. // free memory if an error occurred
  187. //
  188. if(!bSuccess)
  189. {
  190. if(*pAclDestination != NULL)
  191. MyFree(*pAclDestination);
  192. }
  193. return bSuccess;
  194. }
  195. //
  196. // AddSIDToKernelObject()
  197. //
  198. // This function takes a given SID and dwAccess and adds it to a given token.
  199. //
  200. // ** Be sure to restore old kernel object
  201. // ** using call to GetKernelObjectSecurity()
  202. //
  203. BOOL
  204. AddSIDToKernelObjectDacl(PSID pSid,
  205. DWORD dwAccess,
  206. HANDLE OriginalToken,
  207. PSECURITY_DESCRIPTOR* ppSDOld)
  208. {
  209. PSECURITY_DESCRIPTOR pSD = NULL;
  210. DWORD cbByte = MAX_SD, cbNeeded = 0, dwErr = 0;
  211. PACL pOldDacl = NULL, pNewDacl = NULL;
  212. BOOL fDaclPresent = FALSE, fDaclDefaulted = FALSE, fRet = FALSE;
  213. SECURITY_DESCRIPTOR sdNew;
  214. pSD = (PSECURITY_DESCRIPTOR) MyAlloc(cbByte);
  215. if (NULL == pSD)
  216. {
  217. return FALSE;
  218. }
  219. if (!InitializeSecurityDescriptor(
  220. &sdNew,
  221. SECURITY_DESCRIPTOR_REVISION
  222. ))
  223. {
  224. dwErr = GetLastError();
  225. goto ret;
  226. }
  227. if (!GetKernelObjectSecurity(
  228. OriginalToken,
  229. DACL_SECURITY_INFORMATION,
  230. pSD,
  231. cbByte,
  232. &cbNeeded
  233. ))
  234. {
  235. dwErr = GetLastError();
  236. if((cbNeeded > MAX_SD) && (dwErr == ERROR_MORE_DATA))
  237. {
  238. MyFree(pSD);
  239. pSD = NULL;
  240. pSD = (PSECURITY_DESCRIPTOR) MyAlloc(cbNeeded);
  241. if (NULL == pSD)
  242. {
  243. dwErr = GetLastError();
  244. goto ret;
  245. }
  246. dwErr = ERROR_SUCCESS;
  247. if (!GetKernelObjectSecurity(
  248. OriginalToken,
  249. DACL_SECURITY_INFORMATION,
  250. pSD,
  251. cbNeeded,
  252. &cbNeeded
  253. ))
  254. {
  255. dwErr = GetLastError();
  256. }
  257. }
  258. if (dwErr != ERROR_SUCCESS)
  259. {
  260. goto ret;
  261. }
  262. }
  263. if (!GetSecurityDescriptorDacl(
  264. pSD,
  265. &fDaclPresent,
  266. &pOldDacl,
  267. &fDaclDefaulted
  268. ))
  269. {
  270. dwErr = GetLastError();
  271. goto ret;
  272. }
  273. if (!SetSidOnAcl(
  274. pSid,
  275. pOldDacl,
  276. &pNewDacl,
  277. dwAccess,
  278. 0,
  279. TRUE
  280. ))
  281. {
  282. dwErr = GetLastError();
  283. goto ret;
  284. }
  285. if (!SetSecurityDescriptorDacl(
  286. &sdNew,
  287. TRUE,
  288. pNewDacl,
  289. FALSE
  290. ))
  291. {
  292. dwErr = GetLastError();
  293. goto ret;
  294. }
  295. if (!SetKernelObjectSecurity(
  296. OriginalToken,
  297. DACL_SECURITY_INFORMATION,
  298. &sdNew
  299. ))
  300. {
  301. dwErr = GetLastError();
  302. goto ret;
  303. }
  304. *ppSDOld = pSD;
  305. fRet = TRUE;
  306. ret:
  307. if (NULL != pNewDacl)
  308. {
  309. MyFree(pNewDacl);
  310. }
  311. if (!fRet)
  312. {
  313. if (NULL != pSD)
  314. {
  315. MyFree(pSD);
  316. *ppSDOld = NULL;
  317. }
  318. }
  319. return fRet;
  320. }
  321. BOOL
  322. SetPrivilege(
  323. HANDLE hToken, // token handle
  324. LPCTSTR Privilege, // Privilege to enable/disable
  325. BOOL bEnablePrivilege // to enable or disable privilege
  326. )
  327. {
  328. TOKEN_PRIVILEGES tp;
  329. LUID luid;
  330. TOKEN_PRIVILEGES tpPrevious;
  331. DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);
  332. if(!LookupPrivilegeValue( NULL, Privilege, &luid ))
  333. {
  334. return FALSE;
  335. }
  336. //
  337. // first pass. get current privilege setting
  338. //
  339. tp.PrivilegeCount = 1;
  340. tp.Privileges[0].Luid = luid;
  341. tp.Privileges[0].Attributes = 0;
  342. AdjustTokenPrivileges(
  343. hToken,
  344. FALSE,
  345. &tp,
  346. sizeof(TOKEN_PRIVILEGES),
  347. &tpPrevious,
  348. &cbPrevious
  349. );
  350. if (GetLastError() != ERROR_SUCCESS)
  351. {
  352. return FALSE;
  353. }
  354. //
  355. // second pass. set privilege based on previous setting
  356. //
  357. tpPrevious.PrivilegeCount = 1;
  358. tpPrevious.Privileges[0].Luid = luid;
  359. if(bEnablePrivilege)
  360. {
  361. tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
  362. }
  363. else
  364. {
  365. tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
  366. tpPrevious.Privileges[0].Attributes);
  367. }
  368. AdjustTokenPrivileges(
  369. hToken,
  370. FALSE,
  371. &tpPrevious,
  372. cbPrevious,
  373. NULL,
  374. NULL
  375. );
  376. if (GetLastError() != ERROR_SUCCESS)
  377. {
  378. return FALSE;
  379. }
  380. return TRUE;
  381. }
  382. BOOL
  383. SetCurrentPrivilege(
  384. LPCTSTR Privilege, // Privilege to enable/disable
  385. BOOL bEnablePrivilege // to enable or disable privilege
  386. )
  387. {
  388. BOOL bSuccess=FALSE; // assume failure
  389. HANDLE hToken = NULL;
  390. if (!OpenThreadToken(
  391. GetCurrentThread(),
  392. TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
  393. FALSE,
  394. &hToken))
  395. {
  396. if(!OpenProcessToken(
  397. GetCurrentProcess(),
  398. TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
  399. &hToken
  400. ))
  401. {
  402. return FALSE;
  403. }
  404. }
  405. if(SetPrivilege(hToken, Privilege, bEnablePrivilege))
  406. {
  407. bSuccess=TRUE;
  408. }
  409. CloseHandle(hToken);
  410. return bSuccess;
  411. }
  412. //
  413. // GetUserSid
  414. //
  415. // This function takes a token, and returns the user SID from that token.
  416. //
  417. // Note: SID must be freed by MyFree()
  418. // hToken is optional... NULL means we'll grab it.
  419. //
  420. BOOL
  421. GetUserSid(HANDLE hClientToken,
  422. PSID* ppSid,
  423. DWORD* lpcbSid)
  424. {
  425. DWORD cbUserInfo = 0;
  426. PTOKEN_USER pUserInfo = NULL;
  427. PUCHAR pnSubAuthorityCount = 0;
  428. DWORD cbSid = 0;
  429. BOOL fRet = FALSE;
  430. HANDLE hToken = hClientToken;
  431. *ppSid = NULL;
  432. if (NULL == hClientToken)
  433. {
  434. if (!OpenThreadToken(
  435. GetCurrentThread(),
  436. TOKEN_QUERY,
  437. FALSE,
  438. &hToken
  439. ))
  440. {
  441. // not impersonating, use process token...
  442. if (!OpenProcessToken(
  443. GetCurrentProcess(),
  444. TOKEN_QUERY,
  445. &hToken
  446. ))
  447. {
  448. return FALSE;
  449. }
  450. }
  451. }
  452. // this will fail, usually w/ ERROR_INSUFFICIENT_BUFFER
  453. GetTokenInformation(
  454. hToken,
  455. TokenUser,
  456. NULL,
  457. 0,
  458. &cbUserInfo
  459. );
  460. pUserInfo = (PTOKEN_USER) MyAlloc(cbUserInfo);
  461. if (NULL == pUserInfo)
  462. {
  463. return FALSE;
  464. }
  465. if (!GetTokenInformation(
  466. hToken,
  467. TokenUser,
  468. pUserInfo,
  469. cbUserInfo,
  470. &cbUserInfo
  471. ))
  472. {
  473. goto ret;
  474. }
  475. //
  476. // Now that we've got the SID AND ATTRIBUTES struct, get the SID lenght,
  477. // alloc room, and return *just the SID*
  478. //
  479. if (!IsValidSid(pUserInfo->User.Sid))
  480. {
  481. goto ret;
  482. }
  483. pnSubAuthorityCount = GetSidSubAuthorityCount(pUserInfo->User.Sid);
  484. cbSid = GetSidLengthRequired(*pnSubAuthorityCount);
  485. *ppSid = (PSID) MyAlloc(cbSid);
  486. if (NULL == *ppSid )
  487. {
  488. goto ret;
  489. }
  490. if (!CopySid(
  491. cbSid,
  492. *ppSid,
  493. pUserInfo->User.Sid
  494. ))
  495. {
  496. goto copyerr;
  497. }
  498. *lpcbSid = cbSid; // may be useful later on...
  499. fRet = TRUE;
  500. ret:
  501. if (NULL == hClientToken && NULL != hToken)
  502. { // supplied our own
  503. CloseHandle(hToken);
  504. }
  505. if (NULL != pUserInfo)
  506. {
  507. MyFree(pUserInfo);
  508. }
  509. return fRet;
  510. copyerr:
  511. if (NULL != *ppSid)
  512. {
  513. MyFree(*ppSid);
  514. *ppSid = NULL;
  515. }
  516. goto ret;
  517. }
  518. //
  519. // IsLocalSystem()
  520. // This function makes the determination if the given process token
  521. // is running as local system.
  522. //
  523. BOOL
  524. IsLocalSystem(HANDLE hToken)
  525. {
  526. PSID pLocalSid = NULL, pTokenSid = NULL;
  527. SID_IDENTIFIER_AUTHORITY IDAuthorityNT = SECURITY_NT_AUTHORITY;
  528. DWORD cbSid = 0;
  529. BOOL fRet = FALSE;
  530. if (!GetUserSid(
  531. hToken,
  532. &pTokenSid,
  533. &cbSid
  534. ))
  535. {
  536. goto ret;
  537. }
  538. if (!AllocateAndInitializeSid(
  539. &IDAuthorityNT,
  540. 1,
  541. SECURITY_LOCAL_SYSTEM_RID,
  542. 0,0,0,0,0,0,0,
  543. &pLocalSid
  544. ))
  545. {
  546. goto ret;
  547. }
  548. if (EqualSid(pLocalSid, pTokenSid))
  549. {
  550. fRet = TRUE; // got one!
  551. }
  552. ret:
  553. if (NULL != pTokenSid)
  554. {
  555. MyFree(pTokenSid);
  556. }
  557. if (NULL != pLocalSid)
  558. {
  559. FreeSid(pLocalSid);
  560. }
  561. return fRet;
  562. }
  563. //
  564. // GetLocalSystemToken()
  565. //
  566. // This function grabs a process token from a LOCAL SYSTEM process and uses it
  567. // to run as local system for the duration of the test
  568. //
  569. // RevertToSelf() must be called to restore original token
  570. //
  571. //
  572. DWORD
  573. GetLocalSystemToken(
  574. IN ULONG ProcessId,
  575. OUT HANDLE *hPDupToken
  576. )
  577. {
  578. HANDLE hProcess = NULL;
  579. HANDLE hPToken = NULL, hPTokenNew = NULL;
  580. PSECURITY_DESCRIPTOR pSD = NULL;
  581. DWORD cbNeeded = 0, dwErr = S_OK, i = 0;
  582. DWORD cbrgPIDs = sizeof(DWORD) * MAX_PROCESSES;
  583. PSID pSid = NULL;
  584. DWORD cbSid = 0;
  585. BOOL fSet = FALSE;
  586. DWORD cbByte = MAX_SD, cbByte2 = MAX_SD;
  587. //
  588. // Enable debug privilege
  589. //
  590. if(!SetCurrentPrivilege(SE_DEBUG_NAME, TRUE))
  591. {
  592. return GetLastError();
  593. }
  594. if(!SetCurrentPrivilege(SE_TAKE_OWNERSHIP_NAME, TRUE))
  595. {
  596. return GetLastError();
  597. }
  598. if(ProcessId == 0)
  599. {
  600. GetSystemProcessId(L"System",
  601. &ProcessId);
  602. }
  603. //
  604. // Get current user's sid for use in expanding SD.
  605. //
  606. if (!GetUserSid(
  607. NULL,
  608. &pSid,
  609. &cbSid
  610. ))
  611. {
  612. goto ret;
  613. }
  614. //
  615. // Walk processes until we find one that's running as
  616. // local system
  617. //
  618. do {
  619. hProcess = OpenProcess(
  620. PROCESS_ALL_ACCESS,
  621. FALSE,
  622. ProcessId
  623. );
  624. if (NULL == hProcess)
  625. {
  626. dwErr = GetLastError();
  627. goto ret;
  628. }
  629. if (!OpenProcessToken(
  630. hProcess,
  631. READ_CONTROL | WRITE_DAC,
  632. &hPToken
  633. ))
  634. {
  635. dwErr = GetLastError();
  636. goto ret;
  637. }
  638. //
  639. // We've got a token, but we can't use it for
  640. // TOKEN_DUPLICATE access. So, instead, we'll go
  641. // ahead and whack the DACL on the object to grant us
  642. // this access, and get a new token.
  643. // **** BE SURE TO RESTORE hProcess to Original SD!!! ****
  644. //
  645. if (!AddSIDToKernelObjectDacl(
  646. pSid,
  647. TOKEN_DUPLICATE,
  648. hPToken,
  649. &pSD
  650. ))
  651. {
  652. goto ret;
  653. }
  654. fSet = TRUE;
  655. if (!OpenProcessToken(
  656. hProcess,
  657. TOKEN_DUPLICATE,
  658. &hPTokenNew
  659. ))
  660. {
  661. dwErr = GetLastError();
  662. goto ret;
  663. }
  664. //
  665. // Duplicate the token
  666. //
  667. if (!DuplicateTokenEx(
  668. hPTokenNew,
  669. TOKEN_ALL_ACCESS,
  670. NULL,
  671. SecurityImpersonation,
  672. TokenPrimary,
  673. hPDupToken
  674. ))
  675. {
  676. dwErr = GetLastError();
  677. goto ret;
  678. }
  679. if (IsLocalSystem(*hPDupToken))
  680. {
  681. break; // found a local system token
  682. }
  683. // Loop cleanup
  684. if (!SetKernelObjectSecurity(
  685. hPToken,
  686. DACL_SECURITY_INFORMATION,
  687. pSD
  688. ))
  689. {
  690. dwErr = GetLastError();
  691. goto ret;
  692. }
  693. fSet = FALSE;
  694. if (NULL != pSD)
  695. {
  696. MyFree(pSD);
  697. pSD = NULL;
  698. }
  699. if (NULL != hPToken)
  700. {
  701. CloseHandle(hPToken);
  702. hPToken = NULL;
  703. }
  704. if (NULL != hProcess)
  705. {
  706. CloseHandle(hProcess);
  707. hProcess = NULL;
  708. }
  709. } while(FALSE);
  710. if (!ImpersonateLoggedOnUser(*hPDupToken))
  711. {
  712. dwErr = GetLastError();
  713. goto ret;
  714. }
  715. ret:
  716. //***** REMEMBER TO RESTORE ORIGINAL SD TO OBJECT*****
  717. if (fSet)
  718. {
  719. if (!SetKernelObjectSecurity(
  720. hPToken,
  721. DACL_SECURITY_INFORMATION,
  722. pSD
  723. ))
  724. {
  725. dwErr = GetLastError();
  726. }
  727. }
  728. if (NULL != pSid)
  729. {
  730. MyFree(pSid);
  731. }
  732. if (NULL != hPToken)
  733. {
  734. CloseHandle(hPToken);
  735. }
  736. if (NULL != pSD)
  737. {
  738. MyFree(pSD);
  739. }
  740. if (NULL != hProcess)
  741. {
  742. CloseHandle(hProcess);
  743. }
  744. return dwErr;
  745. }
  746. //
  747. // LogoffAndRevert()
  748. //
  749. // This function simply RevertsToSelf(), and then closes the logon token
  750. //
  751. // Params:
  752. //
  753. // hToken - Logon token from LogonUserW
  754. //
  755. // Returns:
  756. //
  757. // dwErr from last failure, S_OK otherwise.
  758. //
  759. DWORD
  760. LogoffAndRevert(void)
  761. {
  762. HANDLE hThread = INVALID_HANDLE_VALUE;
  763. DWORD dwErr = 0;
  764. //
  765. // Verify impersonation, and revert
  766. //
  767. if (OpenThreadToken(
  768. GetCurrentThread(),
  769. TOKEN_QUERY,
  770. TRUE,
  771. &hThread
  772. ))
  773. {
  774. CloseHandle(hThread);
  775. RevertToSelf();
  776. }
  777. return dwErr;
  778. }
  779. #if 0
  780. extern "C"
  781. int __cdecl wmain(
  782. int argc,
  783. WCHAR* argv[]
  784. )
  785. {
  786. LPWSTR wszUPN = NULL;
  787. LPWSTR wszOldPwd = NULL;
  788. LPWSTR wszNewPwd = NULL;
  789. DATA_BLOB* arCipherData = NULL;
  790. INT i = 1;
  791. DWORD dwErr = S_OK;
  792. DWORD dwCleanupErrors = S_OK;
  793. HANDLE hToken = INVALID_HANDLE_VALUE;
  794. HANDLE hLocalSystem = NULL;
  795. HANDLE hProfile = INVALID_HANDLE_VALUE;
  796. BOOL fTest = TRUE;
  797. PSECURITY_DESCRIPTOR pSD = NULL;
  798. ULONG ProcessId = 8;
  799. #if 0
  800. while (i < carg) {
  801. if (!_wcsicmp(rgwszarg[i], L"-?")) {
  802. Usage();
  803. return 0;
  804. }
  805. if (!_wcsicmp(rgwszarg[i], L"-reset")) {
  806. ResetTestUser();
  807. return 0;
  808. }
  809. if (!_wcsicmp(rgwszarg[i], L"-create")) {
  810. CreateTestUser();
  811. return 0;
  812. }
  813. if (!_wcsicmp(rgwszarg[i], L"-user")) {
  814. if (carg < 4) {
  815. Usage();
  816. }
  817. fTest = TRUE;
  818. }
  819. i++;
  820. }
  821. #endif
  822. if( argc == 2 )
  823. {
  824. ProcessId = _wtoi( argv[1] );
  825. }
  826. //
  827. // Enable debug privilege
  828. //
  829. if(!SetCurrentPrivilege(SE_DEBUG_NAME, TRUE)) {
  830. TERROR(L"SetCurrentPrivilege (debug) failed!");
  831. return E_FAIL;
  832. }
  833. if(!SetCurrentPrivilege(SE_TAKE_OWNERSHIP_NAME, TRUE)) {
  834. TERROR(L"SetCurrentPrivilege (TCB) failed!");
  835. return E_FAIL;
  836. }
  837. //
  838. // Run as local system
  839. //
  840. dwErr = GetLocalSystemToken(ProcessId, &hLocalSystem);
  841. if (NULL == hLocalSystem || dwErr != S_OK) {
  842. goto Ret;
  843. }
  844. // dwErr = LogoffAndRevert(hToken, pSD);
  845. {
  846. STARTUPINFO si;
  847. PROCESS_INFORMATION pi;
  848. ZeroMemory( &si, sizeof(si) );
  849. ZeroMemory( &pi, sizeof(pi) );
  850. si.cb = sizeof(si);
  851. si.lpTitle = "NT AUTHORITY\\SYSTEM";
  852. if(!CreateProcessAsUserA(
  853. hLocalSystem,
  854. NULL,
  855. "cmd.exe",
  856. NULL,
  857. NULL,
  858. FALSE,
  859. CREATE_NEW_CONSOLE,
  860. NULL,
  861. NULL,
  862. &si,
  863. &pi
  864. ))
  865. {
  866. TERRORVAL(L"CreateProcessAsUser", GetLastError());
  867. }
  868. }
  869. if (NULL != pSD) {
  870. MyFree(pSD);
  871. pSD = NULL;
  872. }
  873. if (hToken != INVALID_HANDLE_VALUE) {
  874. CloseHandle(hToken);
  875. hToken = INVALID_HANDLE_VALUE;
  876. }
  877. Ret:
  878. if (hToken != INVALID_HANDLE_VALUE) {
  879. CloseHandle(hToken);
  880. }
  881. if (NULL != hLocalSystem) {
  882. RevertToSelf();
  883. CloseHandle(hLocalSystem);
  884. }
  885. return dwErr;
  886. }
  887. #endif
  888. DWORD
  889. GetSystemProcessId(LPWSTR ProcessNameToFind,
  890. DWORD * ProcessId)
  891. {
  892. PSYSTEM_PROCESS_INFORMATION ProcessInfo =NULL;
  893. NTSTATUS NtStatus = 0;
  894. DWORD WinError = 0;
  895. ULONG TotalOffset = 0;
  896. ULONG NumRetry = 0;
  897. ULONG totalTasks = 0;
  898. LONG TheSame = 0;
  899. PUCHAR LargeBuffer = NULL;
  900. ULONG LargeBufferSize = 64*1024;
  901. UNICODE_STRING ProcessName;
  902. retry:
  903. if(NumRetry == 5)
  904. {
  905. WinError = RtlNtStatusToDosError(NtStatus);
  906. return WinError;
  907. }
  908. if (LargeBuffer == NULL)
  909. {
  910. LargeBuffer = (PUCHAR)MyAlloc (LargeBufferSize);
  911. if (LargeBuffer == NULL)
  912. {
  913. return GetLastError ();
  914. }
  915. }
  916. NtStatus = NtQuerySystemInformation(
  917. SystemProcessInformation,
  918. LargeBuffer,
  919. LargeBufferSize,
  920. NULL
  921. );
  922. if (NtStatus == STATUS_INFO_LENGTH_MISMATCH)
  923. {
  924. LargeBufferSize += 8192;
  925. MyFree(LargeBuffer);
  926. LargeBuffer = NULL;
  927. NumRetry++;
  928. goto retry;
  929. }
  930. if(NtStatus != STATUS_SUCCESS)
  931. {
  932. WinError = RtlNtStatusToDosError(NtStatus);
  933. return WinError;
  934. }
  935. NtStatus = RtlInitUnicodeStringEx( &ProcessName, ProcessNameToFind);
  936. if(NtStatus != STATUS_SUCCESS)
  937. {
  938. WinError = RtlNtStatusToDosError(NtStatus);
  939. return WinError;
  940. }
  941. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION) LargeBuffer;
  942. TotalOffset = 0;
  943. while (TRUE)
  944. {
  945. if ( ProcessInfo->ImageName.Buffer )
  946. {
  947. TheSame = RtlCompareUnicodeString((PUNICODE_STRING)&ProcessInfo->ImageName, &ProcessName, TRUE );
  948. if(TheSame == 0)
  949. {
  950. *ProcessId = (DWORD)(DWORD_PTR)ProcessInfo->UniqueProcessId;
  951. break;
  952. }
  953. }
  954. if (ProcessInfo->NextEntryOffset == 0)
  955. {
  956. break;
  957. }
  958. TotalOffset += ProcessInfo->NextEntryOffset;
  959. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&LargeBuffer[TotalOffset];
  960. }
  961. if(LargeBuffer)
  962. {
  963. MyFree (LargeBuffer);
  964. }
  965. return ERROR_SUCCESS;
  966. }