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.

5740 lines
191 KiB

  1. /*
  2. * Devctl.c
  3. *
  4. * IoCrash
  5. *
  6. * Copyright(c) 1997 Microsoft Corporation
  7. *
  8. * NeillC 23-Oct-97
  9. *
  10. * This program is designed to call as many of the user mode native NT API's as
  11. * possible. The program is written to crash drivers as its primary function.
  12. *
  13. */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <math.h>
  18. #include "nt.h"
  19. #include "ntrtl.h"
  20. #include "nturtl.h"
  21. #include <winsock2.h>
  22. #include <mswsock.h>
  23. #include "windows.h"
  24. #include "wmistr.h"
  25. #include "wmiumkm.h"
  26. #include "time.h"
  27. #include "tdi.h"
  28. #include "vdm.h"
  29. #include "sddl.h"
  30. #include "afd.h"
  31. #define MAX_DEVICES 4096
  32. #define PROT_REP 100000
  33. #define MAX_RET 5000
  34. #define DIAG_RET 50
  35. #define CRASH_LINE_SIZE 1024
  36. #define SLOP_SENTINAL 0xA5
  37. #define SLOP 100
  38. #define BIGBUF_SIZE 0x10000
  39. #define RAND_REP 1000
  40. #define MAX_IOCTL_TAILOR 100
  41. #define INITIAL_IOCTL_TAILOR_SIZE 200
  42. #define FLAGS_DO_IOCTL_NULL 0x00000001
  43. #define FLAGS_DO_IOCTL_RANDOM 0x00000002
  44. #define FLAGS_DO_FSCTL_NULL 0x00000004
  45. #define FLAGS_DO_FSCTL_RANDOM 0x00000008
  46. #define FLAGS_DO_USAGE 0x00000010
  47. #define FLAGS_DO_LOGGING 0x00000020
  48. #define FLAGS_DO_POOLCHECK 0x00000040
  49. #define FLAGS_DO_SKIPDONE 0x00000080
  50. #define FLAGS_DO_SKIPCRASH 0x00000100
  51. #define FLAGS_DO_MISC 0x00000200
  52. #define FLAGS_DO_QUERY 0x00000400
  53. #define FLAGS_DO_SUBOPENS 0x00000800
  54. #define FLAGS_DO_ALLDEVS 0x00001000
  55. #define FLAGS_DO_ZEROEA 0x00002000
  56. #define FLAGS_DO_GRAB 0x00004000
  57. #define FLAGS_DO_ERRORS 0x00008000
  58. #define FLAGS_DO_ALERT 0x00010000
  59. #define FLAGS_DO_LPC 0x00020000
  60. #define FLAGS_DO_MAPNULL 0x00040000
  61. #define FLAGS_DO_STREAMS 0x00080000
  62. #define FLAGS_DO_WINSOCK 0x00100000
  63. #define FLAGS_DO_SYNC 0x00200000
  64. #define FLAGS_DO_DISKS 0x00400000
  65. #define FLAGS_DO_PROT 0x00800000
  66. #define FLAGS_DO_SECURITY 0x01000000
  67. #define FLAGS_DO_IMPERSONATION 0x02000000
  68. #define FLAGS_DO_DIRECT_DEVICE 0x04000000
  69. #define FLAGS_DO_FAILURE_INJECTION 0x08000000
  70. #define FLAGS_DO_PRINT_DEVS 0x10000000
  71. #define FLAGS_DO_RANDOM_DEVICE 0x20000000
  72. #define FLAGS_DO_SYMBOLIC 0x40000000
  73. #define FLAGS_DO_OPEN_CLOSE 0x80000000
  74. #define FLAGS_DO_DRIVER 0x00000001
  75. #define DIAG_NOEXCEPTIONS 0x1
  76. #define OPEN_TYPE_TDI_CONNECTION 1
  77. #define OPEN_TYPE_TDI_ADDR_IP 2
  78. #define OPEN_TYPE_TDI_ADDR_NETBIOS 3
  79. #define OPEN_TYPE_TDI_ADDR_IPX 4
  80. #define OPEN_TYPE_TDI_ADDR_APPLE 5
  81. #define OPEN_TYPE_NAMED_PIPE 6
  82. #define OPEN_TYPE_MAIL_SLOT 7
  83. #define OPEN_TYPE_TREE_CONNECT 8
  84. #define OPEN_TYPE_AFD_TRANSPORT 9
  85. #define OPEN_TYPE_AFD_SAN 10
  86. typedef struct _DEVMAP {
  87. OBJECT_NAME_INFORMATION *name;
  88. FILE_NAME_INFORMATION *filename;
  89. HANDLE handle;
  90. DEVICE_TYPE devtype;
  91. ACCESS_MASK access;
  92. } DEVMAP, *PDEVMAP;
  93. //
  94. // Define a structure to keep a track of issued IOCTL's. We do this to try and make a
  95. // guess at what IOCTL's/FSCTL's a driver is actualy processing.
  96. //
  97. typedef struct _IOCTLINFO {
  98. NTSTATUS status;
  99. ULONG ioctl;
  100. ULONG count;
  101. } IOCTLINFO, *PIOCTLINFO;
  102. typedef struct _IOCTLREC {
  103. ULONG total, count, start;
  104. IOCTLINFO ioctl[];
  105. } IOCTLREC, *PIOCTLREC;
  106. typedef struct _CRASHNODE {
  107. struct _CRASHNODE *next;
  108. PWCHAR string;
  109. } CRASHNODE, *PCRASHNODE;
  110. DEVMAP devmap[MAX_DEVICES];
  111. ULONG devscount;
  112. ULONG skipped = 0;
  113. ULONG random_device = 0;
  114. UCHAR *bigbuf;
  115. FILE *skipfile = NULL;
  116. FILE *crashfile = NULL;
  117. FILE *diag_file = NULL;
  118. PCRASHNODE crashlist = NULL;
  119. HANDLE changethread, randthread, alertthread, mainthread;
  120. SOCKET ls, cs;
  121. ULONG flags=0, flags2=0;
  122. ULONG ioctl_min_function=0;
  123. ULONG ioctl_max_function=400 /*0xFFF*/;
  124. ULONG ioctl_min_devtype=0;
  125. ULONG ioctl_max_devtype=200;
  126. ULONG ioctl_inbuf_min=0x0;
  127. ULONG ioctl_inbuf_max=0x200;
  128. ULONG ioctl_outbuf_min=0;
  129. ULONG ioctl_outbuf_max=0x200;
  130. ULONG max_random_calls = 100000;
  131. ULONG max_tailured_calls = 10000;
  132. ULONG progress_counter=0;
  133. ULONG alerted=0;
  134. ULONG cid = 0;
  135. HANDLE process_handle = NULL;
  136. WCHAR lastcrashline[CRASH_LINE_SIZE];
  137. HANDLE sync_event = NULL;
  138. ULONG sessionid = 0;
  139. PCHAR prefix_string = NULL;
  140. HANDLE NonAdminToken=NULL;
  141. UNICODE_STRING DriverName={0};
  142. BOOLEAN Impersonating = FALSE;
  143. HANDLE CompletionPort = NULL;
  144. HANDLE CompletionEvent = NULL;
  145. HANDLE
  146. Create_nonadmin_token ()
  147. /*
  148. Create a token with administrator filtered out.
  149. */
  150. {
  151. HANDLE ProcessToken, RestrictedToken;
  152. SID_AND_ATTRIBUTES AdminSidAttrib;
  153. PSID pSid;
  154. SID_IDENTIFIER_AUTHORITY sia = {SECURITY_WORLD_SID_AUTHORITY};
  155. //
  156. // Open the process token
  157. //
  158. if (!OpenProcessToken (GetCurrentProcess (),
  159. MAXIMUM_ALLOWED,
  160. &ProcessToken)) {
  161. printf ("OpenProcessToken failed %d\n", GetLastError ());
  162. exit (EXIT_FAILURE);
  163. }
  164. if (!AllocateAndInitializeSid (&sia, 1, 0, 0, 0, 0, 0, 0, 0, 0, &pSid)) {
  165. printf ("AllocateAndInitializeSid failed %d\n", GetLastError ());
  166. CloseHandle (ProcessToken);
  167. exit (EXIT_FAILURE);
  168. }
  169. AdminSidAttrib.Sid = pSid;
  170. AdminSidAttrib.Attributes = 0;
  171. if (!CreateRestrictedToken (ProcessToken,
  172. DISABLE_MAX_PRIVILEGE,
  173. 0,
  174. NULL,
  175. 0,
  176. NULL,
  177. 1,
  178. &AdminSidAttrib,
  179. &RestrictedToken)) {
  180. FreeSid (pSid);
  181. CloseHandle (ProcessToken);
  182. printf ("CreateRestrictedToken failed %d\n", GetLastError ());
  183. exit (EXIT_FAILURE);
  184. }
  185. FreeSid (pSid);
  186. CloseHandle (ProcessToken);
  187. if (!DuplicateToken (RestrictedToken,
  188. SecurityDelegation,
  189. &NonAdminToken)) {
  190. CloseHandle (RestrictedToken);
  191. printf ("DuplicateToken failed %d\n", GetLastError ());
  192. exit (EXIT_FAILURE);
  193. }
  194. CloseHandle (RestrictedToken);
  195. return NonAdminToken;
  196. }
  197. VOID
  198. Impersonate_nonadmin ()
  199. {
  200. Impersonating = TRUE;
  201. if (NonAdminToken != NULL && !SetThreadToken (NULL, NonAdminToken)) {
  202. printf ("SetThreadToken failed %d\n", GetLastError ());
  203. exit (EXIT_FAILURE);
  204. }
  205. }
  206. DWORD
  207. Revert_from_admin ()
  208. {
  209. Impersonating = FALSE;
  210. return RevertToSelf ();
  211. }
  212. void
  213. tag_to_wide (PUCHAR t, PWCHAR wt)
  214. {
  215. ULONG i;
  216. for (i = 0; i < 4; i++) {
  217. *wt++ = *t++;
  218. }
  219. }
  220. /*
  221. Try and locate pool leaks by looking at pool tag info and lookaside list info.
  222. Try and locate where handled exceptions might reveal problems in the code.
  223. */
  224. BOOL
  225. print_diags (ULONG diag_flags, ULONG ret)
  226. {
  227. static PSYSTEM_POOLTAG_INFORMATION opb=NULL;
  228. PSYSTEM_POOLTAG_INFORMATION pb;
  229. static PSYSTEM_LOOKASIDE_INFORMATION olpb=NULL;
  230. static ULONG olpbl;
  231. PSYSTEM_LOOKASIDE_INFORMATION lpb;
  232. ULONG pbl, lpbl, i, j, retlen, retlen1;
  233. BOOL found, diff, newtag;
  234. NTSTATUS status;
  235. static ULONG firsterror = 1;
  236. static SYSTEM_EXCEPTION_INFORMATION sei, osei;
  237. WCHAR wtag[4];
  238. static ULONG lpbi = 1, pbi = 1;
  239. if ((flags&FLAGS_DO_POOLCHECK) == 0) {
  240. return FALSE;
  241. }
  242. if (!diag_file) {
  243. diag_file = _wfopen (L"diags.log", L"ab");
  244. if (!diag_file) {
  245. printf ("Failed to open diags.log for diagnostics\n");
  246. exit (EXIT_FAILURE);
  247. }
  248. }
  249. diff = FALSE;
  250. newtag = FALSE;
  251. status = NtQuerySystemInformation (SystemExceptionInformation, &sei, sizeof (sei),
  252. &retlen);
  253. if (!NT_SUCCESS (status)) {
  254. if (firsterror) {
  255. printf ("NtQuerySystemInformation for SystemExceptionInformation failed %x\n",
  256. status);
  257. firsterror = 0;
  258. }
  259. flags &= ~FLAGS_DO_POOLCHECK;
  260. return FALSE;
  261. }
  262. if (sei.ExceptionDispatchCount > osei.ExceptionDispatchCount &&
  263. osei.ExceptionDispatchCount) {
  264. if (!(diag_flags&DIAG_NOEXCEPTIONS)) {
  265. printf ("Exception count changed from %d to %d\n", osei.ExceptionDispatchCount,
  266. sei.ExceptionDispatchCount);
  267. if (ret == DIAG_RET) {
  268. fwprintf (diag_file, L"%s Exception count changed from %d to %d\r\n",
  269. lastcrashline,
  270. osei.ExceptionDispatchCount,
  271. sei.ExceptionDispatchCount);
  272. fflush (diag_file);
  273. } else if (ret < DIAG_RET) {
  274. diff = TRUE;
  275. }
  276. }
  277. }
  278. osei = sei;
  279. while (1) {
  280. /*
  281. Get memory for tag info
  282. */
  283. pbl = sizeof (*pb) + pbi * sizeof (pb->TagInfo[0]);
  284. pb = malloc (pbl);
  285. if (!pb) {
  286. printf ("Failed to allocate memory for pool buffer\n");
  287. exit (EXIT_FAILURE);
  288. }
  289. status = NtQuerySystemInformation (SystemPoolTagInformation, pb, pbl, &retlen1);
  290. if (pbl <= retlen1) {
  291. ULONG pbio = pbi;
  292. pbi = 1 + (retlen1 - sizeof (*pb)) / sizeof (pb->TagInfo[0]);
  293. // printf ("Increasing pooltag list table size to %d from %d\n", pbi, pbio);
  294. free (pb);
  295. continue;
  296. }
  297. if (!NT_SUCCESS (status)) {
  298. if (firsterror) {
  299. printf ("NtQuerySystemInformation failed %x\n", status);
  300. firsterror = 0;
  301. }
  302. flags &= ~FLAGS_DO_POOLCHECK;
  303. free (pb);
  304. return FALSE;
  305. }
  306. break;
  307. }
  308. while (1) {
  309. /*
  310. Get memory for lookaside info
  311. */
  312. lpbl = sizeof (*lpb) * lpbi;
  313. lpb = malloc (lpbl);
  314. if (!lpb) {
  315. printf ("Failed to allocate memory for pool buffer\n");
  316. exit (EXIT_FAILURE);
  317. }
  318. status = NtQuerySystemInformation (SystemLookasideInformation, lpb, lpbl, &retlen);
  319. if (lpbl <= retlen) {
  320. ULONG lpbio = lpbi;
  321. lpbi = 1 + retlen / sizeof (*lpb);
  322. // printf ("Increasing lookaside list table size to %d from %d\n", lpbi, lpbio);
  323. free (lpb);
  324. continue;
  325. }
  326. if (!NT_SUCCESS (status)) {
  327. printf ("NtQuerySystemInformation failed %x\n", status);
  328. flags &= ~FLAGS_DO_POOLCHECK;
  329. free (lpb);
  330. free (pb);
  331. return FALSE;
  332. }
  333. break;
  334. }
  335. lpbl = retlen / sizeof (*lpb);
  336. if (olpb) {
  337. for (i = 0; i < lpbl; i++) {
  338. /*
  339. Quick check here. the tag is probably in the same place it was last time
  340. */
  341. if (i < olpbl && lpb[i].Tag == olpb[i].Tag && lpb[i].Type == olpb[i].Type &&
  342. lpb[i].Size == olpb[i].Size) {
  343. found = TRUE;
  344. j = i;
  345. } else {
  346. /*
  347. It has moved so search them all.
  348. */
  349. for (j = 0; j < olpbl; j++) {
  350. if (lpb[i].Tag == olpb[j].Tag && lpb[i].Type == olpb[j].Type &&
  351. lpb[i].Size == olpb[j].Size) {
  352. found = TRUE;
  353. break;
  354. }
  355. }
  356. }
  357. if (found) {
  358. if (olpb[i].CurrentDepth > lpb[i].CurrentDepth) {
  359. printf ("Lookaside: %4.4s, size %d up %d\n",
  360. &lpb[i].Tag, lpb[i].Size,
  361. olpb[i].CurrentDepth - lpb[i].CurrentDepth);
  362. diff = TRUE;
  363. if (ret == DIAG_RET) {
  364. tag_to_wide ((PUCHAR)&lpb[i].Tag, wtag);
  365. fwprintf (diag_file, L"%s Lookaside: %4.4s, size %d up %d\r\n",
  366. lastcrashline,
  367. wtag, lpb[i].Size,
  368. olpb[i].CurrentDepth - lpb[i].CurrentDepth);
  369. fflush (diag_file);
  370. }
  371. }
  372. } else {
  373. /*
  374. A new tag has appeared here
  375. */
  376. printf ("New Lookaside %4.4s, size %d, depth %d\n",
  377. &lpb[i].Tag, lpb[i].Size,
  378. lpb[i].CurrentDepth);
  379. diff = TRUE;
  380. }
  381. }
  382. free (olpb);
  383. }
  384. /*
  385. now do lookaside information
  386. */
  387. // printf ("Total tags %d\n", pb->Count);
  388. if (opb) {
  389. for (i = 0; i < pb->Count; i++) {
  390. found = FALSE;
  391. if (i < opb->Count && pb->TagInfo[i].TagUlong == opb->TagInfo[i].TagUlong) {
  392. j = i;
  393. found = TRUE;
  394. } else {
  395. for (j = 0; j < pb->Count; j++) {
  396. if (pb->TagInfo[i].TagUlong == opb->TagInfo[j].TagUlong) {
  397. found = TRUE;
  398. break;
  399. }
  400. }
  401. }
  402. if (found) {
  403. if (pb->TagInfo[i].PagedUsed > opb->TagInfo[j].PagedUsed ||
  404. pb->TagInfo[i].NonPagedUsed > opb->TagInfo[j].NonPagedUsed) {
  405. diff = TRUE;
  406. printf ("Pool: %4.4s, Paged up %d, NonPaged up %d\n",
  407. &pb->TagInfo[i].TagUlong,
  408. pb->TagInfo[i].PagedUsed - opb->TagInfo[i].PagedUsed,
  409. pb->TagInfo[i].NonPagedUsed - opb->TagInfo[i].NonPagedUsed);
  410. if (ret == DIAG_RET) {
  411. tag_to_wide ((PUCHAR)&pb->TagInfo[i].TagUlong, wtag);
  412. fwprintf (diag_file, L"%s Pool: %4.4s, Paged up %d, NonPaged up %d\r\n",
  413. lastcrashline,
  414. wtag,
  415. pb->TagInfo[i].PagedUsed - opb->TagInfo[i].PagedUsed,
  416. pb->TagInfo[i].NonPagedUsed - opb->TagInfo[i].NonPagedUsed);
  417. fflush (diag_file);
  418. }
  419. }
  420. } else {
  421. diff = TRUE;
  422. newtag = TRUE;
  423. printf ("New tag %4.4s\n", &pb->TagInfo[i].TagUlong);
  424. }
  425. }
  426. free (opb);
  427. }
  428. opb = pb;
  429. olpb = lpb;
  430. olpbl = lpbl;
  431. return diff;
  432. }
  433. /*
  434. Turn on fault injection in the driver verifier
  435. */
  436. void turn_on_fault_injection ()
  437. {
  438. ULONG svi;
  439. NTSTATUS status;
  440. svi = DRIVER_VERIFIER_SPECIAL_POOLING |
  441. DRIVER_VERIFIER_FORCE_IRQL_CHECKING |
  442. DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES;
  443. status = NtSetSystemInformation (SystemVerifierInformation, &svi, sizeof (svi));
  444. if (!NT_SUCCESS (status)) {
  445. printf ("NtSetSystemInformation for SystemVerifierInformation failed %x\n",
  446. status);
  447. flags &= ~FLAGS_DO_FAILURE_INJECTION; // Turn off flag to prevent errors
  448. }
  449. }
  450. /*
  451. Turn off fault injection in the driver verifier
  452. */
  453. void turn_off_fault_injection ()
  454. {
  455. ULONG svi;
  456. NTSTATUS status;
  457. svi = DRIVER_VERIFIER_SPECIAL_POOLING |
  458. DRIVER_VERIFIER_FORCE_IRQL_CHECKING;
  459. status = NtSetSystemInformation (SystemVerifierInformation, &svi, sizeof (svi));
  460. if (!NT_SUCCESS (status)) {
  461. printf ("NtSetSystemInformation for SystemVerifierInformation failed %x\n",
  462. status);
  463. }
  464. }
  465. /*
  466. Read a line from the crash file and remove returns etc
  467. */
  468. PWCHAR getline (PWCHAR templine, ULONG size, FILE *file)
  469. {
  470. PWCHAR ret;
  471. PWCHAR cp;
  472. ret = fgetws (templine, size, file);
  473. if (ret) {
  474. cp = wcsstr (templine, L"\r");
  475. if (cp)
  476. *cp = '\0';
  477. cp = wcsstr (templine, L"\n");
  478. if (cp)
  479. *cp = '\0';
  480. }
  481. return ret;
  482. }
  483. /*
  484. Add a line to the list of lines that crashed us before
  485. */
  486. VOID add_crash_list (PWCHAR crashline)
  487. {
  488. PCRASHNODE node;
  489. node = malloc (sizeof (CRASHNODE));
  490. if (!node) {
  491. printf ("Memory allocation failed for crash node!\n");
  492. exit (EXIT_FAILURE);
  493. }
  494. node->next = crashlist;
  495. crashlist = node;
  496. node->string = malloc ((wcslen (crashline) + 1) * sizeof (WCHAR));
  497. if (!node->string) {
  498. printf ("Memory allocation failed for crash line!\n");
  499. exit (EXIT_FAILURE);
  500. }
  501. wcscpy (node->string, crashline);
  502. }
  503. /*
  504. See if this operation crashed us before
  505. */
  506. BOOL crashes (PWCHAR path, PWCHAR thing1, PWCHAR thing2, PWCHAR thing3, PWCHAR thing4)
  507. {
  508. PWCHAR crashline = NULL;
  509. PWCHAR templine = NULL;
  510. BOOL result;
  511. HANDLE crashfilehandle;
  512. DWORD retlen;
  513. BOOL opened;
  514. PCRASHNODE node;
  515. ULONG count;
  516. BOOLEAN StoppedImpersonating;
  517. progress_counter++;
  518. _snwprintf (lastcrashline, sizeof (lastcrashline)/sizeof (WCHAR),
  519. L"%s %s %s %s %s", path, thing1, thing2, thing3, thing4);
  520. lastcrashline[sizeof (lastcrashline)/sizeof (WCHAR) - 1] = L'\0';
  521. if ((flags&FLAGS_DO_LOGGING) == 0) {
  522. wprintf (L"%s\n", lastcrashline);
  523. SetConsoleTitleW (lastcrashline);
  524. return FALSE;
  525. }
  526. crashline = malloc (CRASH_LINE_SIZE*sizeof (WCHAR));
  527. if (!crashline) {
  528. printf ("Failed to allocate crash line buffer\n");
  529. exit (EXIT_FAILURE);
  530. }
  531. templine = malloc (CRASH_LINE_SIZE*sizeof (WCHAR));
  532. if (!templine) {
  533. printf ("Failed to allocate crash line buffer\n");
  534. exit (EXIT_FAILURE);
  535. }
  536. StoppedImpersonating = FALSE;
  537. if (Impersonating) {
  538. Revert_from_admin ();
  539. StoppedImpersonating = TRUE;
  540. }
  541. opened = FALSE;
  542. if (!skipfile) {
  543. /*
  544. First time in openen up the files
  545. */
  546. opened = TRUE;
  547. skipfile = _wfopen (L"crash.log", L"ab");
  548. if (skipfile) {
  549. crashfile = _wfopen (L"crashn.log", L"rb");
  550. if (crashfile) {
  551. printf ("Opened crashn.log for reading\n");
  552. crashline[0] = '\0';
  553. while (getline (templine, CRASH_LINE_SIZE, crashfile)) {
  554. if (wcslen (templine) > 0) {
  555. if (flags&FLAGS_DO_SKIPDONE) {
  556. add_crash_list (templine);
  557. }
  558. wcscpy (crashline, templine);
  559. }
  560. }
  561. fclose (crashfile);
  562. crashfile = NULL;
  563. if (crashline[0] != '\0' && wcsncmp (crashline, L"DONE", 4) != 0) {
  564. fputws (crashline, skipfile);
  565. fputws (L"\r\n", skipfile);
  566. }
  567. }
  568. fclose (skipfile);
  569. }
  570. skipfile = _wfopen (L"crash.log", L"rb");
  571. }
  572. if (skipfile && opened) {
  573. while (getline (crashline, CRASH_LINE_SIZE, skipfile)) {
  574. if (flags&FLAGS_DO_SKIPCRASH && wcscmp (crashline, L"DONE") != 0) {
  575. add_crash_list (crashline);
  576. }
  577. }
  578. }
  579. /*
  580. Run through crashing lines looking for a match
  581. */
  582. result = FALSE;
  583. _snwprintf (templine, CRASH_LINE_SIZE, L"%s %s %s %s %s", path, thing1, thing2, thing3, thing4);
  584. templine[CRASH_LINE_SIZE-1] = L'\0';
  585. SetConsoleTitleW (templine);
  586. for (node = crashlist; node; node = node->next) {
  587. if (_wcsicmp (node->string, templine) == 0) {
  588. result = TRUE;
  589. break;
  590. }
  591. }
  592. if (!result) {
  593. print_diags (0, 0);
  594. count = 0;
  595. do {
  596. crashfilehandle = CreateFile("crashn.log", GENERIC_WRITE, 0, NULL,
  597. OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0 );
  598. if (crashfilehandle == INVALID_HANDLE_VALUE) {
  599. printf ("CreateFile failed for crash logging file %d\n", GetLastError ());
  600. if (count++ > 20) {
  601. break;
  602. } else {
  603. Sleep (5000);
  604. }
  605. }
  606. } while (crashfilehandle == INVALID_HANDLE_VALUE);
  607. if (crashfilehandle != INVALID_HANDLE_VALUE) {
  608. SetFilePointer (crashfilehandle, 0, 0, FILE_END);
  609. _snwprintf (templine, CRASH_LINE_SIZE,
  610. L"%s %s %s %s %s\r\n", path, thing1, thing2, thing3, thing4);
  611. templine[CRASH_LINE_SIZE-1] = L'\0';
  612. wprintf (L"%s", templine);
  613. /*
  614. This is a bit excessive and costly but I really want to make sure this gets
  615. logged as the next operation may crash the machine.
  616. */
  617. if (!WriteFile (crashfilehandle, templine, wcslen(templine)*sizeof (WCHAR), &retlen, 0)) {
  618. printf ("WriteFile failed fore crash line %d\n", GetLastError ());
  619. exit (EXIT_FAILURE);
  620. }
  621. if (!FlushFileBuffers (crashfilehandle)) {
  622. printf ("FlushFileBuffers failed for crash file %d\n", GetLastError ());
  623. exit (EXIT_FAILURE);
  624. }
  625. if (!CloseHandle (crashfilehandle)) {
  626. printf ("CloseHandle failed for crash file %d\n", GetLastError ());
  627. exit (EXIT_FAILURE);
  628. }
  629. }
  630. }
  631. if (StoppedImpersonating) {
  632. Impersonate_nonadmin ();
  633. }
  634. free (crashline);
  635. free (templine);
  636. return result;
  637. }
  638. /*
  639. Hack to get a 32 bit random value from a 15 bit source
  640. */
  641. ULONG
  642. rand32(
  643. void
  644. )
  645. {
  646. return(rand() << 17) + rand() + rand();
  647. }
  648. /*
  649. RandInRange - produce a random number in some range
  650. */
  651. ULONG
  652. RandInRange( ULONG lowerb, ULONG upperb )
  653. {
  654. if( lowerb > upperb ) {
  655. ULONG temp;
  656. temp= upperb;
  657. return lowerb + rand32()%(upperb-lowerb);
  658. upperb= lowerb;
  659. upperb= temp;
  660. }
  661. return lowerb + rand32()%(upperb-lowerb);
  662. }
  663. /*
  664. Allocate a buffer with slop and fill the slop with a know value
  665. */
  666. PVOID
  667. reallocslop(
  668. PVOID p,
  669. ULONG len
  670. )
  671. {
  672. PVOID oldp;
  673. progress_counter++;
  674. oldp = p;
  675. p = realloc(oldp,
  676. len + SLOP);
  677. if (p == NULL) {
  678. if (oldp != NULL) {
  679. free (oldp);
  680. }
  681. return NULL;
  682. }
  683. memset(p,
  684. SLOP_SENTINAL,
  685. len + SLOP);
  686. return p;
  687. }
  688. /*
  689. Check to see if the driver wrote too far by checking the slop values
  690. */
  691. VOID
  692. testslop(
  693. PVOID p,
  694. ULONG len,
  695. PWCHAR what,
  696. PWCHAR subwhat
  697. )
  698. {
  699. UCHAR string[100], *pc;
  700. ULONG i;
  701. pc = p;
  702. pc += len;
  703. for (i = 0; i < SLOP; i++, pc++) {
  704. if (*pc != SLOP_SENTINAL) {
  705. wprintf(L"Driver wrote beyond end during %s %s for length %d!\n",
  706. what, subwhat, len);
  707. (void) scanf("%100s",
  708. string);
  709. break;
  710. }
  711. }
  712. }
  713. /*
  714. Issue different sized EA's
  715. */
  716. VOID
  717. do_query_ea(
  718. HANDLE handle,
  719. PWCHAR path
  720. )
  721. {
  722. ULONG l, i, old, ret;
  723. IO_STATUS_BLOCK iosb;
  724. ULONG tmp;
  725. PVOID buf;
  726. NTSTATUS status, last_status;
  727. if (crashes (path, L"NtQueryEaFile", L"", L"", L""))
  728. return;
  729. ret = 0;
  730. buf = NULL;
  731. do {
  732. last_status = 0;
  733. l = 1024;
  734. do {
  735. buf = reallocslop(buf,
  736. l);
  737. if (buf == NULL) {
  738. return;
  739. }
  740. status = NtQueryEaFile (handle, &iosb, buf, l, FALSE, NULL, 0, NULL, FALSE);
  741. if (NT_SUCCESS (status))
  742. status = iosb.Status;
  743. testslop(buf,
  744. l,
  745. L"NtQueryEaFile",
  746. L"");
  747. if (status == STATUS_NOT_IMPLEMENTED ||
  748. status == STATUS_INVALID_INFO_CLASS ||
  749. status == STATUS_INVALID_DEVICE_REQUEST ||
  750. status == STATUS_INVALID_PARAMETER ||
  751. status == STATUS_ACCESS_DENIED) {
  752. // break;
  753. }
  754. if (!NT_SUCCESS(status) &&
  755. status != last_status) {
  756. last_status = status;
  757. if (flags&FLAGS_DO_ERRORS)
  758. printf("NtQueryEaFile failed %x\n",
  759. status);
  760. }
  761. } while (l-- != 0);
  762. if (flags&FLAGS_DO_ZEROEA) {
  763. status = NtQueryEaFile(handle,
  764. &iosb,
  765. (PVOID)-1024,
  766. 0,
  767. FALSE, NULL, 0, NULL, FALSE);
  768. }
  769. if (!NT_SUCCESS(status)) {
  770. if (flags&FLAGS_DO_ERRORS)
  771. printf("NtQueryEaFile failed %x\n",
  772. status);
  773. }
  774. } while (print_diags (0, ret++) && ret < MAX_RET);
  775. status = NtCancelIoFile (handle, &iosb);
  776. free(buf);
  777. if (!(flags&FLAGS_DO_PROT) || crashes (path, L"NtQueryEaFile prot", L"", L"", L""))
  778. return;
  779. status = NtResumeThread (changethread, &tmp);
  780. if (!NT_SUCCESS (status)) {
  781. printf ("NtResumeThread failed %x\n", status);
  782. }
  783. for (i = 1; i < PROT_REP; i++) {
  784. if (!VirtualProtect (buf, 1, PAGE_READWRITE, &old)) {
  785. printf ("VirtualProtect failed %d\n", GetLastError ());
  786. }
  787. status = NtQueryEaFile(handle,
  788. &iosb,
  789. bigbuf,
  790. BIGBUF_SIZE,
  791. FALSE, NULL, 0, NULL, FALSE);
  792. }
  793. status = NtSuspendThread (changethread, &tmp);
  794. if (!NT_SUCCESS (status)) {
  795. printf ("NtResumeThread failed %x\n", status);
  796. }
  797. if (!VirtualProtect (buf, 1, PAGE_READWRITE, &old)) {
  798. printf ("VirtualProtect failed %d\n", GetLastError ());
  799. }
  800. }
  801. /*
  802. Do volume queries of different lengths
  803. */
  804. VOID
  805. do_query_volume(
  806. HANDLE handle,
  807. FS_INFORMATION_CLASS InfoType,
  808. ULONG bufl,
  809. PWCHAR what,
  810. PWCHAR path
  811. )
  812. {
  813. ULONG l, ret;
  814. IO_STATUS_BLOCK iosb;
  815. PVOID buf;
  816. NTSTATUS status, last_status;
  817. if (crashes (path, L"NtQueryVolumeInformationFile", what, L"", L""))
  818. return;
  819. ret = 0;
  820. buf = NULL;
  821. do {
  822. last_status = 0;
  823. l = bufl + 1024;
  824. do {
  825. buf = reallocslop(buf,
  826. l);
  827. if (buf == NULL) {
  828. return;
  829. }
  830. status = NtQueryVolumeInformationFile(handle,
  831. &iosb,
  832. buf,
  833. l,
  834. InfoType);
  835. testslop(buf,
  836. l,
  837. L"NtQueryVolumeInformationFile",
  838. what);
  839. if (status == STATUS_NOT_IMPLEMENTED ||
  840. status == STATUS_INVALID_INFO_CLASS ||
  841. status == STATUS_INVALID_DEVICE_REQUEST ||
  842. status == STATUS_INVALID_PARAMETER ||
  843. status == STATUS_ACCESS_DENIED) {
  844. // break;
  845. }
  846. if (!NT_SUCCESS(status) &&
  847. status != last_status) {
  848. last_status = status;
  849. if (flags&FLAGS_DO_ERRORS)
  850. wprintf(L"NtQueryVolumeInformationFile for %s failed %x\n",
  851. what, status);
  852. }
  853. } while (l-- != 0);
  854. status = NtQueryVolumeInformationFile(handle,
  855. &iosb,
  856. (PVOID)-1024,
  857. 0,
  858. InfoType);
  859. if (!NT_SUCCESS(status)) {
  860. if (flags&FLAGS_DO_ERRORS)
  861. wprintf(L"NtQueryVolumeInformationFile for %s failed %x\n",
  862. what, status);
  863. }
  864. } while (print_diags (0, ret++) && ret < MAX_RET);
  865. status = NtCancelIoFile (handle, &iosb);
  866. free(buf);
  867. }
  868. /*
  869. Do volume sets of different lengths
  870. */
  871. VOID
  872. do_set_volume(
  873. HANDLE handle,
  874. FS_INFORMATION_CLASS InfoType,
  875. ULONG bufl,
  876. PWCHAR what,
  877. PWCHAR path
  878. )
  879. {
  880. ULONG l, i, ret;
  881. IO_STATUS_BLOCK iosb;
  882. PVOID buf;
  883. NTSTATUS status, last_status;
  884. if (crashes (path, L"NtSetVolumeInformationFile", what, L"", L""))
  885. return;
  886. ret = 0;
  887. buf = NULL;
  888. do {
  889. last_status = 0;
  890. l = bufl + 1024;
  891. buf = malloc (l);
  892. if (buf == NULL) {
  893. return;
  894. }
  895. do {
  896. for (i = 0; i < l; i++) {
  897. ((PCHAR)buf)[i] = (CHAR) rand ();
  898. }
  899. progress_counter++;
  900. status = NtSetVolumeInformationFile(handle,
  901. &iosb,
  902. buf,
  903. l,
  904. InfoType);
  905. if (status == STATUS_NOT_IMPLEMENTED ||
  906. status == STATUS_INVALID_INFO_CLASS ||
  907. status == STATUS_INVALID_DEVICE_REQUEST ||
  908. status == STATUS_INVALID_PARAMETER ||
  909. status == STATUS_ACCESS_DENIED) {
  910. // break;
  911. }
  912. if (!NT_SUCCESS(status) &&
  913. status != last_status) {
  914. last_status = status;
  915. if (flags&FLAGS_DO_ERRORS)
  916. wprintf(L"NtSetVolumeInformationFile for %s failed %x\n",
  917. what, status);
  918. }
  919. } while (l-- != 0);
  920. progress_counter++;
  921. status = NtSetVolumeInformationFile(handle,
  922. &iosb,
  923. (PVOID)-1024,
  924. 0,
  925. InfoType);
  926. if (!NT_SUCCESS(status)) {
  927. if (flags&FLAGS_DO_ERRORS)
  928. wprintf(L"NtSetVolumeInformationFile for %s failed %x\n",
  929. what, status);
  930. }
  931. } while (print_diags (0, ret++) && ret < MAX_RET);
  932. status = NtCancelIoFile (handle, &iosb);
  933. free(buf);
  934. }
  935. /*
  936. Do file queries
  937. */
  938. VOID
  939. do_query_file(
  940. HANDLE handle,
  941. FILE_INFORMATION_CLASS InfoType,
  942. ULONG bufl,
  943. PWCHAR what,
  944. PWCHAR path
  945. )
  946. {
  947. ULONG l, i, ret;
  948. IO_STATUS_BLOCK iosb;
  949. PVOID buf;
  950. NTSTATUS status, last_status;
  951. ULONG tmp;
  952. DWORD old;
  953. if (crashes (path, L"NtQueryInformationFile", what, L"", L""))
  954. return;
  955. ret = 0;
  956. buf = NULL;
  957. do {
  958. last_status = 0;
  959. l = bufl + 1024;
  960. do {
  961. buf = reallocslop(buf,
  962. l);
  963. if (buf == NULL) {
  964. return;
  965. }
  966. status = NtQueryInformationFile(handle,
  967. &iosb,
  968. buf,
  969. l,
  970. InfoType);
  971. testslop(buf,
  972. l,
  973. L"NtQueryInformationFile",
  974. what);
  975. if (status == STATUS_NOT_IMPLEMENTED ||
  976. status == STATUS_INVALID_INFO_CLASS ||
  977. status == STATUS_INVALID_DEVICE_REQUEST ||
  978. status == STATUS_INVALID_PARAMETER ||
  979. status == STATUS_ACCESS_DENIED) {
  980. // break;
  981. }
  982. if (!NT_SUCCESS(status) &&
  983. status != last_status) {
  984. last_status = status;
  985. if (flags&FLAGS_DO_ERRORS)
  986. wprintf(L"NtQueryInformationFile for %s failed %x\n",
  987. what, status);
  988. }
  989. } while (l-- != 0);
  990. status = NtQueryInformationFile(handle,
  991. &iosb,
  992. (PVOID)-1024,
  993. 0,
  994. InfoType);
  995. if (!NT_SUCCESS(status)) {
  996. if (flags&FLAGS_DO_ERRORS)
  997. wprintf(L"NtQueryInformationFile for %s failed %x\n",
  998. what, status);
  999. }
  1000. } while (print_diags (0, ret++) && ret < MAX_RET);
  1001. status = NtCancelIoFile (handle, &iosb);
  1002. free(buf);
  1003. if (!(flags&FLAGS_DO_PROT) ||
  1004. crashes (path, L"NtQueryInformationFile prot", L"", L"", L""))
  1005. return;
  1006. status = NtResumeThread (changethread, &tmp);
  1007. if (!NT_SUCCESS (status)) {
  1008. printf ("NtResumeThread failed %x\n", status);
  1009. }
  1010. for (i = 1; i < PROT_REP; i++) {
  1011. if (!VirtualProtect (buf, 1, PAGE_READWRITE, &old)) {
  1012. printf ("VirtualProtect failed %d\n", GetLastError ());
  1013. }
  1014. status = NtQueryInformationFile(handle,
  1015. &iosb,
  1016. bigbuf,
  1017. bufl,
  1018. InfoType);
  1019. }
  1020. status = NtSuspendThread (changethread, &tmp);
  1021. if (!NT_SUCCESS (status)) {
  1022. printf ("NtResumeThread failed %x\n", status);
  1023. }
  1024. if (!VirtualProtect (buf, 1, PAGE_READWRITE, &old)) {
  1025. printf ("VirtualProtect failed %d\n", GetLastError ());
  1026. }
  1027. }
  1028. /*
  1029. Do file sets
  1030. */
  1031. VOID
  1032. do_set_file(
  1033. HANDLE handle,
  1034. FILE_INFORMATION_CLASS InfoType,
  1035. ULONG bufl,
  1036. PWCHAR what,
  1037. PWCHAR path
  1038. )
  1039. {
  1040. ULONG l, i, ret;
  1041. IO_STATUS_BLOCK iosb;
  1042. PVOID buf;
  1043. NTSTATUS status, last_status;
  1044. ULONG tmp;
  1045. DWORD old;
  1046. if (crashes (path, L"NtSetInformationFile", what, L"", L""))
  1047. return;
  1048. ret = 0;
  1049. buf = NULL;
  1050. do {
  1051. last_status = 0;
  1052. l = bufl + 1024;
  1053. buf = malloc (l);
  1054. if (buf == NULL) {
  1055. return;
  1056. }
  1057. do {
  1058. for (i = 0; i < l; i++) {
  1059. ((PCHAR)buf)[i] = (CHAR) rand ();
  1060. }
  1061. progress_counter++;
  1062. status = NtSetInformationFile(handle,
  1063. &iosb,
  1064. buf,
  1065. l,
  1066. InfoType);
  1067. if (status == STATUS_NOT_IMPLEMENTED ||
  1068. status == STATUS_INVALID_INFO_CLASS ||
  1069. status == STATUS_INVALID_DEVICE_REQUEST ||
  1070. status == STATUS_INVALID_PARAMETER ||
  1071. status == STATUS_ACCESS_DENIED) {
  1072. // break;
  1073. }
  1074. if (!NT_SUCCESS(status) &&
  1075. status != last_status) {
  1076. last_status = status;
  1077. if (flags&FLAGS_DO_ERRORS)
  1078. wprintf(L"NtSetInformationFile for %s failed %x\n",
  1079. what, status);
  1080. }
  1081. } while (l-- != 0);
  1082. status = NtSetInformationFile(handle,
  1083. &iosb,
  1084. (PVOID)-1024,
  1085. 0,
  1086. InfoType);
  1087. if (!NT_SUCCESS(status)) {
  1088. if (flags&FLAGS_DO_ERRORS)
  1089. wprintf(L"NtSetInformationFile for %s failed %x\n",
  1090. what, status);
  1091. }
  1092. } while (print_diags (0, ret++) && ret < MAX_RET);
  1093. status = NtCancelIoFile (handle, &iosb);
  1094. free(buf);
  1095. if (!(flags&FLAGS_DO_PROT) ||
  1096. crashes (path, L"NtSetInformationFile prot", L"", L"", L""))
  1097. return;
  1098. status = NtResumeThread (changethread, &tmp);
  1099. if (!NT_SUCCESS (status)) {
  1100. printf ("NtResumeThread failed %x\n", status);
  1101. }
  1102. for (i = 1; i < PROT_REP; i++) {
  1103. if (!VirtualProtect (buf, 1, PAGE_READWRITE, &old)) {
  1104. printf ("VirtualProtect failed %d\n", GetLastError ());
  1105. }
  1106. status = NtSetInformationFile(handle,
  1107. &iosb,
  1108. bigbuf,
  1109. bufl,
  1110. InfoType);
  1111. }
  1112. status = NtSuspendThread (changethread, &tmp);
  1113. if (!NT_SUCCESS (status)) {
  1114. printf ("NtResumeThread failed %x\n", status);
  1115. }
  1116. if (!VirtualProtect (buf, 1, PAGE_READWRITE, &old)) {
  1117. printf ("VirtualProtect failed %d\n", GetLastError ());
  1118. }
  1119. }
  1120. /*
  1121. Do object queries with variable length buffers
  1122. */
  1123. VOID
  1124. do_query_object(
  1125. HANDLE handle,
  1126. OBJECT_INFORMATION_CLASS InfoType,
  1127. ULONG bufl,
  1128. PWCHAR what,
  1129. PWCHAR path
  1130. )
  1131. {
  1132. ULONG l, ret;
  1133. IO_STATUS_BLOCK iosb;
  1134. PVOID buf;
  1135. NTSTATUS status, last_status;
  1136. last_status = 0;
  1137. if (crashes (path, L"NtQueryObject", what, L"", L""))
  1138. return;
  1139. buf = NULL;
  1140. ret = 0;
  1141. do {
  1142. l = bufl + 1024;
  1143. do {
  1144. buf = reallocslop(buf,
  1145. l);
  1146. if (buf == NULL) {
  1147. return;
  1148. }
  1149. status = NtQueryObject(handle,
  1150. InfoType,
  1151. buf,
  1152. l,
  1153. NULL);
  1154. testslop(buf, l, L"NtQueryObject", what);
  1155. if (!NT_SUCCESS(status) &&
  1156. status != last_status) {
  1157. last_status = status;
  1158. if (flags&FLAGS_DO_ERRORS)
  1159. wprintf(L"NtQueryObject for %s failed %x\n",
  1160. what, status);
  1161. }
  1162. } while (l-- != 0);
  1163. status = NtQueryObject(handle,
  1164. InfoType,
  1165. (PVOID)-1024,
  1166. 0,
  1167. NULL);
  1168. if (!NT_SUCCESS(status)) {
  1169. if (flags&FLAGS_DO_ERRORS)
  1170. wprintf(L"NtQueryObject for %s failed %x\n",
  1171. what, status);
  1172. }
  1173. } while (print_diags (0, ret++) && ret < MAX_RET);
  1174. status = NtCancelIoFile (handle, &iosb);
  1175. free(buf);
  1176. }
  1177. /*
  1178. Do query security
  1179. */
  1180. VOID
  1181. do_query_security(
  1182. HANDLE handle,
  1183. SECURITY_INFORMATION InfoType,
  1184. ULONG bufl,
  1185. PWCHAR what,
  1186. PWCHAR path
  1187. )
  1188. {
  1189. ULONG l, i, tmp, ret;
  1190. IO_STATUS_BLOCK iosb;
  1191. PVOID buf;
  1192. NTSTATUS status, last_status;
  1193. ULONG ln;
  1194. DWORD old;
  1195. if (crashes (path, L"NtQuerySecurityObject", what, L"", L""))
  1196. return;
  1197. buf = NULL;
  1198. ret = 0;
  1199. do {
  1200. last_status = 0;
  1201. l = bufl + 1024;
  1202. do {
  1203. buf = reallocslop(buf,
  1204. l);
  1205. if (buf == NULL) {
  1206. return;
  1207. }
  1208. status = NtQuerySecurityObject(handle,
  1209. InfoType,
  1210. buf,
  1211. l,
  1212. &ln);
  1213. testslop(buf, l, L"NtQuerySecurityObject", what);
  1214. if (!NT_SUCCESS(status) &&
  1215. status != last_status && status) {
  1216. last_status = status;
  1217. if (flags&FLAGS_DO_ERRORS)
  1218. wprintf(L"NtQuerySecurityObject for %s failed %x\n",
  1219. what, status);
  1220. }
  1221. } while (l-- != 0);
  1222. status = NtQuerySecurityObject(handle,
  1223. InfoType,
  1224. (PVOID)-1024,
  1225. 0,
  1226. &ln);
  1227. if (!NT_SUCCESS(status)) {
  1228. if (flags&FLAGS_DO_ERRORS)
  1229. wprintf(L"NtQuerySecurityObject for %s failed %x\n",
  1230. what, status);
  1231. }
  1232. } while (print_diags (0, ret++) && ret < MAX_RET);
  1233. status = NtCancelIoFile (handle, &iosb);
  1234. free(buf);
  1235. if (!(flags&FLAGS_DO_PROT) ||
  1236. crashes (path, L"NtQuerySecurityFile prot", L"", L"", L""))
  1237. return;
  1238. status = NtResumeThread (changethread, &tmp);
  1239. if (!NT_SUCCESS (status)) {
  1240. printf ("NtResumeThread failed %x\n", status);
  1241. }
  1242. for (i = 1; i < PROT_REP; i++) {
  1243. if (!VirtualProtect (buf, 1, PAGE_READWRITE, &old)) {
  1244. printf ("VirtualProtect failed %d\n", GetLastError ());
  1245. }
  1246. status = NtQuerySecurityObject(handle,
  1247. InfoType,
  1248. bigbuf,
  1249. bufl,
  1250. &ln);
  1251. }
  1252. status = NtSuspendThread (changethread, &tmp);
  1253. if (!NT_SUCCESS (status)) {
  1254. printf ("NtResumeThread failed %x\n", status);
  1255. }
  1256. if (!VirtualProtect (buf, 1, PAGE_READWRITE, &old)) {
  1257. printf ("VirtualProtect failed %d\n", GetLastError ());
  1258. }
  1259. }
  1260. /*
  1261. Do set security
  1262. */
  1263. VOID
  1264. do_set_security(
  1265. HANDLE handle,
  1266. SECURITY_INFORMATION InfoType,
  1267. ULONG bufl,
  1268. PWCHAR what,
  1269. PWCHAR path
  1270. )
  1271. {
  1272. ULONG l, i, tmp, ret;
  1273. IO_STATUS_BLOCK iosb;
  1274. PVOID buf;
  1275. NTSTATUS status, last_status;
  1276. ULONG ln;
  1277. DWORD old;
  1278. PSECURITY_DESCRIPTOR psd;
  1279. LPTSTR tsd;
  1280. if (crashes (path, L"NtSetSecurityObject", what, L"", L""))
  1281. return;
  1282. psd = malloc (l = 4096);
  1283. if (!psd) {
  1284. printf ("Failed to allocate security descriptor space\n");
  1285. return;
  1286. }
  1287. status = NtQuerySecurityObject(handle,
  1288. InfoType,
  1289. psd,
  1290. l,
  1291. &ln);
  1292. if (!NT_SUCCESS(status)) {
  1293. free (psd);
  1294. if (flags&FLAGS_DO_ERRORS)
  1295. wprintf(L"NtQuerySecurityObject for %s failed %x\n",
  1296. what, status);
  1297. return;
  1298. }
  1299. if (InfoType) {
  1300. if (ConvertSecurityDescriptorToStringSecurityDescriptor (psd,
  1301. SDDL_REVISION_1,
  1302. InfoType,
  1303. &tsd,
  1304. NULL)) {
  1305. printf ("%ws: %s\n", what, tsd);
  1306. LocalFree (tsd);
  1307. } else {
  1308. printf ("ConvertSecurityDescriptorToStringSecurityDescriptor failed %d\n", GetLastError ());
  1309. }
  1310. }
  1311. buf = NULL;
  1312. ret = 0;
  1313. do {
  1314. last_status = 0;
  1315. status = NtSetSecurityObject(handle,
  1316. InfoType,
  1317. psd);
  1318. if (!NT_SUCCESS(status) &&
  1319. status != last_status && status) {
  1320. last_status = status;
  1321. if (flags&FLAGS_DO_ERRORS)
  1322. wprintf(L"NtSetSecurityObject for %s failed %x\n",
  1323. what, status);
  1324. }
  1325. status = NtCancelIoFile (handle, &iosb);
  1326. } while (print_diags (0, ret++) && ret < MAX_RET);
  1327. free(psd);
  1328. }
  1329. /*
  1330. Do all the query functions
  1331. */
  1332. NTSTATUS
  1333. query_object(
  1334. HANDLE handle,
  1335. PDEVMAP devmap,
  1336. PWCHAR path
  1337. )
  1338. {
  1339. OBJECT_NAME_INFORMATION *on = NULL;
  1340. FILE_NAME_INFORMATION *fn = NULL;
  1341. ULONG sfn, son;
  1342. FILE_FS_DEVICE_INFORMATION devinfo;
  1343. NTSTATUS status;
  1344. static IO_STATUS_BLOCK iosb;
  1345. sfn = sizeof (*fn) + 1024;
  1346. son = sizeof (*on) + 1024;
  1347. fn = reallocslop(NULL,
  1348. sfn);
  1349. if (fn == NULL) {
  1350. return STATUS_INSUFFICIENT_RESOURCES;
  1351. }
  1352. on = reallocslop(NULL,
  1353. son);
  1354. if (on == NULL) {
  1355. free (fn);
  1356. return STATUS_INSUFFICIENT_RESOURCES;
  1357. }
  1358. if (devmap) {
  1359. devmap->filename = fn;
  1360. devmap->name = on;
  1361. }
  1362. if (fn == NULL || on == NULL) {
  1363. printf("Memory allocation failure in query_object!\n");
  1364. exit(EXIT_FAILURE);
  1365. }
  1366. status = NtQueryObject(handle,
  1367. ObjectNameInformation,
  1368. on,
  1369. son,
  1370. NULL);
  1371. testslop(on,
  1372. son, L"NtQueryObject", L"ObjectNameInformation");
  1373. if (!NT_SUCCESS(status)) {
  1374. if (flags&FLAGS_DO_ERRORS) {
  1375. wprintf(L"NtQueryObject for ObjectNameInformation failed %x\n",
  1376. status);
  1377. }
  1378. on->Name.Length = 0;
  1379. } else {
  1380. wprintf (L"Object name is %s\n", on->Name.Buffer);
  1381. }
  1382. status = NtQueryInformationFile(handle,
  1383. &iosb,
  1384. fn,
  1385. sfn,
  1386. FileNameInformation);
  1387. testslop(fn,
  1388. sfn,
  1389. L"NtQueryInformationFile",
  1390. L"FileNameInformation");
  1391. if (NT_SUCCESS(status)) {
  1392. status = iosb.Status;
  1393. }
  1394. if (!NT_SUCCESS(status)) {
  1395. if (flags&FLAGS_DO_ERRORS)
  1396. wprintf(L"NtQueryInformationFile for FileNameInformation failed %x\n",
  1397. status);
  1398. fn->FileNameLength = 0;
  1399. }
  1400. if (!devmap) {
  1401. free (fn);
  1402. free (on);
  1403. }
  1404. status = NtQueryVolumeInformationFile(handle,
  1405. &iosb,
  1406. &devinfo,
  1407. sizeof (devinfo),
  1408. FileFsDeviceInformation);
  1409. if (NT_SUCCESS(status)) {
  1410. status = iosb.Status;
  1411. }
  1412. if (!NT_SUCCESS(status)) {
  1413. if (flags&FLAGS_DO_ERRORS)
  1414. wprintf(L"NtQueryVolumeInformationFile for FileFsDeviceInformation failed %x\n",
  1415. status);
  1416. if (devmap)
  1417. devmap->devtype = 0;
  1418. } else {
  1419. if (devmap)
  1420. devmap->devtype = devinfo.DeviceType;
  1421. // printf("Got the device number for a device!\n");
  1422. }
  1423. if (flags&FLAGS_DO_QUERY) {
  1424. //
  1425. // Do loads of different queries with different buffer lengths.
  1426. //
  1427. do_query_object(handle,
  1428. ObjectNameInformation,
  1429. sizeof (OBJECT_NAME_INFORMATION),
  1430. L"ObjectNameInformation",
  1431. path);
  1432. do_query_file(handle,
  1433. FileBasicInformation,
  1434. sizeof (FILE_BASIC_INFORMATION),
  1435. L"FileBasicInformation",
  1436. path);
  1437. do_query_file(handle,
  1438. FileStandardInformation,
  1439. sizeof (FILE_STANDARD_INFORMATION),
  1440. L"FileStandardInformation",
  1441. path);
  1442. do_query_file(handle,
  1443. FileInternalInformation,
  1444. sizeof (FILE_INTERNAL_INFORMATION),
  1445. L"FileInternalInformation",
  1446. path);
  1447. do_query_file(handle,
  1448. FileEaInformation,
  1449. sizeof (FILE_EA_INFORMATION),
  1450. L"FileEaInformation",
  1451. path);
  1452. do_query_file(handle,
  1453. FileAccessInformation,
  1454. sizeof (FILE_ACCESS_INFORMATION),
  1455. L"FileAccessInformation",
  1456. path);
  1457. do_query_file(handle,
  1458. FileNameInformation,
  1459. sizeof (FILE_NAME_INFORMATION) + 1024,
  1460. L"FileNameInformation",
  1461. path);
  1462. //
  1463. // We end up turning off alertable handle with this.
  1464. //
  1465. // do_query_file(handle,
  1466. // FileModeInformation,
  1467. // sizeof (FILE_MODE_INFORMATION),
  1468. // L"FileModeInformation",
  1469. // path);
  1470. do_query_file(handle,
  1471. FileAlignmentInformation,
  1472. sizeof (FILE_ALIGNMENT_INFORMATION),
  1473. L"FileAlignmentInformation",
  1474. path);
  1475. do_query_file(handle,
  1476. FileAllInformation,
  1477. sizeof (FILE_ALL_INFORMATION),
  1478. L"FileAllInformation",
  1479. path);
  1480. do_query_file(handle,
  1481. FileStreamInformation,
  1482. sizeof (FILE_STREAM_INFORMATION),
  1483. L"FileStreamInformation",
  1484. path);
  1485. do_query_file(handle,
  1486. FilePipeInformation,
  1487. sizeof (FILE_PIPE_INFORMATION),
  1488. L"FilePipeInformation",
  1489. path);
  1490. do_query_file(handle,
  1491. FilePipeLocalInformation,
  1492. sizeof (FILE_PIPE_LOCAL_INFORMATION),
  1493. L"FilePipeLocalInformation",
  1494. path);
  1495. do_query_file(handle,
  1496. FilePipeRemoteInformation,
  1497. sizeof (FILE_PIPE_REMOTE_INFORMATION),
  1498. L"FilePipeRemoteInformation",
  1499. path);
  1500. do_query_file(handle,
  1501. FileCompressionInformation,
  1502. sizeof (FILE_COMPRESSION_INFORMATION),
  1503. L"FileCompressionInformation",
  1504. path);
  1505. do_query_file(handle,
  1506. FileObjectIdInformation,
  1507. sizeof (FILE_OBJECTID_INFORMATION),
  1508. L"FileObjectIdInformation",
  1509. path);
  1510. do_query_file(handle,
  1511. FileMailslotQueryInformation,
  1512. sizeof (FILE_MAILSLOT_QUERY_INFORMATION),
  1513. L"FileMailslotQueryInformation",
  1514. path);
  1515. do_query_file(handle,
  1516. FileQuotaInformation,
  1517. sizeof (FILE_QUOTA_INFORMATION),
  1518. L"FileQuotaInformation",
  1519. path);
  1520. do_query_file(handle,
  1521. FileReparsePointInformation,
  1522. sizeof (FILE_REPARSE_POINT_INFORMATION),
  1523. L"FileReparsePointInformation",
  1524. path);
  1525. do_query_file(handle,
  1526. FileNetworkOpenInformation,
  1527. sizeof (FILE_NETWORK_OPEN_INFORMATION),
  1528. L"FileNetworkOpenInformation",
  1529. path);
  1530. do_query_file(handle,
  1531. FileAttributeTagInformation,
  1532. sizeof (FILE_ATTRIBUTE_TAG_INFORMATION),
  1533. L"FileAttributeTagInformation",
  1534. path);
  1535. do_set_file(handle,
  1536. FileBasicInformation,
  1537. sizeof (FILE_BASIC_INFORMATION),
  1538. L"FileBasicInformation",
  1539. path);
  1540. do_set_file(handle,
  1541. FileRenameInformation,
  1542. sizeof (FILE_RENAME_INFORMATION),
  1543. L"FileRenameInformation",
  1544. path);
  1545. do_set_file(handle,
  1546. FileLinkInformation,
  1547. sizeof (FILE_LINK_INFORMATION),
  1548. L"FileLinkInformation",
  1549. path);
  1550. do_set_file(handle,
  1551. FileDispositionInformation,
  1552. sizeof (FILE_DISPOSITION_INFORMATION),
  1553. L"FileDispositionInformation",
  1554. path);
  1555. do_set_file(handle,
  1556. FilePositionInformation,
  1557. sizeof (FILE_POSITION_INFORMATION),
  1558. L"FilePositionInformation",
  1559. path);
  1560. do_set_file(handle,
  1561. FileAllocationInformation,
  1562. sizeof (FILE_ALLOCATION_INFORMATION),
  1563. L"FileAllocationInformation",
  1564. path);
  1565. do_set_file(handle,
  1566. FileEndOfFileInformation,
  1567. sizeof (FILE_END_OF_FILE_INFORMATION),
  1568. L"FileEndOfFileInformation",
  1569. path);
  1570. do_set_file(handle,
  1571. FilePipeInformation,
  1572. sizeof (FILE_PIPE_INFORMATION),
  1573. L"FilePipeInformation",
  1574. path);
  1575. do_set_file(handle,
  1576. FilePipeRemoteInformation,
  1577. sizeof (FILE_PIPE_REMOTE_INFORMATION),
  1578. L"FilePipeRemoteInformation",
  1579. path);
  1580. do_set_file(handle,
  1581. FileMailslotSetInformation,
  1582. sizeof (FILE_MAILSLOT_SET_INFORMATION),
  1583. L"FileMailslotSetInformation",
  1584. path);
  1585. do_set_file(handle,
  1586. FileObjectIdInformation,
  1587. sizeof (FILE_OBJECTID_INFORMATION),
  1588. L"FileObjectIdInformation",
  1589. path);
  1590. do_set_file(handle,
  1591. FileMoveClusterInformation,
  1592. sizeof (FILE_MOVE_CLUSTER_INFORMATION),
  1593. L"FileMoveClusterInformation",
  1594. path);
  1595. do_set_file(handle,
  1596. FileQuotaInformation,
  1597. sizeof (FILE_QUOTA_INFORMATION),
  1598. L"FileQuotaInformation",
  1599. path);
  1600. do_set_file(handle,
  1601. FileTrackingInformation,
  1602. sizeof (FILE_TRACKING_INFORMATION),
  1603. L"FileTrackingInformation",
  1604. path);
  1605. do_set_file(handle,
  1606. FileValidDataLengthInformation,
  1607. sizeof (FILE_VALID_DATA_LENGTH_INFORMATION),
  1608. L"FileValidDataLengthInformation",
  1609. path);
  1610. do_set_file(handle,
  1611. FileShortNameInformation,
  1612. sizeof (FILE_NAME_INFORMATION) + 1024,
  1613. L"FileShortNameInformation",
  1614. path);
  1615. do_query_volume(handle,
  1616. FileFsVolumeInformation,
  1617. sizeof( FILE_FS_VOLUME_INFORMATION ) + 1024,
  1618. L"FileFsVolumeInformation",
  1619. path);
  1620. do_query_volume(handle,
  1621. FileFsSizeInformation,
  1622. sizeof( FILE_FS_SIZE_INFORMATION ),
  1623. L"FileFsSizeInformation",
  1624. path);
  1625. do_query_volume(handle,
  1626. FileFsDeviceInformation,
  1627. sizeof( FILE_FS_DEVICE_INFORMATION ) + 1024,
  1628. L"FileFsDeviceInformation",
  1629. path);
  1630. do_query_volume(handle,
  1631. FileFsAttributeInformation,
  1632. sizeof( FILE_FS_ATTRIBUTE_INFORMATION ),
  1633. L"FileFsAttributeInformation",
  1634. path);
  1635. do_query_volume(handle,
  1636. FileFsControlInformation,
  1637. sizeof( FILE_FS_CONTROL_INFORMATION ),
  1638. L"FileFsControlInformation",
  1639. path);
  1640. do_query_volume(handle,
  1641. FileFsFullSizeInformation,
  1642. sizeof( FILE_FS_SIZE_INFORMATION ),
  1643. L"FileFsFullSizeInformation",
  1644. path);
  1645. do_query_volume(handle,
  1646. FileFsObjectIdInformation,
  1647. sizeof( FILE_FS_OBJECTID_INFORMATION ) + 1024,
  1648. L"FileFsObjectIdInformation",
  1649. path);
  1650. do_query_volume(handle,
  1651. FileFsDriverPathInformation,
  1652. sizeof( FILE_FS_DRIVER_PATH_INFORMATION ) + 1024,
  1653. L"FileFsDriverPathInformation",
  1654. path);
  1655. do_set_volume(handle,
  1656. FileFsObjectIdInformation,
  1657. sizeof( FILE_FS_OBJECTID_INFORMATION ) + 1024,
  1658. L"FileFsObjectIdInformation",
  1659. path);
  1660. do_set_volume(handle,
  1661. FileFsControlInformation,
  1662. sizeof( FILE_FS_CONTROL_INFORMATION ) + 1024,
  1663. L"FileFsControlInformation",
  1664. path);
  1665. do_set_volume(handle,
  1666. FileFsLabelInformation,
  1667. sizeof( FILE_FS_LABEL_INFORMATION ) + 1024,
  1668. L"FileFsLabelInformation",
  1669. path);
  1670. }
  1671. if (flags&FLAGS_DO_SECURITY) {
  1672. do_query_security(handle,
  1673. 0,
  1674. 1024,
  1675. L"NONE",
  1676. path);
  1677. do_query_security(handle,
  1678. OWNER_SECURITY_INFORMATION,
  1679. 1024,
  1680. L"OWNER_SECURITY_INFORMATION",
  1681. path);
  1682. do_query_security(handle,
  1683. GROUP_SECURITY_INFORMATION,
  1684. 1024,
  1685. L"GROUP_SECURITY_INFORMATION",
  1686. path);
  1687. do_query_security(handle,
  1688. DACL_SECURITY_INFORMATION,
  1689. 1024,
  1690. L"DACL_SECURITY_INFORMATION",
  1691. path);
  1692. do_query_security(handle,
  1693. SACL_SECURITY_INFORMATION,
  1694. 1024,
  1695. L"SACL_SECURITY_INFORMATION",
  1696. path);
  1697. do_set_security(handle,
  1698. 0,
  1699. 1024,
  1700. L"NONE",
  1701. path);
  1702. do_set_security(handle,
  1703. OWNER_SECURITY_INFORMATION,
  1704. 1024,
  1705. L"OWNER_SECURITY_INFORMATION",
  1706. path);
  1707. do_set_security(handle,
  1708. GROUP_SECURITY_INFORMATION,
  1709. 1024,
  1710. L"GROUP_SECURITY_INFORMATION",
  1711. path);
  1712. do_set_security(handle,
  1713. DACL_SECURITY_INFORMATION,
  1714. 1024,
  1715. L"DACL_SECURITY_INFORMATION",
  1716. path);
  1717. do_set_security(handle,
  1718. SACL_SECURITY_INFORMATION,
  1719. 1024,
  1720. L"SACL_SECURITY_INFORMATION",
  1721. path);
  1722. }
  1723. return status;
  1724. }
  1725. /*
  1726. Do the fast queries on the open path
  1727. */
  1728. NTSTATUS
  1729. try_fast_query_delete_etc(
  1730. POBJECT_ATTRIBUTES poa,
  1731. PWCHAR path,
  1732. PWCHAR type)
  1733. {
  1734. PVOID fi = NULL;
  1735. NTSTATUS status;
  1736. ULONG ret;
  1737. if (!(flags&FLAGS_DO_MISC))
  1738. return 0;
  1739. status = STATUS_SUCCESS;
  1740. if (!crashes (path, L"NtQueryAttributesFile", type, L"", L"")) {
  1741. ret = 0;
  1742. do {
  1743. fi = reallocslop(fi,
  1744. sizeof (FILE_BASIC_INFORMATION));
  1745. if (fi == NULL) {
  1746. return STATUS_INSUFFICIENT_RESOURCES;
  1747. }
  1748. status = NtQueryAttributesFile (poa, fi);
  1749. if (!NT_SUCCESS (status)) {
  1750. if (flags&FLAGS_DO_ERRORS)
  1751. printf ("NtQueryAttributesFile failed %x\n", status);
  1752. }
  1753. testslop(fi,
  1754. sizeof (FILE_BASIC_INFORMATION), L"NtQueryAttributesFile", L"");
  1755. } while (print_diags (0, ret++) && ret < MAX_RET);
  1756. }
  1757. if (!crashes (path, L"NtQueryFullAttributesFile", type, L"", L"")) {
  1758. ret = 0;
  1759. do {
  1760. fi = reallocslop(fi,
  1761. sizeof (FILE_NETWORK_OPEN_INFORMATION));
  1762. if (fi == NULL) {
  1763. return STATUS_INSUFFICIENT_RESOURCES;
  1764. }
  1765. status = NtQueryFullAttributesFile (poa, fi);
  1766. if (!NT_SUCCESS (status)) {
  1767. if (flags&FLAGS_DO_ERRORS)
  1768. printf ("NtQueryFullAttributesFile failed %x\n", status);
  1769. }
  1770. testslop(fi,
  1771. sizeof (FILE_NETWORK_OPEN_INFORMATION), L"NtQueryFULLAttributesFile", L"");
  1772. } while (print_diags (0, ret++) && ret < MAX_RET);
  1773. }
  1774. if (!crashes (path, L"NtDeleteFile", type, L"", L"")) {
  1775. ret = 0;
  1776. do {
  1777. status = NtDeleteFile(poa);
  1778. if (!NT_SUCCESS (status)) {
  1779. if (flags&FLAGS_DO_ERRORS)
  1780. printf ("NtDeleteFile failed %x\n", status);
  1781. }
  1782. } while (print_diags (0, ret++) && ret < MAX_RET);
  1783. }
  1784. free (fi);
  1785. return status;
  1786. }
  1787. /*
  1788. Do a whole bunch of random things
  1789. */
  1790. NTSTATUS misc_functions(
  1791. HANDLE handle,
  1792. PWCHAR path,
  1793. ULONG sync
  1794. )
  1795. {
  1796. IO_STATUS_BLOCK iosb;
  1797. NTSTATUS status;
  1798. PVOID buf;
  1799. ULONG bufl;
  1800. LONG i;
  1801. HANDLE sectionhandle;
  1802. LARGE_INTEGER bo, bl;
  1803. ULONG ret, managed_read, managed_write;
  1804. if (!(flags&FLAGS_DO_MISC))
  1805. return STATUS_SUCCESS;
  1806. buf = malloc (bufl = 1024);
  1807. if (buf == 0) {
  1808. printf ("Failed to allocate buffer!\n");
  1809. exit (EXIT_FAILURE);
  1810. }
  1811. managed_read = 0;
  1812. if (!sync) {
  1813. if (!crashes (path, L"NtReadFile", L"", L"", L"")) {
  1814. for (i = bufl; i >= 0; i--) {
  1815. ret = 0;
  1816. do {
  1817. progress_counter++;
  1818. bo.QuadPart = 0;
  1819. status = NtReadFile (handle, NULL, NULL, NULL, &iosb, buf, i,
  1820. &bo, NULL);
  1821. if (NT_SUCCESS (status)) {
  1822. status = iosb.Status;
  1823. managed_read = 1;
  1824. }
  1825. if (!NT_SUCCESS (status)) {
  1826. if (flags&FLAGS_DO_ERRORS)
  1827. printf ("NtReadFile failed %x\n", status);
  1828. }
  1829. progress_counter++;
  1830. bo.QuadPart = 0x7FFFFFFFFFFFFFFF - i + 1;
  1831. status = NtReadFile (handle, NULL, NULL, NULL, &iosb, buf, i,
  1832. &bo, NULL);
  1833. if (NT_SUCCESS (status))
  1834. status = iosb.Status;
  1835. if (!NT_SUCCESS (status)) {
  1836. if (flags&FLAGS_DO_ERRORS)
  1837. printf ("NtReadFile failed %x\n", status);
  1838. }
  1839. NtCancelIoFile (handle, &iosb);
  1840. } while (print_diags (0, ret++) && ret < MAX_RET);
  1841. }
  1842. }
  1843. if (managed_read) {
  1844. printf ("Managed to read from the device\n");
  1845. if (diag_file) {
  1846. fwprintf (diag_file, L"Managed to read from device %s\r\n", path);
  1847. }
  1848. }
  1849. managed_write = 0;
  1850. if (!crashes (path, L"NtWriteFile", L"", L"", L"")) {
  1851. for (i = bufl; i >= 0; i--) {
  1852. ret = 0;
  1853. do {
  1854. progress_counter++;
  1855. bo.QuadPart = 0;
  1856. status = NtWriteFile (handle, NULL, NULL, NULL, &iosb, buf, i,
  1857. &bo, NULL);
  1858. if (NT_SUCCESS (status)) {
  1859. status = iosb.Status;
  1860. managed_write = 0;
  1861. }
  1862. if (!NT_SUCCESS (status)) {
  1863. if (flags&FLAGS_DO_ERRORS)
  1864. printf ("NtWriteFile failed %x\n", status);
  1865. }
  1866. /*
  1867. Wrap to negative call
  1868. */
  1869. progress_counter++;
  1870. bo.QuadPart = 0x7FFFFFFFFFFFFFFF - i + 1;
  1871. status = NtWriteFile (handle, NULL, NULL, NULL, &iosb, buf, i,
  1872. &bo, NULL);
  1873. if (NT_SUCCESS (status))
  1874. status = iosb.Status;
  1875. if (!NT_SUCCESS (status)) {
  1876. if (flags&FLAGS_DO_ERRORS)
  1877. printf ("NtWriteFile failed %x\n", status);
  1878. }
  1879. /*
  1880. Do an append call.
  1881. */
  1882. progress_counter++;
  1883. bo.QuadPart = -1;
  1884. status = NtWriteFile (handle, NULL, NULL, NULL, &iosb, buf, i,
  1885. &bo, NULL);
  1886. if (NT_SUCCESS (status))
  1887. status = iosb.Status;
  1888. if (!NT_SUCCESS (status)) {
  1889. if (flags&FLAGS_DO_ERRORS)
  1890. printf ("NtWriteFile failed %x\n", status);
  1891. }
  1892. NtCancelIoFile (handle, &iosb);
  1893. } while (print_diags (0, ret++) && ret < MAX_RET);
  1894. }
  1895. }
  1896. if (managed_write) {
  1897. printf ("Managed to write to the device\n");
  1898. if (diag_file) {
  1899. fwprintf (diag_file, L"Managed to write to the device %s\r\n", path);
  1900. }
  1901. }
  1902. }
  1903. if (!crashes (path, L"NtCancelIoFile", L"", L"", L"")) {
  1904. ret = 0;
  1905. do {
  1906. status = NtCancelIoFile (handle, &iosb);
  1907. if (NT_SUCCESS (status))
  1908. status = iosb.Status;
  1909. if (!NT_SUCCESS (status)) {
  1910. if (flags&FLAGS_DO_ERRORS)
  1911. printf ("NtCancelIoFile failed %x\n", status);
  1912. }
  1913. } while (print_diags (0, ret++) && ret < MAX_RET);
  1914. }
  1915. if (!crashes (path, L"NtFlushBuffersFile", L"", L"", L"")) {
  1916. ret = 0;
  1917. do {
  1918. progress_counter++;
  1919. status = NtFlushBuffersFile (handle, &iosb);
  1920. if (NT_SUCCESS (status))
  1921. status = iosb.Status;
  1922. if (!NT_SUCCESS (status)) {
  1923. if (flags&FLAGS_DO_ERRORS)
  1924. printf ("NtFlushBuffersFile failed %x\n", status);
  1925. }
  1926. } while (print_diags (0, ret++) && ret < MAX_RET);
  1927. }
  1928. if (!crashes (path, L"NtQueryDirectoryFile", L"FileNamesInformation", L"", L"")) {
  1929. ULONG first = 1, j, datalen, l;
  1930. WCHAR bufn[1024];
  1931. PFILE_NAMES_INFORMATION tfni;
  1932. for (i = bufl; i >= 0; i--) {
  1933. ret = 0;
  1934. do {
  1935. progress_counter++;
  1936. status = NtQueryDirectoryFile (handle, NULL, NULL, NULL, &iosb, buf, i,
  1937. FileNamesInformation, FALSE, NULL, TRUE);
  1938. if (!NT_SUCCESS (status)) {
  1939. if (flags&FLAGS_DO_ERRORS)
  1940. printf ("NtQueryDirectoryFile failed for type FileNamesInformation %x\n",
  1941. status);
  1942. } else if (first && status != STATUS_PENDING) {
  1943. first = 0;
  1944. datalen = (ULONG) iosb.Information;
  1945. for (j = 0; j < datalen; j += tfni->NextEntryOffset) {
  1946. tfni = (PFILE_NAMES_INFORMATION)((PCHAR)buf + j);
  1947. memset (bufn, 0, sizeof (bufn));
  1948. l = tfni->FileNameLength / sizeof (WCHAR);
  1949. if (l >= sizeof (bufn) / sizeof (bufn[0]))
  1950. l = sizeof (bufn) / sizeof (bufn[0]) - 1;
  1951. wcsncpy (bufn, tfni->FileName, l);
  1952. wprintf (L"-> %s\n", bufn);
  1953. if (tfni->NextEntryOffset == 0)
  1954. break;
  1955. }
  1956. }
  1957. } while (print_diags (0, ret++) && ret < MAX_RET);
  1958. }
  1959. }
  1960. if (!crashes (path, L"NtQueryDirectoryFile", L"FileDirectoryInformation", L"", L"")) {
  1961. for (i = bufl; i >= 0; i--) {
  1962. ret = 0;
  1963. do {
  1964. progress_counter++;
  1965. status = NtQueryDirectoryFile (handle, NULL, NULL, NULL, &iosb, buf, i,
  1966. FileDirectoryInformation, FALSE, NULL, TRUE);
  1967. if (NT_SUCCESS (status))
  1968. status = iosb.Status;
  1969. if (!NT_SUCCESS (status)) {
  1970. if (flags&FLAGS_DO_ERRORS)
  1971. printf ("NtQueryDirectoryFile failed for type FileDirectoryInformation %x\n", status);
  1972. }
  1973. } while (print_diags (0, ret++) && ret < MAX_RET);
  1974. }
  1975. }
  1976. if (!crashes (path, L"NtQueryDirectoryFile", L"FileFullDirectoryInformation", L"", L"")) {
  1977. for (i = bufl; i >= 0; i--) {
  1978. ret = 0;
  1979. do {
  1980. progress_counter++;
  1981. status = NtQueryDirectoryFile (handle, NULL, NULL, NULL, &iosb, buf, i,
  1982. FileFullDirectoryInformation, FALSE, NULL, TRUE);
  1983. if (NT_SUCCESS (status))
  1984. status = iosb.Status;
  1985. if (!NT_SUCCESS (status)) {
  1986. if (flags&FLAGS_DO_ERRORS)
  1987. printf ("NtQueryDirectoryFile failed for type FileFullDirectoryInformation %x\n", status);
  1988. }
  1989. } while (print_diags (0, ret++) && ret < MAX_RET);
  1990. }
  1991. }
  1992. if (!crashes (path, L"NtQueryDirectoryFile", L"FileBothDirectoryInformation", L"", L"")) {
  1993. for (i = bufl; i >= 0; i--) {
  1994. ret = 0;
  1995. do {
  1996. progress_counter++;
  1997. status = NtQueryDirectoryFile (handle, NULL, NULL, NULL, &iosb, buf, i,
  1998. FileBothDirectoryInformation, FALSE, NULL, TRUE);
  1999. if (NT_SUCCESS (status))
  2000. status = iosb.Status;
  2001. if (!NT_SUCCESS (status)) {
  2002. if (flags&FLAGS_DO_ERRORS)
  2003. printf ("NtQueryDirectoryFile failed for type FileBothDirectoryInformation %x\n", status);
  2004. }
  2005. } while (print_diags (0, ret++) && ret < MAX_RET);
  2006. }
  2007. }
  2008. if (!crashes (path, L"NtQueryDirectoryFile", L"FileObjectIdInformation", L"", L"")) {
  2009. for (i = bufl; i >= 0; i--) {
  2010. ret = 0;
  2011. do {
  2012. progress_counter++;
  2013. status = NtQueryDirectoryFile (handle, NULL, NULL, NULL, &iosb, buf, i,
  2014. FileObjectIdInformation, FALSE, NULL, TRUE);
  2015. if (NT_SUCCESS (status))
  2016. status = iosb.Status;
  2017. if (!NT_SUCCESS (status)) {
  2018. if (flags&FLAGS_DO_ERRORS)
  2019. printf ("NtQueryDirectoryFile failed for type FileObjectIdInformation %x\n", status);
  2020. }
  2021. } while (print_diags (0, ret++) && ret < MAX_RET);
  2022. }
  2023. }
  2024. if (!crashes (path, L"NtQueryDirectoryFile", L"FileQuotaInformation", L"", L"")) {
  2025. for (i = bufl; i >= 0; i--) {
  2026. ret = 0;
  2027. do {
  2028. progress_counter++;
  2029. status = NtQueryDirectoryFile (handle, NULL, NULL, NULL, &iosb, buf, i,
  2030. FileQuotaInformation, FALSE, NULL, TRUE);
  2031. if (NT_SUCCESS (status))
  2032. status = iosb.Status;
  2033. if (!NT_SUCCESS (status)) {
  2034. if (flags&FLAGS_DO_ERRORS)
  2035. printf ("NtQueryDirectoryFile failed for type FileQuotaInformation %x\n", status);
  2036. }
  2037. } while (print_diags (0, ret++) && ret < MAX_RET);
  2038. }
  2039. }
  2040. if (!crashes (path, L"NtQueryDirectoryFile", L"FileReparsePointInformation", L"", L"")) {
  2041. for (i = bufl; i >= 0; i--) {
  2042. ret = 0;
  2043. do {
  2044. progress_counter++;
  2045. status = NtQueryDirectoryFile (handle, NULL, NULL, NULL, &iosb, buf, i,
  2046. FileReparsePointInformation, FALSE, NULL, TRUE);
  2047. if (NT_SUCCESS (status))
  2048. status = iosb.Status;
  2049. if (!NT_SUCCESS (status)) {
  2050. if (flags&FLAGS_DO_ERRORS)
  2051. printf ("NtQueryDirectoryFile failed for type FileReparsePointInformation %x\n", status);
  2052. }
  2053. } while (print_diags (0, ret++) && ret < MAX_RET);
  2054. }
  2055. }
  2056. if (!crashes (path, L"NtVdmContol", L"VdmQueryDir", L"", L"")) {
  2057. VDMQUERYDIRINFO vqdi;
  2058. UNICODE_STRING name;
  2059. memset (&vqdi, 0, sizeof (vqdi));
  2060. RtlInitUnicodeString (&name, L"*");
  2061. for (i = bufl; i >= 0; i--) {
  2062. ret = 0;
  2063. do {
  2064. progress_counter++;
  2065. vqdi.FileHandle = handle;
  2066. vqdi.FileInformation = buf;
  2067. vqdi.Length = bufl;
  2068. vqdi.FileName = &name;
  2069. status = NtVdmControl(VdmQueryDir, &vqdi);
  2070. if (!NT_SUCCESS (status)) {
  2071. if (flags&FLAGS_DO_ERRORS)
  2072. printf ("NtVdmControl failed for type VdmQueryDir %x\n", status);
  2073. }
  2074. } while (print_diags (0, ret++) && ret < MAX_RET);
  2075. }
  2076. }
  2077. if (!sync) {
  2078. if (!crashes (path, L"NtNotifyChangeDirectoryFile", L"", L"", L"")) {
  2079. for (i = bufl; i >= 0; i--) {
  2080. ret = 0;
  2081. do {
  2082. progress_counter++;
  2083. status = NtNotifyChangeDirectoryFile (handle,
  2084. NULL,
  2085. NULL,
  2086. NULL,
  2087. &iosb,
  2088. buf,
  2089. i,
  2090. FILE_NOTIFY_CHANGE_FILE_NAME,
  2091. FALSE);
  2092. if (NT_SUCCESS (status))
  2093. status = iosb.Status;
  2094. if (!NT_SUCCESS (status)) {
  2095. if (flags&FLAGS_DO_ERRORS)
  2096. printf ("NtNotifyChangeDirectoryFile failed %x\n", status);
  2097. }
  2098. NtCancelIoFile (handle, &iosb);
  2099. } while (print_diags (0, ret++) && ret < MAX_RET);
  2100. }
  2101. }
  2102. }
  2103. /*
  2104. Query the EA info
  2105. */
  2106. do_query_ea (handle, path);
  2107. if (!crashes (path, L"NtCreateSection", L"", L"", L"")) {
  2108. ret = 0;
  2109. do {
  2110. status = NtCreateSection (&sectionhandle, GENERIC_READ,
  2111. NULL, NULL, PAGE_READONLY, SEC_COMMIT, handle);
  2112. if (NT_SUCCESS (status)) {
  2113. printf ("Created a section!\n");
  2114. status = NtClose (sectionhandle);
  2115. if (!NT_SUCCESS (status)) {
  2116. printf ("NtClose on section handle failed %x\n", status);
  2117. }
  2118. } else if (flags&FLAGS_DO_ERRORS){
  2119. printf ("NtCreateSection failed %x\n", status);
  2120. }
  2121. } while (print_diags (0, ret++) && ret < MAX_RET);
  2122. ret = 0;
  2123. do {
  2124. status = NtCreateSection (&sectionhandle, GENERIC_READ,
  2125. NULL, NULL, PAGE_READONLY, SEC_IMAGE, handle);
  2126. if (NT_SUCCESS (status)) {
  2127. printf ("Created a section!\n");
  2128. status = NtClose (sectionhandle);
  2129. if (!NT_SUCCESS (status)) {
  2130. printf ("NtClose on section handle failed %x\n", status);
  2131. }
  2132. } else if (flags&FLAGS_DO_ERRORS){
  2133. printf ("NtCreateSection failed for image %x\n", status);
  2134. }
  2135. } while (print_diags (0, ret++) && ret < MAX_RET);
  2136. }
  2137. if (!crashes (path, L"NtLockFile", L"", L"", L"")) {
  2138. ret = 0;
  2139. do {
  2140. progress_counter++;
  2141. bl.QuadPart = 1;
  2142. bo.QuadPart = 1;
  2143. status = NtLockFile (handle, NULL, NULL, NULL, &iosb, &bo, &bl, 0, TRUE, FALSE);
  2144. if (NT_SUCCESS (status) && status != STATUS_PENDING) {
  2145. NtUnlockFile (handle, &iosb, &bo, &bl, 0);
  2146. }
  2147. if (!NT_SUCCESS (status)) {
  2148. if (flags&FLAGS_DO_ERRORS)
  2149. printf ("NtLockFile failed %x\n", status);
  2150. }
  2151. NtCancelIoFile (handle, &iosb);
  2152. } while (print_diags (0, ret++) && ret < MAX_RET);
  2153. }
  2154. if (!crashes (path, L"NtUnlockFile", L"", L"", L"")) {
  2155. ret = 0;
  2156. do {
  2157. progress_counter++;
  2158. status = NtUnlockFile (handle, &iosb, &bo, &bl, 0);
  2159. if (NT_SUCCESS (status))
  2160. status = iosb.Status;
  2161. if (!NT_SUCCESS (status)) {
  2162. if (flags&FLAGS_DO_ERRORS)
  2163. printf ("NtUnlockFile failed %x\n", status);
  2164. }
  2165. } while (print_diags (0, ret++) && ret < MAX_RET);
  2166. }
  2167. if (!crashes (path, L"NtQueryQuotaInformationFile", L"", L"", L"")) {
  2168. for (i = bufl; i >= 0; i--) {
  2169. ret = 0;
  2170. do {
  2171. progress_counter++;
  2172. status = NtQueryQuotaInformationFile(handle, &iosb, buf, i, FALSE, NULL, 0,
  2173. NULL, TRUE);
  2174. if (NT_SUCCESS (status))
  2175. status = iosb.Status;
  2176. if (!NT_SUCCESS (status)) {
  2177. if (flags&FLAGS_DO_ERRORS)
  2178. printf ("NtQueryQuotaInformationFile failed %x\n", status);
  2179. }
  2180. } while (print_diags (0, ret++) && ret < MAX_RET);
  2181. }
  2182. }
  2183. if (flags&FLAGS_DO_WINSOCK) {
  2184. if (!crashes (path, L"TransmitFile", L"", L"", L"")) {
  2185. progress_counter++;
  2186. if (!TransmitFile (cs, handle, 10, 0, NULL, NULL, TF_WRITE_BEHIND)) {
  2187. if (flags&FLAGS_DO_ERRORS)
  2188. printf ("TransmitFile failed %d\n", WSAGetLastError ());
  2189. }
  2190. }
  2191. }
  2192. NtCancelIoFile (devmap->handle, &iosb);
  2193. free (buf);
  2194. return status;
  2195. }
  2196. /*
  2197. Get the access mask for this handle
  2198. */
  2199. NTSTATUS
  2200. get_handle_access (HANDLE handle, PACCESS_MASK access)
  2201. {
  2202. NTSTATUS status;
  2203. OBJECT_BASIC_INFORMATION obi;
  2204. //
  2205. // Find out our handle access so we can know what IOCTLs and FSCTLs we can do.
  2206. //
  2207. status = NtQueryObject (handle,
  2208. ObjectBasicInformation,
  2209. &obi,
  2210. sizeof (obi),
  2211. NULL);
  2212. if (NT_SUCCESS (status)) {
  2213. *access = obi.GrantedAccess;
  2214. } else {
  2215. printf ("NtQueryObject for handle access failed %x\n", status);
  2216. *access = 0;
  2217. }
  2218. return status;
  2219. }
  2220. NTSTATUS check_tdi_handle (HANDLE handle)
  2221. {
  2222. NTSTATUS status;
  2223. IO_STATUS_BLOCK iosb;
  2224. TDI_REQUEST_QUERY_INFORMATION trqi;
  2225. TDI_PROVIDER_INFO tpi;
  2226. trqi.QueryType = TDI_QUERY_PROVIDER_INFORMATION;
  2227. status = NtDeviceIoControlFile (handle, sync_event, NULL, NULL,
  2228. &iosb,
  2229. IOCTL_TDI_QUERY_INFORMATION,
  2230. &trqi,
  2231. sizeof (trqi),
  2232. &tpi,
  2233. sizeof (tpi));
  2234. if (status == STATUS_PENDING) {
  2235. status = NtWaitForSingleObject (sync_event, FALSE, NULL);
  2236. if (!NT_SUCCESS (status)) {
  2237. printf ("NtWaitForSingleObject failed %x\n", status);
  2238. } else {
  2239. status = iosb.Status;
  2240. }
  2241. }
  2242. if (!NT_SUCCESS (status)) {
  2243. printf ("NtDeviceIoControlFile failed for IOCTL_TDI_QUERY_INFORMATION %x\n", status);
  2244. return status;
  2245. }
  2246. printf ("Detected a TDI driver\n");
  2247. return status;
  2248. }
  2249. //
  2250. // Do a load of opens etc relative from the current handle
  2251. //
  2252. NTSTATUS
  2253. do_sub_open_etc(
  2254. HANDLE handle,
  2255. PWCHAR s,
  2256. PWCHAR path
  2257. )
  2258. {
  2259. OBJECT_ATTRIBUTES oa;
  2260. UNICODE_STRING name;
  2261. NTSTATUS status;
  2262. IO_STATUS_BLOCK iosb;
  2263. ACCESS_MASK access;
  2264. LARGE_INTEGER tmo;
  2265. PWCHAR as;
  2266. if (wcslen (s) > 30) {
  2267. as = L"Big...";
  2268. } else {
  2269. as = s;
  2270. }
  2271. if (crashes (path, L"Sub open", as, L"", L""))
  2272. return STATUS_SUCCESS;
  2273. wprintf (L"Doing sub open for %s\n", as);
  2274. RtlInitUnicodeString (&name, s);
  2275. InitializeObjectAttributes(&oa,
  2276. &name,
  2277. OBJ_CASE_INSENSITIVE,
  2278. handle,
  2279. NULL);
  2280. status = NtCreateFile(&handle,
  2281. MAXIMUM_ALLOWED,
  2282. &oa,
  2283. &iosb,
  2284. NULL,
  2285. 0,
  2286. 0,
  2287. FILE_OPEN,
  2288. 0,
  2289. NULL,
  2290. 0);
  2291. if (NT_SUCCESS (status))
  2292. status = iosb.Status;
  2293. if (NT_SUCCESS (status)) {
  2294. status = get_handle_access (handle, &access);
  2295. wprintf (L"Sub open for %s worked with access %x\n", as, access);
  2296. if (DELETE&access) {
  2297. printf ("Got delete access to device\n");
  2298. if (diag_file) {
  2299. fwprintf (diag_file, L"Got DELETE access to %s\r\n", path);
  2300. }
  2301. }
  2302. if (WRITE_DAC&access) {
  2303. printf ("Got write_dac access to device\n");
  2304. if (diag_file) {
  2305. fwprintf (diag_file, L"Got WRITE_DAC access to %s\r\n", path);
  2306. }
  2307. }
  2308. if (WRITE_OWNER&access) {
  2309. printf ("Got write_owner access to device\n");
  2310. if (diag_file) {
  2311. fwprintf (diag_file, L"Got WRITE_OWNER access to %s\r\n", path);
  2312. }
  2313. }
  2314. if (FILE_WRITE_ACCESS&access) {
  2315. printf ("Got write access to device\n");
  2316. if (diag_file) {
  2317. fwprintf (diag_file, L"Got FILE_WRITE_ACCESS access to %s\r\n", path);
  2318. }
  2319. }
  2320. if (FILE_READ_ACCESS&access) {
  2321. printf ("Got read access to device\n");
  2322. if (diag_file) {
  2323. fwprintf (diag_file, L"Got FILE_READ_ACCESS access to %s\r\n", path);
  2324. }
  2325. }
  2326. query_object(handle, NULL, path);
  2327. misc_functions (handle, path, 0);
  2328. status = NtClose (handle);
  2329. if (!NT_SUCCESS (status)) {
  2330. printf ("NtClose failed %x\n", status);
  2331. }
  2332. } else {
  2333. printf ("NtCreateFile failed %x\n", status);
  2334. }
  2335. if (crashes (path, L"Sub create pipe", as, L"", L""))
  2336. return STATUS_SUCCESS;
  2337. tmo.QuadPart = 1000;
  2338. status = NtCreateNamedPipeFile (&handle,
  2339. MAXIMUM_ALLOWED,
  2340. &oa,
  2341. &iosb,
  2342. FILE_SHARE_READ|FILE_SHARE_WRITE,
  2343. FILE_CREATE,
  2344. 0,
  2345. FILE_PIPE_MESSAGE_TYPE,
  2346. FILE_PIPE_MESSAGE_MODE,
  2347. FILE_PIPE_COMPLETE_OPERATION,
  2348. 10,
  2349. 1000, 1000,
  2350. &tmo);
  2351. if (NT_SUCCESS (status))
  2352. status = iosb.Status;
  2353. if (NT_SUCCESS (status)) {
  2354. status = get_handle_access (handle, &access);
  2355. wprintf (L"Sub create pipe for %s worked with access %x\n", as, access);
  2356. if (DELETE&access) {
  2357. printf ("Got delete access to device\n");
  2358. }
  2359. if (WRITE_DAC&access) {
  2360. printf ("Got write_dac access to device\n");
  2361. }
  2362. if (WRITE_OWNER&access) {
  2363. printf ("Got write_owner access to device\n");
  2364. }
  2365. query_object(handle, NULL, path);
  2366. misc_functions (handle, path, 0);
  2367. status = NtClose (handle);
  2368. if (!NT_SUCCESS (status)) {
  2369. printf ("NtClose failed %x\n", status);
  2370. }
  2371. } else {
  2372. printf ("NtCreateNamedPipeFile failed %x\n", status);
  2373. }
  2374. if (crashes (path, L"Sub create mailslot", as, L"", L""))
  2375. return STATUS_SUCCESS;
  2376. tmo.QuadPart = 1000;
  2377. status = NtCreateMailslotFile (&handle,
  2378. MAXIMUM_ALLOWED,
  2379. &oa,
  2380. &iosb,
  2381. 0,
  2382. 1024,
  2383. 256,
  2384. &tmo);
  2385. if (NT_SUCCESS (status)) {
  2386. status = get_handle_access (handle, &access);
  2387. wprintf (L"Sub create mailslot for %s worked with access %x\n", as, access);
  2388. if (DELETE&access) {
  2389. printf ("Got delete access to device\n");
  2390. }
  2391. if (WRITE_DAC&access) {
  2392. printf ("Got write_dac access to device\n");
  2393. }
  2394. if (WRITE_OWNER&access) {
  2395. printf ("Got write_owner access to device\n");
  2396. }
  2397. query_object(handle, NULL, path);
  2398. misc_functions (handle, path, 0);
  2399. status = NtClose (handle);
  2400. if (!NT_SUCCESS (status)) {
  2401. printf ("NtClose failed %x\n", status);
  2402. }
  2403. } else {
  2404. printf ("NtCreateMailslotFile failed %x\n", status);
  2405. }
  2406. try_fast_query_delete_etc (&oa, path, L"Sub open");
  2407. return status;
  2408. }
  2409. //
  2410. // Try a few opens relative to the device its self.
  2411. //
  2412. NTSTATUS
  2413. try_funny_opens(
  2414. HANDLE handle,
  2415. PWCHAR path
  2416. )
  2417. {
  2418. ULONG ret, i;
  2419. static PWCHAR big=NULL;
  2420. static ULONG bigl;
  2421. if (!(flags&FLAGS_DO_SUBOPENS))
  2422. return 0;
  2423. if (big == NULL) {
  2424. big = malloc (bigl = 0x10000);
  2425. if (big == NULL) {
  2426. printf ("Memory allocation failure in try_funny_opens!\n");
  2427. exit (EXIT_FAILURE);
  2428. }
  2429. bigl /= sizeof (big[0]);
  2430. for (i = 0; i < bigl; i++)
  2431. big[i] = 'A';
  2432. big[bigl - 3] = '\0';
  2433. }
  2434. ret = 0;
  2435. do {
  2436. do_sub_open_etc (handle, L"", path);
  2437. do_sub_open_etc (handle, L" ", path);
  2438. do_sub_open_etc (handle, L"\\", path);
  2439. do_sub_open_etc (handle, L"\\\\\\\\\\\\", path);
  2440. do_sub_open_etc (handle, big, path);
  2441. if (flags&FLAGS_DO_STREAMS) {
  2442. do_sub_open_etc (handle, L":", path);
  2443. do_sub_open_etc (handle, L" :", path);
  2444. do_sub_open_etc (handle, L": ", path);
  2445. do_sub_open_etc (handle, L": ", path);
  2446. do_sub_open_etc (handle, L"::", path);
  2447. do_sub_open_etc (handle, L": :", path);
  2448. do_sub_open_etc (handle, L"::$UNUSED", path);
  2449. do_sub_open_etc (handle, L"::$STANDARD_INFORMATION", path);
  2450. do_sub_open_etc (handle, L"::$ATTRIBUTE_LIST", path);
  2451. do_sub_open_etc (handle, L"::$FILE_NAME", path);
  2452. do_sub_open_etc (handle, L"::$OBJECT_ID", path);
  2453. do_sub_open_etc (handle, L"::$SECURITY_DESCRIPTOR", path);
  2454. do_sub_open_etc (handle, L"::$VOLUME_NAME", path);
  2455. do_sub_open_etc (handle, L"::$VOLUME_INFORMATION", path);
  2456. do_sub_open_etc (handle, L"::$DATA", path);
  2457. do_sub_open_etc (handle, L"::$INDEX_ROOT", path);
  2458. do_sub_open_etc (handle, L"::$INDEX_ALLOCATION", path);
  2459. do_sub_open_etc (handle, L"::$BITMAP", path);
  2460. do_sub_open_etc (handle, L"::$REPARSE_POINT", path);
  2461. do_sub_open_etc (handle, L"::$EA_INFORMATION", path);
  2462. do_sub_open_etc (handle, L"::$PROPERTY_SET", path);
  2463. do_sub_open_etc (handle, L"::$FIRST_USER_DEFINED_ATTRIBUTE", path);
  2464. do_sub_open_etc (handle, L"::$END", path);
  2465. }
  2466. } while (print_diags (0, ret++) && ret < MAX_RET);
  2467. return 0;
  2468. }
  2469. VOID
  2470. randomize_buf(
  2471. PVOID buf,
  2472. ULONG bufl
  2473. )
  2474. {
  2475. ULONG i;
  2476. PUCHAR pc = buf;
  2477. for (i = 0; i < bufl; i++) {
  2478. pc[i] = rand() & 0xff;
  2479. }
  2480. }
  2481. /*
  2482. Thread used to randomize buffers
  2483. */
  2484. DWORD WINAPI
  2485. randomize(
  2486. PVOID buf
  2487. )
  2488. {
  2489. ULONG i;
  2490. PUCHAR pc = buf;
  2491. while (1) {
  2492. try {
  2493. for (i = 0; i < BIGBUF_SIZE; i++) {
  2494. pc[i] = rand() & 0xff;
  2495. }
  2496. } except (EXCEPTION_EXECUTE_HANDLER) {
  2497. }
  2498. Sleep (0);
  2499. }
  2500. return 0;
  2501. }
  2502. // changeprot and alerter won't return and we do not need to be
  2503. // told this by the compiler
  2504. #pragma warning(disable:4715)
  2505. DWORD WINAPI
  2506. changeprot(
  2507. PVOID buf
  2508. )
  2509. {
  2510. DWORD old;
  2511. while (1) {
  2512. if (!VirtualProtect (buf, 1, PAGE_READONLY, &old)) {
  2513. printf ("VirtualProtect failed %d\n", GetLastError ());
  2514. }
  2515. Sleep (1);
  2516. if (!VirtualProtect (buf, 1, PAGE_NOACCESS, &old)) {
  2517. printf ("VirtualProtect failed %d\n", GetLastError ());
  2518. }
  2519. Sleep (1);
  2520. if (!VirtualProtect (buf, 1, PAGE_GUARD|PAGE_READONLY, &old)) {
  2521. printf ("VirtualProtect failed %d\n", GetLastError ());
  2522. }
  2523. Sleep (1);
  2524. }
  2525. return 0;
  2526. }
  2527. /*
  2528. Thread used to alert the main
  2529. */
  2530. DWORD WINAPI
  2531. alerter(
  2532. PVOID handle
  2533. )
  2534. {
  2535. NTSTATUS status;
  2536. ULONG last = progress_counter, count;
  2537. //
  2538. // Do a nasty hack to keep the main thread moving if it gets stuck in a sync IOCTL
  2539. //
  2540. while (1) {
  2541. if (flags&FLAGS_DO_ALERT) {
  2542. Sleep (0);
  2543. } else {
  2544. last = progress_counter;
  2545. Sleep (60000);
  2546. if (progress_counter == 0 || progress_counter != last) {
  2547. continue;
  2548. }
  2549. printf ("Alerting thread\n");
  2550. }
  2551. // status = NtAlertResumeThread ((HANDLE) handle, &count);
  2552. // if (!NT_SUCCESS (status)) {
  2553. // printf ("NtAlertResumeThread failed %x\n", status);
  2554. // }
  2555. status = NtAlertThread ((HANDLE) handle);
  2556. if (!NT_SUCCESS (status)) {
  2557. printf ("NtAlertThread failed %x\n", status);
  2558. }
  2559. alerted++;
  2560. if (alerted > 10) {
  2561. if (diag_file) {
  2562. fwprintf (diag_file, L"Main thread appears hung. Teminating process\r\n");
  2563. fflush (diag_file);
  2564. NtTerminateProcess (NtCurrentProcess (), 0);
  2565. }
  2566. }
  2567. }
  2568. return 0;
  2569. }
  2570. #pragma warning(3:4715)
  2571. void record_ioctl (PIOCTLREC *piorec, ULONG ioctl, NTSTATUS status)
  2572. {
  2573. PIOCTLREC iorec = *piorec, oldiorec;
  2574. IOCTLINFO tmp;
  2575. ULONG i, j, new;
  2576. if (!iorec) {
  2577. iorec = malloc (sizeof (*iorec) +
  2578. INITIAL_IOCTL_TAILOR_SIZE * sizeof (iorec->ioctl[0]));
  2579. if (!iorec) {
  2580. return;
  2581. }
  2582. *piorec = iorec;
  2583. iorec->total = INITIAL_IOCTL_TAILOR_SIZE;
  2584. iorec->count = 0;
  2585. iorec->start = 0;
  2586. }
  2587. new = 1;
  2588. for (i = 0; i < iorec->count; i++) {
  2589. if (iorec->ioctl[i].ioctl == ioctl && iorec->ioctl[i].status == status) {
  2590. return;
  2591. }
  2592. if (iorec->ioctl[i].status == status) {
  2593. new = 0;
  2594. if (iorec->ioctl[i].count > MAX_IOCTL_TAILOR) {
  2595. return; // too many seen of this one
  2596. }
  2597. if (++iorec->ioctl[i].count > MAX_IOCTL_TAILOR) {
  2598. printf ("Removing IOCTLs with status %X\n", status);
  2599. for (j = i + 1; j < iorec->count; j++) {
  2600. if (iorec->ioctl[j].status == status) {
  2601. /*
  2602. printf ("Removing IOCTL %X with status %X\n",
  2603. iorec->ioctl[j].ioctl, iorec->ioctl[j].status);
  2604. */
  2605. iorec->ioctl[j] = iorec->ioctl[--iorec->count];
  2606. j--;
  2607. }
  2608. }
  2609. tmp = iorec->ioctl[iorec->start];
  2610. iorec->ioctl[iorec->start++] = iorec->ioctl[i];
  2611. iorec->ioctl[i] = tmp;
  2612. return;
  2613. }
  2614. break;
  2615. }
  2616. }
  2617. if (new) {
  2618. printf ("New status for IOCTL %X status %X\n", ioctl, status);
  2619. }
  2620. if (iorec->total == iorec->count) {
  2621. oldiorec = iorec;
  2622. iorec = realloc (oldiorec, sizeof (*iorec) +
  2623. iorec->total * 2 * sizeof (iorec->ioctl[0]));
  2624. if (iorec == NULL) {
  2625. if (oldiorec != NULL) {
  2626. free (oldiorec);
  2627. }
  2628. return;
  2629. }
  2630. *piorec = iorec;
  2631. iorec->total *= 2;
  2632. }
  2633. i = iorec->count;
  2634. iorec->ioctl[i].status = status;
  2635. iorec->ioctl[i].ioctl = ioctl;
  2636. iorec->ioctl[i].count = 0;
  2637. iorec->count = i + 1;
  2638. }
  2639. void do_tailored_ioctl (PDEVMAP devmap,
  2640. PWCHAR path,
  2641. PIOCTLREC iorec,
  2642. ULONG fsctl)
  2643. {
  2644. ULONG method, ioctl_val;
  2645. PVOID inbuf, outbuf;
  2646. ULONG inlen, outlen;
  2647. static IO_STATUS_BLOCK static_iosb;
  2648. ULONG ret;
  2649. ULONG i, j, k;
  2650. WCHAR num[20];
  2651. NTSTATUS status;
  2652. ULONG tmp;
  2653. DWORD old;
  2654. ULONG done_something;
  2655. if (!iorec) {
  2656. return;
  2657. }
  2658. do {
  2659. done_something = 0;
  2660. for (i = 1; i < iorec->count; i++) {
  2661. IOCTLINFO ii;
  2662. if (iorec->ioctl[i-1].ioctl < iorec->ioctl[i].ioctl) {
  2663. continue;
  2664. } else if (iorec->ioctl[i-1].ioctl == iorec->ioctl[i].ioctl &&
  2665. iorec->ioctl[i-1].count <= iorec->ioctl[i].count) {
  2666. continue;
  2667. }
  2668. ii = iorec->ioctl[i-1];
  2669. iorec->ioctl[i-1] = iorec->ioctl[i];
  2670. iorec->ioctl[i] = ii;
  2671. done_something = 1;
  2672. }
  2673. } while (done_something);
  2674. for (i = 0; i < iorec->count; i++) {
  2675. if (iorec->ioctl[i].count >= MAX_IOCTL_TAILOR) {
  2676. continue;
  2677. }
  2678. if (i > 0 && iorec->ioctl[i].ioctl == iorec->ioctl[i-1].ioctl) {
  2679. continue;
  2680. }
  2681. ioctl_val = iorec->ioctl[i].ioctl;
  2682. method = ioctl_val&0x3;
  2683. _snwprintf (num, sizeof (num) / sizeof (WCHAR), L"%%X%X", ioctl_val);
  2684. num[sizeof (num) / sizeof (WCHAR) - 1] = L'\0';
  2685. if (crashes (path, L"IOCTL value", num, L"", L""))
  2686. continue;
  2687. alerted = 0;
  2688. for (j = 0; j < max_tailured_calls; j += RAND_REP) {
  2689. ret = 0;
  2690. do {
  2691. if (ret != 0) {
  2692. printf ("Re-doing random with ioctl %%X%x\n", ioctl_val);
  2693. }
  2694. for (k = 0; k < RAND_REP; k++) {
  2695. switch(method) {
  2696. case METHOD_BUFFERED :
  2697. inlen = RandInRange( ioctl_inbuf_min, ioctl_inbuf_max );
  2698. outlen = RandInRange( ioctl_outbuf_min, ioctl_outbuf_max );
  2699. inbuf = bigbuf;
  2700. if (outlen == 0)
  2701. outbuf = (PVOID) -1024;
  2702. else
  2703. outbuf = bigbuf;
  2704. randomize_buf (inbuf, inlen);
  2705. break;
  2706. case METHOD_IN_DIRECT :
  2707. case METHOD_OUT_DIRECT :
  2708. inlen = RandInRange( ioctl_inbuf_min, ioctl_inbuf_max );
  2709. outlen = RandInRange( ioctl_outbuf_min, ioctl_outbuf_max );
  2710. inbuf = bigbuf;
  2711. outbuf = &bigbuf[BIGBUF_SIZE - outlen];
  2712. randomize_buf (inbuf, inlen);
  2713. randomize_buf (outbuf, outlen);
  2714. break;
  2715. case METHOD_NEITHER :
  2716. switch (rand ()&3) {
  2717. //
  2718. // Completely random pointers. We may corrupt ourselves here
  2719. // case 0 :
  2720. // inlen = rand32();
  2721. // outlen = rand32();
  2722. //
  2723. // inbuf = (PVOID)rand32();
  2724. // outbuf = (PVOID)rand32();
  2725. // break;
  2726. //
  2727. // Kernel crashing pointers with smallish lengths
  2728. case 1 :
  2729. inbuf = (PVOID) -1024;
  2730. outbuf = (PVOID) -1024;
  2731. inlen = RandInRange( ioctl_inbuf_min, ioctl_inbuf_max );
  2732. outlen = RandInRange( ioctl_outbuf_min, ioctl_outbuf_max );
  2733. break;
  2734. //
  2735. // Good pointers
  2736. case 0 :
  2737. case 2 :
  2738. inlen = RandInRange( ioctl_inbuf_min, ioctl_inbuf_max );
  2739. outlen = RandInRange( ioctl_outbuf_min, ioctl_outbuf_max );
  2740. inbuf = &bigbuf[BIGBUF_SIZE - outlen];
  2741. outbuf = &bigbuf[BIGBUF_SIZE - outlen];
  2742. break;
  2743. //
  2744. // Bad user mode pointers
  2745. case 3 :
  2746. inlen = rand() & 0xFFFF;
  2747. outlen = rand() & 0xFFFF;
  2748. inbuf = UintToPtr( rand() & 0xFFFF );
  2749. outbuf = UintToPtr( rand() & 0xFFFF );
  2750. break;
  2751. break;
  2752. }
  2753. }
  2754. progress_counter++;
  2755. if (!fsctl) {
  2756. status = NtDeviceIoControlFile(devmap->handle,
  2757. NULL,
  2758. NULL,
  2759. NULL,
  2760. &static_iosb,
  2761. ioctl_val,
  2762. inbuf,
  2763. inlen,
  2764. outbuf,
  2765. outlen);
  2766. } else {
  2767. status = NtFsControlFile(devmap->handle,
  2768. NULL,
  2769. NULL,
  2770. NULL,
  2771. &static_iosb,
  2772. ioctl_val,
  2773. inbuf,
  2774. inlen,
  2775. outbuf,
  2776. outlen);
  2777. }
  2778. }
  2779. NtCancelIoFile (devmap->handle, &static_iosb);
  2780. if (alerted > 5) {
  2781. break;
  2782. }
  2783. } while (print_diags ((method == METHOD_BUFFERED)?0:DIAG_NOEXCEPTIONS, ret++) && ret < MAX_RET);
  2784. if (alerted > 5) {
  2785. break;
  2786. }
  2787. }
  2788. if (!(flags&FLAGS_DO_PROT) ||
  2789. crashes (path, L"IOCTL prot value", num, L"", L"")) {
  2790. continue;
  2791. }
  2792. status = NtResumeThread (changethread, &tmp);
  2793. if (!NT_SUCCESS (status)) {
  2794. printf ("NtResumeThread failed %x\n", status);
  2795. }
  2796. for (i = 1; i < PROT_REP; i += RAND_REP) {
  2797. ret = 0;
  2798. do {
  2799. if (ret != 0) {
  2800. printf ("Re-doing random with ioctl %%X%x\n", ioctl_val);
  2801. }
  2802. for (k = 0; k < RAND_REP; k++) {
  2803. if (!VirtualProtect (bigbuf, 1, PAGE_READWRITE, &old)) {
  2804. printf ("VirtualProtect failed %d\n", GetLastError ());
  2805. }
  2806. inlen = RandInRange( ioctl_inbuf_min, ioctl_inbuf_max );
  2807. outlen = RandInRange( ioctl_outbuf_min, ioctl_outbuf_max );
  2808. inbuf = bigbuf;
  2809. outbuf = bigbuf;
  2810. progress_counter++;
  2811. if (!fsctl) {
  2812. status = NtDeviceIoControlFile(devmap->handle,
  2813. NULL,
  2814. NULL,
  2815. NULL,
  2816. &static_iosb,
  2817. ioctl_val,
  2818. inbuf,
  2819. inlen,
  2820. outbuf,
  2821. outlen);
  2822. } else {
  2823. status = NtFsControlFile(devmap->handle,
  2824. NULL,
  2825. NULL,
  2826. NULL,
  2827. &static_iosb,
  2828. ioctl_val,
  2829. inbuf,
  2830. inlen,
  2831. outbuf,
  2832. outlen);
  2833. }
  2834. }
  2835. NtCancelIoFile (devmap->handle, &static_iosb);
  2836. if (alerted > 5) {
  2837. break;
  2838. }
  2839. } while (print_diags (DIAG_NOEXCEPTIONS, ret++) && ret < MAX_RET);
  2840. if (alerted > 5) {
  2841. break;
  2842. }
  2843. }
  2844. status = NtSuspendThread (changethread, &tmp);
  2845. if (!NT_SUCCESS (status)) {
  2846. printf ("NtResumeThread failed %x\n", status);
  2847. }
  2848. if (!VirtualProtect (bigbuf, 1, PAGE_READWRITE, &old)) {
  2849. printf ("VirtualProtect failed %d\n", GetLastError ());
  2850. }
  2851. }
  2852. }
  2853. NTSTATUS
  2854. do_ioctl(
  2855. PDEVMAP devmap,
  2856. PWCHAR path
  2857. )
  2858. {
  2859. ULONG function, method, access, i, j, ioctl_val;
  2860. static IO_STATUS_BLOCK static_iosb;
  2861. PVOID inbuf, outbuf;
  2862. ULONG inlen, outlen;
  2863. ULONG tmp;
  2864. NTSTATUS status;
  2865. ULONG devtype;
  2866. ULONG ret;
  2867. BOOL hit_leak;
  2868. WCHAR num[20];
  2869. PIOCTLREC iorec = NULL, fsrec = NULL;
  2870. ULONG set_rand;
  2871. if ((flags&(FLAGS_DO_IOCTL_NULL|FLAGS_DO_FSCTL_NULL)) &&
  2872. ioctl_inbuf_min == 0 && ioctl_outbuf_min == 0) {
  2873. //
  2874. // do I/O calls with no buffer
  2875. //
  2876. for (function = ioctl_min_function; function <= ioctl_max_function; function++) {
  2877. _snwprintf (num, sizeof (num) / sizeof (WCHAR), L"%d", function);
  2878. num[sizeof (num) / sizeof (WCHAR) - 1] = L'\0';
  2879. if (crashes (path, L"IOCTL function ", num, L"", L""))
  2880. continue;
  2881. for (devtype = ioctl_min_devtype; devtype <= ioctl_max_devtype; devtype++) {
  2882. ret = 0;
  2883. do {
  2884. if (ret != 0)
  2885. printf ("Re-doing devtype = %d, function = %d\n", devtype, function);
  2886. hit_leak = FALSE;
  2887. for (access = FILE_ANY_ACCESS;
  2888. access <= (devmap->access&(FILE_READ_ACCESS|FILE_WRITE_ACCESS));
  2889. access++) {
  2890. for (method = 0; method < 4; method++) {
  2891. ioctl_val = CTL_CODE(devtype, function, method, access);
  2892. progress_counter++;
  2893. if ((flags&FLAGS_DO_IOCTL_NULL)) {
  2894. status = NtDeviceIoControlFile(devmap->handle,
  2895. NULL, NULL, NULL,
  2896. &static_iosb,
  2897. ioctl_val,
  2898. (PVOID) -1024,
  2899. 0,
  2900. (PVOID) -1024,
  2901. 0);
  2902. record_ioctl (&iorec, ioctl_val, status);
  2903. }
  2904. if ((flags&FLAGS_DO_FSCTL_NULL)) {
  2905. status = NtFsControlFile(devmap->handle, NULL, NULL, NULL,
  2906. &static_iosb,
  2907. ioctl_val,
  2908. (PVOID) -1024,
  2909. 0,
  2910. (PVOID) -1024,
  2911. 0);
  2912. record_ioctl (&fsrec, ioctl_val, status);
  2913. }
  2914. Sleep (0);
  2915. }
  2916. }
  2917. if (ret > (MAX_RET * 95 ) / 100) {
  2918. NtCancelIoFile (devmap->handle, &static_iosb);
  2919. //
  2920. // Report exceptions for method buffered.
  2921. // This may be ok but its worth knowing.
  2922. //
  2923. if (print_diags ((method == METHOD_BUFFERED)?0:DIAG_NOEXCEPTIONS, ret++)) {
  2924. printf ("IOCTL/FSCTL %x devtype %x (%d) function %x (%d) access %x method %x\n",
  2925. ioctl_val, devtype, devtype, function, function,
  2926. access, method);
  2927. hit_leak = TRUE;
  2928. }
  2929. }
  2930. NtCancelIoFile (devmap->handle, &static_iosb);
  2931. } while ((hit_leak || print_diags ((method == METHOD_BUFFERED)?0:DIAG_NOEXCEPTIONS, ret++)) && ret < MAX_RET);
  2932. }
  2933. }
  2934. }
  2935. if (flags&(FLAGS_DO_IOCTL_RANDOM|FLAGS_DO_FSCTL_RANDOM) &&
  2936. !crashes (path, L"IOCTL", L"random", L"", L"")) {
  2937. // if (!(flags&FLAGS_DO_RANDOM_DEVICE)) {
  2938. // status = NtResumeThread (randthread, &tmp);
  2939. // if (!NT_SUCCESS (status)) {
  2940. // printf ("NtResumeThread failed %x\n", status);
  2941. // }
  2942. // }
  2943. for (i = 0; i < max_random_calls; i += RAND_REP) {
  2944. if (ioctl_min_function >= ioctl_max_function)
  2945. function = ioctl_min_function;
  2946. else
  2947. function = RandInRange( ioctl_min_function, ioctl_max_function );
  2948. ret = 0;
  2949. do {
  2950. if (ret != 0) {
  2951. printf ("Re-doing random with function %x\n", function);
  2952. }
  2953. for (j = 0; j < RAND_REP; j++) {
  2954. if (ioctl_min_devtype >= ioctl_max_devtype)
  2955. devtype = ioctl_min_devtype;
  2956. else
  2957. devtype = RandInRange( ioctl_min_devtype, ioctl_max_devtype );
  2958. switch (rand ()&3) {
  2959. case 0 :
  2960. if (fsrec && fsrec->count - fsrec->start) {
  2961. devtype = fsrec->ioctl[fsrec->start +
  2962. (rand()%(fsrec->count - fsrec->start))].ioctl>>16;
  2963. }
  2964. break;
  2965. case 1 :
  2966. if (iorec && iorec->count - iorec->start) {
  2967. devtype = iorec->ioctl[iorec->start +
  2968. (rand()%(iorec->count - iorec->start))].ioctl>>16;
  2969. }
  2970. break;
  2971. case 2 :
  2972. case 3 :
  2973. break;
  2974. }
  2975. method = rand() & 0x3;
  2976. access = rand() & devmap->access&(FILE_READ_ACCESS|FILE_WRITE_ACCESS);
  2977. ioctl_val = CTL_CODE(devtype,
  2978. function,
  2979. method,
  2980. access);
  2981. set_rand = 0;
  2982. switch(method) {
  2983. case METHOD_BUFFERED :
  2984. inlen = RandInRange( ioctl_inbuf_min, ioctl_inbuf_max );
  2985. outlen = RandInRange( ioctl_outbuf_min, ioctl_outbuf_max );
  2986. inbuf = bigbuf;
  2987. if (outlen == 0)
  2988. outbuf = (PVOID) -1024;
  2989. else
  2990. outbuf = bigbuf;
  2991. set_rand = 1;
  2992. break;
  2993. case METHOD_IN_DIRECT :
  2994. case METHOD_OUT_DIRECT :
  2995. inlen = RandInRange( ioctl_inbuf_min, ioctl_inbuf_max );
  2996. outlen = RandInRange( ioctl_outbuf_min, ioctl_outbuf_max );
  2997. inbuf = bigbuf;
  2998. outbuf = &bigbuf[BIGBUF_SIZE - outlen];
  2999. // printf ("%p %d %p %d\n", inbuf, inlen, outbuf, outlen);
  3000. set_rand = 1;
  3001. break;
  3002. case METHOD_NEITHER :
  3003. switch (rand ()&3) {
  3004. //
  3005. // Completely random pointers. We may corrupt ourselves here
  3006. // case 0 :
  3007. // inlen = rand32();
  3008. // outlen = rand32();
  3009. //
  3010. // inbuf = (PVOID)rand32();
  3011. // outbuf = (PVOID)rand32();
  3012. // break;
  3013. //
  3014. // Kernel crashing pointers with smallish lengths
  3015. case 1 :
  3016. inbuf = (PVOID) -1024;
  3017. outbuf = (PVOID) -1024;
  3018. inlen = RandInRange( ioctl_inbuf_min, ioctl_inbuf_max );
  3019. outlen = RandInRange( ioctl_outbuf_min, ioctl_outbuf_max );
  3020. break;
  3021. //
  3022. // Good pointers
  3023. case 0 :
  3024. case 2 :
  3025. inlen = RandInRange( ioctl_inbuf_min, ioctl_inbuf_max );
  3026. outlen = RandInRange( ioctl_outbuf_min, ioctl_outbuf_max );
  3027. inbuf = &bigbuf[BIGBUF_SIZE - outlen];
  3028. outbuf = &bigbuf[BIGBUF_SIZE - outlen];
  3029. set_rand = 1;
  3030. break;
  3031. //
  3032. // Bad user mode pointers
  3033. case 3 :
  3034. inlen = rand() & 0xFFFF;
  3035. outlen = rand() & 0xFFFF;
  3036. inbuf = UintToPtr( rand() & 0xFFFF);
  3037. outbuf = UintToPtr( rand() & 0xFFFF);
  3038. break;
  3039. break;
  3040. }
  3041. }
  3042. if (set_rand) {
  3043. randomize_buf (inbuf, inlen);
  3044. }
  3045. progress_counter++;
  3046. if (flags&FLAGS_DO_IOCTL_RANDOM) {
  3047. status = NtDeviceIoControlFile(devmap->handle,
  3048. NULL,
  3049. NULL,
  3050. NULL,
  3051. &static_iosb,
  3052. ioctl_val,
  3053. inbuf,
  3054. inlen,
  3055. outbuf,
  3056. outlen);
  3057. record_ioctl (&iorec, ioctl_val, status);
  3058. }
  3059. if (flags&FLAGS_DO_FSCTL_RANDOM) {
  3060. status = NtFsControlFile(devmap->handle,
  3061. NULL,
  3062. NULL,
  3063. NULL,
  3064. &static_iosb,
  3065. ioctl_val,
  3066. inbuf,
  3067. inlen,
  3068. outbuf,
  3069. outlen);
  3070. record_ioctl (&fsrec, ioctl_val, status);
  3071. }
  3072. }
  3073. NtCancelIoFile (devmap->handle, &static_iosb);
  3074. } while (print_diags ((method == METHOD_BUFFERED)?0:DIAG_NOEXCEPTIONS, ret++) && ret < MAX_RET);
  3075. }
  3076. // if (!(flags&FLAGS_DO_RANDOM_DEVICE)) {
  3077. // status = NtSuspendThread (randthread, &tmp);
  3078. // if (!NT_SUCCESS (status)) {
  3079. // printf ("NtSuspendThread failed %x\n", status);
  3080. // }
  3081. // }
  3082. }
  3083. if (flags&FLAGS_DO_IOCTL_RANDOM) {
  3084. do_tailored_ioctl (devmap, path, iorec, 0);
  3085. }
  3086. if (flags&FLAGS_DO_FSCTL_RANDOM) {
  3087. do_tailored_ioctl (devmap, path, fsrec, 1);
  3088. }
  3089. if (iorec) {
  3090. free (iorec);
  3091. }
  3092. if (fsrec) {
  3093. free (fsrec);
  3094. }
  3095. return 0;
  3096. }
  3097. PFILE_FULL_EA_INFORMATION build_adr_ea (PCHAR name, USHORT adrtype,
  3098. USHORT adrl, PVOID padr,
  3099. PULONG peal)
  3100. {
  3101. PFILE_FULL_EA_INFORMATION ea = NULL;
  3102. TRANSPORT_ADDRESS UNALIGNED *pta;
  3103. TA_ADDRESS *ptaa;
  3104. ULONG eal;
  3105. ULONG nl;
  3106. nl = strlen (name);
  3107. eal = sizeof (FILE_FULL_EA_INFORMATION) + nl +
  3108. sizeof (TRANSPORT_ADDRESS) - 1 + adrl;
  3109. ea = malloc (eal);
  3110. if (!ea) {
  3111. printf ("Failed to allocate %d bytes\n", eal);
  3112. exit (EXIT_FAILURE);
  3113. }
  3114. memset (ea, 0, eal);
  3115. ea->EaNameLength = (UCHAR) nl;
  3116. strcpy (ea->EaName, name);
  3117. ea->EaValueLength = (USHORT)(eal - sizeof (*ea) - nl);
  3118. pta = (TRANSPORT_ADDRESS UNALIGNED *)(ea->EaName + nl + 1);
  3119. pta->TAAddressCount = 1;
  3120. ptaa = (TA_ADDRESS *) pta->Address;
  3121. ptaa->AddressLength = adrl;
  3122. ptaa->AddressType = adrtype;
  3123. memcpy (ptaa->Address, padr, adrl);
  3124. *peal = eal;
  3125. return ea;
  3126. }
  3127. PFILE_FULL_EA_INFORMATION build_con_ea (PCHAR name, CONNECTION_CONTEXT ctx,
  3128. PULONG peal)
  3129. {
  3130. PFILE_FULL_EA_INFORMATION ea = NULL;
  3131. CONNECTION_CONTEXT UNALIGNED *pctx;
  3132. ULONG eal;
  3133. ULONG nl;
  3134. nl = strlen (name);
  3135. eal = sizeof (FILE_FULL_EA_INFORMATION) + nl +
  3136. sizeof (ctx);
  3137. ea = malloc (eal);
  3138. if (!ea) {
  3139. printf ("Failed to allocate %d bytes\n", eal);
  3140. exit (EXIT_FAILURE);
  3141. }
  3142. memset (ea, 0, eal);
  3143. ea->EaNameLength = (UCHAR) nl;
  3144. strcpy (ea->EaName, name);
  3145. ea->EaValueLength = (USHORT)(eal - sizeof (*ea) - nl);
  3146. pctx = (CONNECTION_CONTEXT UNALIGNED*) (ea->EaName + nl + 1);
  3147. *pctx = ctx;
  3148. *peal = eal;
  3149. return ea;
  3150. }
  3151. PFILE_FULL_EA_INFORMATION build_simple_ea (PCHAR name, PVOID Block, ULONG BlockLen,
  3152. PULONG peal)
  3153. {
  3154. PFILE_FULL_EA_INFORMATION ea = NULL;
  3155. PVOID pBlock;
  3156. ULONG eal;
  3157. ULONG nl;
  3158. nl = strlen (name);
  3159. eal = sizeof (FILE_FULL_EA_INFORMATION) + nl +
  3160. BlockLen;
  3161. ea = malloc (eal);
  3162. if (!ea) {
  3163. printf ("Failed to allocate %d bytes\n", eal);
  3164. exit (EXIT_FAILURE);
  3165. }
  3166. memset (ea, 0, eal);
  3167. ea->EaNameLength = (UCHAR) nl;
  3168. strcpy (ea->EaName, name);
  3169. ea->EaValueLength = (USHORT)(eal - sizeof (*ea) - nl);
  3170. pBlock = (PVOID) (ea->EaName + nl + 1);
  3171. memcpy (pBlock, Block, BlockLen);
  3172. *peal = eal;
  3173. return ea;
  3174. }
  3175. #define DRIVER_PREFIX1 L"\\Driver\\"
  3176. #define DRIVER_PREFIX2 L"\\FileSystem\\"
  3177. NTSTATUS
  3178. check_driver (HANDLE handle,
  3179. PUNICODE_STRING DriverName)
  3180. /*
  3181. Check to see if the specified device object is associated with the driver object
  3182. */
  3183. {
  3184. PFILE_FS_DRIVER_PATH_INFORMATION fsDpInfo;
  3185. ULONG fsDpSize;
  3186. ULONG DriverBufferLength;
  3187. UNICODE_STRING us;
  3188. NTSTATUS status;
  3189. IO_STATUS_BLOCK iosb;
  3190. DriverBufferLength = sizeof (DRIVER_PREFIX1);
  3191. if (sizeof (DRIVER_PREFIX2) > DriverBufferLength) {
  3192. DriverBufferLength = sizeof (DRIVER_PREFIX2);
  3193. }
  3194. DriverBufferLength += DriverName->Length;
  3195. fsDpSize = sizeof(FILE_FS_DRIVER_PATH_INFORMATION) + DriverBufferLength;
  3196. fsDpInfo = malloc (fsDpSize);
  3197. if (fsDpInfo == 0) {
  3198. printf ("Failed to allocate buffer for driver query\n");
  3199. exit (EXIT_FAILURE);
  3200. }
  3201. ZeroMemory(fsDpInfo, fsDpSize);
  3202. us.MaximumLength = (USHORT)DriverBufferLength;
  3203. us.Length = 0;
  3204. us.Buffer = fsDpInfo->DriverName;
  3205. RtlAppendUnicodeToString (&us, DRIVER_PREFIX1);
  3206. RtlAppendUnicodeStringToString (&us, DriverName);
  3207. fsDpInfo->DriverNameLength = us.Length;
  3208. status = NtQueryVolumeInformationFile(handle,
  3209. &iosb,
  3210. fsDpInfo,
  3211. fsDpSize,
  3212. FileFsDriverPathInformation);
  3213. if (NT_SUCCESS (status)) {
  3214. if (fsDpInfo->DriverInPath) {
  3215. status = STATUS_SUCCESS;
  3216. } else {
  3217. status = -1;
  3218. }
  3219. free (fsDpInfo);
  3220. return status;
  3221. }
  3222. us.MaximumLength = (USHORT)DriverBufferLength;
  3223. us.Length = 0;
  3224. us.Buffer = fsDpInfo->DriverName;
  3225. RtlAppendUnicodeToString (&us, DRIVER_PREFIX2);
  3226. RtlAppendUnicodeStringToString (&us, DriverName);
  3227. fsDpInfo->DriverNameLength = us.Length;
  3228. status = NtQueryVolumeInformationFile(handle,
  3229. &iosb,
  3230. fsDpInfo,
  3231. fsDpSize,
  3232. FileFsDriverPathInformation);
  3233. if (!NT_SUCCESS (status)) {
  3234. printf ("NtQueryVolumeInformationFile for FileFsDriverPathInformation failed %x\n", status);
  3235. exit (EXIT_FAILURE);
  3236. }
  3237. if (fsDpInfo->DriverInPath) {
  3238. status = STATUS_SUCCESS;
  3239. } else {
  3240. status = -1;
  3241. }
  3242. free (fsDpInfo);
  3243. return status;
  3244. }
  3245. DWORD
  3246. WINAPI
  3247. do_open_close_thread (
  3248. LPVOID arg)
  3249. {
  3250. ULONG i;
  3251. POBJECT_ATTRIBUTES oa = arg;
  3252. NTSTATUS status;
  3253. IO_STATUS_BLOCK iosb;
  3254. HANDLE handle;
  3255. if ((flags&FLAGS_DO_IMPERSONATION) && !SetThreadToken (NULL, NonAdminToken)) {
  3256. printf ("SetThreadToken failed %d\n", GetLastError ());
  3257. exit (EXIT_FAILURE);
  3258. }
  3259. for (i = 0; i < 10000; i++) {
  3260. status = NtCreateFile (&handle,
  3261. MAXIMUM_ALLOWED,
  3262. oa,
  3263. &iosb,
  3264. NULL,
  3265. 0,
  3266. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  3267. FILE_OPEN,
  3268. 0,
  3269. NULL,
  3270. 0);
  3271. if (NT_SUCCESS (status)) {
  3272. status = NtClose (handle);
  3273. if (!NT_SUCCESS (status)) {
  3274. printf ("NtClose failed %x\n", status);
  3275. exit (EXIT_FAILURE);
  3276. }
  3277. }
  3278. }
  3279. RevertToSelf ();
  3280. return 0;
  3281. }
  3282. VOID
  3283. do_open_close (POBJECT_ATTRIBUTES oa,
  3284. PUNICODE_STRING name,
  3285. PWCHAR path)
  3286. /*
  3287. Open and close the device rapidly to catch open close races
  3288. */
  3289. {
  3290. #define MAX_OPEN_THREAD 4
  3291. HANDLE Thread[MAX_OPEN_THREAD];
  3292. ULONG i;
  3293. DWORD id;
  3294. if (crashes (path, L"OPENCLOSE", L"", L"", L"")) {
  3295. return;
  3296. }
  3297. for (i = 0; i < MAX_OPEN_THREAD; i++) {
  3298. Thread[i] = CreateThread (NULL, 0, do_open_close_thread, oa, 0, &id);
  3299. if (Thread[i] == NULL) {
  3300. printf ("CreateThread failed %d\n", GetLastError ());
  3301. exit (EXIT_FAILURE);
  3302. }
  3303. }
  3304. for (i = 0; i < MAX_OPEN_THREAD; i++) {
  3305. WaitForSingleObject (Thread[i], INFINITE);
  3306. CloseHandle (Thread[i]);
  3307. }
  3308. }
  3309. /*
  3310. Open device with various options
  3311. */
  3312. NTSTATUS
  3313. open_device(
  3314. HANDLE parent,
  3315. PUNICODE_STRING name,
  3316. PDEVMAP devmap,
  3317. BOOL synch, // Do a synchronous open
  3318. BOOL addbackslash, // Add trailing backslash to name
  3319. BOOL direct, // Do a direct open
  3320. ULONG opentype, // Connection, address etc.
  3321. PWCHAR path
  3322. )
  3323. {
  3324. NTSTATUS status;
  3325. IO_STATUS_BLOCK iosb;
  3326. ULONG i, l, lw, first;
  3327. WCHAR dn[1024];
  3328. UNICODE_STRING dnu;
  3329. ULONG options;
  3330. OBJECT_ATTRIBUTES oa;
  3331. ACCESS_MASK am;
  3332. ULONG share;
  3333. PFILE_FULL_EA_INFORMATION pea = NULL;
  3334. ULONG eal = 0;
  3335. TDI_ADDRESS_IP ipaddr;
  3336. TDI_ADDRESS_NETBIOS netbiosaddr;
  3337. TDI_ADDRESS_IPX ipxaddr;
  3338. TDI_ADDRESS_APPLETALK appleaddr;
  3339. AFD_SWITCH_OPEN_PACKET aswop;
  3340. union {
  3341. AFD_OPEN_PACKET aop;
  3342. UCHAR buf [FIELD_OFFSET (AFD_OPEN_PACKET, TransportDeviceName) + 64];
  3343. } aopbuf;
  3344. LARGE_INTEGER tmo;
  3345. PCHAR api;
  3346. if (direct && !(FLAGS_DO_DIRECT_DEVICE&flags)) {
  3347. return STATUS_ACCESS_DENIED;
  3348. }
  3349. l = name->Length;
  3350. if (l >= sizeof (dn))
  3351. l = sizeof (dn) - 1;
  3352. lw = l / sizeof (dn[0]);
  3353. wcsncpy (dn, name->Buffer, lw);
  3354. dn[lw] = '\0';
  3355. RtlInitUnicodeString (&dnu, dn);
  3356. if (addbackslash && dnu.Length < sizeof (dn)) {
  3357. dn[min (dnu.Length, sizeof (dn) - sizeof (dn[0]))/sizeof(dn[0])] = '\\';
  3358. dnu.Length += 2;
  3359. }
  3360. dn[min(dnu.Length, sizeof (dn) - sizeof (dn[0]))/sizeof(dn[0])] = 0;
  3361. InitializeObjectAttributes(&oa,
  3362. &dnu,
  3363. OBJ_CASE_INSENSITIVE,
  3364. parent,
  3365. NULL);
  3366. if ((flags2&FLAGS_DO_DRIVER) != 0) {
  3367. HANDLE handle;
  3368. status = NtCreateFile (&handle,
  3369. MAXIMUM_ALLOWED,
  3370. &oa,
  3371. &iosb,
  3372. NULL,
  3373. 0,
  3374. FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  3375. FILE_OPEN,
  3376. 0,
  3377. NULL,
  3378. 0);
  3379. if (NT_SUCCESS (status)) {
  3380. status = check_driver (handle, &DriverName);
  3381. NtClose (handle);
  3382. if (!NT_SUCCESS (status)) {
  3383. return status;
  3384. }
  3385. } else {
  3386. wprintf(L"Failed to open device %s for driver checking %x\n",
  3387. dn, status);
  3388. return -1;
  3389. }
  3390. }
  3391. if ((flags&FLAGS_DO_OPEN_CLOSE) && !synch && !direct && opentype == 0) {
  3392. do_open_close (&oa,
  3393. name,
  3394. path);
  3395. }
  3396. devmap->handle = NULL;
  3397. if (direct) {
  3398. options = 0;
  3399. am = SYNCHRONIZE|FILE_READ_ATTRIBUTES|READ_CONTROL|WRITE_OWNER|WRITE_DAC;
  3400. } else if (synch) {
  3401. options = FILE_SYNCHRONOUS_IO_ALERT;
  3402. am = MAXIMUM_ALLOWED|SYNCHRONIZE;
  3403. } else {
  3404. options = 0;
  3405. am = MAXIMUM_ALLOWED;
  3406. }
  3407. if (opentype == OPEN_TYPE_NAMED_PIPE) {
  3408. share = FILE_SHARE_READ|FILE_SHARE_WRITE;
  3409. } else if (opentype == OPEN_TYPE_TREE_CONNECT) {
  3410. share = FILE_SHARE_READ|FILE_SHARE_WRITE;
  3411. options |= FILE_CREATE_TREE_CONNECTION;
  3412. } else {
  3413. share = 0;
  3414. }
  3415. if (opentype == OPEN_TYPE_TDI_CONNECTION) {
  3416. pea = build_con_ea (TdiConnectionContext, (CONNECTION_CONTEXT) 12345, &eal);
  3417. } else if (opentype == OPEN_TYPE_TDI_ADDR_IP) {
  3418. memset (&ipaddr, 0, sizeof (ipaddr));
  3419. pea = build_adr_ea (TdiTransportAddress,
  3420. TDI_ADDRESS_TYPE_IP,
  3421. sizeof (ipaddr), &ipaddr,
  3422. &eal);
  3423. } else if (opentype == OPEN_TYPE_TDI_ADDR_NETBIOS) {
  3424. memset (&netbiosaddr, 0, sizeof (netbiosaddr));
  3425. pea = build_adr_ea (TdiTransportAddress,
  3426. TDI_ADDRESS_TYPE_NETBIOS,
  3427. sizeof (netbiosaddr), &netbiosaddr,
  3428. &eal);
  3429. } else if (opentype == OPEN_TYPE_TDI_ADDR_IPX) {
  3430. memset (&ipxaddr, 0, sizeof (ipxaddr));
  3431. pea = build_adr_ea (TdiTransportAddress,
  3432. TDI_ADDRESS_TYPE_IPX,
  3433. sizeof (ipxaddr), &ipxaddr,
  3434. &eal);
  3435. } else if (opentype == OPEN_TYPE_TDI_ADDR_APPLE) {
  3436. memset (&appleaddr, 0, sizeof (appleaddr));
  3437. pea = build_adr_ea (TdiTransportAddress,
  3438. TDI_ADDRESS_TYPE_APPLETALK,
  3439. sizeof (appleaddr), &appleaddr,
  3440. &eal);
  3441. } else if (opentype == OPEN_TYPE_AFD_TRANSPORT) {
  3442. memset (&aopbuf.aop, 0, sizeof (aopbuf.aop));
  3443. aopbuf.aop.__f.EndpointFlags = rand32()&AFD_ENDPOINT_VALID_FLAGS;
  3444. aopbuf.aop.GroupID = 0;
  3445. aopbuf.aop.TransportDeviceNameLength = sizeof (L"\\Device\\Tcp") - sizeof (WCHAR);
  3446. wcscpy (aopbuf.aop.TransportDeviceName, L"\\Device\\Tcp");
  3447. pea = build_simple_ea (AfdOpenPacket, &aopbuf, sizeof (aopbuf),
  3448. &eal);
  3449. } else if (opentype == OPEN_TYPE_AFD_SAN) {
  3450. memset (&aswop, 0, sizeof (aswop));
  3451. aswop.CompletionPort = CompletionPort;
  3452. aswop.CompletionEvent = CompletionEvent;
  3453. pea = build_simple_ea (AfdSwitchOpenPacket, &aswop, sizeof (aswop),
  3454. &eal);
  3455. }
  3456. wprintf(L"Trying to open device %s %s %s %s\n",
  3457. dn, direct?L"direct ":L"", synch?L"synchronous":L"",
  3458. pea?L"TDI open":(opentype == OPEN_TYPE_NAMED_PIPE)?
  3459. L"NamedPipe":(opentype == OPEN_TYPE_MAIL_SLOT)?
  3460. L"Mailslot":L"");
  3461. if (crashes (path, L"Open", direct?L"direct":L"", synch?L"synchronous":L"",
  3462. addbackslash?L"Add backslash":L""))
  3463. status = STATUS_ACCESS_DENIED;
  3464. else {
  3465. do {
  3466. if (opentype == OPEN_TYPE_NAMED_PIPE) {
  3467. tmo.QuadPart = -1000;
  3468. api = "NtCreateNamedPipeFile";
  3469. status = NtCreateNamedPipeFile (&devmap->handle,
  3470. am,
  3471. &oa,
  3472. &iosb,
  3473. share,
  3474. FILE_CREATE,
  3475. options,
  3476. FILE_PIPE_MESSAGE_TYPE,
  3477. FILE_PIPE_MESSAGE_MODE,
  3478. FILE_PIPE_COMPLETE_OPERATION,
  3479. 10,
  3480. 1000, 1000,
  3481. &tmo);
  3482. } else if (opentype == OPEN_TYPE_MAIL_SLOT) {
  3483. tmo.QuadPart = -1000;
  3484. api = "NtCreateMailslotFile";
  3485. status = NtCreateMailslotFile (&devmap->handle,
  3486. am,
  3487. &oa,
  3488. &iosb,
  3489. options,
  3490. 1024,
  3491. 256,
  3492. &tmo);
  3493. } else {
  3494. api = "NtCreateFile";
  3495. status = NtCreateFile(&devmap->handle,
  3496. am,
  3497. &oa,
  3498. &iosb,
  3499. NULL,
  3500. 0,
  3501. share,
  3502. FILE_OPEN,
  3503. options,
  3504. pea,
  3505. eal);
  3506. }
  3507. if (status == STATUS_SHARING_VIOLATION) {
  3508. printf ("Hit file share violation for %X\n", share);
  3509. if (share&FILE_SHARE_READ) {
  3510. share &= ~FILE_SHARE_READ;
  3511. if (share&FILE_SHARE_WRITE) {
  3512. share &= ~FILE_SHARE_WRITE;
  3513. if (share&FILE_SHARE_DELETE) {
  3514. break;
  3515. } else {
  3516. share |= FILE_SHARE_DELETE;
  3517. }
  3518. } else {
  3519. share |= FILE_SHARE_WRITE;
  3520. }
  3521. } else {
  3522. share |= FILE_SHARE_READ;
  3523. }
  3524. } else if (status == STATUS_ACCESS_DENIED) {
  3525. printf ("Hit file protection violation for %X\n", am);
  3526. if (am&MAXIMUM_ALLOWED) {
  3527. am &= ~MAXIMUM_ALLOWED;
  3528. am |= FILE_READ_DATA|FILE_WRITE_DATA|SYNCHRONIZE|FILE_READ_ATTRIBUTES|
  3529. READ_CONTROL|FILE_APPEND_DATA;
  3530. } else if (am&FILE_WRITE_DATA) {
  3531. am &= ~FILE_WRITE_DATA;
  3532. } else if (am&FILE_APPEND_DATA) {
  3533. am &= ~FILE_APPEND_DATA;
  3534. } else if (am&FILE_READ_DATA) {
  3535. am &= ~FILE_READ_DATA;
  3536. } else if (am&WRITE_OWNER) {
  3537. am &= ~WRITE_OWNER;
  3538. } else if (am&WRITE_DAC) {
  3539. am &= ~WRITE_DAC;
  3540. } else if (am&WRITE_DAC) {
  3541. am &= ~WRITE_DAC;
  3542. } else if (am&READ_CONTROL) {
  3543. am &= ~READ_CONTROL;
  3544. } else if (am&FILE_READ_ATTRIBUTES) {
  3545. am &= ~FILE_READ_ATTRIBUTES;
  3546. } else {
  3547. break;
  3548. }
  3549. }
  3550. } while (status == STATUS_SHARING_VIOLATION || status == STATUS_ACCESS_DENIED);
  3551. }
  3552. if (pea)
  3553. free (pea);
  3554. if (NT_SUCCESS(status)) {
  3555. status = get_handle_access (devmap->handle, &devmap->access);
  3556. }
  3557. if (NT_SUCCESS(status)) {
  3558. wprintf(L"Opened file %s with access %x\n",
  3559. dn,
  3560. devmap->access);
  3561. if (DELETE&devmap->access) {
  3562. printf ("Got delete access to device\n");
  3563. }
  3564. if (WRITE_DAC&devmap->access) {
  3565. printf ("Got write_dac access to device\n");
  3566. }
  3567. if (WRITE_OWNER&devmap->access) {
  3568. printf ("Got write_owner access to device\n");
  3569. }
  3570. query_object(devmap->handle, devmap, path);
  3571. misc_functions (devmap->handle, path, synch);
  3572. } else {
  3573. if (status != STATUS_INVALID_DEVICE_REQUEST &&
  3574. status != STATUS_ACCESS_DENIED) {
  3575. printf("%s failed %x\n", api,
  3576. status);
  3577. }
  3578. }
  3579. if ((direct && synch) || (addbackslash & !synch && !direct)) // Only do this twice
  3580. try_fast_query_delete_etc (&oa, path, L"Top open");
  3581. return status;
  3582. }
  3583. /*
  3584. Compare routine for sorting the object directory
  3585. */
  3586. int __cdecl compare_unicode (const void *arg1, const void *arg2)
  3587. {
  3588. POBJECT_DIRECTORY_INFORMATION s1, s2;
  3589. ULONG i, j;
  3590. s1 = (POBJECT_DIRECTORY_INFORMATION) arg1;
  3591. s2 = (POBJECT_DIRECTORY_INFORMATION) arg2;
  3592. for (i = 0, j = 0;
  3593. (i < s1->Name.Length / sizeof (WCHAR)) &&
  3594. (j < s2->Name.Length / sizeof (WCHAR)); i++, j++) {
  3595. if (s1->Name.Buffer[i] < s2->Name.Buffer[j])
  3596. return -1;
  3597. else if (s1->Name.Buffer[i] > s2->Name.Buffer[j])
  3598. return +1;
  3599. }
  3600. if (i > j)
  3601. return -1;
  3602. else if (i < j)
  3603. return +1;
  3604. else
  3605. return 0;
  3606. }
  3607. /*
  3608. Do all the various different opens looking for handles
  3609. */
  3610. NTSTATUS do_device_opens (HANDLE handle,
  3611. PUNICODE_STRING name,
  3612. PDEVMAP devmap,
  3613. PULONG devscount,
  3614. PWCHAR path,
  3615. PWCHAR devbuf)
  3616. {
  3617. NTSTATUS status;
  3618. ULONG do_tdi_opens=0;
  3619. ULONG do_afd_opens=0;
  3620. ULONG OrigDevCount;
  3621. ULONG Left;
  3622. PWCHAR cp;
  3623. OrigDevCount = *devscount;
  3624. for (cp = name->Buffer, Left = name->Length / sizeof (WCHAR); Left > 0; Left--, cp++) {
  3625. if (Left >= 3) {
  3626. if ((cp[0] == L'A' || cp[0] == L'a') &&
  3627. (cp[1] == L'F' || cp[1] == L'f') &&
  3628. (cp[2] == L'D' || cp[2] == L'd')) {
  3629. printf ("Trying AFD opens\n");
  3630. do_afd_opens = 1;
  3631. break;
  3632. }
  3633. }
  3634. }
  3635. if (flags&FLAGS_DO_SYNC) {
  3636. status = open_device(handle,
  3637. name,
  3638. &devmap[*devscount],
  3639. TRUE, /* Synchronous */
  3640. FALSE, /* No added backslash */
  3641. FALSE, /* No direct device open */
  3642. 0,
  3643. path);
  3644. if (NT_SUCCESS(status)) {
  3645. if (NT_SUCCESS (check_tdi_handle (devmap[*devscount].handle))) {
  3646. do_tdi_opens = 1;
  3647. }
  3648. try_funny_opens(devmap[*devscount].handle, path);
  3649. do_ioctl(&devmap[*devscount], path);
  3650. *devscount = *devscount + 1;
  3651. } else {
  3652. if (status == -1) {
  3653. return status;
  3654. } else {
  3655. wprintf(L"Failed to open device %s status is %x\n",
  3656. devbuf,
  3657. status);
  3658. }
  3659. }
  3660. }
  3661. status = open_device(handle,
  3662. name,
  3663. &devmap[*devscount],
  3664. FALSE, /* Synchronous */
  3665. FALSE, /* No added backslash */
  3666. FALSE, /* No direct device access */
  3667. 0,
  3668. path);
  3669. if (NT_SUCCESS(status)) {
  3670. if (!do_tdi_opens && NT_SUCCESS (check_tdi_handle (devmap[*devscount].handle))) {
  3671. do_tdi_opens = 1;
  3672. }
  3673. try_funny_opens(devmap[*devscount].handle, path);
  3674. do_ioctl(&devmap[*devscount], path);
  3675. *devscount = *devscount + 1;
  3676. } else {
  3677. if (status == -1) {
  3678. return status;
  3679. } else {
  3680. wprintf(L"Failed to open device %s status is %x\n",
  3681. devbuf,
  3682. status);
  3683. }
  3684. }
  3685. status = open_device(handle,
  3686. name,
  3687. &devmap[*devscount],
  3688. FALSE, /* Synchronous */
  3689. TRUE, /* No added backslash */
  3690. FALSE, /* No direct device access */
  3691. 0,
  3692. path);
  3693. if (NT_SUCCESS(status)) {
  3694. try_funny_opens(devmap[*devscount].handle, path);
  3695. do_ioctl(&devmap[*devscount], path);
  3696. *devscount = *devscount + 1;
  3697. } else {
  3698. if (status == -1) {
  3699. return status;
  3700. } else {
  3701. wprintf(L"Failed to open device %s status is %x\n",
  3702. devbuf,
  3703. status);
  3704. }
  3705. }
  3706. if (flags&FLAGS_DO_SYNC) {
  3707. status = open_device(handle,
  3708. name,
  3709. &devmap[*devscount],
  3710. TRUE, /* Synchronous */
  3711. FALSE, /* No added backslash */
  3712. TRUE, /* Direct device access */
  3713. 0,
  3714. path);
  3715. if (NT_SUCCESS(status)) {
  3716. try_funny_opens(devmap[*devscount].handle, path);
  3717. do_ioctl(&devmap[*devscount], path);
  3718. *devscount = *devscount + 1;
  3719. } else {
  3720. if (status == -1) {
  3721. return status;
  3722. } else {
  3723. wprintf(L"Failed to open device %s status is %x\n",
  3724. devbuf,
  3725. status);
  3726. }
  3727. }
  3728. }
  3729. if (flags&FLAGS_DO_SYNC) {
  3730. status = open_device(handle,
  3731. name,
  3732. &devmap[*devscount],
  3733. TRUE, /* Synchronous */
  3734. FALSE, /* No added backslash */
  3735. FALSE, /* Direct device access */
  3736. OPEN_TYPE_NAMED_PIPE,
  3737. path);
  3738. if (NT_SUCCESS(status)) {
  3739. try_funny_opens(devmap[*devscount].handle, path);
  3740. do_ioctl(&devmap[*devscount], path);
  3741. *devscount = *devscount + 1;
  3742. } else {
  3743. if (status == -1) {
  3744. return status;
  3745. } else {
  3746. wprintf(L"Failed to open device %s status is %x\n",
  3747. devbuf,
  3748. status);
  3749. }
  3750. }
  3751. status = open_device(handle,
  3752. name,
  3753. &devmap[*devscount],
  3754. TRUE, /* Synchronous */
  3755. FALSE, /* No added backslash */
  3756. FALSE, /* Direct device access */
  3757. OPEN_TYPE_MAIL_SLOT,
  3758. path);
  3759. if (NT_SUCCESS(status)) {
  3760. try_funny_opens(devmap[*devscount].handle, path);
  3761. do_ioctl(&devmap[*devscount], path);
  3762. *devscount = *devscount + 1;
  3763. } else {
  3764. if (status == -1) {
  3765. return status;
  3766. } else {
  3767. wprintf(L"Failed to open device %s status is %x\n",
  3768. devbuf,
  3769. status);
  3770. }
  3771. }
  3772. }
  3773. status = open_device(handle,
  3774. name,
  3775. &devmap[*devscount],
  3776. FALSE, /* Synchronous */
  3777. FALSE, /* No added backslash */
  3778. FALSE, /* Direct device access */
  3779. OPEN_TYPE_NAMED_PIPE,
  3780. path);
  3781. if (NT_SUCCESS(status)) {
  3782. try_funny_opens(devmap[*devscount].handle, path);
  3783. do_ioctl(&devmap[*devscount], path);
  3784. *devscount = *devscount + 1;
  3785. } else {
  3786. if (status == -1) {
  3787. return status;
  3788. } else {
  3789. wprintf(L"Failed to open device %s status is %x\n",
  3790. devbuf,
  3791. status);
  3792. }
  3793. }
  3794. status = open_device(handle,
  3795. name,
  3796. &devmap[*devscount],
  3797. FALSE, /* Synchronous */
  3798. FALSE, /* No added backslash */
  3799. FALSE, /* Direct device access */
  3800. OPEN_TYPE_MAIL_SLOT,
  3801. path);
  3802. if (NT_SUCCESS(status)) {
  3803. try_funny_opens(devmap[*devscount].handle, path);
  3804. do_ioctl(&devmap[*devscount], path);
  3805. *devscount = *devscount + 1;
  3806. } else {
  3807. if (status == -1) {
  3808. return status;
  3809. } else {
  3810. wprintf(L"Failed to open device %s status is %x\n",
  3811. devbuf,
  3812. status);
  3813. }
  3814. }
  3815. status = open_device(handle,
  3816. name,
  3817. &devmap[*devscount],
  3818. FALSE, /* Synchronous */
  3819. FALSE, /* No added backslash */
  3820. FALSE, /* Direct device access */
  3821. OPEN_TYPE_TREE_CONNECT,
  3822. path);
  3823. if (NT_SUCCESS(status)) {
  3824. try_funny_opens(devmap[*devscount].handle, path);
  3825. do_ioctl(&devmap[*devscount], path);
  3826. *devscount = *devscount + 1;
  3827. } else {
  3828. if (status == -1) {
  3829. return status;
  3830. } else {
  3831. wprintf(L"Failed to open device %s status is %x\n",
  3832. devbuf,
  3833. status);
  3834. }
  3835. }
  3836. if (do_tdi_opens) {
  3837. status = open_device(handle,
  3838. name,
  3839. &devmap[*devscount],
  3840. FALSE, /* Synchronous */
  3841. FALSE, /* No added backslash */
  3842. FALSE, /* Direct device access */
  3843. OPEN_TYPE_TDI_CONNECTION,
  3844. path);
  3845. if (NT_SUCCESS(status)) {
  3846. try_funny_opens(devmap[*devscount].handle, path);
  3847. do_ioctl(&devmap[*devscount], path);
  3848. *devscount = *devscount + 1;
  3849. } else {
  3850. if (status == -1) {
  3851. return status;
  3852. } else {
  3853. wprintf(L"Failed to open device %s status is %x\n",
  3854. devbuf,
  3855. status);
  3856. }
  3857. }
  3858. status = open_device(handle,
  3859. name,
  3860. &devmap[*devscount],
  3861. FALSE, /* Synchronous */
  3862. FALSE, /* No added backslash */
  3863. FALSE, /* Direct device access */
  3864. OPEN_TYPE_TDI_ADDR_IP,
  3865. path);
  3866. if (NT_SUCCESS(status)) {
  3867. try_funny_opens(devmap[*devscount].handle, path);
  3868. do_ioctl(&devmap[*devscount], path);
  3869. *devscount = *devscount + 1;
  3870. } else {
  3871. if (status == -1) {
  3872. return status;
  3873. } else {
  3874. wprintf(L"Failed to open device %s status is %x\n",
  3875. devbuf,
  3876. status);
  3877. }
  3878. }
  3879. status = open_device(handle,
  3880. name,
  3881. &devmap[*devscount],
  3882. FALSE, /* Synchronous */
  3883. FALSE, /* No added backslash */
  3884. FALSE, /* Direct device access */
  3885. OPEN_TYPE_TDI_ADDR_IPX,
  3886. path);
  3887. if (NT_SUCCESS(status)) {
  3888. try_funny_opens(devmap[*devscount].handle, path);
  3889. do_ioctl(&devmap[*devscount], path);
  3890. *devscount = *devscount + 1;
  3891. } else {
  3892. if (status == -1) {
  3893. return status;
  3894. } else {
  3895. wprintf(L"Failed to open device %s status is %x\n",
  3896. devbuf,
  3897. status);
  3898. }
  3899. }
  3900. status = open_device(handle,
  3901. name,
  3902. &devmap[*devscount],
  3903. FALSE, /* Synchronous */
  3904. FALSE, /* No added backslash */
  3905. FALSE, /* Direct device access */
  3906. OPEN_TYPE_TDI_ADDR_NETBIOS,
  3907. path);
  3908. if (NT_SUCCESS(status)) {
  3909. try_funny_opens(devmap[*devscount].handle, path);
  3910. do_ioctl(&devmap[*devscount], path);
  3911. *devscount = *devscount + 1;
  3912. } else {
  3913. if (status == -1) {
  3914. return status;
  3915. } else {
  3916. wprintf(L"Failed to open device %s status is %x\n",
  3917. devbuf,
  3918. status);
  3919. }
  3920. }
  3921. status = open_device(handle,
  3922. name,
  3923. &devmap[*devscount],
  3924. FALSE, /* Synchronous */
  3925. FALSE, /* No added backslash */
  3926. FALSE, /* Direct device access */
  3927. OPEN_TYPE_TDI_ADDR_APPLE,
  3928. path);
  3929. if (NT_SUCCESS(status)) {
  3930. try_funny_opens(devmap[*devscount].handle, path);
  3931. do_ioctl(&devmap[*devscount], path);
  3932. *devscount = *devscount + 1;
  3933. } else {
  3934. if (status == -1) {
  3935. return status;
  3936. } else {
  3937. wprintf(L"Failed to open device %s status is %x\n",
  3938. devbuf,
  3939. status);
  3940. }
  3941. }
  3942. }
  3943. if (do_afd_opens) {
  3944. status = open_device(handle,
  3945. name,
  3946. &devmap[*devscount],
  3947. FALSE, /* Synchronous */
  3948. FALSE, /* No added backslash */
  3949. FALSE, /* Direct device access */
  3950. OPEN_TYPE_AFD_TRANSPORT,
  3951. path);
  3952. if (NT_SUCCESS(status)) {
  3953. try_funny_opens(devmap[*devscount].handle, path);
  3954. do_ioctl(&devmap[*devscount], path);
  3955. *devscount = *devscount + 1;
  3956. } else {
  3957. if (status == -1) {
  3958. return status;
  3959. } else {
  3960. wprintf(L"Failed to open device %s status is %x\n",
  3961. devbuf,
  3962. status);
  3963. }
  3964. }
  3965. status = open_device(handle,
  3966. name,
  3967. &devmap[*devscount],
  3968. FALSE, /* Synchronous */
  3969. FALSE, /* No added backslash */
  3970. FALSE, /* Direct device access */
  3971. OPEN_TYPE_AFD_SAN,
  3972. path);
  3973. if (NT_SUCCESS(status)) {
  3974. try_funny_opens(devmap[*devscount].handle, path);
  3975. do_ioctl(&devmap[*devscount], path);
  3976. *devscount = *devscount + 1;
  3977. } else {
  3978. if (status == -1) {
  3979. return status;
  3980. } else {
  3981. wprintf(L"Failed to open device %s status is %x\n",
  3982. devbuf,
  3983. status);
  3984. }
  3985. }
  3986. }
  3987. if (OrigDevCount == *devscount) {
  3988. crashes (path, L"FAILED all open attempts", L"", L"", L"");
  3989. }
  3990. crashes (path, L"DONE", L"", L"", L"");
  3991. return status;
  3992. }
  3993. NTSTATUS
  3994. do_lpc_connect (HANDLE handle,
  3995. PUNICODE_STRING name,
  3996. PDEVMAP devmap,
  3997. PULONG devscount,
  3998. PWCHAR path,
  3999. PWCHAR devbuf)
  4000. {
  4001. HANDLE nhandle;
  4002. NTSTATUS status;
  4003. SECURITY_QUALITY_OF_SERVICE qos;
  4004. ULONG maxmsg, i, opened;
  4005. UNICODE_STRING fullname;
  4006. RtlInitUnicodeString (&fullname, path);
  4007. qos.ImpersonationLevel = SecurityImpersonation;
  4008. qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  4009. qos.EffectiveOnly = TRUE;
  4010. opened = 0;
  4011. for (i = 0; i < 1000; i++) {
  4012. status = NtConnectPort (&nhandle, &fullname, &qos, NULL, NULL, &maxmsg, NULL, NULL);
  4013. if (!NT_SUCCESS (status)) {
  4014. wprintf (L"NtConnectPort failed to %s %x\n", path, status);
  4015. return status;
  4016. }
  4017. opened++;
  4018. status = NtClose (nhandle);
  4019. if (!NT_SUCCESS (status)) {
  4020. wprintf (L"NtClose of port handle failed %x\n", status);
  4021. }
  4022. }
  4023. if (opened) {
  4024. wprintf (L"Opened port %ws %d times\n", path, opened);
  4025. }
  4026. return status;
  4027. }
  4028. /*
  4029. Traverse the object tree looking for devices
  4030. */
  4031. NTSTATUS
  4032. recurse(
  4033. HANDLE handle,
  4034. PUNICODE_STRING name,
  4035. PDEVMAP devmap,
  4036. PULONG devscount,
  4037. PWCHAR path,
  4038. ULONG depth
  4039. )
  4040. {
  4041. HANDLE nhandle, shandle;
  4042. NTSTATUS status;
  4043. OBJECT_ATTRIBUTES oa;
  4044. OBJECT_DIRECTORY_INFORMATION *od;
  4045. PVOID buffer;
  4046. ULONG bufferlen;
  4047. ULONG context;
  4048. ULONG retlen;
  4049. ULONG ul;
  4050. UNICODE_STRING equiv;
  4051. WCHAR buf[100], devbuf[200], objtype[80];
  4052. PWCHAR npath = NULL, oldnpath;
  4053. static WCHAR ans[100]={0};
  4054. ULONG c;
  4055. if (depth > 10) {
  4056. return STATUS_SUCCESS;
  4057. }
  4058. InitializeObjectAttributes(&oa,
  4059. name,
  4060. OBJ_CASE_INSENSITIVE,
  4061. handle,
  4062. NULL);
  4063. wcsncpy(devbuf,
  4064. name->Buffer,
  4065. sizeof (devbuf) / sizeof (devbuf[0]));
  4066. devbuf[sizeof (devbuf) / sizeof (devbuf[0]) - 1] = L'\0';
  4067. status = NtOpenDirectoryObject(&nhandle,
  4068. MAXIMUM_ALLOWED/*DIRECTORY_QUERY | DIRECTORY_TRAVERSE*/,
  4069. &oa);
  4070. if (NT_SUCCESS(status)) {
  4071. context = 0;
  4072. bufferlen = 0x10000;
  4073. buffer = malloc(bufferlen);
  4074. if (buffer == NULL) {
  4075. printf ("Failed to allocate memory for query buffer\n");
  4076. exit (EXIT_FAILURE);
  4077. }
  4078. status = NtQueryDirectoryObject(nhandle,
  4079. buffer,
  4080. bufferlen,
  4081. FALSE,
  4082. TRUE,
  4083. &context,
  4084. &retlen);
  4085. if (NT_SUCCESS(status)) {
  4086. for (od = (POBJECT_DIRECTORY_INFORMATION) buffer, c = 0;
  4087. od->Name.Length != 0 || od->TypeName.Length != 0; od++, c++)
  4088. ;
  4089. qsort (buffer, c, sizeof (*od), compare_unicode);
  4090. for (od = (POBJECT_DIRECTORY_INFORMATION) buffer;
  4091. *devscount < MAX_DEVICES; od++) {
  4092. if (od->Name.Length == 0 &&
  4093. od->TypeName.Length == 0) {
  4094. break;
  4095. }
  4096. wcsncpy(devbuf,
  4097. od->Name.Buffer,
  4098. sizeof (devbuf) / sizeof (devbuf[0]));
  4099. devbuf[sizeof (devbuf) / sizeof (devbuf[0]) - 1] = L'\0';
  4100. wcsncpy(objtype,
  4101. od->TypeName.Buffer,
  4102. sizeof (objtype) / sizeof (objtype[0]));
  4103. objtype[sizeof (objtype) / sizeof (objtype[0]) - 1] = L'\0';
  4104. oldnpath = npath;
  4105. npath = realloc (oldnpath,
  4106. (wcslen (path) + 1 + wcslen (devbuf) + 1) *
  4107. sizeof (WCHAR));
  4108. if (!npath) {
  4109. if (oldnpath != NULL) {
  4110. free (oldnpath);
  4111. }
  4112. printf ("Memory allocation failed for path buffer!");
  4113. exit (EXIT_FAILURE);
  4114. }
  4115. wcscpy (npath, path);
  4116. if (path[wcslen (path)-1] != '\\' &&
  4117. devbuf[wcslen (devbuf)-1] != '\\')
  4118. wcscat (npath, L"\\");
  4119. wcscat (npath, devbuf);
  4120. if (wcsncmp(objtype,
  4121. L"Directory",
  4122. od->TypeName.Length / sizeof (WCHAR)) == 0) {
  4123. recurse(nhandle,
  4124. &od->Name,
  4125. devmap,
  4126. devscount,
  4127. npath,
  4128. depth+1);
  4129. } else if (!(flags&FLAGS_DO_LPC) && (
  4130. wcsncmp(objtype,
  4131. L"Device",
  4132. od->TypeName.Length / sizeof (WCHAR)) == 0 ||
  4133. (wcsncmp(objtype,
  4134. L"SymbolicLink",
  4135. od->TypeName.Length / sizeof (WCHAR)) == 0 && (flags&FLAGS_DO_SYMBOLIC)))) {
  4136. if (!(flags&FLAGS_DO_ALLDEVS)) {
  4137. if (skipped == 0) {
  4138. ans[0] = 0;
  4139. skipped = 1;
  4140. }
  4141. if (ans[0] == '/') {
  4142. // wprintf (L"Matching \"%s\" against \"%s\"\n", &ans[1], devbuf);
  4143. if (_wcsnicmp (&ans[1], devbuf, wcslen (&ans[1])) != 0)
  4144. continue;
  4145. } else if (ans[0] == '?' || (flags&FLAGS_DO_PRINT_DEVS)) {
  4146. if (prefix_string) {
  4147. printf ("%s %ws\\%ws\n", prefix_string, path, devbuf);
  4148. } else {
  4149. printf ("%ws %ws\\%ws\n", objtype, path, devbuf);
  4150. }
  4151. continue;
  4152. }
  4153. progress_counter = 0;
  4154. if (flags & FLAGS_DO_RANDOM_DEVICE) {
  4155. if (random_device > 0) {
  4156. // wprintf (L"%s %s\\%s\n", objtype, path, devbuf);
  4157. random_device--;
  4158. continue;
  4159. }
  4160. } else if (ans[0] != 'a' && ans[0] != 'A') {
  4161. wprintf (L"Open device %s %s\\%s? ", objtype, path, devbuf);
  4162. (void) wscanf (L"%100s", ans);
  4163. if (ans[0] == 'q' || ans[0] == 'Q') {
  4164. exit (EXIT_SUCCESS);
  4165. } else if (ans[0] != 'y' && ans[0] != 'Y' &&
  4166. ans[0] != 'a' && ans[0] != 'A') {
  4167. continue;
  4168. }
  4169. }
  4170. }
  4171. if (!(flags&FLAGS_DO_DISKS)) {
  4172. if (wcsstr (path, L"Harddisk") ||
  4173. wcsstr (path, L"Ide") ||
  4174. wcsstr (path, L"Scsi")) {
  4175. printf ("Skipping this device as it looks like a disk\n");
  4176. continue;
  4177. }
  4178. }
  4179. if (flags&FLAGS_DO_FAILURE_INJECTION) {
  4180. turn_on_fault_injection ();
  4181. }
  4182. if (flags&FLAGS_DO_IMPERSONATION) {
  4183. Impersonate_nonadmin ();
  4184. }
  4185. status = do_device_opens (nhandle,
  4186. &od->Name,
  4187. devmap,
  4188. devscount,
  4189. npath,
  4190. devbuf);
  4191. if (flags&FLAGS_DO_IMPERSONATION) {
  4192. if (!Revert_from_admin ()) {
  4193. printf ("Revert_from_admin failed %d\n", GetLastError ());
  4194. exit (EXIT_FAILURE);
  4195. }
  4196. }
  4197. if (flags&FLAGS_DO_FAILURE_INJECTION) {
  4198. turn_off_fault_injection ();
  4199. }
  4200. print_diags (0, 0);
  4201. if (flags & FLAGS_DO_RANDOM_DEVICE) {
  4202. break;
  4203. }
  4204. } else if ((flags&FLAGS_DO_LPC) &&
  4205. wcsncmp(od->TypeName.Buffer,
  4206. L"Port",
  4207. od->TypeName.Length / sizeof (WCHAR)) == 0) {
  4208. if (!(flags&FLAGS_DO_ALLDEVS)) {
  4209. if (skipped == 0) {
  4210. ans[0] = 0;
  4211. skipped = 1;
  4212. }
  4213. if (ans[0] == '/') {
  4214. wprintf (L"Matching \"%s\" against \"%s\"\n", &ans[1], devbuf);
  4215. if (_wcsnicmp (&ans[1], devbuf, wcslen (&ans[1])) != 0)
  4216. continue;
  4217. } else if (ans[0] == '?') {
  4218. wprintf (L"%s\\%s\n", path, devbuf);
  4219. continue;
  4220. } else if (ans[0] == 'q' || ans[0] == 'Q') {
  4221. exit (EXIT_SUCCESS);
  4222. }
  4223. if (ans[0] != 'a' && ans[0] != 'A') {
  4224. wprintf (L"Open LPC port %s\\%s? ", path, devbuf);
  4225. (void) wscanf (L"%100s", ans);
  4226. if (ans[0] != 'y' && ans[0] != 'Y' &&
  4227. ans[0] != 'a' && ans[0] != 'A')
  4228. continue;
  4229. }
  4230. if (flags&FLAGS_DO_IMPERSONATION) {
  4231. Impersonate_nonadmin ();
  4232. }
  4233. status = do_lpc_connect (nhandle,
  4234. &od->Name,
  4235. devmap,
  4236. devscount,
  4237. npath,
  4238. devbuf);
  4239. if (flags&FLAGS_DO_IMPERSONATION) {
  4240. if (!Revert_from_admin ()) {
  4241. printf ("Revert_from_admin failed %d\n", GetLastError ());
  4242. exit (EXIT_FAILURE);
  4243. }
  4244. }
  4245. }
  4246. }
  4247. }
  4248. } else {
  4249. if (status != STATUS_NO_MORE_ENTRIES) {
  4250. wprintf(L"NtQueryDirectoryObject failed %x for directory %s\n",
  4251. status,
  4252. devbuf);
  4253. }
  4254. }
  4255. free(buffer);
  4256. NtClose(nhandle);
  4257. } else {
  4258. wprintf(L"NtOpenDirectoryObject failed %x for directory %s\n",
  4259. status,
  4260. devbuf);
  4261. }
  4262. free (npath);
  4263. return status;
  4264. }
  4265. /*
  4266. Look who registers for WMI
  4267. */
  4268. void do_wmi ()
  4269. {
  4270. UNICODE_STRING name;
  4271. OBJECT_ATTRIBUTES oa;
  4272. NTSTATUS status;
  4273. PKMREGINFO reginfo = NULL;
  4274. HANDLE handle;
  4275. IO_STATUS_BLOCK iosb;
  4276. ULONG reginfol, i;
  4277. RtlInitUnicodeString (&name, L"\\Device\\WMIServiceDevice\\");
  4278. InitializeObjectAttributes (&oa, &name, OBJ_CASE_INSENSITIVE, NULL, NULL);
  4279. status = NtOpenFile (&handle,
  4280. MAXIMUM_ALLOWED|SYNCHRONIZE,
  4281. &oa,
  4282. &iosb,
  4283. FILE_SHARE_READ|FILE_SHARE_WRITE,
  4284. FILE_SYNCHRONOUS_IO_NONALERT);
  4285. if (NT_SUCCESS (status)) {
  4286. status = iosb.Status;
  4287. }
  4288. if (!NT_SUCCESS (status)) {
  4289. // printf ("Failed to open WMI device %x\n", status);
  4290. return;
  4291. }
  4292. reginfo = malloc (reginfol = 4096);
  4293. if (!reginfo) {
  4294. printf ("Memory allocation failure for WMI buffer\n");
  4295. exit (EXIT_FAILURE);
  4296. }
  4297. status = NtDeviceIoControlFile (handle,
  4298. NULL,
  4299. NULL,
  4300. NULL,
  4301. &iosb,
  4302. IOCTL_WMI_GET_ALL_REGISTRANT,
  4303. NULL,
  4304. 0,
  4305. reginfo,
  4306. reginfol);
  4307. if (NT_SUCCESS (status)) {
  4308. status = iosb.Status;
  4309. }
  4310. if (!NT_SUCCESS (status)) {
  4311. printf ("NtDeviceIoControlFile failed %X\n", status);
  4312. } else {
  4313. for (i = 0; i < iosb.Information / sizeof (*reginfo); i++) {
  4314. printf ("Device %x registered with WMI\n", reginfo[i].ProviderId);
  4315. }
  4316. }
  4317. if (reginfo)
  4318. free (reginfo);
  4319. status = NtClose (handle);
  4320. if (!NT_SUCCESS (status)) {
  4321. printf ("NtClose failed %x\n", status);
  4322. }
  4323. }
  4324. /*
  4325. Thread to read from a socket so we can test out transmit file
  4326. */
  4327. DWORD WINAPI do_listen (LPVOID arg)
  4328. {
  4329. SOCKET s;
  4330. struct sockaddr_in sockaddr;
  4331. int l;
  4332. int status;
  4333. DWORD retlen;
  4334. CHAR buf[100];
  4335. l = sizeof (sockaddr);
  4336. s = accept (ls, (struct sockaddr *) &sockaddr, &l);
  4337. if (s == INVALID_SOCKET) {
  4338. printf ("Socket failed %d\n", WSAGetLastError ());
  4339. exit (EXIT_FAILURE);
  4340. }
  4341. while (1) {
  4342. l = recv (s, buf, sizeof (buf), 0);
  4343. if (l == 0) {
  4344. break;
  4345. }
  4346. if (l == SOCKET_ERROR) {
  4347. printf ("recv failed %d\n", WSAGetLastError ());
  4348. exit (EXIT_FAILURE);
  4349. }
  4350. }
  4351. return 0;
  4352. }
  4353. void do_handle_grab (PDEVMAP devmap,
  4354. PULONG devscount)
  4355. {
  4356. NTSTATUS status;
  4357. CLIENT_ID clid;
  4358. OBJECT_ATTRIBUTES oa;
  4359. HANDLE handle;
  4360. InitializeObjectAttributes (&oa, NULL, 0, NULL, NULL);
  4361. clid.UniqueThread = 0;
  4362. clid.UniqueProcess = UlongToHandle( cid );
  4363. status = NtOpenProcess (&handle, PROCESS_DUP_HANDLE, &oa, &clid);
  4364. if (!NT_SUCCESS (status)) {
  4365. printf ("NtOpenProcess for process %d failed %x\n", cid, status);
  4366. return;
  4367. }
  4368. status = NtDuplicateObject (handle, process_handle, NtCurrentProcess (),
  4369. &devmap->handle, 0, 0, DUPLICATE_SAME_ACCESS);
  4370. if (NT_SUCCESS (status)) {
  4371. *devscount += 1;
  4372. status = get_handle_access (devmap->handle, &devmap->access);
  4373. if (NT_SUCCESS(status)) {
  4374. wprintf(L"Grabbed handle with access %x\n",
  4375. devmap->access);
  4376. if (DELETE&devmap->access) {
  4377. printf ("Got delete access to device\n");
  4378. }
  4379. if (WRITE_DAC&devmap->access) {
  4380. printf ("Got write_dac access to device\n");
  4381. }
  4382. if (WRITE_OWNER&devmap->access) {
  4383. printf ("Got write_owner access to device\n");
  4384. }
  4385. }
  4386. query_object(devmap->handle, devmap, L"HANDLE");
  4387. misc_functions (devmap->handle, L"HANDLE", 0);
  4388. InitializeObjectAttributes (&oa, NULL, 0, devmap->handle, NULL);
  4389. try_fast_query_delete_etc (&oa, L"HANDLE", L"Top open");
  4390. try_funny_opens(devmap->handle, L"HANDLE");
  4391. do_ioctl(devmap, L"HANDLE");
  4392. } else {
  4393. printf ("NtDuplicateObject failed %x\n", status);
  4394. }
  4395. status = NtClose (handle);
  4396. if (!NT_SUCCESS (status)) {
  4397. printf ("NtClose for process handle failed %x\n", status);
  4398. return;
  4399. }
  4400. }
  4401. //
  4402. // Parse command line
  4403. //
  4404. void process_parameters(int argc, char *argv[], PUNICODE_STRING name, long *flags, long *flags2)
  4405. {
  4406. char c, nc, *p, st;
  4407. int i;
  4408. NTSTATUS status;
  4409. *flags = FLAGS_DO_IOCTL_NULL|FLAGS_DO_IOCTL_RANDOM|
  4410. FLAGS_DO_FSCTL_NULL|FLAGS_DO_FSCTL_RANDOM|
  4411. FLAGS_DO_LOGGING|FLAGS_DO_SKIPCRASH|FLAGS_DO_POOLCHECK|
  4412. FLAGS_DO_MISC|FLAGS_DO_QUERY|FLAGS_DO_SUBOPENS|FLAGS_DO_ZEROEA|
  4413. FLAGS_DO_DISKS|FLAGS_DO_SECURITY|FLAGS_DO_OPEN_CLOSE|
  4414. FLAGS_DO_DIRECT_DEVICE|FLAGS_DO_SYMBOLIC|FLAGS_DO_IMPERSONATION;
  4415. *flags2 = 0;
  4416. name->Length = name->MaximumLength = 0;
  4417. name->Buffer = NULL;
  4418. while (--argc) {
  4419. p = *++argv;
  4420. st = *p;
  4421. if (st == '/' || st == '-' || st == '+') {
  4422. c = *++p;
  4423. nc = *++p;
  4424. nc = (char) toupper (nc);
  4425. switch (toupper (c)) {
  4426. case 'I' :
  4427. if (nc == 'R') {
  4428. if (st == '-')
  4429. *flags &= ~FLAGS_DO_IOCTL_RANDOM;
  4430. else
  4431. *flags |= FLAGS_DO_IOCTL_RANDOM;
  4432. } else if (nc == 'N') {
  4433. if (st == '-')
  4434. *flags &= ~FLAGS_DO_IOCTL_NULL;
  4435. else
  4436. *flags |= FLAGS_DO_IOCTL_NULL;
  4437. } else if (nc == 'F') {
  4438. if (st == '-')
  4439. *flags &= ~(FLAGS_DO_IOCTL_NULL|FLAGS_DO_FSCTL_NULL|
  4440. FLAGS_DO_IOCTL_RANDOM|FLAGS_DO_FSCTL_RANDOM);
  4441. else
  4442. *flags |= FLAGS_DO_IOCTL_NULL|FLAGS_DO_FSCTL_NULL|
  4443. FLAGS_DO_IOCTL_RANDOM|FLAGS_DO_FSCTL_RANDOM;
  4444. } else if (nc == 'M') {
  4445. if (st == '-')
  4446. *flags &= ~FLAGS_DO_IMPERSONATION;
  4447. else
  4448. *flags |= FLAGS_DO_IMPERSONATION;
  4449. } else if (nc == 'L') {
  4450. if (argc > 1) {
  4451. ioctl_inbuf_min = atoi (*++argv);
  4452. ioctl_inbuf_min = min (ioctl_inbuf_min, BIGBUF_SIZE);
  4453. argc--;
  4454. printf ("IOCTL/FSCTL lower input buffer limit %d\n", ioctl_inbuf_min);
  4455. } else {
  4456. printf ("IOCTL/FSCTL lower input limit missing\n");
  4457. }
  4458. } else if (nc == 'U') {
  4459. if (argc > 1) {
  4460. ioctl_inbuf_max = atoi (*++argv);
  4461. ioctl_inbuf_max = min (ioctl_inbuf_max, BIGBUF_SIZE);
  4462. argc--;
  4463. printf ("IOCTL/FSCTL upper input buffer limit %d\n", ioctl_inbuf_max);
  4464. } else {
  4465. printf ("IOCTL/FSCTL upper input limit missing\n");
  4466. }
  4467. } else if (!nc) {
  4468. if (st == '-')
  4469. *flags &= ~(FLAGS_DO_IOCTL_NULL|FLAGS_DO_IOCTL_RANDOM);
  4470. else
  4471. *flags |= FLAGS_DO_IOCTL_NULL|FLAGS_DO_IOCTL_RANDOM;
  4472. }
  4473. break;
  4474. case 'F' :
  4475. if (nc == 'L') {
  4476. if (argc > 1) {
  4477. ioctl_min_function = atoi (*++argv);
  4478. ioctl_min_function = min (ioctl_min_function, 0xFFF);
  4479. argc--;
  4480. printf ("IOCTL/FSCTL lower function limit %d\n", ioctl_min_function);
  4481. } else {
  4482. printf ("IOCTL/FSCTL lower function limit missing\n");
  4483. }
  4484. } else if (nc == 'U') {
  4485. if (argc > 1) {
  4486. ioctl_max_function = atoi (*++argv);
  4487. ioctl_max_function = min (ioctl_max_function, 0xFFF);
  4488. argc--;
  4489. printf ("IOCTL/FSCTL upper function limit %d\n", ioctl_max_function);
  4490. } else {
  4491. printf ("IOCTL/FSCTL upper function limit missing\n");
  4492. }
  4493. } else if (nc == 'R') {
  4494. if (st == '-')
  4495. *flags &= ~FLAGS_DO_FSCTL_RANDOM;
  4496. else
  4497. *flags |= FLAGS_DO_FSCTL_RANDOM;
  4498. } else if (nc == 'N') {
  4499. if (st == '-')
  4500. *flags &= ~FLAGS_DO_FSCTL_NULL;
  4501. else
  4502. *flags |= FLAGS_DO_FSCTL_NULL;
  4503. } else if (nc == 'I') {
  4504. if (st == '-')
  4505. *flags &= ~FLAGS_DO_FAILURE_INJECTION;
  4506. else
  4507. *flags |= FLAGS_DO_FAILURE_INJECTION;
  4508. } else if (!nc) {
  4509. if (st == '-')
  4510. *flags &= ~(FLAGS_DO_FSCTL_NULL|FLAGS_DO_FSCTL_RANDOM);
  4511. else
  4512. *flags |= FLAGS_DO_FSCTL_NULL|FLAGS_DO_FSCTL_RANDOM;
  4513. }
  4514. break;
  4515. case 'C' :
  4516. if (st == '-')
  4517. *flags &= ~FLAGS_DO_SKIPCRASH;
  4518. else
  4519. *flags |= FLAGS_DO_SKIPCRASH;
  4520. break;
  4521. case 'L' :
  4522. if (st == '-')
  4523. *flags &= ~FLAGS_DO_LOGGING;
  4524. else
  4525. *flags |= FLAGS_DO_LOGGING;
  4526. break;
  4527. case 'P' :
  4528. if (!nc) {
  4529. if (st == '-')
  4530. *flags &= ~FLAGS_DO_POOLCHECK;
  4531. else
  4532. *flags |= FLAGS_DO_POOLCHECK;
  4533. } else if (nc == 'R') {
  4534. if (st == '-')
  4535. *flags &= ~FLAGS_DO_PROT;
  4536. else
  4537. *flags |= FLAGS_DO_PROT;
  4538. } else if (nc == 'D') {
  4539. if (st == '-')
  4540. *flags &= ~FLAGS_DO_PRINT_DEVS;
  4541. else
  4542. *flags |= FLAGS_DO_PRINT_DEVS;
  4543. } else if (nc == 'S') {
  4544. if (argc > 1) {
  4545. prefix_string = *++argv;
  4546. argc--;
  4547. } else {
  4548. printf ("Prefix string missing\n");
  4549. }
  4550. }
  4551. break;
  4552. case 'R' :
  4553. if (!nc) {
  4554. if (st == '-')
  4555. *flags &= ~FLAGS_DO_SKIPDONE;
  4556. else
  4557. *flags |= FLAGS_DO_SKIPDONE;
  4558. } else if (nc == 'D') {
  4559. if (st == '-')
  4560. *flags &= ~FLAGS_DO_RANDOM_DEVICE;
  4561. else
  4562. *flags |= FLAGS_DO_RANDOM_DEVICE;
  4563. }
  4564. break;
  4565. case 'M' :
  4566. if (st == '-')
  4567. *flags &= ~FLAGS_DO_MISC;
  4568. else
  4569. *flags |= FLAGS_DO_MISC;
  4570. break;
  4571. case 'N' :
  4572. if (st == '-')
  4573. *flags &= ~FLAGS_DO_MAPNULL;
  4574. else
  4575. *flags |= FLAGS_DO_MAPNULL;
  4576. break;
  4577. case 'O' :
  4578. if (nc == 'L') {
  4579. if (argc > 1) {
  4580. ioctl_outbuf_min = atoi (*++argv);
  4581. ioctl_outbuf_min = min (ioctl_outbuf_min, BIGBUF_SIZE);
  4582. argc--;
  4583. printf ("IOCTL/FSCTL lower output buffer limit %d\n", ioctl_outbuf_min);
  4584. } else {
  4585. printf ("IOCTL/FSCTL lower output limit missing\n");
  4586. }
  4587. } else if (nc == 'U') {
  4588. if (argc > 1) {
  4589. ioctl_outbuf_max = atoi (*++argv);
  4590. ioctl_outbuf_max = min (ioctl_outbuf_max, BIGBUF_SIZE);
  4591. argc--;
  4592. printf ("IOCTL/FSCTL upper output buffer limit %d\n", ioctl_outbuf_max);
  4593. } else {
  4594. printf ("IOCTL/FSCTL upper output limit missing\n");
  4595. }
  4596. } else if (nc == 'C') {
  4597. if (st == '-') {
  4598. *flags &= ~FLAGS_DO_OPEN_CLOSE;
  4599. } else {
  4600. *flags |= FLAGS_DO_OPEN_CLOSE;
  4601. }
  4602. }
  4603. break;
  4604. case 'S' :
  4605. if (nc == 'D') {
  4606. if (st == '-')
  4607. *flags &= ~FLAGS_DO_SECURITY;
  4608. else
  4609. *flags |= FLAGS_DO_SECURITY;
  4610. } else if (nc == 'L'){
  4611. if (st == '-')
  4612. *flags &= ~FLAGS_DO_SYMBOLIC;
  4613. else
  4614. *flags |= FLAGS_DO_SYMBOLIC;
  4615. } else {
  4616. if (st == '-')
  4617. *flags &= ~FLAGS_DO_SUBOPENS;
  4618. else
  4619. *flags |= FLAGS_DO_SUBOPENS;
  4620. }
  4621. break;
  4622. case 'Q' :
  4623. if (st == '-')
  4624. *flags &= ~FLAGS_DO_QUERY;
  4625. else
  4626. *flags |= FLAGS_DO_QUERY;
  4627. break;
  4628. case 'A' :
  4629. if (nc == 'L') {
  4630. if (st == '-')
  4631. *flags &= ~FLAGS_DO_ALERT;
  4632. else
  4633. *flags |= FLAGS_DO_ALERT;
  4634. } else {
  4635. if (st == '-')
  4636. *flags &= ~FLAGS_DO_ALLDEVS;
  4637. else
  4638. *flags |= FLAGS_DO_ALLDEVS;
  4639. }
  4640. break;
  4641. case 'E' :
  4642. if (st == '-')
  4643. *flags &= ~FLAGS_DO_ZEROEA;
  4644. else
  4645. *flags |= FLAGS_DO_ZEROEA;
  4646. break;
  4647. case 'Z' :
  4648. if (st == '-')
  4649. *flags &= ~FLAGS_DO_LPC;
  4650. else
  4651. *flags |= FLAGS_DO_LPC;
  4652. break;
  4653. case 'V' :
  4654. if (st == '-')
  4655. *flags &= ~FLAGS_DO_ERRORS;
  4656. else
  4657. *flags |= FLAGS_DO_ERRORS;
  4658. break;
  4659. case 'J' :
  4660. if (st == '-')
  4661. *flags &= ~FLAGS_DO_STREAMS;
  4662. else
  4663. *flags |= FLAGS_DO_STREAMS;
  4664. break;
  4665. case 'W' :
  4666. if (st == '-')
  4667. *flags &= ~FLAGS_DO_WINSOCK;
  4668. else
  4669. *flags |= FLAGS_DO_WINSOCK;
  4670. break;
  4671. case 'K' :
  4672. if (st == '-')
  4673. *flags &= ~FLAGS_DO_SYNC;
  4674. else
  4675. *flags |= FLAGS_DO_SYNC;
  4676. break;
  4677. case 'T' :
  4678. if (nc == 'T') {
  4679. if (argc > 1) {
  4680. max_tailured_calls = atoi (*++argv);
  4681. argc--;
  4682. max_tailured_calls = ((max_tailured_calls + RAND_REP - 1) / RAND_REP) *
  4683. RAND_REP;
  4684. printf ("IOCTL/FSCTL tailured calls %d\n", max_tailured_calls);
  4685. } else {
  4686. printf ("IOCTL/FSCTL tailured calls value is missing\n");
  4687. }
  4688. } else {
  4689. if (argc > 1) {
  4690. max_random_calls = atoi (*++argv);
  4691. argc--;
  4692. max_random_calls = ((max_random_calls + RAND_REP - 1) / RAND_REP) *
  4693. RAND_REP;
  4694. printf ("IOCTL/FSCTL random calls %d\n", max_random_calls);
  4695. } else {
  4696. printf ("IOCTL/FSCTL random calls value is missing\n");
  4697. }
  4698. }
  4699. break;
  4700. case 'D' :
  4701. if (nc == 'L') {
  4702. if (argc > 1) {
  4703. ioctl_min_devtype = atoi (*++argv);
  4704. argc--;
  4705. ioctl_min_devtype = min (ioctl_min_devtype, 0xFFFF);
  4706. printf ("IOCTL/FSCTL lower device type limit %d\n",
  4707. ioctl_min_devtype);
  4708. } else {
  4709. printf ("IOCTL/FSCTL lower device type limit missing\n");
  4710. }
  4711. } else if (nc == 'U') {
  4712. if (argc > 1) {
  4713. ioctl_max_devtype = atoi (*++argv);
  4714. ioctl_max_devtype = min (ioctl_max_devtype, 0xFFFF);
  4715. argc--;
  4716. printf ("IOCTL/FSCTL upper device type limit %d\n",
  4717. ioctl_max_devtype);
  4718. } else {
  4719. printf ("IOCTL/FSCTL upper device type limit missing\n");
  4720. }
  4721. } else if (nc == 'D') {
  4722. if (st == '-')
  4723. *flags &= ~FLAGS_DO_DIRECT_DEVICE;
  4724. else
  4725. *flags |= FLAGS_DO_DIRECT_DEVICE;
  4726. break;
  4727. } else if (nc == 'R') {
  4728. if (st == '-') {
  4729. *flags2 &= ~FLAGS_DO_DRIVER;
  4730. } else {
  4731. *flags2 |= FLAGS_DO_DRIVER;
  4732. *flags |= FLAGS_DO_ALLDEVS;
  4733. if (argc > 1) {
  4734. status = RtlCreateUnicodeStringFromAsciiz (&DriverName, *++argv);
  4735. if (!NT_SUCCESS (status)) {
  4736. printf ("RtlCreateUnicodeStringFromAsciiz failed %x\n", status);
  4737. exit (EXIT_FAILURE);
  4738. }
  4739. argc--;
  4740. } else {
  4741. printf ("Input driver name missing on command line\n");
  4742. }
  4743. }
  4744. break;
  4745. } else if (!nc) {
  4746. if (argc > 1) {
  4747. status = RtlCreateUnicodeStringFromAsciiz (name, *++argv);
  4748. if (!NT_SUCCESS (status)) {
  4749. printf ("RtlCreateUnicodeStringFromAsciiz failed %x\n", status);
  4750. exit (EXIT_FAILURE);
  4751. }
  4752. argc--;
  4753. } else {
  4754. printf ("Input device missing on command line\n");
  4755. }
  4756. }
  4757. break;
  4758. case 'G':
  4759. if (argc > 2) {
  4760. *flags |= FLAGS_DO_GRAB;
  4761. cid = atoi (*++argv);
  4762. process_handle = UlongToHandle( atoi (*++argv) );
  4763. argc -= 2;
  4764. } else {
  4765. printf ("Client ID and handle missing\n");
  4766. }
  4767. break;
  4768. case 'Y' :
  4769. if (st == '-')
  4770. *flags &= ~FLAGS_DO_DISKS;
  4771. else
  4772. *flags |= FLAGS_DO_DISKS;
  4773. break;
  4774. case '?':
  4775. case 'H':
  4776. default :
  4777. *flags |= FLAGS_DO_USAGE;
  4778. break;
  4779. }
  4780. } else {
  4781. status = RtlCreateUnicodeStringFromAsciiz (name, *argv);
  4782. if (!NT_SUCCESS (status)) {
  4783. printf ("RtlCreateUnicodeStringFromAsciiz failed %x\n", status);
  4784. exit (EXIT_FAILURE);
  4785. }
  4786. }
  4787. }
  4788. ioctl_inbuf_max = max (ioctl_inbuf_min, ioctl_inbuf_max);
  4789. ioctl_outbuf_max = max (ioctl_outbuf_min, ioctl_outbuf_max);
  4790. if (prefix_string && (*flags&FLAGS_DO_PRINT_DEVS) == 0) {
  4791. prefix_string = NULL;
  4792. }
  4793. return;
  4794. }
  4795. /*
  4796. Print out usage message
  4797. */
  4798. void
  4799. do_usage (void)
  4800. {
  4801. printf ("devctl [/i] [/l] [/il nn] [/iu mm] [devnam]\n\n");
  4802. printf ("/ and + enable options, - disables options\n\n");
  4803. printf ("/a\tDo all devices in system. Don't prompt for yes/no etc\n");
  4804. printf ("/al\tAlert the main thread periodically\n");
  4805. printf ("/c\tEnable or disable skipping operations that aborted or crashed\n");
  4806. printf ("/dd\tEnable or disable the direct device open paths\n");
  4807. printf ("/dl nn\tSets max for device type portion of IOCTL/FSCTL code, default 0\n");
  4808. printf ("/dr drv\tOnly runs on device objects with driver <drv> in their stack\n");
  4809. printf ("/du nn\tSets min limit for device type portion of IOCTL/FSCTL code, default 200\n");
  4810. printf ("/e\tEnable or disable zero length EA's, needed on checked builds\n");
  4811. printf ("/f\tEnable or disable all FSCTL paths\n");
  4812. printf ("/fi\tEnable or disable turning on failure injection in the driver verifier\n");
  4813. printf ("/fn\tEnable or disable FSCTL paths with null buffers\n");
  4814. printf ("/fr\tEnable or disable FSCTL paths with random buffers\n");
  4815. printf ("/fl nn\tSets max for function portion of IOCTL and FSCTL code, default 0\n");
  4816. printf ("/fu nn\tSets min for function portion of IOCTL and FSCTL code, default 400\n");
  4817. printf ("/g c h\tGrabs a handle from another process\n");
  4818. printf ("/h /?\tPrints this message\n");
  4819. printf ("/i\tEnable or disable all IOCTL paths\n");
  4820. printf ("/if\tEnable or disable all FSCTL and IOCTL paths\n");
  4821. printf ("/in\tEnable or disable IOCTL paths with null buffers\n");
  4822. printf ("/il nnn\tSet lower input buffer size\n");
  4823. printf ("/im\tEnable or disable the impersonation of a non-admin during the test\n");
  4824. printf ("/iu nnn\tSet upper input buffer size\n");
  4825. printf ("/ir\tEnable or disable IOCTL paths with random buffers\n");
  4826. printf ("/j\tEnable or disable relative stream opens for filesystems\n");
  4827. printf ("/k\tEnable or disable synchronous handles\n");
  4828. printf ("/l\tEnable or disable logging and skipping failing functions\n");
  4829. printf ("/m\tEnable or disable the misc functions\n");
  4830. printf ("/n\tMap zero page so that NULL pointer de-references don't raise\n");
  4831. printf ("/oc\tEnable or disable the multithreaded open and close stage\n");
  4832. printf ("/ol nnn\tSet lower output buffer size\n");
  4833. printf ("/ou nnn\tSet upper output buffer size\n");
  4834. printf ("/p\tEnable or disable the checks on pool usage via tags and lookaside lists\n");
  4835. printf ("/pd\tPrint out device objects and symbolic links and exit\n");
  4836. printf ("/pr\tEnable or disable protection change tests\n");
  4837. printf ("/ps sss\tSet prefix string for use with /pd\n");
  4838. printf ("/q\tEnable or disable the normal handle query functions\n");
  4839. printf ("/r\tEnable or disable skipping operations already logged as done\n");
  4840. printf ("/rd\tSelect a random device object or symbolic link for testing\n");
  4841. printf ("/s\tEnable or disable the sub or relative opens to obtain handles\n");
  4842. printf ("/sd\tEnable or disable the query and set security functions\n");
  4843. printf ("/sl\tEnable or disable the opening of symbolic links\n");
  4844. printf ("/se nnn\tSet session id to nnn\n");
  4845. printf ("/t nn\tSet max IOCTL/FSCTL calls made with random buffers, default 100000\n");
  4846. printf ("/tt nn\tSet max tailured calls made for discovered IOCTLs/FSCTLs, default 10000\n");
  4847. printf ("/v\tEnable or disable the printing of error status values for calls\n");
  4848. printf ("/w\tEnable or disable the winsock TransmitFile test\n");
  4849. printf ("/y\tEnable or disable touching disk devices\n");
  4850. printf ("\n");
  4851. printf ("Defaults: devctl -a -al +c +dd +dl 0 -dr +du 200 +e +fn +fr +fl 0 fu 400 +im\n");
  4852. printf (" +il 0 +in +iu 512 +ir -j -k +l +m -n +oc +ol 0 +ou 512 +p -pr\n");
  4853. printf (" +q +s +sd +sl +t 100000 +tt 10000 -v -w +y\n");
  4854. }
  4855. void change_session (ULONG sessionid)
  4856. {
  4857. HANDLE token;
  4858. if (!OpenProcessToken (NtCurrentProcess (), MAXIMUM_ALLOWED, &token)) {
  4859. printf ("OpenProcessToken failed %d\n", GetLastError ());
  4860. return;
  4861. }
  4862. if (SetTokenInformation (token, TokenSessionId, &sessionid, sizeof (sessionid))) {
  4863. printf ("Token session ID changed to %d\n", sessionid);
  4864. } else {
  4865. printf ("SetTokenInformation failed %d\n", GetLastError ());
  4866. }
  4867. if (!CloseHandle (token)) {
  4868. printf ("CloseHandle failed %d\n", GetLastError ());
  4869. return;
  4870. }
  4871. }
  4872. BOOL
  4873. EnableDebugPrivilege (
  4874. )
  4875. {
  4876. struct
  4877. {
  4878. DWORD Count;
  4879. LUID_AND_ATTRIBUTES Privilege [1];
  4880. } Info;
  4881. HANDLE Token;
  4882. BOOL Result;
  4883. //
  4884. // open the process token
  4885. //
  4886. Result = OpenProcessToken (
  4887. GetCurrentProcess (),
  4888. TOKEN_ADJUST_PRIVILEGES,
  4889. & Token);
  4890. if( Result != TRUE )
  4891. {
  4892. return FALSE;
  4893. }
  4894. //
  4895. // prepare the info structure
  4896. //
  4897. Info.Count = 1;
  4898. Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
  4899. Result = LookupPrivilegeValue (
  4900. NULL,
  4901. SE_DEBUG_NAME,
  4902. &(Info.Privilege[0].Luid));
  4903. if( Result != TRUE )
  4904. {
  4905. CloseHandle( Token );
  4906. return FALSE;
  4907. }
  4908. //
  4909. // adjust the privileges
  4910. //
  4911. Result = AdjustTokenPrivileges (
  4912. Token,
  4913. FALSE,
  4914. (PTOKEN_PRIVILEGES) &Info,
  4915. 0,
  4916. NULL,
  4917. NULL);
  4918. if( Result != TRUE || GetLastError() != ERROR_SUCCESS )
  4919. {
  4920. CloseHandle( Token );
  4921. return FALSE;
  4922. }
  4923. CloseHandle( Token );
  4924. return TRUE;
  4925. }
  4926. void
  4927. __cdecl
  4928. main(
  4929. int argc, char **argv
  4930. )
  4931. {
  4932. ULONG seed, i;
  4933. UNICODE_STRING us;
  4934. ULONG id, tmp;
  4935. DWORD old;
  4936. NTSTATUS status;
  4937. UNICODE_STRING name;
  4938. WSADATA wsadata;
  4939. WORD version;
  4940. int istatus;
  4941. SOCKET s;
  4942. struct sockaddr_in sockaddr;
  4943. char nameb[255];
  4944. HOSTENT *host;
  4945. struct in_addr localaddr;
  4946. DWORD retlen;
  4947. int t;
  4948. HANDLE listenthread;
  4949. struct sockaddr_in laddr;
  4950. SIZE_T size;
  4951. PVOID base;
  4952. //
  4953. // Turn off popups for a missing floppy etc
  4954. //
  4955. SetErrorMode(SEM_FAILCRITICALERRORS);
  4956. Create_nonadmin_token ();
  4957. //
  4958. // Create and event for any requests we really need to work on a async handle
  4959. //
  4960. status = NtCreateEvent (&sync_event, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE);
  4961. if (!NT_SUCCESS (status)) {
  4962. printf ("NtCreateEvent failed %x\n", status);
  4963. exit (EXIT_FAILURE);
  4964. }
  4965. status = NtCreateEvent (&CompletionEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE);
  4966. if (!NT_SUCCESS (status)) {
  4967. printf ("NtCreateEvent failed %x\n", status);
  4968. exit (EXIT_FAILURE);
  4969. }
  4970. CompletionPort = CreateIoCompletionPort (INVALID_HANDLE_VALUE, NULL, 0, 0);
  4971. if (CompletionPort == NULL) {
  4972. printf ("CreateIoCompletionPort failed %d\n", GetLastError ());
  4973. exit (EXIT_FAILURE);
  4974. }
  4975. process_parameters (argc, argv, &name, &flags, &flags2);
  4976. if (flags&FLAGS_DO_USAGE) {
  4977. do_usage ();
  4978. exit (EXIT_SUCCESS);
  4979. }
  4980. EnableDebugPrivilege ();
  4981. /*
  4982. Seed RNG
  4983. */
  4984. // printf("Seed? ");
  4985. // scanf("%d", &seed);
  4986. // srand(seed);
  4987. srand ((unsigned) time (NULL));
  4988. //
  4989. // Build a socket etc to handle the TransmitFile API
  4990. //
  4991. do {
  4992. if (!(flags&FLAGS_DO_WINSOCK))
  4993. break;
  4994. if (flags&FLAGS_DO_PRINT_DEVS)
  4995. break;
  4996. version = MAKEWORD (2, 0);
  4997. istatus = WSAStartup (version, &wsadata);
  4998. if (istatus != 0) {
  4999. printf ("Failed to start winsock %x!\n", istatus);
  5000. flags &= ~FLAGS_DO_WINSOCK;
  5001. break;
  5002. }
  5003. istatus = gethostname (nameb, sizeof (nameb));
  5004. if (istatus != 0) {
  5005. printf ("Gethostname failed %d\n", WSAGetLastError ());
  5006. flags &= ~FLAGS_DO_WINSOCK;
  5007. break;
  5008. }
  5009. host = gethostbyname (nameb);
  5010. if (!host) {
  5011. printf ("Gethostbyname failed %d\n", WSAGetLastError ());
  5012. flags &= ~FLAGS_DO_WINSOCK;
  5013. break;
  5014. }
  5015. localaddr = *(struct in_addr *) host->h_addr_list[0];
  5016. ls = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  5017. if (ls == INVALID_SOCKET) {
  5018. printf ("Socket failed %d\n", WSAGetLastError ());
  5019. flags &= ~FLAGS_DO_WINSOCK;
  5020. break;
  5021. }
  5022. memset (&sockaddr, 0, sizeof (sockaddr));
  5023. sockaddr.sin_family = AF_INET;
  5024. sockaddr.sin_port = htons (0);
  5025. sockaddr.sin_addr = localaddr;
  5026. istatus = bind (ls, (struct sockaddr *) &sockaddr, sizeof (sockaddr));
  5027. if (istatus != 0) {
  5028. printf ("Bind failed %d\n", WSAGetLastError ());
  5029. flags &= ~FLAGS_DO_WINSOCK;
  5030. break;
  5031. }
  5032. istatus = listen (ls, 2);
  5033. if (istatus != 0) {
  5034. printf ("Listen failed %d\n", WSAGetLastError ());
  5035. flags &= ~FLAGS_DO_WINSOCK;
  5036. break;
  5037. }
  5038. t = sizeof (laddr);
  5039. istatus = getsockname (ls, (struct sockaddr *) &laddr, &t);
  5040. if (istatus != 0) {
  5041. printf ("Getsockname failed %d\n", WSAGetLastError ());
  5042. flags &= ~FLAGS_DO_WINSOCK;
  5043. break;
  5044. }
  5045. printf ("Listen socket on port %d address %s\n",
  5046. ntohs (laddr.sin_port), inet_ntoa (laddr.sin_addr));
  5047. listenthread = CreateThread (NULL, 0, do_listen, NULL, 0, &id);
  5048. if (!listenthread) {
  5049. printf ("CreateThread failed %d\n", GetLastError ());
  5050. flags &= ~FLAGS_DO_WINSOCK;
  5051. break;
  5052. }
  5053. cs = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  5054. if (cs == INVALID_SOCKET) {
  5055. printf ("Socket failed %d\n", WSAGetLastError ());
  5056. flags &= ~FLAGS_DO_WINSOCK;
  5057. break;
  5058. }
  5059. istatus = connect (cs, (struct sockaddr *) &laddr, sizeof (laddr));
  5060. if (istatus != 0) {
  5061. printf ("connect failed %d\n", WSAGetLastError ());
  5062. flags &= ~FLAGS_DO_WINSOCK;
  5063. break;
  5064. }
  5065. } while (FALSE);
  5066. //
  5067. // Build a big buffer to pass to requests
  5068. //
  5069. bigbuf = VirtualAlloc(NULL, BIGBUF_SIZE + SLOP, MEM_COMMIT, PAGE_READWRITE);
  5070. if (!bigbuf) {
  5071. printf ("Failed to allocate I/O buffers %x\n", GetLastError ());
  5072. exit (EXIT_FAILURE);
  5073. }
  5074. //
  5075. // Map the zero page and fill it with junk
  5076. //
  5077. if (flags&FLAGS_DO_MAPNULL) {
  5078. base = (PVOID) 1;
  5079. size = 1;
  5080. status = NtAllocateVirtualMemory (NtCurrentProcess (), &base, 1, &size,
  5081. MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
  5082. if (!NT_SUCCESS (status)) {
  5083. printf ("NtAllocateVirtualMemory for zero page failed %x\n", status);
  5084. exit (EXIT_FAILURE);
  5085. }
  5086. for (i = 0; i < size; i++) {
  5087. *((PUCHAR) base + i) = (UCHAR) rand ();
  5088. }
  5089. }
  5090. // randthread = CreateThread (NULL, 0, randomize, bigbuf, CREATE_SUSPENDED, &id);
  5091. // if (!randthread) {
  5092. // printf ("Failed to create radomizing thread %x\n", GetLastError ());
  5093. // exit (EXIT_FAILURE);
  5094. // }
  5095. //
  5096. // Create a thread to change the page protection of our buffer if need be
  5097. //
  5098. if (flags&FLAGS_DO_PROT) {
  5099. changethread = CreateThread (NULL, 0, changeprot, bigbuf, CREATE_SUSPENDED, &id);
  5100. if (!changethread) {
  5101. printf ("Failed to create protection change thread %x\n", GetLastError ());
  5102. exit (EXIT_FAILURE);
  5103. }
  5104. }
  5105. //
  5106. // Get a real handle to our thread to pass to other threads
  5107. //
  5108. status = NtDuplicateObject (NtCurrentProcess (), NtCurrentThread (),
  5109. NtCurrentProcess (), &mainthread,
  5110. 0, 0, DUPLICATE_SAME_ACCESS);
  5111. if (!NT_SUCCESS (status)) {
  5112. printf ("NtDuplcateObject failed %x\n", status);
  5113. exit (EXIT_FAILURE);
  5114. }
  5115. //
  5116. // Create a thread to alert this one periodicaly or when it thinks we are stuck
  5117. //
  5118. alertthread = CreateThread (NULL, 0, alerter, mainthread, 0, &id);
  5119. if (!alertthread) {
  5120. printf ("Failed to create alerting thread %x\n", GetLastError ());
  5121. exit (EXIT_FAILURE);
  5122. }
  5123. // status = NtSuspendThread (changethread, &tmp);
  5124. // if (!NT_SUCCESS (status)) {
  5125. // printf ("NtSuspendThread failed %x\n", status);
  5126. // }
  5127. // status = NtSuspendThread (randthread, &tmp);
  5128. // if (!NT_SUCCESS (status)) {
  5129. // printf ("NtSuspendThread failed %x\n", status);
  5130. // }
  5131. if (!VirtualProtect (bigbuf, 1, PAGE_READWRITE, &old)) {
  5132. printf ("VirtualProtect failed %d\n", GetLastError ());
  5133. }
  5134. devscount = 0;
  5135. print_diags (0, 0);
  5136. if (flags&FLAGS_DO_GRAB) {
  5137. do_handle_grab (devmap,
  5138. &devscount);
  5139. }
  5140. /*
  5141. * Crash the system.
  5142. */
  5143. if (name.Length > 0) {
  5144. if (flags&FLAGS_DO_IMPERSONATION) {
  5145. Impersonate_nonadmin ();
  5146. }
  5147. status = do_device_opens (NULL,
  5148. &name,
  5149. devmap,
  5150. &devscount,
  5151. name.Buffer,
  5152. name.Buffer);
  5153. if (flags&FLAGS_DO_IMPERSONATION) {
  5154. if (!Revert_from_admin ()) {
  5155. printf ("Revert_from_admin failed %d\n", GetLastError ());
  5156. exit (EXIT_FAILURE);
  5157. }
  5158. }
  5159. } else {
  5160. do_wmi ();
  5161. random_device = (rand () % 1345) + 1;
  5162. while (1) {
  5163. RtlInitUnicodeString(&us,
  5164. L"\\");
  5165. skipped = 0;
  5166. recurse(0,
  5167. &us,
  5168. devmap,
  5169. &devscount,
  5170. L"",
  5171. 1);
  5172. for (i = 0; i < devscount; i++) {
  5173. free (devmap[i].name);
  5174. devmap[i].name = NULL;
  5175. free (devmap[i].filename);
  5176. devmap[i].filename = NULL;
  5177. NtClose(devmap[i].handle);
  5178. }
  5179. devscount = 0;
  5180. if (flags&(FLAGS_DO_ALLDEVS|FLAGS_DO_PRINT_DEVS)) {
  5181. break;
  5182. }
  5183. if ((flags&FLAGS_DO_RANDOM_DEVICE) && (random_device == 0)) {
  5184. Sleep (30*1000);
  5185. random_device = (rand () % 1345) + 1;
  5186. }
  5187. }
  5188. }
  5189. if ((flags&FLAGS_DO_PRINT_DEVS) == 0) {
  5190. crashes (L"DONE", L"", L"", L"", L"");
  5191. }
  5192. exit(EXIT_SUCCESS);
  5193. }