Example of use libnet (14) ---- mechanism of contract mining BPF from the libnet: NSFocus Security Team finishing: small four
-------------------------------------------------- -------------------- / ** /usr/src/sys/Net/if_ethersubr.c*/int Ether_Output (IFP, M, DST, RT0) Register Struct IFNET * ifp; struct mbuf * m; struct sockaddr * dst; struct rTentry * RT0; {u_char ESRC [6], EDST [6]; Register Struct Ether_Header * EH; INT HLEN; Struct Arpcom * ac = ifp2ac (IFP); INT HDRCMPLT = 0; ... HLEN = Ether_HDR_LEN; SWITCH (DST-> sa_family) {... ... case pseudo_af_hdrcmplt: hdrcmplt = 1; EH = (struct ether_header *) DST-> sa_data; (void ) Memcpy (ESRC, EH-> Ether_SHOST, SIZEOF (ESRC)); / * * Falling processing * / case AF_UNSPEC: LOOP_COPY = -1; / * if this is for us, don't do it * / eH = Struct ether_header *) DST-> sa_data; (void) Memcpy (EDST, EH-> Ether_DHOST, SIZEOF (EDST)); T Ype = EH-> Ether_TYPE; Break; ...} / * end of switch * / / * * Add local net header. if no space in first MBUF, Allocate Another. * / M_Prepend (M, SIZEOF (Struct Ether_Header), m_dontwait); if (m == 0) {senderr (enobufs);} eh = mtod (m, struct ether_header *); (void) Memcpy (& EH-> Ether_TYPE, & TYPE, SIZEOF (EH-> Ether_TYPE) ); (Void) Memcpy (EH-> Ether_DHOST, EDST, SIZEOF (EDST)); if (HDrCMPLT) {(void) Memcpy (eh-> Ether_shost, esrc, sizeof (eh-> ether_shost);} else {/ * * Pay attention to this stupid behavior, get the source MAC address directly from the interface * / (void) Memcpy (eh->
Ether_shost, ac_enaddr, sizeof (eh-> ether_shost);} ... / * * Continue with link-layer output * / return (Ether_output_frame (IFP, m));} / * end of ether_output * / ------------------------------------------------ ---------------------- 2002-01-21 09: 20HHUU As the following questions in the FreeBSD version of Smth> Do not understand why that behavior is stupid, now 5.0 The same is as follows: In fact, the source Mac is transferred from the main adjustment. Of course, the initial source Mac is also acquired, or specified in the BPF. Due to a historical reasons, it has not been removed from the judgment assignment. When the BPF is not involved, it is a simple synonym. When it is involved in the BPF, this redundant pick-up MAC moves to fail to fail the specified source MAC. In other words, there is no such thing as it does not affect the normal protocol stack, this sentence is redundant to the protocol stack. Unfortunately, this redundancy happens to destroy BPF. This issue discussed this problem in the favorite of FreeBSD, not for safety considerations, which is completely historical. The author of Libnet recommends using the loadable kernel module to modify this Ether_output function, not recompile the kernel. Unfortunately, LKM is provided in the LIBNET installation package, not KLD. FREEBSD 3.1 provides the loading kernel module technology (LKM), FreeBSD 4.x begins to provide a dynamic kernel link mechanism (KLD), you can easily understand the upgrade of LKM, see << FreeBSD 4.x Dynamic Nuclear Link Mechanism (KLD Programming Guide >> Strengthening Understanding. In order to dynamically load fkld, ensure that kern.secureLevel is less than or equal to 0 # sysctl kern.securelevelkerkern.secureevel: -1 <- this is the default value # ok, what we have to do now is to write this fkld, wow, is it a big head , Nonsense, my head is also very big, the last time I touch fkld is 2000-11-18 23:36, write a rootkit package, now I have to come back is more difficult, depressed. See the example of / usr / share / example / kld / cdev / directory.
-------------------------------------------------- -------------------- SYS / SYS / Queue.h / ** Tail Queue Definitions. * / # define tailq_head (name, type) / Struct Name / {/ struct type * tqh_first; / * first element * / / struct type ** tqh_last; / * addr of last next element * / /} # define TAILQ_ENTRY (type) / struct / {/ struct type * tqe_next; / * next element * / / Struct Type ** TQE_PREV; / * Address of Previous Next Element * / / / }Sys/net/if_var.htailq_head/var.htailq_head (IFNetHead, IFNET); SYS / NET / IF.CSTRUCT IFNetHead IFNet; SYS / NET / IF_VAR.H / ** Structure Defining a network interface. * / Struct ifnet {... char * if_name; / * name, EG "en" or "lo" * / TAILQ_ENTRY (ifnet) if_link; / * all struct ifnets are chained * / struct ifaddrhead if_addrhead; / * linked list of addresses per if * / int if_pcount; / * number of promiscuous listeners * / struct bpf_if * if_bpf ; / * packet filter structure * / u_short if_index; / * numeric abbreviation for this if * / short if_unit; / * sub-unit for lower level driver * / short if_timer; / * time 'til if_watchdog called * / short if_flags;
/ * UP / DOWN, BROADCAST, ETC. * / ... / * * Procedure Handles * / INT (* if_output) / * Output Routine (Enqueue) * / __p ((Struct IFNet *, Struct Mbuf *, Struct SockAddr *, Struct RTENTRY *); ... int (* if_ioctl) / * ioctl routine * / __p (Struct IFNET *, U_LONG, CADDR_T)); ...}; -------------------------------------------------- ------------------ Analysis is not done, the code is as follows ----------------------- ---------------------------------------------- / ** Dig this function from /usr/src/system/iF_ethersubr.c, then modify * / static int fake_ether_output (Register Struct IFNET * IFP, STRUCT MBUF * M, STRUCT SOCKADDR * DST, STRUCT RTENTRY * RT0) { #define ifp2ac (IFP) ((Struct Arpcom *) IFP) #define senderr (e) DO {Error = (e); goto bad;} whiled; int error = 0; int hdrcmplt = 0; u_charESRC [6], EDST [6]; Register Struct RTENTRY * RT; Register Struct Ether_Header * EH; INT OFF, LOOP_COPY = 0; / * * Link Layer Header LengHT * / INT HLEN; Struct Arpcom * AC = IFP2AC (IFP) ; If (ifp-> if_flags & (iff_up | iff_running))! = (Iff_up | iff_running)) {Senderr (ENETDOWN);}} = r = r i ((r) {IF ((RT-> RT_FLAGS & RTF_UP) = = 0) {RT0 = RT = Rtalloc1 (DST, 1, 0UL); if (RT0) {RT-> RT_REFCNT -;
} Else {senderr (ElStunreach);}}} (rt-> rt_flags &} {if (RT-> RT_GWROUTE == 0) {goto lookup;} if ((rt = rt-> rt_gwroute) -> RT_Flags & RTF_UP) == 0) {RTFREE (RT); RT = RT0; Lookup: Rt-> rt_gwroute = r rooo (rt-> rt_gateway, 1, 0ul); IF ((rt = rt-> rt_gwroute) == 0) { Senderr (EHOSTUNREACH);}}} f (rt-> RT_FLAGS & RTF_REECT) {if (RT-> RT_RMX.RMX_EXPIRE == 0 || Time_second
(Void) Memcpy (EDST, EH-> Ether_DHOST, SIZEOF (EDST)); / * * FreeBSD Kernel Hacking: Unified Allowed Source Mac * Add by Scz@nsfocus.com 2001-12-21 15:57 * / (void ) Memcpy (ESRC, EH-> Ether_SHOST, SIZEOF (ESRC)); type = EH-> Ether_TYPE; Break; default: printf ("% s% d: can't Handle AF% D / N", IFP-> IF_NAME , ifp-> if_unit, dst-> sa_family); senderr (EAFNOSUPPORT);..} / * * Add local net header If no space in first mbuf, allocate another * / M_PREPEND (m, sizeof (struct ether_header), M_DONTWAIT) ; If (m == 0) {senderr (enobufs);} eh = mtod (m, struct ether_header *); (void) Memcpy (& EH-> Ether_TYPE, & TYPE, SIZEOF (EH-> Ether_TYPE)); (void) Memcpy (EH-> Ether_DHOST, EDST, SIZEOF (EDST)); if (HDrCMPLT) {(void) Memcpy (EH-> Ether_SHOST, ESRC, SIZEOF (EH-> Ether_shost);} else {/ * * freebsd kernel Hacking : Unified allowed to specify source Mac * Add By scz@nsfocus.com 2001-12-21 15:57 * / (void) Memcpy (EH-> Ether_SHOST, ESRC, SIZEOF (EH-> Ether_shost); / * * (void) Memcpy (EH-> Ether_shost, Ac-> ac_enaddr, sizeof (eh-> ether_shost); * /} / * * if a simplex interface, and the packet is being Sent to company * Ethernet address or a Broadcast address, loopback a copy. * xxx to make A Simplex Device Behave Exactly Like A Duplex * Device, We Should Copy In The Case of sending tour in * Ethernet Address (thus letting the origin). However, we don '
T DO That Here for Security * Reasons and Compatibility. * / IF ((ifp-> if_flags & iff_simplex) && (Loop_copy! = -1)) {IF ((M-> M_Flags & M_BCAST) || LOOP_COPY> 0)) {struct MBUF * n = m_copy (m, 0, (int) m_copyAll); (void) if_simloop (IFP, N, DST-> sa_family, hlen);} else if (bcmp (BCMP (EH-> Ether_DHOST EH-> Ether_SHOST, Ether_ADDR_LEN) == 0) {(void) if_simloop (IFP, M, DST-> Sa_Family, HLEN); return (0);}} / * * Handle Ng_Ether (4) processing, if any * / If (ng_ether_output_p! = Null) {if ((Error = (* ng_ether_output_p) (IFP, & M))! = 0) {BAD: IF (M! = NULL) {m_freem (m);} return (error);} Return (Error); } IF (m == null) {RETURN (0);}} / * * Continue with link-layer output * / return (Ether_out PUT_FRAME (IFP, M));} / * End of favor_Output * / ------------------------------------------------------------------------------------------------------------------------------------------------------------ ----------------------------------- This is the link layer on the FreeBSD system, with Linux In the same way, it can be arbitrarily forged by the source MAC. It does not need to recompile the FreeBSD kernel, just test it. Looking at some of the previous discussions, some people think this so-called source MAC restriction is an inappropriate code left in the freeBSD development process, which is not safe to consider. Now look back to see our main motivation today, excavate the BPF's happly mechanism from the Libnet.
In the file freebsd_arpsend.c, the only thing you need to pay attention to the libnet_write_link_Layer () function -------------------------------- ----------------------------------- int libnet_write_link_Layer (struct libnet_link_int * l, const char * device, u_char * buf, int LEN) {INT C; C = Write (L-> FD, BUF, LEN); RETURN (C);} / ** low level packet interface struct * / struct libnet_link_int {int fd; / * link layer file descriptor * / int linktype; / * link type * / int linkoffset; / * link header size (offset till network layer) * / u_char * device; / * device name * /}; struct libnet_link_int * libnet_open_link_interface (char * device, char * ebuf) {struct ifreq ifr; struct libnet_link_int * l; #if defined (BIOCGHDRCMPLT) && defined (BIOCSHDRCMPLT) u_int spoof_eth_src = 1; #endif l-> fd = libnet_bpf_open (ebuf); ... ... / * * Attach Netwo RK interface to bpf device. * / strncpy (ifr.ifr_name, device, sizeof (ifr.ifr_name)); IF (IOCTL (L-> FD, BiocSetif, (CADDR_T) & IFR) == -1) {.... .. goto bad;.} ... ... / * * NetBSD and FreeBSD BPF have an ioctl for enabling / disabling * automatic filling of the link level source address * / # if defined (BIOCGHDRCMPLT) && defined (BIOCSHDRCMPLT) if (ioctl (l-> fd, biocshdrcmplt, & spoof_eth_src) == -1) {... ... GOTO BAD;} #ENDIF ... ...} / * end of libnet_open_link_interface * / ------ -------------------------------------------------- -------------- Libnet_bpf_open () is done to open / dev / bpf0 device files.