Well, today we will write some bytes in a ethernet network. We will use a NE2000 lan card. I hope you still have one.
Documentation needed for this is:
Writing Drivers for the
DP8390 NIC Family of
Ethernet Controllers
From National Semiconductor.
My PCI card is in 0xbf00 as base address. You might need to know the base address of your card. Some are 0x300.
Compile with gcc -O -o testne2000 testne2000.c kbhit.c
testne2000.c:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <getopt.h>
#if defined(__linux__) && __GNU_LIBRARY__ == 1
#include <asm/io.h>
#else
#include <sys/io.h>
#endif
#if !defined(__OPTIMIZE__)
#error You must compile this driver with "-O"!
#endif
#define COMMAND 0xbf00
#define DATACONFIGURATION COMMAND+0x0E
#define COMMAND 0xbf00
#define PAGESTART COMMAND+01
#define PAGESTOP COMMAND+02
#define BOUNDARY COMMAND+03
#define TRANSMITSTATUS COMMAND+04
#define TRANSMITPAGE COMMAND+04
#define TRANSMITBYTECOUNT0 COMMAND+0x05
#define NCR COMMAND+05
#define TRANSMITBYTECOUNT1 COMMAND+0x06
#define INTERRUPTSTATUS COMMAND+0x07
#define CURRENT COMMAND+07
#define REMOTESTARTADDRESS0 COMMAND+0x08
#define CRDMA0 COMMAND+0x08
#define REMOTESTARTADDRESS1 COMMAND+0x09
#define CRDMA1 COMMAND+0x09
#define REMOTEBYTECOUNT0 COMMAND+0x0A
#define REMOTEBYTECOUNT1 COMMAND+0x0B
#define RECEIVESTATUS COMMAND+0x0C
#define RECEIVECONFIGURATION COMMAND+0x0C
#define TRANSMITCONFIGURATION COMMAND+0x0D
#define FAE TALLY COMMAND+0x0D
#define DATACONFIGURATION COMMAND+0x0E
#define CRC TALLY COMMAND+0x0E
#define INTERRUPTMASK COMMAND+0x0F
#define MISS PKT TALLY COMMAND+0x0F
#define IOPORT COMMAND+0x10
#define PSTART 0x46
#define PSTOP 0x80
#define TRANSMITBUFFER 0x40
#define NE_P1_PAR0 0x01 // Physical Address Register 0
#define NE_P1_PAR1 0x02 // Physical Address Register 1
#define NE_P1_PAR2 0x03 // Physical Address Register 2
#define NE_P1_PAR3 0x04 // Physical Address Register 3
#define NE_P1_PAR4 0x05 // Physical Address Register 4
#define NE_P1_PAR5 0x06 // Physical Address Register 5
#define NE_P1_CURR 0x07 // Current RX ring-buffer page
#define NE_P1_MAR0 0x08 // Multicast Address Register 0
#define NE_P1_MAR1 0x09 // Multicast Address Register 1
#define NE_P1_MAR2 0x0A // Multicast Address Register 2
#define NE_P1_MAR3 0x0B // Multicast Address Register 3
#define NE_P1_MAR4 0x0C // Multicast Address Register 4
#define NE_P1_MAR5 0x0D // Multicast Address Register 5
#define NE_P1_MAR6 0x0E // Multicast Address Register 6
#define NE_P1_MAR7 0x0F // Multicast Address Register 7
#define ETHER_ADDR_LEN 6
struct ether_addr {
unsigned short addr[ETHER_ADDR_LEN];
};
struct ne {
//dev_t devno; // Device number
struct ether_addr hwaddr; // MAC address
unsigned short iobase; // Configured I/O base
unsigned short irq; // Configured IRQ
unsigned short membase; // Configured memory base
unsigned short memsize; // Configured memory size
unsigned short asic_addr; // ASIC I/O bus address
unsigned short nic_addr; // NIC (DP8390) I/O bus address
//struct interrupt intr; // Interrupt object for driver
//struct dpc dpc; // DPC for driver
unsigned short rx_ring_start; // Start address of receive ring
unsigned short rx_ring_end; // End address of receive ring
unsigned char rx_page_start; // Start of receive ring
unsigned char rx_page_stop; // End of receive ring
unsigned char next_pkt; // Next unread received packet
//struct event rdc; // Remote DMA completed event
//struct event ptx; // Packet transmitted event
//struct mutex txlock; // Transmit lock
};
static int ne_probe(struct ne *ne) {
unsigned char byte,i;
// Reset
//msleep(5000);
byte=inb(0xbf00);
outb(0x21,0xbf00);
// sleep(1);
printf("Command reg %x\n",byte);
outb(0x58,DATACONFIGURATION);
outb(0x00,REMOTEBYTECOUNT0);
outb(0x00,REMOTEBYTECOUNT1);
outb(0x00,RECEIVECONFIGURATION);
outb(0x20,TRANSMITPAGE);
outb(0x02,TRANSMITCONFIGURATION);
outb(0x26,PAGESTART);
outb(0x26,BOUNDARY);
outb(0x40,PAGESTOP);
outb(0x61,COMMAND);
for (i = 0; i < 6; i++)
{
outb(ne->hwaddr.addr[i],COMMAND + NE_P1_PAR0 + i);
}
for (i = 0; i < ETHER_ADDR_LEN; i++)
{
printf("PAR %x %x\n",inb(COMMAND + NE_P1_PAR0 + i),ne->hwaddr.addr[i]);
}
// Actually the ethernet address is overwritten later on wit 0xA5A5. You can fix it. I will put a useful payload later
outb(0x26,CURRENT);
outb(0x22,COMMAND);
outb(0xff,INTERRUPTSTATUS);
outb(0x0B,INTERRUPTMASK);
outb(0x00,TRANSMITCONFIGURATION);
//send a packet
int count =100;
outb(count & 0xff,REMOTEBYTECOUNT0);
outb(count >>8 , REMOTEBYTECOUNT1);
outb(0x00, REMOTESTARTADDRESS0);
outb(TRANSMITBUFFER, REMOTESTARTADDRESS1);
outb(0x12,COMMAND);
for (i=0;i<100;i++)
outw(0xA5A5,IOPORT);
int s=0;
s=inb(INTERRUPTSTATUS);
while(s!=0x40)
s=inb(INTERRUPTSTATUS);
printf("Interrup status %x\n",s);
outb(0x40,INTERRUPTSTATUS);
s=inb(INTERRUPTSTATUS);
printf("Interrup status %x\n",s);
outb(TRANSMITBUFFER,TRANSMITPAGE);
outb(count & 0xff,TRANSMITBYTECOUNT0);
outb(count >>8 ,TRANSMITBYTECOUNT1);
outb(0x26,COMMAND);
return 1;
}
int main(char argc, char **argv)
{
if (iopl(3)) {perror("iopl error"); exit(1);}
struct ne *NIC;
NIC = (struct ne *) malloc(sizeof(struct ne));
NIC->hwaddr.addr[0]=0x00;
NIC->hwaddr.addr[1]=0xA0;
NIC->hwaddr.addr[2]=0xFF;
NIC->hwaddr.addr[3]=0xFF;
NIC->hwaddr.addr[4]=0x58;
NIC->hwaddr.addr[5]=0x33;
int i;
ne_probe(NIC);
return 0;
}
The getch and hitkb are not mine: (those are turboc things I guess)
kbhit.c
#include "kbhit.h"
#include <termios.h>
#include <unistd.h> // for read()
static struct termios initial_settings, new_settings;
static int peek_character = -1;
void init_keyboard()
{
tcgetattr(0,&initial_settings);
new_settings = initial_settings;
new_settings.c_lflag &= ~ICANON;
new_settings.c_lflag &= ~ECHO;
new_settings.c_lflag &= ~ISIG;
new_settings.c_cc[VMIN] = 1;
new_settings.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &new_settings);
}
void close_keyboard()
{
tcsetattr(0, TCSANOW, &initial_settings);
}
int kbhit()
{
unsigned char ch;
int nread;
if (peek_character != -1) return 1;
new_settings.c_cc[VMIN]=0;
tcsetattr(0, TCSANOW, &new_settings);
nread = read(0,&ch,1);
new_settings.c_cc[VMIN]=1;
tcsetattr(0, TCSANOW, &new_settings);
if(nread == 1)
{
peek_character = ch;
return 1;
}
return 0;
}
int readch()
{
char ch;
if(peek_character != -1)
{
ch = peek_character;
peek_character = -1;
return ch;
}
read(0,&ch,1);
return ch;
}
int getch()
{
char ch;
if(peek_character != -1)
{
ch = peek_character;
peek_character = -1;
return ch;
}
read(0,&ch,1);
return ch;
}
The kbhit.n
#ifndef KBHIT_H
#define KBHIT_H
void init_keyboard(void);
void close_keyboard(void);
int kbhit(void);
int readch(void);
int getch(void);
#endif
The frame cannot be captured with wireshark because it is being written directly to the hardware!.
I will also clean up the code later.
Check the screenshoot.
No hay comentarios:
Publicar un comentario