mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-06 09:35:20 +00:00
Adding process_open_ports and listening_sockets virtual tables to Windows (#2760)
This commit is contained in:
parent
601ace89fa
commit
7f5345ec7e
@ -36,6 +36,8 @@ else()
|
||||
endif()
|
||||
|
||||
if(WINDOWS)
|
||||
ADD_OSQUERY_LINK_CORE("ws2_32.lib")
|
||||
ADD_OSQUERY_LINK_CORE("iphlpapi.lib")
|
||||
ADD_OSQUERY_LINK_CORE("netapi32.lib")
|
||||
ADD_OSQUERY_LINK_CORE("rpcrt4.lib")
|
||||
ADD_OSQUERY_LINK_CORE("shlwapi.lib")
|
||||
|
270
osquery/tables/networking/windows/process_open_sockets.cpp
Normal file
270
osquery/tables/networking/windows/process_open_sockets.cpp
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osquery/core.h>
|
||||
#include <osquery/core/conversions.h>
|
||||
#include <osquery/logger.h>
|
||||
#include <osquery/tables.h>
|
||||
|
||||
#include "win_sockets.h"
|
||||
|
||||
namespace osquery {
|
||||
namespace tables {
|
||||
|
||||
WinSockets::WinSockets() {
|
||||
auto pSockTable = allocateSocketTable(IPPROTO_TCP, AF_INET);
|
||||
if (status_.ok()) {
|
||||
tcpTable_ = static_cast<MIB_TCPTABLE_OWNER_PID*>(pSockTable);
|
||||
} else {
|
||||
TLOG << "Error allocating the TCP IPv4 socket table";
|
||||
return;
|
||||
}
|
||||
|
||||
pSockTable = allocateSocketTable(IPPROTO_TCP, AF_INET6);
|
||||
if (status_.ok()) {
|
||||
tcp6Table_ = static_cast<MIB_TCP6TABLE_OWNER_PID*>(pSockTable);
|
||||
} else {
|
||||
TLOG << "Error allocating the TCP IPv6 socket table";
|
||||
return;
|
||||
}
|
||||
|
||||
pSockTable = allocateSocketTable(IPPROTO_UDP, AF_INET);
|
||||
if (status_.ok()) {
|
||||
udpTable_ = static_cast<MIB_UDPTABLE_OWNER_PID*>(pSockTable);
|
||||
} else {
|
||||
TLOG << "Error allocating the UDP IPv4 socket table";
|
||||
return;
|
||||
}
|
||||
|
||||
pSockTable = allocateSocketTable(IPPROTO_UDP, AF_INET6);
|
||||
if (status_.ok()) {
|
||||
udp6Table_ = static_cast<MIB_UDP6TABLE_OWNER_PID*>(pSockTable);
|
||||
} else {
|
||||
TLOG << "Error allocating the UDP IPv6 socket table";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WinSockets::~WinSockets() {
|
||||
if (tcpTable_ != nullptr) {
|
||||
free(tcpTable_);
|
||||
tcpTable_ = nullptr;
|
||||
}
|
||||
if (tcp6Table_ != nullptr) {
|
||||
free(tcp6Table_);
|
||||
tcp6Table_ = nullptr;
|
||||
}
|
||||
if (udpTable_ != nullptr) {
|
||||
free(udpTable_);
|
||||
udpTable_ = nullptr;
|
||||
}
|
||||
if (udp6Table_ != nullptr) {
|
||||
free(udp6Table_);
|
||||
udp6Table_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void WinSockets::parseSocketTable(WinSockTableType sockType,
|
||||
QueryData& results) {
|
||||
unsigned int numEntries;
|
||||
switch (sockType) {
|
||||
case WinSockTableType::tcp:
|
||||
numEntries = tcpTable_->dwNumEntries;
|
||||
break;
|
||||
case WinSockTableType::tcp6:
|
||||
numEntries = tcp6Table_->dwNumEntries;
|
||||
break;
|
||||
case WinSockTableType::udp:
|
||||
numEntries = udpTable_->dwNumEntries;
|
||||
break;
|
||||
case WinSockTableType::udp6:
|
||||
numEntries = udp6Table_->dwNumEntries;
|
||||
break;
|
||||
default:
|
||||
numEntries = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < numEntries; i++) {
|
||||
Row r;
|
||||
std::vector<char> localAddr(128, 0x0);
|
||||
std::vector<char> remoteAddr(128, 0x0);
|
||||
|
||||
auto proto = static_cast<unsigned int>(sockType);
|
||||
r["protocol"] = INTEGER(proto);
|
||||
|
||||
switch (sockType) {
|
||||
case WinSockTableType::tcp: {
|
||||
auto tcpLocalAddr = tcpTable_->table[i].dwLocalAddr;
|
||||
auto retVal =
|
||||
InetNtopA(AF_INET, &tcpLocalAddr, localAddr.data(), localAddr.size());
|
||||
if (retVal == nullptr) {
|
||||
TLOG << "Error converting network local address to string: "
|
||||
<< WSAGetLastError();
|
||||
}
|
||||
r["local_port"] =
|
||||
INTEGER(ntohs(static_cast<u_short>(tcpTable_->table[i].dwLocalPort)));
|
||||
auto tcpRemoteAddr = tcpTable_->table[i].dwRemoteAddr;
|
||||
retVal = InetNtopA(
|
||||
AF_INET, &tcpRemoteAddr, remoteAddr.data(), remoteAddr.size());
|
||||
if (retVal == nullptr) {
|
||||
TLOG << "Error converting network remote address to string: "
|
||||
<< WSAGetLastError();
|
||||
}
|
||||
r["remote_address"] = remoteAddr.data();
|
||||
r["remote_port"] = INTEGER(
|
||||
ntohs(static_cast<u_short>(tcpTable_->table[i].dwRemotePort)));
|
||||
r["pid"] = INTEGER(tcpTable_->table[i].dwOwningPid);
|
||||
r["family"] = INTEGER(AF_INET);
|
||||
break;
|
||||
}
|
||||
|
||||
case WinSockTableType::tcp6: {
|
||||
auto tcp6LocalAddr = tcp6Table_->table[i].ucLocalAddr;
|
||||
auto retVal = InetNtopA(
|
||||
AF_INET6, tcp6LocalAddr, localAddr.data(), localAddr.size());
|
||||
if (retVal == nullptr) {
|
||||
TLOG << "Error converting network local address to string: "
|
||||
<< WSAGetLastError();
|
||||
}
|
||||
r["local_port"] = INTEGER(
|
||||
ntohs(static_cast<u_short>(tcp6Table_->table[i].dwLocalPort)));
|
||||
auto tcp6RemoteAddr = tcp6Table_->table[i].ucRemoteAddr;
|
||||
retVal = InetNtopA(
|
||||
AF_INET6, tcp6RemoteAddr, remoteAddr.data(), remoteAddr.size());
|
||||
if (retVal == nullptr) {
|
||||
TLOG << "Error converting network remote address to string: "
|
||||
<< WSAGetLastError();
|
||||
}
|
||||
r["remote_address"] = remoteAddr.data();
|
||||
r["remote_port"] = INTEGER(
|
||||
ntohs(static_cast<u_short>(tcp6Table_->table[i].dwRemotePort)));
|
||||
r["pid"] = INTEGER(tcp6Table_->table[i].dwOwningPid);
|
||||
r["family"] = INTEGER(AF_INET6);
|
||||
break;
|
||||
}
|
||||
|
||||
case WinSockTableType::udp: {
|
||||
auto udpLocalAddr = udpTable_->table[i].dwLocalAddr;
|
||||
auto retVal =
|
||||
InetNtopA(AF_INET, &udpLocalAddr, localAddr.data(), localAddr.size());
|
||||
if (retVal == nullptr) {
|
||||
TLOG << "Error converting network local address to string: "
|
||||
<< WSAGetLastError();
|
||||
}
|
||||
r["local_port"] =
|
||||
INTEGER(ntohs(static_cast<u_short>(udpTable_->table[i].dwLocalPort)));
|
||||
r["remote_address"] = "0";
|
||||
r["remote_port"] = INTEGER(0);
|
||||
r["pid"] = INTEGER(udpTable_->table[i].dwOwningPid);
|
||||
r["family"] = INTEGER(AF_INET);
|
||||
break;
|
||||
}
|
||||
|
||||
case WinSockTableType::udp6: {
|
||||
auto udp6LocalAddr = udp6Table_->table[i].ucLocalAddr;
|
||||
auto retVal = InetNtopA(
|
||||
AF_INET6, udp6LocalAddr, localAddr.data(), localAddr.size());
|
||||
if (retVal == nullptr) {
|
||||
TLOG << "Error converting network local address to string: "
|
||||
<< WSAGetLastError();
|
||||
}
|
||||
r["local_port"] = INTEGER(
|
||||
ntohs(static_cast<u_short>(udp6Table_->table[i].dwLocalPort)));
|
||||
r["remote_address"] = "0";
|
||||
r["remote_port"] = INTEGER(0);
|
||||
r["pid"] = INTEGER(udp6Table_->table[i].dwOwningPid);
|
||||
r["family"] = INTEGER(AF_INET6);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
r["local_address"] = localAddr.data();
|
||||
results.push_back(r);
|
||||
}
|
||||
}
|
||||
|
||||
void* WinSockets::allocateSocketTable(unsigned long protocol,
|
||||
unsigned long family) {
|
||||
unsigned long ret = 0;
|
||||
unsigned long buffsize = 0;
|
||||
void* pSockTable = nullptr;
|
||||
|
||||
/// Allocate the TCP Socket Tables
|
||||
if (protocol == IPPROTO_TCP) {
|
||||
ret = GetExtendedTcpTable(
|
||||
pSockTable, &buffsize, true, family, TCP_TABLE_OWNER_PID_ALL, 0);
|
||||
if (ret == ERROR_INSUFFICIENT_BUFFER) {
|
||||
pSockTable = static_cast<void*>(malloc(buffsize));
|
||||
if (pSockTable == nullptr) {
|
||||
status_ = Status(
|
||||
1, "Unable to allocate sufficient memory for the TCP socket table");
|
||||
}
|
||||
}
|
||||
ret = GetExtendedTcpTable(pSockTable,
|
||||
reinterpret_cast<PULONG>(&buffsize),
|
||||
true,
|
||||
family,
|
||||
TCP_TABLE_OWNER_PID_ALL,
|
||||
0);
|
||||
if (ret != NO_ERROR) {
|
||||
status_ = Status(1,
|
||||
"Error retrieving the socket table: ( " +
|
||||
std::to_string(GetLastError()) + " )");
|
||||
}
|
||||
}
|
||||
/// Allocate the UDP Socket Tables
|
||||
else {
|
||||
ret = GetExtendedUdpTable(pSockTable,
|
||||
reinterpret_cast<PULONG>(&buffsize),
|
||||
true,
|
||||
family,
|
||||
UDP_TABLE_OWNER_PID,
|
||||
0);
|
||||
if (ret == ERROR_INSUFFICIENT_BUFFER) {
|
||||
pSockTable = static_cast<void*>(malloc(buffsize));
|
||||
if (pSockTable == nullptr) {
|
||||
status_ = Status(
|
||||
1, "Unable to allocate sufficient memory for the UDP socket table");
|
||||
}
|
||||
}
|
||||
ret = GetExtendedUdpTable(pSockTable,
|
||||
reinterpret_cast<PULONG>(&buffsize),
|
||||
true,
|
||||
family,
|
||||
UDP_TABLE_OWNER_PID,
|
||||
0);
|
||||
if (ret != NO_ERROR) {
|
||||
status_ = Status(1,
|
||||
"Error retrieving the socket table: ( " +
|
||||
std::to_string(GetLastError()) + " )");
|
||||
}
|
||||
}
|
||||
return pSockTable;
|
||||
}
|
||||
|
||||
QueryData genOpenSockets(QueryContext& context) {
|
||||
QueryData results;
|
||||
WinSockets sockTable;
|
||||
|
||||
sockTable.parseSocketTable(WinSockTableType::tcp, results);
|
||||
|
||||
sockTable.parseSocketTable(WinSockTableType::tcp6, results);
|
||||
|
||||
sockTable.parseSocketTable(WinSockTableType::udp, results);
|
||||
|
||||
sockTable.parseSocketTable(WinSockTableType::udp6, results);
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
54
osquery/tables/networking/windows/win_sockets.h
Normal file
54
osquery/tables/networking/windows/win_sockets.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ws2tcpip.h>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Iphlpapi.h>
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
namespace osquery {
|
||||
namespace tables {
|
||||
|
||||
enum class WinSockTableType { tcp, tcp6, udp, udp6 };
|
||||
|
||||
class WinSockets : private boost::noncopyable {
|
||||
public:
|
||||
/// Retreives all of the socket table structures from the Windows API
|
||||
WinSockets();
|
||||
|
||||
/// Ensures that all Socket tables have been deallocated
|
||||
~WinSockets();
|
||||
|
||||
/// Parses all of the socket entries and populates the results QueryData
|
||||
void parseSocketTable(WinSockTableType sockType, QueryData& results);
|
||||
|
||||
/// Returns the status of the Sockets Table
|
||||
Status getStatus() const {
|
||||
return status_;
|
||||
};
|
||||
|
||||
private:
|
||||
Status status_;
|
||||
MIB_TCPTABLE_OWNER_PID* tcpTable_ = nullptr;
|
||||
MIB_TCP6TABLE_OWNER_PID* tcp6Table_ = nullptr;
|
||||
MIB_UDPTABLE_OWNER_PID* udpTable_ = nullptr;
|
||||
MIB_UDP6TABLE_OWNER_PID* udp6Table_ = nullptr;
|
||||
|
||||
/// Helper function to allocate a table based off of family and protocol
|
||||
void* WinSockets::allocateSocketTable(unsigned long protocol,
|
||||
unsigned long family);
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user