iphook.cpp
上传用户:ykzxjx
上传日期:2022-04-03
资源大小:1175k
文件大小:13k
开发平台:

Visual C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright 1999 - 2000 Mark Roddy
  4. // All Rights Reserved
  5. //
  6. // Hollis Technology Solutions
  7. // 94 Dow Road
  8. // Hollis, NH 03049
  9. // info@hollistech.com
  10. //
  11. // Synopsis: 
  12. // 
  13. //
  14. // Version Information:
  15. //
  16. // $Header: /iphook/sys/driver/iphook.cpp 4     1/27/00 10:35p Markr $ 
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. #include "iphookKrnl.h"
  20. HTS_DEBUG_THIS_FILE
  21. //
  22. // local functions
  23. //
  24. NTSTATUS
  25. IpfStartHooking(PVOID context);
  26. NTSTATUS 
  27. IpfStopHooking(PVOID context);
  28. IP_HOOK_GLOBAL_DATA ipGlobal;
  29. CPP_DRIVER_ENTRY(PDRIVER_OBJECT DriverObject,
  30.                  PUNICODE_STRING RegistryPath)
  31. {
  32. NTSTATUS Status = STATUS_SUCCESS;
  33. //
  34. // setup our standard entry points
  35. //
  36. DriverObject->MajorFunction[IRP_MJ_CREATE]         = IpHookCreate;
  37.     DriverObject->MajorFunction[IRP_MJ_CLOSE]          = IpHookClose;
  38.     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IpHookDeviceControl;
  39. DriverObject->DriverUnload = IpHookUnload;
  40. //
  41. // before we get too deeply involved in this mess, lets see if the
  42. // ipfilter driver is actually installed.
  43. //
  44. Status = ipGlobal.initDevice();
  45. if (!NT_SUCCESS(Status)) {
  46. HtsDebugPrint(HTS_DEBUG_HIGH, "initDevice failed error %xn", Status);
  47. return Status;
  48. }
  49. Status = ipGlobal.createThread();
  50. if (!NT_SUCCESS(Status)) {
  51. HtsDebugPrint(HTS_DEBUG_HIGH, "createThread failed error %xn", Status);
  52. return Status;
  53. }  
  54. //
  55. // create a device object that applications can open to control the ip hook driver.
  56. //
  57. UNICODE_STRING deviceName;
  58. RtlInitUnicodeString(&deviceName, IPHOOK_DEV_NAME);
  59. PDEVICE_OBJECT ourDevice = NULL;
  60. Status = IoCreateDevice(
  61. DriverObject,
  62. 0,
  63. &deviceName,
  64. IPHOOK_DEVICE_TYPE,
  65. 0,
  66. FALSE, // well perhaps this should be true.
  67. &ourDevice);  
  68. if (!NT_SUCCESS(Status)) {
  69. //
  70. // oh well, what can we do?
  71. //
  72. HtsDebugPrint(HTS_DEBUG_HIGH, "IoCreateDevice failed status %xn", Status);
  73. return Status;
  74. }
  75. UNICODE_STRING SymbolicLinkName;
  76. RtlInitUnicodeString(&SymbolicLinkName, IPHOOK_USER_DEV_NAME);
  77. //
  78. // create a symbolic link that exposes our device object to user space.
  79. //
  80. Status = IoCreateSymbolicLink(
  81. &SymbolicLinkName,
  82. &deviceName);
  83. if (!NT_SUCCESS(Status)) {
  84. //
  85. // we have to delete the device object here
  86. //
  87. IoDeleteDevice(ourDevice);
  88. HtsDebugPrint(HTS_DEBUG_HIGH, "IoCreateSymbolicLink failed status %xn", Status);
  89. }
  90. return Status;
  91. }
  92. void
  93. IpHookUnload(PDRIVER_OBJECT DriverObject)
  94. {
  95. HtsDebugPrint(HTS_DEBUG_LOW, "IpHookUnloadn");
  96. //
  97. HtsAssert(!ipGlobal.owned()); 
  98. //
  99. // delete our symbolic link
  100. //
  101. UNICODE_STRING SymbolicLinkName;
  102. RtlInitUnicodeString(&SymbolicLinkName, IPHOOK_USER_DEV_NAME);
  103. (void) IoDeleteSymbolicLink( &SymbolicLinkName );
  104. //
  105. // delete our device object(s)
  106. //
  107. while (DriverObject->DeviceObject) {
  108. IoDeleteDevice(DriverObject->DeviceObject);
  109. }
  110. }
  111. //
  112. // Create
  113. //
  114. // If we are going to support a read data interface then
  115. // we need to do something here to track operations.
  116. //
  117. //
  118. NTSTATUS 
  119. IpHookCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
  120. {
  121. HtsDebugPrint(HTS_DEBUG_LOW, "IpHookCreaten");
  122. return STATUS_SUCCESS;
  123. }
  124. //
  125. // Close
  126. //
  127. // If we are going to support a read data interface then
  128. // we need to do something here to track operations.
  129. //
  130. // On last close terminate hooking if active.
  131. //
  132. NTSTATUS 
  133. IpHookClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
  134. {
  135. PVOID context = IoGetCurrentIrpStackLocation(Irp)->FileObject;
  136. HtsDebugPrint(HTS_DEBUG_LOW, "IpHookClose context %xn", context);
  137. //
  138. // ok lets see if the caller owned the interface and do an implicit release if he did.
  139. //
  140. if (ipGlobal.IsOwner(context)) {
  141. //
  142. // bingo!
  143. //
  144. (void) IpfStopHooking(context);
  145. }
  146. return STATUS_SUCCESS;
  147. }
  148. //
  149. // DeviceControl
  150. //
  151. // Provide an interface to start Ip Hooking, stop Ip Hooking.
  152. //
  153. NTSTATUS 
  154. IpHookDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
  155. {
  156. HtsDebugPrint(HTS_DEBUG_LOW, "IpHookDeviceControln");
  157. //
  158. // get our stack location so we can decode this fellow
  159. //
  160. PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
  161. //
  162. // get the control code.
  163. //
  164. ULONG controlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
  165. NTSTATUS Status = STATUS_SUCCESS;
  166. switch (controlCode) {
  167. case START_IP_HOOK:
  168. Status = IpfStartHooking(IoStack->FileObject);
  169. break;
  170. case STOP_IP_HOOK:
  171. Status = IpfStopHooking(IoStack->FileObject);
  172. break;
  173. case HOOK_THIS:
  174. //
  175. // see if we are hooking,
  176. // a stronger test would be to see
  177. // if this caller owns the interface
  178. // as in 
  179. // ipGlobal.IsOwner(IoStack->FileObject);
  180. //
  181. if ( !ipGlobal.owned() ) {
  182. //
  183. // bag it
  184. //
  185. Status = STATUS_UNSUCCESSFUL;
  186. break;
  187. }
  188. {
  189. //
  190. // make sure the buffer makes sense, we will not
  191. // revalidate later.
  192. //
  193. PIPHOOK_BUFFER buffer = (PIPHOOK_BUFFER) MmGetSystemAddressForMdl(Irp->MdlAddress);
  194. if (!validIpHookBuffer(buffer)) {
  195. HtsDebugPrint(HTS_DEBUG_LOW, "Invalid Buffer Tagn");
  196. return HtsIrpReturn(Irp, STATUS_DATA_ERROR);
  197. }
  198. ULONG size = sizeof(IPHOOK_BUFFER) + 
  199. ((buffer->entries - 1) * sizeof(IPHOOK_DATA));
  200. if (size > IoStack->Parameters.DeviceIoControl.OutputBufferLength) {
  201. HtsDebugPrint(HTS_DEBUG_LOW, "Invalid buffer lengthn");
  202. return HtsIrpReturn(Irp, STATUS_INFO_LENGTH_MISMATCH);
  203. }
  204. }
  205. IoMarkIrpPending(Irp);
  206. ipGlobal.queueRequest(Irp);
  207. return STATUS_PENDING;
  208. default:
  209. HtsDebugPrint(HTS_DEBUG_HIGH, "Unexpected control code %xn", controlCode);
  210. //
  211. // we don't understand this so get rid of it.
  212. //
  213. Status = STATUS_INVALID_DEVICE_REQUEST;
  214. break;
  215. }
  216. return HtsIrpReturn(Irp, Status);
  217. }
  218. //
  219. // the hooker herself!
  220. //
  221. PF_FORWARD_ACTION 
  222. IpHookFilter(IN unsigned char *PacketHeader,
  223.  IN unsigned char *Packet, 
  224.  IN unsigned int PacketLength, 
  225.  IN unsigned int RecvInterfaceIndex, 
  226.  IN unsigned int SendInterfaceIndex, 
  227.  IN IPAddr RecvLinkNextHop, 
  228.  IN IPAddr SendLinkNextHop)
  229. {
  230. PF_FORWARD_ACTION action = PF_PASS;
  231. __try {
  232. //
  233. // is this interface single threaded or multi threaded?
  234. //
  235. ULONG sequence = ipGlobal.getSequence();
  236. HtsDebugPrint(HTS_DEBUG_LOW, "IpHookFilter PacketHeader %x Packet %x PacketLength %xn",
  237.   PacketHeader, Packet, PacketLength);
  238. UCHAR header0 = *PacketHeader; //see what this is
  239. //
  240. // if iph_verlen & 0xf0 != 0x40 we have 
  241. // something other than an IPV4 packet.
  242. //
  243. // if iph_verlen & 0xf0 != 0x60 then not
  244. // only is this not an IPV4 packet, but it 
  245. // isn't an IPV6 packet either.
  246. //
  247. if ((header0 & 0xf0) == 0x40) {
  248. PIPHOOK_DATA iphookdata = ipGlobal.getBuffer();
  249. //
  250. // ok its IPv4 or reasonably close!
  251. //
  252. if (iphookdata) {
  253. ULARGE_INTEGER ticks;
  254. KeQueryTickCount((PLARGE_INTEGER)&ticks);
  255. iphookdata->tag = IPHOOK_DATA_TAG;
  256.   
  257. iphookdata->sequence = sequence; // ? see above ?
  258. iphookdata->header = *(IPHeader *) PacketHeader;
  259. iphookdata->timestamp = ticks.QuadPart;
  260. iphookdata->dataLength = PacketLength;
  261. if (RecvInterfaceIndex != INVALID_PF_IF_INDEX ) {
  262. iphookdata->direction = 0;
  263. iphookdata->nextHop = RecvLinkNextHop;
  264. iphookdata->ifIndex = RecvInterfaceIndex;
  265. } else {
  266. iphookdata->direction = 1;
  267. iphookdata->nextHop = SendLinkNextHop;
  268. iphookdata->ifIndex = SendInterfaceIndex;
  269. }
  270. } else {
  271. HtsDebugPrint(HTS_DEBUG_LOW, "IpHookFilter: no buffern");
  272. }
  273. }
  274. }
  275. __except(HTS_EXCEPTION_FILTER ) {
  276. //
  277. // cross your fingers and keep going
  278. //
  279. HtsDebugPrint(HTS_DEBUG_HIGH, "IpHookFilter continuing from exception");
  280. }
  281. return action;
  282. }
  283. NTSTATUS
  284. IpfStartHooking(PVOID context)
  285. {
  286. HtsDebugPrint(HTS_DEBUG_LOW, "IpfStartHooking context %x owner %xn",
  287.   PsGetCurrentThread(),
  288.   ipGlobal.owner());
  289. if (FALSE == ipGlobal.setOwner(context)) {
  290. //
  291. // some other thread owns the interface,
  292. // bail out
  293. //
  294. HtsDebugPrint(HTS_DEBUG_LOW, "In Usen");
  295. return STATUS_CONNECTION_IN_USE; 
  296. //
  297. // we own the interface! now try to start it up
  298. //
  299. PF_SET_EXTENSION_HOOK_INFO extensionHook = { IpHookFilter, };
  300. KEVENT event;
  301. KeInitializeEvent(&event, NotificationEvent, FALSE);
  302. IO_STATUS_BLOCK IoStatus;
  303. PIRP Irp = 
  304. IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER,
  305.   ipGlobal.getIpDevice(),
  306.   (PVOID) &extensionHook,
  307.   sizeof(PF_SET_EXTENSION_HOOK_INFO),
  308.   NULL,
  309.   0,
  310.   FALSE,
  311.   &event,
  312.   &IoStatus);
  313. if (!Irp) {
  314. //
  315. // we need to free up the interface!
  316. //
  317. HtsDebugPrint(HTS_DEBUG_HIGH, "IoBuildDeviceIoControlRequest no IRP!n");
  318. ipGlobal.freeOwner(context);
  319. return STATUS_INSUFFICIENT_RESOURCES;
  320. }
  321. //
  322. // ok now send our IRP to the filter driver
  323. //
  324. NTSTATUS Status = IoCallDriver(ipGlobal.getIpDevice(), Irp);
  325. if (Status == STATUS_PENDING) {
  326. NTSTATUS WaitStatus = KeWaitForSingleObject(&event, UserRequest, KernelMode, FALSE, NULL);
  327. if (WaitStatus  != STATUS_SUCCESS ) {
  328. //
  329. // bummer!
  330. //
  331. HtsDebugPrint(HTS_DEBUG_HIGH, "KeWaitForSingleObject failed status %xn", WaitStatus);
  332. //
  333. // we need to free up the interface!
  334. //
  335. ipGlobal.freeOwner(context);
  336. return WaitStatus;
  337. }
  338. }
  339. Status = IoStatus.Status;
  340. if (!NT_SUCCESS(Status)) {
  341. //
  342. // we need to free up the interface!
  343. //
  344. ipGlobal.freeOwner(context);
  345. }
  346. HtsDebugPrint(HTS_DEBUG_LOW, "IpfStartHooking returns %xn", Status);
  347. return Status;
  348. }
  349. //
  350. // NB failure modes here other than the caller isn't the owning thread are
  351. // truly bogus. Only a cursory attempt is made to deal with them. Basically the 
  352. // strategy is to propogate the failure back to the caller but leave the 
  353. // filter interface in place.
  354. //
  355. NTSTATUS
  356. IpfStopHooking(PVOID context)
  357. {
  358. HtsDebugPrint(HTS_DEBUG_LOW, "IpfStopHooking context %x owner %xn",
  359.   context,
  360.   ipGlobal.owner());
  361. //
  362. // see if this is even legitimate
  363. //
  364. if (ipGlobal.IsOwner(context) == FALSE) {
  365. return STATUS_INVALID_OWNER;
  366. }
  367. //
  368. // ok so it is us, and we is the thread, so we can only be here ONCE
  369. // so we are already serialized, so everything is groovey. Except other
  370. // threads could open the hook device after we release ownership,
  371. // and new reads could arrive (but not on this thread.)
  372. //
  373. //
  374. // we own the interface! now try to start it up
  375. //
  376. PF_SET_EXTENSION_HOOK_INFO extensionHook = { (PacketFilterExtensionPtr) NULL, };
  377. KEVENT event;
  378. KeInitializeEvent(&event, NotificationEvent, FALSE);
  379. IO_STATUS_BLOCK IoStatus;
  380. PIRP Irp = 
  381. IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER,
  382.   ipGlobal.getIpDevice(),
  383.   (PVOID) &extensionHook,
  384.   sizeof(PF_SET_EXTENSION_HOOK_INFO),
  385.   NULL,
  386.   0,
  387.   FALSE,
  388.   &event,
  389.   &IoStatus);
  390. if (!Irp) {
  391. HtsDebugPrint(HTS_DEBUG_HIGH,  "IoBuildDeviceIoControlRequest No IRPn");
  392. return STATUS_INSUFFICIENT_RESOURCES;
  393. }
  394. //
  395. // ok now send our IRP to the filter driver
  396. //
  397. NTSTATUS Status = IoCallDriver(ipGlobal.getIpDevice(), Irp);
  398. if (Status == STATUS_PENDING) {
  399. NTSTATUS WaitStatus = KeWaitForSingleObject(&event, UserRequest, KernelMode, FALSE, NULL);
  400. if (WaitStatus  != STATUS_SUCCESS ) {
  401. HtsDebugPrint(HTS_DEBUG_HIGH, "KeWaitForSingleObject failed status %xn", WaitStatus);
  402. //
  403. // bummer!
  404. //
  405. return WaitStatus;
  406. }
  407. }
  408. Status = IoStatus.Status;
  409. if (NT_SUCCESS(Status)) {
  410. //
  411. // we need to free up the interface!
  412. //
  413. ipGlobal.freeOwner(context);
  414. }
  415. HtsDebugPrint(HTS_DEBUG_LOW, "IpfStopHooking return %xn", Status);
  416. return Status;
  417. }
  418. //
  419. // IP_HOOK_GLOBAL_DATA and associates, LLC
  420. //
  421. VOID
  422. GlobalCancel(
  423.     IN PDEVICE_OBJECT DeviceObject,
  424.     IN PIRP Irp
  425.     )
  426. {
  427. KIRQL irql = Irp->CancelIrql;
  428. IoReleaseCancelSpinLock(irql);
  429. PVOID context;
  430. ipGlobal.lock(context);
  431. //
  432. // this irp is in our queue
  433. //
  434. RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
  435. HtsIrpReturn(Irp, STATUS_CANCELLED);
  436. ipGlobal.unlock(context);
  437. }
  438. ///////////////////////////////////////////////////////////////////////////////
  439. // 
  440. // Change History Log
  441. //
  442. // $Log: /iphook/sys/driver/iphook.cpp $
  443. // 
  444. // 4     1/27/00 10:35p Markr
  445. // Prepare to release!
  446. //
  447. ///////////////////////////////////////////////////////////////////////////////