⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcapsend.c

📁 我已经编译通过的Nmapwin!学习扫描器的人有用!
💻 C
📖 第 1 页 / 共 2 页
字号:

//	resolves an ip addr into a nexthop and index
static int ip2route(const struct in_addr *dest, DWORD *nexthop, DWORD *ifi)
{
	static DWORD last_ip = 0;
	static int last_nexthop;
	static int last_ifi;

	MIB_IPFORWARDROW route;

	//	check the cache
	if(last_ip == dest->s_addr)
	{
		if(nexthop) *nexthop = last_nexthop;
		if(ifi) *ifi = last_ifi;
		return 0;
	}

	if(0 != get_best_route(dest->s_addr, &route))
		return -1;	//	failure

	last_ip = 0;	//	if we abort, mark as bad

	//	Compute the next hop
	switch(route.dwForwardType)
	{
	case 3:
		//	local route; the dest is the next hop
		last_nexthop = dest->s_addr;
		break;

	case 4:
		//	remote route; use the specified gateway
		last_nexthop = route.dwForwardNextHop;
		break;

	case 2:
		fatal("corrupt route table\n");
		break;

	default:
		fatal("unknown route format %d\n", route.dwForwardType);
		break;
	}

	//	save the index
	last_ifi = winif2ifi(route.dwForwardIfIndex);

	//	mark it valid
	last_ip = dest->s_addr;

	//	Try to return the answer
	if(nexthop) *nexthop = last_nexthop;
	if(ifi) *ifi = last_ifi;

	if(o.debugging > 1)
	{
		printf("%s is routed through ", inet_ntoa(*(struct in_addr*)&last_ip));
		printf("%s\n", inet_ntoa(*(struct in_addr*)&last_nexthop));
	}

	return 0;
}

//	The adapter cache
typedef struct _IFC_ROW {
	int ifi;
	LPADAPTER pAdapter;
	BYTE phys[MAXLEN_PHYSADDR];
	int physlen;
	DWORD type;
} IFC_ROW;

static IFC_ROW last_if = {-1};

/*
static int numif = 0;
static IFC_ROW *ifcache = 0;
*/
static void cleanup_if_cache()
{
	if(last_if.pAdapter)
	{
		PacketCloseAdapter(last_if.pAdapter);
		last_if.pAdapter = 0;
	}

	last_if.ifi = -1;
}

static LPADAPTER if2adapter(int ifi, BYTE* phys, int *physlen, DWORD *type)
{
	const WINIP_IF *ifentry;
	char *name;

	EnterCriticalSection(&csAdapter);

	if(last_if.ifi == ifi)
	{
		if(last_if.physlen == -1) return 0;
		if(last_if.pAdapter)
		{
			if(physlen && (*physlen < last_if.physlen)) return 0;
			if(phys) memcpy(phys, last_if.phys, last_if.physlen);
			*physlen = last_if.physlen;
			if(type) *type = last_if.type;

			//	we do not release the CS
			return last_if.pAdapter;
		}
	}

	ifentry = ifi2ifentry(ifi);
	if(!ifentry || !ifentry->pcapname)
	{
		LeaveCriticalSection(&csAdapter);
		return 0;	//	Can't do this one...
	}

	cleanup_if_cache();

	last_if.pAdapter = PacketOpenAdapter(ifentry->pcapname);

	//	This is required on Win9x (defaults to 0)
	//	It's probably a good idea on WinNT/2K
	PacketSetNumWrites(last_if.pAdapter, 1);

	if(!last_if.pAdapter)
	{
		last_if.physlen = -1;
		LeaveCriticalSection(&csAdapter);
		return 0;
	}

	last_if.physlen = ifentry->physlen;
	memcpy(last_if.phys, ifentry->physaddr, ifentry->physlen);
	last_if.type = ifentry->type;
	last_if.ifi = ifi;

	//	Try to return the answer
	if(physlen && (*physlen < last_if.physlen))
	{
		LeaveCriticalSection(&csAdapter);
		return 0;
	}
	if(phys) memcpy(phys, last_if.phys, last_if.physlen);
	*physlen = last_if.physlen;
	if(type) *type = last_if.type;

	//	We do not leave the CS
	return last_if.pAdapter;
}

static void releaseadapter()
{
	LeaveCriticalSection(&csAdapter);
}

//	The almighty pcapsendraw
//	This is the whole point of this file :)
int pcapsendraw(const char *packet, int len, 
	   struct sockaddr *to, int tolen) 
{
	struct sockaddr_in *sin = (struct sockaddr_in *) to;
	int cb = 0;
	int nRes, i;
	DWORD nextip;
	int ifi;
	LPADAPTER pAdap;
	BYTE myphys[MAXLEN_PHYSADDR], tphys[MAXLEN_PHYSADDR];
	int physlen = MAXLEN_PHYSADDR;
	DWORD type;

	if(!pcapsend_inited)
		fatal("pcapsendraw: pcapsend not initialized\n");

	if(-1 == ip2route(&sin->sin_addr, &nextip, &ifi))
	{
		WSASetLastError(WSAENETUNREACH);
		return -1;	//	no route to host
	}

	//	check the failcache
	EnterCriticalSection(&csFailCache);
	for(i = 0; i < FAILCACHELEN; i++)
	{
		if(failcache[i].ip == nextip && failcache[i].ifi == ifi)
		{
			//	it failed
			WSASetLastError(WSAEHOSTUNREACH);
#ifdef THREAD_DEBUG
			printf("sendto: autofailed %s\n", inet_ntoa(*(struct in_addr*)&failcache[i].ip));
#endif
			LeaveCriticalSection(&csFailCache);
			return -1;
		}
	}
	LeaveCriticalSection(&csFailCache);

	//	Read the data
	nRes = SearchARP(nextip, ifi, tphys, &physlen);
	if(-1 == nRes)
	{
		//	defer the send
		AddPacketToQueue(packet, len, nextip, ifi);
		return len;	//	it's in the queue, so it worked...
	}

	//	otherwise, we have an address
	pAdap = if2adapter(ifi, myphys, &physlen, &type);
	if(!pAdap)
		fatal("can't send to this interface\n");
	realsend(pAdap, packet, len, tphys, myphys, physlen, type, ETH_IP);
	releaseadapter();
	return len;
}

void pcapsend_init()
{
	int i, nRes;
	DWORD id;

	if(pcapsend_inited) return;
	pcapsend_inited = 1;

	if(o.debugging > 1)
		printf("Initializing winpcap send support...");

	for(i = 0; i < SENDQUEUE_LEN; i++)
	{
		Q_FREE *f;
		sendqueue[i].ifi = -1;
		f = (Q_FREE*)&sendqueue[i];
		f->next = nextfree;
		nextfree = f;
	}

	InitializeCriticalSection(&csQueue);
	InitializeCriticalSection(&csAdapter);
	InitializeCriticalSection(&csFailCache);
	InitializeCriticalSection(&csArpCache);
	InitializeCriticalSection(&csArpTable);

	hEvWakeup = CreateEvent(0, 0, 0, 0);
	hSemQueue = CreateSemaphore(0, SENDQUEUE_LEN, SENDQUEUE_LEN, 0);

	//	allocate the ARP cache
	arpalloclen = 0;
	pArpTable = (PMIB_IPNETTABLE)&i;
	nRes = GetIpNetTableSafe(pArpTable, &arpalloclen, FALSE);
	if(arpalloclen == 0)
	{
		if(o.debugging)
			printf("ARP table length failure (%lu) during init -- try kludge1 :(\n", nRes);
		arpalloclen = 100 * sizeof(MIB_IPNETROW) + 8;
	}

	//	Read the data
	arpalloclen += 3 * sizeof(MIB_IPNETROW);
	pArpTable = (PMIB_IPNETTABLE)malloc(arpalloclen);
	if(!pArpTable)
	{
		pcapsend_inited = 0;
		fatal("out of memory\n");
	}
	nRes = GetIpNetTableSafe(pArpTable, &arpalloclen, TRUE);

	if(nRes != NO_ERROR)
	{
		if(o.debugging)
			printf("ARP failure (%lu) during init -- trying kludge2\n", nRes);
		pArpTable->dwNumEntries = 0;
	}

	//	Start the send thread
	hThread = (HANDLE)_beginthreadex(0, 0, SendThreadProc, 0, 0, &id);
	if(!hThread)
	{
		pcapsend_inited = 0;
		fatal("failed to start thread\n");
	}

	atexit(pcapsend_cleanup);

	pcapsend_inited = 1;

	if(o.debugging > 1)
		printf(" Done\n");
}

//	the name cache
typedef struct _IFNAME_ROW {
	int ifi;
	char name[128];
	DWORD ip;	//	This is one of the interface's IPs
	DWORD type;
} IFNAME_ROW;

static IFNAME_ROW *names = 0;
static int num_names;

static void pcapsend_cleanup(void)
{
	if(!pcapsend_inited)
		return;

	assert(!killthread);

	killthread = 1;
	SetEvent(hEvWakeup);
	if(WAIT_TIMEOUT == WaitForSingleObject(hThread, 10000))
	{
		error("timed out waiting for thread exit; terminating...\n");
		TerminateThread(hThread, 0);
	}

	CloseHandle(hEvWakeup);
	CloseHandle(hThread);
	CloseHandle(hSemQueue);
	DeleteCriticalSection(&csQueue);
	DeleteCriticalSection(&csAdapter);
	DeleteCriticalSection(&csFailCache);
	DeleteCriticalSection(&csArpCache);
	DeleteCriticalSection(&csArpTable);
	cleanup_if_cache();

	if(names) free(names);
	if(pArpTable) free(pArpTable);
}

//	safe implementation for getbestroute
typedef DWORD (__stdcall *PGBR)(DWORD, DWORD, PMIB_IPFORWARDROW);
int get_best_route(DWORD dest, PMIB_IPFORWARDROW r)
{
	static PGBR GBR = 0;
	static int inited = 0;

	int winif = -1, ifi = -1;

	if(!inited)
	{
		HINSTANCE hInst = GetModuleHandle("iphlpapi.dll");
		inited = 1;
		if(hInst && !wo.nt4route)
			GBR = (PGBR)GetProcAddress(hInst, "GetBestRoute");
		if(o.debugging > 1 && !GBR)
			printf("get_best_route: using NT4-compatible method\n");
	}

	//	Find the index
	if(*o.device)
	{
		ifi = name2ifi(o.device);
		winif = ifi2winif(ifi);
		if(winif == -1)
			fatal("get_best_route: nonexistant interface \"%s\"\n", o.device);
	}

	//	Can we simply redirect?
tryagain:
	if(GBR)
	{
		DWORD source = 0;
		DWORD nRes;

		if(ifi != -1)
		{
			if(-1 == ifi2ipaddr(ifi, (struct in_addr*)&source))
				source = 0;	//	wtf?
		}

		nRes = GBR(dest, source, r);
		if(nRes == ERROR_CALL_NOT_IMPLEMENTED)
		{
			GBR = 0;
			goto tryagain;
		}

		if(nRes != 0) return nRes;

		//	verify we have a good match
		if(winif != -1 && r->dwForwardIfIndex != winif)
			return -1;

		return 0;
	}

	//	We need to do this for real
	else
	{
		PMIB_IPFORWARDTABLE pTable = 0;
		int cb = 0;
		int bestmatch = -1;
		int bestmask, bestmetric;
		int nRes, i;

		nRes = GetIpForwardTableSafe(pTable, &cb, FALSE);
		if(cb == 0) return (nRes ? nRes : -1);

		cb += sizeof(MIB_IPFORWARDROW);
		pTable = (PMIB_IPFORWARDTABLE)_alloca(cb);
		nRes = GetIpForwardTableSafe(pTable, &cb, FALSE);
		if(nRes != NO_ERROR) return nRes;

		if(pTable->dwNumEntries < 1) return -1;

		for(i = 0; i < pTable->dwNumEntries; i++)
		{
			//	is it a match?
			if(pTable->table[i].dwForwardDest != (dest & pTable->table[i].dwForwardMask))
				continue;

			if(winif != -1 && pTable->table[i].dwForwardIfIndex != winif) continue;

/*			if(bestmatch == -1 || (pTable->table[i].dwForwardMask > bestmask)
				|| (pTable->table[i].dwForwardMask == bestmask
				&& pTable->table[i].dwForwardMetric1 < bestmetric))*/
			if(bestmatch == -1 || (pTable->table[i].dwForwardMetric1 > bestmetric)
				|| (pTable->table[i].dwForwardMetric1 == bestmetric
				&& pTable->table[i].dwForwardMask > bestmask))

			{
				bestmatch = i;
				bestmask = pTable->table[i].dwForwardMask;
				bestmetric = pTable->table[i].dwForwardMetric1;
			}
		}

		if(bestmatch == -1) return -1;

		memcpy(r, &pTable->table[bestmatch], sizeof(MIB_IPFORWARDROW));

		return 0;
	}
}

//	ARP cache
static void AddToARPCache(DWORD ip, int ifi, BYTE *phys, int physlen)
{
	if(physlen > MAXLEN_PHYSADDR)
		fatal("physical address too long!\n");

	foo0("addtoarpcache: try acquire csArpCache\n");
	EnterCriticalSection(&csArpCache);
	foo0("addtoarpcache: acquired csArpCache\n");
	arpcache[arpfirst].ifi = ifi;
	arpcache[arpfirst].ip = ip;
	memcpy(arpcache[arpfirst].phys, phys, physlen);
	arpcache[arpfirst].physlen = physlen;
	arpfirst = (arpfirst + 1) % ARPCACHELEN;
	LeaveCriticalSection(&csArpCache);
}

static int lookupip(DWORD ip, DWORD ifi)
{
	DWORD time = GetTickCount();
	int nRes;
	int low, high;
	int pass = 0;
	DWORD winif = ifi2winif(ifi);

	EnterCriticalSection(&csArpTable);

	goto pass0;

pass1:
	pass = 1;

	if(arprefresh)
	{
		//	refresh
		int len = arpalloclen;

#ifdef THREAD_DEBUG
		printf("lookupip: refreshing ARP table\n");
#endif

		arprefresh = 0;

readarp:
		nRes = GetIpNetTableSafe(pArpTable, &len, TRUE);

		if(nRes == ERROR_MORE_DATA)
			len += 2 * sizeof(MIB_IPNETROW);	//	give the benefit of the doubt

		if(len == arpalloclen && nRes != NO_ERROR)
		{
			//	Windows bug -- just assume the table is empty
			pArpTable->dwNumEntries = 0;
			LeaveCriticalSection(&csArpTable);
			return -1;
		}

		if(len > arpalloclen)
		{
			//	need to try that again
			free(pArpTable);
			pArpTable = (PMIB_IPNETTABLE)malloc(len);
			arpalloclen = len;
			if(!pArpTable) fatal("out of memory\n");
			goto readarp;	//	please don't infinite loop!
		}
	}

pass0:

	low = 0;
	high = pArpTable->dwNumEntries - 1;
	while(low <= high)
	{
		int i = low + (high - low) / 2;
		if(pArpTable->table[i].dwAddr == ip
			&& pArpTable->table[i].dwType != 2)
		{
			//	we found it
			if(pArpTable->table[i].dwIndex != winif)
			{
				fatal("lookupip: found ip on wrong interface\n"
					"e-mail amluto@hotmail.com if you think this should have worked\n");
			}

			LeaveCriticalSection(&csArpTable);
			return i;
		}

		//	Otherwise, we need to narrow search region
		if(pArpTable->table[i].dwAddr < ip)
			low = i + 1;
		else high = i - 1;
	}

	if(pass == 0) goto pass1;

	LeaveCriticalSection(&csArpTable);
	return -1;
}

static int SearchARP(DWORD ip, int ifi, BYTE *phys, int *physlen)
{
	int i;

	foo0("searcharp: try acquire csArpCache\n");
	EnterCriticalSection(&csArpCache);
	foo0("searcharp: acquired csArpCache\n");

	//	Is it in the ARP cache?
	for(i = 0; i < ARPCACHELEN; i++)
	{
		if(arpcache[i].ip == ip && arpcache[i].ifi == ifi)
		{
			//	we got it!
			if(*physlen < arpcache[i].physlen)
				fatal("searcharp: can't return the answer\n");

			memcpy(phys, arpcache[i].phys, arpcache[i].physlen);
			*physlen = arpcache[i].physlen;
#ifdef THREAD_DEBUG
			printf("searcharp: found %s in cache\n", inet_ntoa(*(struct in_addr*)&ip));
#endif
			LeaveCriticalSection(&csArpCache);
			return 0;
		}
	}

	//	else look it up
	i = lookupip(ip, ifi);

	LeaveCriticalSection(&csArpCache);

	if(i == -1) return -1;

	if(*physlen < pArpTable->table[i].dwPhysAddrLen)
		fatal("insufficient space for physaddr\n");

	*physlen = pArpTable->table[i].dwPhysAddrLen;
	memcpy(phys, pArpTable->table[i].bPhysAddr,
		pArpTable->table[i].dwPhysAddrLen);

#ifdef THREAD_DEBUG
	printf("searcharp: found %s in system ARP table\n", inet_ntoa(*(struct in_addr*)&ip));
#endif

	AddToARPCache(ip, ifi, phys, pArpTable->table[i].dwPhysAddrLen);

	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -