c - How to inject packets into Receive (Rx) path using LWF driver on Windows? -
i developing ndis 6 light-weight filter (lwf) driver based on winpcap. can imagine there're 2 paths network adapter: tx
, rx
.
tx
sending way.
rx
receiving way.
we know winpcap able send packets network (so tx
way). want know if it's possible send packets rx
, means injecting packet adapter , pretending packet arrival packet network.
first don't know if viable? if yes, continue read:
i have written code, using ndisfindicatereceivenetbufferlists
call indicate crafted packet upper layer, free packet in filterreturnnetbufferlists
handler. upper layer modules including windows os know there's new packet coming network (actually not truth).
however, approach doesn't work. used nping
(from nmap) ping gateway, , nping window freezes, can't terminated task manager. must driver halt.
i noticed way should possible based on:
jeffery's answer post: is filtersendnetbufferlists handler must ndis filter use ndisfsendnetbufferlists?
an exaplanation microsoft: https://msdn.microsoft.com/en-us/library/windows/hardware/ff570452(v=vs.85).aspx
an example provided osr: https://www.osronline.com/showthread.cfm?link=242847
then analyzed log printed driver. seems ndisfindicatereceivenetbufferlists
call (used sending rx
) called once, driver works on other jobs, while ring 3 nping
died. reused of code existing well-running code npf_sendcompleteex
(this handler of send complete normal tx
). don't think part have bugs?
the whole code base hosted on github: https://github.com/nmap/npcap
it doesn't contain faulty code in post, haven't submit it, provide backgrounds if need:)
my injecting code:
ntstatus npf_write( in pdevice_object deviceobject, in pirp irp ) { popen_instance open; popen_instance groupopen; popen_instance tempopen; pio_stack_location irpsp; ulong sendflags = 0; pnet_buffer_list pnetbufferlist; ndis_status status; ulong numsends; ulong numsentpackets; trace_enter(); irpsp = iogetcurrentirpstacklocation(irp); open = irpsp->fileobject->fscontext; if (npf_startusingopeninstance(open) == false) { // // irp_mj_cleanup received, fail request // irp->iostatus.information = 0; irp->iostatus.status = status_cancelled; iocompleterequest(irp, io_no_increment); trace_exit(); return status_cancelled; } numsends = open->nwrites; // // validate send parameters set ioctl // if (numsends == 0) { npf_stopusingopeninstance(open); irp->iostatus.information = 0; irp->iostatus.status = status_success; iocompleterequest(irp, io_no_increment); trace_exit(); return status_success; } // // validate input parameters: // 1. packet size should greater 0, // 2. less-equal max frame size link layer , // 3. maximum frame size of link layer should not zero. // if (irpsp->parameters.write.length == 0 || // check buffer provided user not empty open->maxframesize == 0 || // check maxframesize correctly initialized irp->mdladdress == null || irpsp->parameters.write.length > open->maxframesize) // check fame size smaller mtu { trace_message(packet_debug_loud, "frame size out of range, or maxframesize = 0. send aborted"); npf_stopusingopeninstance(open); irp->iostatus.information = 0; irp->iostatus.status = status_unsuccessful; iocompleterequest(irp, io_no_increment); trace_exit(); return status_unsuccessful; } // // increment ref counter of binding handle, if possible // if (npf_startusingbinding(open) == false) { trace_message(packet_debug_loud, "adapter unbinding, cannot send packets"); npf_stopusingopeninstance(open); irp->iostatus.information = 0; irp->iostatus.status = status_invalid_device_request; iocompleterequest(irp, io_no_increment); trace_exit(); return status_invalid_device_request; } ndisacquirespinlock(&open->writelock); if (open->writeinprogress) { // write operation in progress ndisreleasespinlock(&open->writelock); npf_stopusingbinding(open); trace_message(packet_debug_loud, "another send operation in progress, aborting."); npf_stopusingopeninstance(open); irp->iostatus.information = 0; irp->iostatus.status = status_unsuccessful; iocompleterequest(irp, io_no_increment); trace_exit(); return status_unsuccessful; } else { open->writeinprogress = true; ndisresetevent(&open->ndiswritecompleteevent); } ndisreleasespinlock(&open->writelock); trace_message2(packet_debug_loud, "max frame size = %u, packet size = %u", open->maxframesize, irpsp->parameters.write.length); // // reset number of packets pending sendcomplete // open->transmitpendingpackets = 0; ndisresetevent(&open->writeevent); numsentpackets = 0; while (numsentpackets < numsends) { pnetbufferlist = ndisallocatenetbufferandnetbufferlist(open->packetpool, 0, 0, irp->mdladdress, 0, irp->mdladdress->bytecount); if (pnetbufferlist != null) { // // packet available, prepare , send ndissend. // // // if asked, set flags packet. // currently, situation in set flags disable reception of loopback // packets, i.e. of packets sent us. // //if (open->skipsentpackets) //{ // npfsetnblflags(pnetbufferlist, g_sendpacketflags); //} // packet hasn't buffer needs not freed after every single write reserved(pnetbufferlist)->freebufafterwrite = false; // save irp associated packet // reserved(ppacket)->irp=irp; // attach writes buffer packet interlockedincrement(&open->transmitpendingpackets); ndisresetevent(&open->ndiswritecompleteevent); //receive packets before sending them assert(open->grouphead != null); if (open->grouphead != null) { groupopen = open->grouphead->groupnext; } else { //this impossible groupopen = open->groupnext; } #ifdef have_wfp_loopback_support // not capture send traffic send, if our loopback adapter. if (open->loopback == false) { #endif while (groupopen != null) { tempopen = groupopen; if (tempopen->adapterbindingstatus == adapter_bound && tempopen->skipsentpackets == false) { npf_tapexforeachopen(tempopen, pnetbufferlist); } groupopen = tempopen->groupnext; } #ifdef have_wfp_loopback_support } #endif pnetbufferlist->sourcehandle = open->adapterhandle; npfsetnblchildopen(pnetbufferlist, open); //save child open object in packets //sendflags |= ndis_send_flags_check_for_loopback; // recognize ieee802.1q tagged packet, no many adapters support vlan tag packet sending, no use end users, // , code examines data lacks efficiency, left commented, sending part unfinished. // code refers win10pcap @ https://github.com/softethervpn/win10pcap. // if (open->loopback == false) // { // puchar pheaderbuffer; // uint ifres; // // boolean withvlantag = false; // uint vlanid = 0; // uint vlanuserpriority = 0; // uint vlancanformatid = 0; // // ndisquerymdl( // irp->mdladdress, // &pheaderbuffer, // &ifres, // normalpagepriority); // // // determine if packet ieee802.1q tagged packet. // if (ifres >= 18) // { // if (pheaderbuffer[12] == 0x81 && pheaderbuffer[13] == 0x00) // { // ushort ptmpvlantag = 0; // // ((uchar *)(&ptmpvlantag))[0] = pheaderbuffer[15]; // ((uchar *)(&ptmpvlantag))[1] = pheaderbuffer[14]; // // vlanid = ptmpvlantag & 0x0fff; // vlanuserpriority = (ptmpvlantag >> 13) & 0x07; // vlancanformatid = (ptmpvlantag >> 12) & 0x01; // // if (vlanid != 0) // { // withvlantag = true; // } // } // } // } // // call mac // #ifdef have_wfp_loopback_support if (open->loopback == true) { npf_loopbacksendnetbufferlists(open->grouphead, pnetbufferlist); } else #endif #ifdef have_send_to_receive_path_support if (open->sendtorxpath == true) { if_loud(dbgprint("hahahahahahahahahahahaha:: sendtorxpath, open->adapterhandle=%p, pnetbufferlist=%u\n", open->adapterhandle, pnetbufferlist);) // pretend receive these packets network , indicate them upper layers ndisfindicatereceivenetbufferlists( open->adapterhandle, pnetbufferlist, ndis_default_port_number, 1, 0); } else #endif { ndisfsendnetbufferlists(open->adapterhandle, pnetbufferlist, ndis_default_port_number, sendflags); } numsentpackets ++; } else { // // no packets available in transmit pool, wait time. // event gets signalled when @ least half of tx packet pool packets // available // ndiswaitevent(&open->writeevent, 1); } } // // when reach point, packets have been enqueued ndissend, // need wait packets completed sendcomplete // (if of ndissend requests returned status_pending) // ndiswaitevent(&open->ndiswritecompleteevent, 0); // // packets have been transmitted, release use of adapter binding // npf_stopusingbinding(open); // // no more writes in progress // ndisacquirespinlock(&open->writelock); open->writeinprogress = false; ndisreleasespinlock(&open->writelock); npf_stopusingopeninstance(open); // // complete irp , return success // irp->iostatus.status = status_success; irp->iostatus.information = irpsp->parameters.write.length; iocompleterequest(irp, io_no_increment); trace_exit(); return status_success; }
my filterreturnnetbufferlists handler:
_use_decl_annotations_ void npf_returnex( ndis_handle filtermodulecontext, pnet_buffer_list netbufferlists, ulong returnflags ) /*++ routine description: filterreturnnetbufferlists handler. filterreturnnetbufferlists optional function. if provided, ndis calls filterreturnnetbufferlists return ownership of 1 or more netbufferlists , embedded netbuffers filter driver. if handler null, ndis skip calling filter when returning netbufferlists underlying miniport , call next lower driver in stack. filter doesn't provide filterreturnnetbufferlists handler cannot originate receive indication on own. arguments: filterinstancecontext - our filter context area netbufferlists - linked list of netbufferlists filter driver indicated in previous call ndisfindicatereceivenetbufferlists returnflags - flags specifying if caller @ dispatch_level --*/ { popen_instance childopen; popen_instance groupopen; popen_instance tempopen; boolean freebufafterwrite; pnet_buffer_list pnetbuflist; pnet_buffer_list pnextnetbuflist; pnet_buffer currbuff; pmdl pmdl; popen_instance open = (popen_instance) filtermodulecontext; trace_enter(); #ifdef have_send_to_receive_path_support pnetbuflist = netbufferlists; while (pnetbuflist != null) { pnextnetbuflist = net_buffer_list_next_nbl(pnetbuflist); net_buffer_list_next_nbl(pnetbuflist) = null; if (pnetbuflist->sourcehandle == open->adapterhandle) //this our self-sent packets { trace_message(packet_debug_loud, "hahahaha own send rx packets"); childopen = npfgetnblchildopen(pnetbuflist); //get child open object sends these packets freebufafterwrite = reserved(pnetbuflist)->freebufafterwrite; if (freebufafterwrite) { // // packet sent npf_bufferedwrite() // //free nbl allocate myself currbuff = net_buffer_list_first_nb(pnetbuflist); while (currbuff) { pmdl = net_buffer_first_mdl(currbuff); ndisfreemdl(pmdl); //free mdl currbuff = net_buffer_next_nb(currbuff); } ndisfreenetbufferlist(pnetbuflist); //free nbl } else { // // packet sent npf_write() // //free nbl allocate myself ndisfreenetbufferlist(pnetbuflist); //free nbl } // if should false, open grouphead itself, grouphead known ndis , invoked in npf_sendcompleteex() function. if (open->grouphead != null) { groupopen = open->grouphead->groupnext; } else { groupopen = open->groupnext; } //groupopen = open->groupnext; while (groupopen != null) { tempopen = groupopen; if (childopen == tempopen) //only indicate specific child open object { npf_sendcompleteexforeachopen(tempopen, freebufafterwrite); break; } groupopen = tempopen->groupnext; } } else { trace_message(packet_debug_loud, "hahahaha not own send rx packets"); // return received nbls. if removed nbls chain, make // sure chain isn't empty (i.e., netbufferlists!=null). ndisfreturnnetbufferlists(open->adapterhandle, pnetbuflist, returnflags); } pnetbuflist = pnextnetbuflist; } #else // return received nbls. if removed nbls chain, make // sure chain isn't empty (i.e., netbufferlists!=null). ndisfreturnnetbufferlists(open->adapterhandle, netbufferlists, returnflags); #endif trace_exit(); }
my log:
00010269 58.36443710 mdl 42 00010270 58.36444092 hahahahahahahahahahahaha:: sendtorxpath, open->adapterhandle=fffffa8003c24010, pnetbufferlist=68928096 00010271 58.36450577 --> npf_returnex 00010272 58.36450577 npf_returnex: hahahaha own send rx packets 00010273 58.36451340 <-- npf_returnex 00010274 59.04499054 --> npf_networkclassify 00010275 59.04499817 --> npf_ispacketselfsent 00010276 59.04499817 <-- npf_ispacketselfsent 00010277 59.04499817 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010278 59.04500961 <-- npf_networkclassify 00010279 59.04502869 --> npf_sendex 00010280 59.04503632 --> npf_sendcompleteex 00010281 59.04504395 <-- npf_sendcompleteex 00010282 59.04504395 <-- npf_sendex 00010283 59.04520798 --> npf_networkclassify 00010284 59.04520798 --> npf_ispacketselfsent 00010285 59.04521561 <-- npf_ispacketselfsent 00010286 59.04521561 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010287 59.04522324 <-- npf_networkclassify 00010288 59.04529953 --> npf_sendex 00010289 59.04529953 --> npf_sendcompleteex 00010290 59.04530716 <-- npf_sendcompleteex 00010291 59.04530716 <-- npf_sendex 00010292 59.04531097 --> npf_networkclassify 00010293 59.04531097 --> npf_ispacketselfsent 00010294 59.04531097 <-- npf_ispacketselfsent 00010295 59.04531860 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010296 59.04531860 <-- npf_networkclassify 00010297 59.04541397 --> npf_networkclassify 00010298 59.04541397 --> npf_ispacketselfsent 00010299 59.04541397 <-- npf_ispacketselfsent 00010300 59.04542160 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010301 59.04542160 <-- npf_networkclassify 00010302 59.04543304 --> npf_sendex 00010303 59.04543304 received on cpu 0 3 00010304 59.04544067 received on cpu 0 2 00010305 59.04544067 mdl 62 00010306 59.04544067 next mdl 24 , added 00010307 59.04544830 --> npf_sendcompleteex 00010308 59.04547882 <-- npf_sendcompleteex 00010309 59.04548645 <-- npf_sendex 00010310 59.04558563 --> npf_networkclassify 00010311 59.04558563 --> npf_ispacketselfsent 00010312 59.04558563 <-- npf_ispacketselfsent 00010313 59.04559326 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010314 59.04560089 <-- npf_networkclassify 00010315 59.04560471 --> npf_sendex 00010316 59.04561234 received on cpu 0 4 00010317 59.04561234 received on cpu 0 3 00010318 59.04561234 mdl 42 00010319 59.04561996 next mdl 24 , added 00010320 59.04561996 --> npf_sendcompleteex 00010321 59.04562378 <-- npf_sendcompleteex 00010322 59.04562378 <-- npf_sendex 00010323 59.15098953 --> npf_networkclassify 00010324 59.15098953 --> npf_ispacketselfsent 00010325 59.15099335 <-- npf_ispacketselfsent 00010326 59.15099335 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010327 59.15103912 <-- npf_networkclassify 00010328 59.15105820 --> npf_sendex 00010329 59.15106583 --> npf_sendcompleteex 00010330 59.15106583 <-- npf_sendcompleteex 00010331 59.15106583 <-- npf_sendex 00010332 59.15113449 --> npf_networkclassify 00010333 59.15113449 --> npf_ispacketselfsent 00010334 59.15114212 <-- npf_ispacketselfsent 00010335 59.15114212 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010336 59.15114975 <-- npf_networkclassify 00010337 59.15118027 --> npf_sendex 00010338 59.15118027 --> npf_sendcompleteex 00010339 59.15118790 <-- npf_sendcompleteex 00010340 59.15118790 <-- npf_sendex 00010341 59.15118790 --> npf_networkclassify 00010342 59.15119171 --> npf_ispacketselfsent 00010343 59.15119171 <-- npf_ispacketselfsent 00010344 59.15119171 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010345 59.15119934 <-- npf_networkclassify 00010346 59.15123367 --> npf_networkclassify 00010347 59.15123749 --> npf_ispacketselfsent 00010348 59.15123749 <-- npf_ispacketselfsent 00010349 59.15123749 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010350 59.15124512 <-- npf_networkclassify 00010351 59.15125275 --> npf_sendex 00010352 59.15125275 received on cpu 1 1 00010353 59.15125656 received on cpu 1 1 00010354 59.15132904 mdl 62 00010355 59.15133286 next mdl 24 , added 00010356 59.15134048 --> npf_sendcompleteex 00010357 59.15134811 <-- npf_sendcompleteex 00010358 59.15134811 <-- npf_sendex 00010359 59.15138626 --> npf_networkclassify 00010360 59.15138626 --> npf_ispacketselfsent 00010361 59.15138626 <-- npf_ispacketselfsent 00010362 59.15139389 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010363 59.15139771 <-- npf_networkclassify 00010364 59.15140533 --> npf_sendex 00010365 59.15140533 received on cpu 1 2 00010366 59.15140533 received on cpu 1 2 00010367 59.15141296 mdl 42 00010368 59.15141296 next mdl 24 , added 00010369 59.15141296 --> npf_sendcompleteex 00010370 59.15141678 <-- npf_sendcompleteex 00010371 59.15141678 <-- npf_sendex 00010372 59.19804001 --> npf_sendex 00010373 59.19805527 --> npf_sendcompleteex 00010374 59.19805527 <-- npf_sendcompleteex 00010375 59.19805527 <-- npf_sendex 00010376 59.35518646 --> npf_networkclassify 00010377 59.35519409 --> npf_ispacketselfsent 00010378 59.35519409 <-- npf_ispacketselfsent 00010379 59.35519409 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010380 59.35520554 <-- npf_networkclassify 00010381 59.35526276 --> npf_sendex 00010382 59.35527039 --> npf_sendcompleteex 00010383 59.35527802 <-- npf_sendcompleteex 00010384 59.35527802 <-- npf_sendex 00010385 59.35528183 --> npf_networkclassify 00010386 59.35528183 --> npf_ispacketselfsent 00010387 59.35528183 <-- npf_ispacketselfsent 00010388 59.35528946 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010389 59.35528946 <-- npf_networkclassify 00010390 59.35543823 --> npf_networkclassify 00010391 59.35543823 --> npf_ispacketselfsent 00010392 59.35543823 <-- npf_ispacketselfsent 00010393 59.35544205 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010394 59.35544968 <-- npf_networkclassify 00010395 59.35546112 --> npf_sendex 00010396 59.35546875 received on cpu 0 5 00010397 59.35546875 received on cpu 0 4 00010398 59.35547638 mdl 42 00010399 59.35547638 next mdl 50 , added 00010400 59.35548019 --> npf_sendcompleteex 00010401 59.35548019 <-- npf_sendcompleteex 00010402 59.35548782 <-- npf_sendex 00010403 59.47556305 --> npf_tapex 00010404 59.47557068 --> npf_returnex 00010405 59.47557068 npf_returnex: hahahaha not own send rx packets 00010406 59.47557068 <-- npf_returnex 00010407 59.47557831 <-- npf_tapex 00010408 59.58328247 --> npf_tapex 00010409 59.58329773 --> npf_returnex 00010410 59.58329773 npf_returnex: hahahaha not own send rx packets 00010411 59.58329773 <-- npf_returnex 00010412 59.58329773 <-- npf_tapex 00010413 59.58549881 --> npf_tapex 00010414 59.58550262 --> npf_returnex 00010415 59.58551025 npf_returnex: hahahaha not own send rx packets 00010416 59.58551025 <-- npf_returnex 00010417 59.58551025 <-- npf_tapex 00010418 60.11791992 --> npf_networkclassify 00010419 60.11791992 --> npf_ispacketselfsent 00010420 60.11792755 <-- npf_ispacketselfsent 00010421 60.11792755 npf_networkclassify: npf_networkclassify: npf_ispacketselfsent() [bselfsent: 0] 00010422 60.11793900 <-- npf_networkclassify 00010423 60.11795807 --> npf_sendex 00010424 60.11796570 received on cpu 0 6 00010425 60.11796570 received on cpu 0 5 00010426 60.11796951 mdl 42 00010427 60.11796951 next mdl 50 , added
the correct using ndisfindicatereceivenetbufferlists based on msdn: https://msdn.microsoft.com/en-us/library/windows/hardware/ff570448(v=vs.85).aspx
Comments
Post a Comment