mirror of
https://github.com/rapid7/metasploit-payloads
synced 2024-11-26 17:41:08 +01:00
Land #599, Bind to the specified LocalHost
This commit is contained in:
commit
ca639d4756
@ -19,6 +19,52 @@
|
|||||||
extern IN6_ADDR in6addr_any;
|
extern IN6_ADDR in6addr_any;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int get_ai_family(const char* address) {
|
||||||
|
struct addrinfo* resolved_host = NULL;
|
||||||
|
struct addrinfo hints = {
|
||||||
|
.ai_family = AF_UNSPEC,
|
||||||
|
.ai_flags = AI_NUMERICHOST
|
||||||
|
};
|
||||||
|
|
||||||
|
int ai_family = AF_UNSPEC;
|
||||||
|
if (getaddrinfo(address, NULL, &hints, &resolved_host) == 0) {
|
||||||
|
ai_family = resolved_host->ai_family;
|
||||||
|
freeaddrinfo(resolved_host);
|
||||||
|
}
|
||||||
|
return ai_family;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The inet_pton function is not available prior to Windows 8.1 so
|
||||||
|
// use getaddrinfo.
|
||||||
|
static int inet_pton(int af, const char* src, void* dst) {
|
||||||
|
struct addrinfo* resolved_host = NULL;
|
||||||
|
struct addrinfo hints = {
|
||||||
|
.ai_family = af,
|
||||||
|
.ai_flags = AI_NUMERICHOST
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((af != AF_INET) && (af != AF_INET6)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ai_family = AF_UNSPEC;
|
||||||
|
if (getaddrinfo(src, NULL, &hints, &resolved_host)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (resolved_host->ai_family != af) { // verify the returned address is of the expected family
|
||||||
|
freeaddrinfo(resolved_host);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (af == AF_INET) {
|
||||||
|
memcpy(dst, &((struct sockaddr_in*)resolved_host->ai_addr)->sin_addr, sizeof(struct in_addr));
|
||||||
|
} else if (af == AF_INET6) {
|
||||||
|
memcpy(dst, &((struct sockaddr_in6*)resolved_host->ai_addr)->sin6_addr, sizeof(struct in_addr6));
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(resolved_host);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Deallocates and cleans up the attributes of a tcp server socket context.
|
* @brief Deallocates and cleans up the attributes of a tcp server socket context.
|
||||||
* @param ctx Pointer to the context to free.
|
* @param ctx Pointer to the context to free.
|
||||||
@ -283,6 +329,7 @@ DWORD request_net_tcp_server_channel_open(Remote * remote, Packet * packet)
|
|||||||
StreamChannelOps chops = { 0 };
|
StreamChannelOps chops = { 0 };
|
||||||
USHORT localPort = 0;
|
USHORT localPort = 0;
|
||||||
BOOL v4Fallback = FALSE;
|
BOOL v4Fallback = FALSE;
|
||||||
|
int ai_family = AF_UNSPEC;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -305,12 +352,28 @@ DWORD request_net_tcp_server_channel_open(Remote * remote, Packet * packet)
|
|||||||
localPort = (USHORT)(met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_LOCAL_PORT) & 0xFFFF);
|
localPort = (USHORT)(met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_LOCAL_PORT) & 0xFFFF);
|
||||||
localHost = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_LOCAL_HOST);
|
localHost = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_LOCAL_HOST);
|
||||||
|
|
||||||
ctx->fd = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
|
if ((localHost) && (strlen(localHost) == 0)) {
|
||||||
|
// normalize empty host strings
|
||||||
|
localHost = NULL;
|
||||||
|
}
|
||||||
|
if (localHost) {
|
||||||
|
ai_family = get_ai_family(localHost);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ai_family = AF_INET6;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->fd = WSASocket(ai_family, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
|
||||||
if (ctx->fd == INVALID_SOCKET)
|
if (ctx->fd == INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
v4Fallback = TRUE;
|
if ((ai_family == AF_INET6) && (!localHost)) {
|
||||||
|
// if the socket that failed to be created was IPv6 but it was only selected because not
|
||||||
|
// address was specified, fail back to IPv4
|
||||||
|
ai_family = AF_INET;
|
||||||
|
ctx->fd = WSASocket(ai_family, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (ai_family == AF_INET6)
|
||||||
{
|
{
|
||||||
int no = 0;
|
int no = 0;
|
||||||
if (setsockopt(ctx->fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&no, sizeof(no)) == SOCKET_ERROR)
|
if (setsockopt(ctx->fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&no, sizeof(no)) == SOCKET_ERROR)
|
||||||
@ -319,29 +382,46 @@ DWORD request_net_tcp_server_channel_open(Remote * remote, Packet * packet)
|
|||||||
// support IPv4 and IPv6 we'd need to create two separate sockets. IPv6 on XP isn't that common
|
// support IPv4 and IPv6 we'd need to create two separate sockets. IPv6 on XP isn't that common
|
||||||
// so instead, we'll just revert back to v4 and listen on that one address instead.
|
// so instead, we'll just revert back to v4 and listen on that one address instead.
|
||||||
closesocket(ctx->fd);
|
closesocket(ctx->fd);
|
||||||
v4Fallback = TRUE;
|
ai_family = AF_INET;
|
||||||
|
ctx->fd = WSASocket(ai_family, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ctx->fd == INVALID_SOCKET) {
|
||||||
|
BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. WSASocket failed");
|
||||||
|
}
|
||||||
|
|
||||||
struct sockaddr_in6 sockAddr = { 0 };
|
struct sockaddr_in6 sockAddr = { 0 };
|
||||||
DWORD sockAddrSize = 0;
|
DWORD sockAddrSize = 0;
|
||||||
|
|
||||||
if (v4Fallback)
|
if (ai_family == AF_INET)
|
||||||
{
|
{
|
||||||
struct sockaddr_in* v4Addr = (struct sockaddr_in*)&sockAddr;
|
struct sockaddr_in* v4Addr = (struct sockaddr_in*)&sockAddr;
|
||||||
v4Addr->sin_addr.s_addr = localHost == NULL ? htons(INADDR_ANY) : inet_addr(localHost);
|
if (localHost) {
|
||||||
|
inet_pton(AF_INET, localHost, &v4Addr->sin_addr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v4Addr->sin_addr.s_addr = INADDR_ANY;
|
||||||
|
}
|
||||||
v4Addr->sin_family = AF_INET;
|
v4Addr->sin_family = AF_INET;
|
||||||
v4Addr->sin_port = htons(localPort);
|
v4Addr->sin_port = htons(localPort);
|
||||||
sockAddrSize = sizeof(struct sockaddr_in);
|
sockAddrSize = sizeof(struct sockaddr_in);
|
||||||
}
|
}
|
||||||
else
|
else if (ai_family == AF_INET6)
|
||||||
{
|
{
|
||||||
// TODO: add IPv6 address binding support
|
if (localHost) {
|
||||||
sockAddr.sin6_addr = in6addr_any;
|
inet_pton(AF_INET6, localHost, &sockAddr.sin6_addr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sockAddr.sin6_addr = in6addr_any;
|
||||||
|
}
|
||||||
sockAddr.sin6_family = AF_INET6;
|
sockAddr.sin6_family = AF_INET6;
|
||||||
sockAddr.sin6_port = htons(localPort);
|
sockAddr.sin6_port = htons(localPort);
|
||||||
sockAddrSize = sizeof(struct sockaddr_in6);
|
sockAddrSize = sizeof(struct sockaddr_in6);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. bind failed, invalid address", ERROR_INVALID_PARAMETER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (bind(ctx->fd, (SOCKADDR *)&sockAddr, sockAddrSize) == SOCKET_ERROR)
|
if (bind(ctx->fd, (SOCKADDR *)&sockAddr, sockAddrSize) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
@ -364,7 +444,7 @@ DWORD request_net_tcp_server_channel_open(Remote * remote, Packet * packet)
|
|||||||
BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. WSAEventSelect failed");
|
BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. WSAEventSelect failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->ipv6 = !v4Fallback;
|
ctx->ipv6 = ai_family == AF_INET6;
|
||||||
|
|
||||||
memset(&chops, 0, sizeof(StreamChannelOps));
|
memset(&chops, 0, sizeof(StreamChannelOps));
|
||||||
chops.native.context = ctx;
|
chops.native.context = ctx;
|
||||||
|
Loading…
Reference in New Issue
Block a user