Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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