Click here to Skip to main content
Click here to Skip to main content

Raw Ethernet Packet Sending

By , 24 Oct 2003
Rate this:
Please Sign up or sign in to vote.

Sample Image - "SendRawPacket.jpg

Introduction

This purpose of this article is to explain how to send a raw Ethernet packet using C# on a Microsoft platform. A raw Ethernet packet is the complete Layer 2 network frame that is sent to the physical wire. Sending a frame like this allows you to manipulate the target and source MAC addresses and the Layer 3 protocol fields.

Background

You may be thinking, "Why would anyone want to do this?". Well, I was trying to create an application (using C#) that would make a typical Windows computer with 2 NICs act as a Layer 2 Network device. My goal was to listen for packets on a network interface and send the exact same packet out of the opposite interface, basically a packet repeater. To do this, I needed to be able to read a raw Ethernet packet (easy) and then write that same raw Ethernet packet (difficult). The sent packet needed to be exactly like the read packet, Ethernet header and all. I did a great deal of research online, and did not find a whole lot of info, just a few hints here and there.

The first problem was that Windows does not include a way to programmatically send a raw Ethernet packet. After some research, I realized that I needed to create a NDIS Protocol Driver (PassThru and Intermediate drivers will also work) to interface with the network adapters at a very low level. Luckily, the Windows Driver Development Kits (DDKs) included samples that would accomplish this for me. Great, the hard part down right......yeah, that is what I thought too. Now I had to interface with the driver from managed C# code.

Well, enough of the background.....on to the code.....

Part 1 - NDIS Protocol Driver

So, like I said, the DDK provides a suitable NDIS driver for sending raw packets. I compiled this, creating the .inf and .sys files for the driver (I have included the compiled driver, altered to fit my needs, in the attached zip file). After running a few test, I found that I could:

  1. Only receive packets destined for me and
  2. I could only send packets with a source address of my adapter.

Well, this was not acceptable. I needed to receive any packets on my LAN segment, and send those same packets regardless of the source address. So after looking through the driver code, I figured out how to accomplish that.

To receive any packets, the driver had to be set to Promiscuous mode. The following code segment was what was altered to accomplish this.

// ndisprot.h
// line 177
// Add NDIS_PACKET_TYPE_PROMISCUOUS to support promiscuous mode reading

#define NUIOO_PACKET_FILTER  (NDIS_PACKET_TYPE_DIRECTED|    \
                              NDIS_PACKET_TYPE_MULTICAST|   \
                              NDIS_PACKET_TYPE_BROADCAST|   \
                              NDIS_PACKET_TYPE_PROMISCUOUS)     // **Added**

To send any packets, the following code segment had to be commented out

// send.c
// line 136
// Comment out to support sending packets from any MAC source address

     // To prevent applications from sending packets with spoofed
     // mac address, we will do the following check to make sure the source 
     // address in the packet is same as the current MAC address of the NIC.
     //
     if ((pIrp->RequestorMode == UserMode) && 
          !NPROT_MEM_CMP(pEthHeader->SrcAddr, 
          pOpenContext->CurrentAddress, NPROT_MAC_ADDR_LEN))
     {
            DEBUGP(DL_WARN, ("Write: Failing with invalid Source address"));
            NtStatus = STATUS_INVALID_PARAMETER;
            break;
     }

Once those changes were made, the NDIS Driver performed perfect for what I needed.

Part 2 - C# RawEthernet Application

The code for the RawEthernet application is commented fairly well, so I am not going to go into a lot of detail on the code here. I am just going to highlight the important steps in the code.

Writing information to a device driver is somewhat similar to writing to a file. We open the driver file by calling the CreateFile API. This returns a handle that we can use to write to and read from the driver. Next, we can bind the driver handle to a specific adapter by using the DeviceIoControl API. Binding the adapter lets us access the NDIS Driver on a specific network adapter. After all this, the writing is simple. We use the WriteFile API. The ReadFile API can be used in a similar manner to read incoming network data as well.

To send a packet, we have to create a byte representation on the packet that we want to send. The following shows the Ethernet header (first 14 bytes of packet) in byte format

DD DD DD DD DD DD SS SS SS SS SS SS PP PP <data follows>
  • D = Destination MAC Address
  • S = Source MAC Address
  • P = Next Layer Protocol (0800 = IP)

You can use a packet sniffer (Ethereal, Snoop, EtherPeeks) to verify that you are sending a raw data packet on the network medium. The packet that this application currently sends is a very simple data packet that served no purpose other than to show the concept. This can easily be changed to reflect a real packet, such as a ping or anything else that you can think of.

Running the sample

NDIS Driver

You can install the NDIS Driver by opening your network adapter properties and clicking the "Install" button, selecting "Protocol", and then choosing "Have Disk". Then browse to the .inf file and click "OK". This will then load the driver onto every adapter that you have in your system.

Important - Make sure that it is enabled, there should be a check in the box next to "Raw Packet NDIS Protocol Driver".

Important - Open a command prompt and type "net start ndisprot" to start the driver service.

Note - The beauty of having this driver is that you can disable every other protocol in the Adapter's protocol list (i.e. Internet Protocol) and you will still be able to send and receive packets. Your machine will not even have an address, but because we are working at Layer 2, you don't need one. (This driver will work even if you keep all of the other protocols enabled)

RawEthernet application

The zip file contains the source and compiled binary for the RawEthernet application. Once the driver is installed and enabled, simply run the EXE to see the packets being sent.

Other items

I have been working on getting this to work asynchronously so that I can send and receive on the same adapter at the same time. When I get some more time, I will put out an article on how async file works.

That is about it for now...if you have any questions or comments, feel free to contact me.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

miahrugger
Web Developer
United States United States
MCSE, MCSD, MCDBA, CCNA

Comments and Discussions

 
QuestionStream continuously PinmemberMember 107056517-Apr-14 22:53 
QuestionHow to Receive Frame.........Need Help PinmemberMember 1054093523-Jan-14 1:38 
QuestionCan't add driver as protocol PinmemberFlorian Rosmann8-Oct-13 8:18 
GeneralMy vote of 5 PinprofessionalMarco Bertschi26-Jun-13 8:36 
QuestionWindows 7 NDIS driver problem PinmemberMember 800437224-Feb-12 12:44 
AnswerRe: Windows 7 NDIS driver problem [modified] PinmemberGonzalo Brusella7-Mar-12 10:31 
AnswerRe: Windows 7 NDIS driver problem Pinmembermfogar012-May-12 21:48 
GeneralMy vote of 5 PinmemberG. Cadel21-Jul-11 8:36 
QuestionC/C++ interface to driver (Visual C++) unicode enviroment [modified] PinmemberUlterior19806-Jul-11 4:47 
GeneralMy vote of 5 PinmemberUlterior198030-Jun-11 15:02 
GeneralThis example in VB.NET Pinmemberemicroxxx8-Sep-10 4:08 
GeneralMy vote of 5 Pinmembersanjaykhan200418-Jul-10 19:34 
GeneralDriver could not be opened Pinmembermsba5815-Jul-10 10:37 
GeneralGreat article PinmemberSebastien LEBRETON25-Mar-10 7:36 
GeneralRe: Great article PinmemberWDanielS30-Mar-10 2:24 
GeneralVista PinmemberNneet12-Jan-09 3:07 
GeneralRe: Vista PinmemberNneet16-Jan-09 0:13 
QuestionMissing packets (HELP) PinmemberRemco Postma5-Jan-09 4:29 
AnswerRe: Missing packets (HELP) Pinmemberdeathmarch2-Feb-09 1:26 
QuestionSending packets speed Pinmemberpr_Ilya9-Dec-08 1:58 
AnswerRe: Sending packets speed PinmemberJimmyO17-Sep-09 20:25 
QuestionCan I use this program to make a product ? Pinmemberzifq26-Nov-08 2:57 
GeneralCannot get it to work Pinmembercharleswalker16-Sep-08 20:41 
QuestionDoRead? PinmemberBigBenDk1-Aug-08 0:03 
GeneralReadFile with variable bytesToRead number Pinmemberannoyingwebsite@dodgeit.com2-Jun-08 22:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140415.2 | Last Updated 25 Oct 2003
Article Copyright 2003 by miahrugger
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid