Click here to Skip to main content
15,884,838 members
Articles / Programming Languages / C#
Article

Raw Ethernet Packet Sending

Rate me:
Please Sign up or sign in to vote.
4.92/5 (86 votes)
24 Oct 20035 min read 579.3K   10.6K   150   135
This article explains how to send a raw Ethernet packet using C# and a NDIS Protocol Driver.

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


Written By
Web Developer
United States United States
MCSE, MCSD, MCDBA, CCNA

Comments and Discussions

 
QuestionHow to retreive Remote IP, Subnet mask, Gateway Pin
80Eddy3-Aug-08 7:28
80Eddy3-Aug-08 7:28 
QuestionDoRead? Pin
BigBenDk1-Aug-08 0:03
BigBenDk1-Aug-08 0:03 
GeneralReadFile with variable bytesToRead number Pin
MeNot2-Jun-08 22:29
MeNot2-Jun-08 22:29 
GeneralRe: ReadFile with variable bytesToRead number Pin
BigBenDk1-Aug-08 3:54
BigBenDk1-Aug-08 3:54 
GeneralFix for loopback adapter Pin
cjones28520-Mar-08 3:26
cjones28520-Mar-08 3:26 
QuestionTimeOut on ReadFile Pin
Keld18-Feb-08 2:02
Keld18-Feb-08 2:02 
GeneralNot supported for some wifi cards Pin
quantjump20-Nov-07 12:47
quantjump20-Nov-07 12:47 
GeneralI have troubles with the installation... Pin
SoFx009-Oct-07 1:38
SoFx009-Oct-07 1:38 
Can somebody tell me how to install ndisprot.sys for the dial up connection?
Is it posible?

I have troubles during the described procedure of installation. The message said that drivers for this adapter couldn't been found.

Help me, please...
GeneralRe: I have troubles with the installation... Pin
tricychloramine16-Oct-07 11:28
tricychloramine16-Oct-07 11:28 
GeneralRe: I have troubles with the installation... Pin
SoFx0017-Oct-07 5:02
SoFx0017-Oct-07 5:02 
GeneralDropping packets Pin
TTTCoder2-Sep-07 11:00
TTTCoder2-Sep-07 11:00 
GeneralUse on unconnected NIC Pin
iwdu1507-Aug-07 15:52
iwdu1507-Aug-07 15:52 
Generalcalling the RawEthernet by C and adding new commands to the original C# program Pin
bouteh27-Jun-07 16:16
bouteh27-Jun-07 16:16 
GeneralRe: calling the RawEthernet by C and adding new commands to the original C# program Pin
Member 139328652-Apr-20 22:41
Member 139328652-Apr-20 22:41 
GeneralOVERLAPPED IO Pin
Nigel de Costa12-Jun-07 0:59
Nigel de Costa12-Jun-07 0:59 
GeneralRe: OVERLAPPED IO Pin
BigBenDk4-Aug-08 6:03
BigBenDk4-Aug-08 6:03 
GeneralRe: OVERLAPPED IO Pin
Nigel de Costa4-Aug-08 6:06
Nigel de Costa4-Aug-08 6:06 
QuestionTcpIp and Ndis Packet ! Pin
Mandorle12-Apr-07 0:15
Mandorle12-Apr-07 0:15 
Generalto read data from ethernet interface Pin
shriharsha.HM5-Mar-07 20:33
shriharsha.HM5-Mar-07 20:33 
QuestionProblems with simultaneous sends and receives Pin
Stinger.91119-Feb-07 21:12
Stinger.91119-Feb-07 21:12 
AnswerRe: Problems with simultaneous sends and receives Pin
chocobu25-Jun-07 3:21
chocobu25-Jun-07 3:21 
Questionsend raw data via virtual adapter [modified] Pin
Eddie_20064-Feb-07 19:22
Eddie_20064-Feb-07 19:22 
Questionnet start ndisprot -- Error Pin
Claudio T.19-Jan-07 0:15
Claudio T.19-Jan-07 0:15 
AnswerRe: net start ndisprot -- Error Pin
Eddie_20063-Feb-07 17:30
Eddie_20063-Feb-07 17:30 
AnswerRe: net start ndisprot -- Error Pin
Claudio T.4-Feb-07 1:14
Claudio T.4-Feb-07 1:14 

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

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