Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for SNI and dynamic certificate #198

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
Version 3.4
-----------
* Add support for SNI on Windows - dynamically generate a certificate based
on client request using Server Name Indicator on Windows platform
* Sign the new certificate with either a static CA certificate, or
with a newly generated CA
* Add config options to specify a path to static CA certificate

Version 3.3
-----------
* Hide logging in DNS listener and Diverter for blacklisted processes
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

D O C U M E N T A T I O N

FakeNet-NG 3.3 is a next generation dynamic network analysis tool for malware
FakeNet-NG 3.4 is a next generation dynamic network analysis tool for malware
analysts and penetration testers. It is open source and designed for the latest
versions of Windows (and Linux, for certain modes of operation). FakeNet-NG is
based on the excellent Fakenet tool developed by Andrew Honig and Michael
Expand Down
10 changes: 10 additions & 0 deletions docs/contributors.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,13 @@ mentor Tina Johnson (@tinajohnson) to add HTML- and text-based reporting of
network-based indicators (NBIs) to FakeNet-NG, requiring significant work
throughout the codebase to facilitate the necessary communication and tracking
between components.

## Server Name Indication

Nhan Huynh (@htnhan) added support for Server Name Indication to FakeNet-NG
for the Windows platform by implementing dynamic generation of server
certificates.

## Maintenance

Tina Johnson (@tinajohnson) and Michael Bailey (@strictlymike)
20 changes: 14 additions & 6 deletions fakenet/configs/default.ini
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ NetworkMode: Auto
# DebugLevel: specify fine-grained debug print flags to enable. Enabling all
# logging when verbose mode is selected results in overwhelming output, hence
# this setting. Valid values (comma-separated) are:
#
#
# GENPKT Generic packet information
# GENPKTV Packet analysis, displays IP, TCP, UDP fields, very wide output
# CB Diverter packet handler callback start/finish logging
Expand Down Expand Up @@ -88,7 +88,7 @@ FixDNS: Yes
# ephemeral change.
ModifyLocalDNS: Yes

# Enable 'StopDNSService' to stop Windows DNS client to see the actual
# Enable 'StopDNSService' to stop Windows DNS client to see the actual
# processes resolving domains. This is a no-op on Linux, until such time as DNS
# caching is observed to interfere with finding the pid associated with a DNS
# request.
Expand All @@ -99,16 +99,16 @@ StopDNSService: Yes
# 'DefaultUDPListener' will handle TCP and UDP traffic going to unspecified ports.
#
# NOTE: Setting default UDP listener will intercept all DNS traffic unless you
# enable a dedicated UDP port 53 DNS listener or add UDP port 53 to the
# enable a dedicated UDP port 53 DNS listener or add UDP port 53 to the
# 'BlackListPortsUDP' below so that system's default DNS server is used instead.

RedirectAllTraffic: Yes
DefaultTCPListener: ProxyTCPListener
DefaultUDPListener: ProxyUDPListener

# Specify TCP and UDP ports to ignore when diverting packets.
# Specify TCP and UDP ports to ignore when diverting packets.
# For example, you may want to avoid diverting UDP port 53 (DNS) traffic
# when trying to intercept a specific process while allowing the rest to
# when trying to intercept a specific process while allowing the rest to
# function normally
#
# NOTE: This setting is only honored when 'RedirectAllTraffic' is enabled.
Expand All @@ -131,7 +131,7 @@ BlackListPortsUDP: 67, 68, 137, 138, 443, 1900, 5355
# Listener Configuration
#
# Listener configuration consists of generic settings used by the diverter which
# are the same for all listeners and listener specific settings.
# are the same for all listeners and listener specific settings.
#
# NOTE: Listener section names will be used for logging.
#
Expand Down Expand Up @@ -199,6 +199,11 @@ BlackListPortsUDP: 67, 68, 137, 138, 443, 1900, 5355
# hostname string, !hostname to insert the actual hostname
# of the system, or !random to generate a random hostname
# between 1 and 15 characters (inclusive).
# * Static_CA - Set FakeNet to use user provided CA certificate to sign generated certificates.
# * CA_Cert - CA certificate in PEM format to be used when Static_CA config is set. Manually
# add this certificate to Windows trust store before executing FakeNet.
# * CA_Key - CA private key in PEM format to be used when Static_CA config is set.


[ProxyTCPListener]
Enabled: True
Expand All @@ -207,6 +212,9 @@ Listener: ProxyListener
Port: 38926
Listeners: HTTPListener, RawListener, FTPListener, DNSListener, POPListener, SMTPListener, TFTPListener, IRCListener
Hidden: False
Static_CA: No
CA_Cert: configs/fakenet_ca.crt
CA_Key: configs/fakenet_ca.key

[ProxyUDPListener]
Enabled: True
Expand Down
18 changes: 18 additions & 0 deletions fakenet/configs/fakenet_ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC2jCCAcKgAwIBAgIDAh5sMA0GCSqGSIb3DQEBCwUAMCUxCzAJBgNVBAYTAlVT
MRYwFAYDVQQDDA1mYWtlbmV0LmZsYXJlMB4XDTI1MDExNzA5MzU1MloXDTI1MTEx
MzEwMDQ0OVowJTELMAkGA1UEBhMCVVMxFjAUBgNVBAMMDWZha2VuZXQuZmxhcmUw
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNy0pIJbYx6RiJff737Oqc
r17kBh/7wt20svoxI8gtYcidprDZ0vwfBO9OugzB/NHfFiJk3NpZky9UAHRM3Xpg
CHdC/HNe1ilXN+NjTmhvpZiG2fl9u0C30tN/2l6UEkuD1AeNl5HZZddtjPOaKHFO
0+xojIebSi1MwJXSLVo/MNjygKt93YQiHA8N8Z0sQnAuYEydhejLvjxrMD7V+ENF
4a3ZyWLard6vPGm/Sk++sULRx4W32YxZfuom/yiuNTDI/+gRh+Yvs2CRycbVDWkq
OynZu/ONtXMsgUlZpuQE6JeKeEcPPp9k0GByoZZJaTBAigbdkba8dexv/4O8UIMj
AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBACqF
1RHwQgoOVz3Yf2Vaw8Nv8aEAFe79OAXF/dxJ5pY2Dnhusn1vJo7QsyyKRfQ/Vfaz
F9DKDiUPqfrxRHY1VOBm1+fOKGxSZUMNKTwJLRc25Fg/SLVO1NU022WcnZlc+jKx
47oekFkiMzUKofiZbhbciECinwIrq7d0TnBaB6vc9XC+NhcSxgBHKMP/sBd/UbF4
3PS481XaBTVeZEi+s3v6FNrlIouHmb8aNpz+DuLX/emF/O0yGnbKeQH51jvwZZZM
mOJpIVmKnsZ3wfWKXdOUmDpsUOWLNk2it31UleAfLFaLWcKcIF356h+KAy0gHRfr
FVALnTQ2m7HYAKk18D4=
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions fakenet/configs/fakenet_ca.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDNy0pIJbYx6RiJ
ff737Oqcr17kBh/7wt20svoxI8gtYcidprDZ0vwfBO9OugzB/NHfFiJk3NpZky9U
AHRM3XpgCHdC/HNe1ilXN+NjTmhvpZiG2fl9u0C30tN/2l6UEkuD1AeNl5HZZddt
jPOaKHFO0+xojIebSi1MwJXSLVo/MNjygKt93YQiHA8N8Z0sQnAuYEydhejLvjxr
MD7V+ENF4a3ZyWLard6vPGm/Sk++sULRx4W32YxZfuom/yiuNTDI/+gRh+Yvs2CR
ycbVDWkqOynZu/ONtXMsgUlZpuQE6JeKeEcPPp9k0GByoZZJaTBAigbdkba8dexv
/4O8UIMjAgMBAAECggEAMID+GIQe7aORX3KdYiTqZRSmalsRNb8Hjzvx4RwcZana
5WFw5F4og00f9C/AqwYiFxD5+Ujeg+c/a+6Rer5mxfSo21ZyAMO8SazIANNtpQbk
LMB6X8p/JfRgWg2HZiHrv339a79yJkmtHUpv7gEjN5+WZEve+Fhi1ei8RyXeU+8M
uDYK0BQl5xhXEVQECkzu4P7hV3jLT+jW+GMznWWhvUOQVc9gmzAgYKx6aGhgk+r8
tdtpFJlIipJukJOwaZdOHzZAnXm/WEJDTrhDc36xr7+I3yKwzGry6hPPhjyC0lri
BAY7I/aMeOEUycI2UhDBhW1HC6CKO5mDD5wUT9CRnQKBgQDms7eU3bkNzpgQ46mv
qibIqkVSOxzDqNIKmTdo5iCk8tyruJ7wzDLkUTFPvCv5voWQq53AUv8OtYf5mZtd
mhGgiEkcN2/F61UXRTcWo3XJJR9y9gnSBQTWyOsB8wQ6vbzbh38xEWC1K/7gKs/Y
dz7TOJudgAZtRviwg48iHZZXhQKBgQDkXFs076l0imLJE/at3qMr6c2oakfiznqe
mpKi3VFF0w1Eu0k3HuaUS6Y8JZg3awBWgmiJCsE7DzxnjpZRN/VlGpS1M2CHlcqT
TKE8n6MGR0PteIxWK0dKRqeQLpNUd1ib3oHv/nw3WN7MZW+Tiawl0nozJ9Y3octA
GRoPd7+shwKBgBUimcr1lSKCrsO9V6pUOEFh9//UkooKSVPXPZBKpOr3pOfGfikp
S/BGz/GyF4VFww7B6i3YbK14TAC95dHpb3v5gFkpawAC00TSfn2AdCX9VKg/ih7H
fu3+cik3jkejYk3qV+iy4t02Lp9yzJ/ULNlE8ly3gd85BUeGhfJmK4PRAoGBAMPj
nbGJLJl15EuMvnxjkSEoTGx9zvB2IqVO/x6KLx9wbd9ZsPKBpVXslsrdjPds6DtN
XpLAEQWyiiRjIfrFv9Fcvde6HMHx8nXstBsm7VeDZnecgvWf5mWGulJqQaOhRPdg
JaJTcQahS22WTeIHpQ5EwOKE97N9LLbtUXeXR2qdAoGBAL3Y6CiMu8Q/oOTDsdDs
6Si0NZexy7frzT+kCgh4yJxEYhqCBo2AUeK62M0Id2T1tlUieLyvX0j9VAsOLLeD
FdJhbx3N7UOHpwqjUekkPLsw+YpGEW8Zb8pJbImNNi35foglO+voFXYiaaY9daL6
DUK0CtoxZRZErZtjRY882WKa
-----END PRIVATE KEY-----
4 changes: 2 additions & 2 deletions fakenet/diverters/diverterbase.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2016-2023 Mandiant, Inc. All rights reserved.
# Copyright (C) 2016-2024 Mandiant, Inc. All rights reserved.

import os
import abc
Expand Down Expand Up @@ -958,7 +958,7 @@ def _build_cmd(self, tmpl, pid, comm, src_ip, sport, dst_ip, dport):
except KeyError as e:
self.logger.error(('Failed to build ExecuteCmd for port %d due ' +
'to erroneous format key: %s') %
(dport, e.message))
(dport, e))

return cmd

Expand Down
28 changes: 14 additions & 14 deletions fakenet/diverters/linutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,10 @@ def start(self, timeout_sec=0.5):
self._bound = True
except OSError as e:
self.logger.error('Failed to start queue for %s: %s' %
(str(self), e.message))
(str(self), e))
except RuntimeWarning as e:
self.logger.error('Failed to start queue for %s: %s' %
(str(self), e.message))
(str(self), e))

if not self._bound:
return False
Expand All @@ -166,7 +166,7 @@ def start(self, timeout_sec=0.5):
self._thread.start()
self._started = True
except RuntimeError as e:
self.logger.error('Failed to start queue thread: %s' % (e.message))
self.logger.error('Failed to start queue thread: %s' % (e))

return self._started

Expand Down Expand Up @@ -251,7 +251,7 @@ def parse(self, multi=False, max_col=None):
retval = cb_retval
break
except IOError as e:
self.logger.error('Failed accessing %s: %s' % (path, e.message))
self.logger.error('Failed accessing %s: %s' % (path, e))
# All or nothing
retval = [] if multi else None

Expand Down Expand Up @@ -313,7 +313,7 @@ def linux_capture_iptables(self):
ret = p.wait()
except OSError as e:
self.logger.error('Error executing iptables-save: %s' %
(e.message))
(e))

return ret

Expand All @@ -328,7 +328,7 @@ def linux_restore_iptables(self):
ret = p.wait()
except OSError as e:
self.logger.error('Error executing iptables-restore: %s' %
(e.message))
(e))

return ret

Expand All @@ -351,7 +351,7 @@ def linux_flush_iptables(self):
self.logger.error('Received return code %d from %s' +
(ret, cmd))
except OSError as e:
self.logger.error('Error executing %s: %s' % (cmd, e.message))
self.logger.error('Error executing %s: %s' % (cmd, e))

return rets

Expand Down Expand Up @@ -388,7 +388,7 @@ def linux_get_current_nfnlq_bindings(self):
self.logger.debug(('Failed to open %s to enumerate netfilter '
'netlink queues, caller may proceed as if '
'none are in use: %s') %
(procfs_path, e.message))
(procfs_path, e))

return qnos

Expand Down Expand Up @@ -445,7 +445,7 @@ def _linux_get_ifaces(self):
ifaces.append(fields[0].strip())
except IOError as e:
self.logger.error('Failed to open %s to enumerate interfaces: %s' %
(procfs_path, e.message))
(procfs_path, e))

return ifaces

Expand All @@ -472,7 +472,7 @@ def linux_modifylocaldns_ephemeral(self):
except IOError as e:
self.logger.error(('Failed to open %s to save DNS ' +
'configuration: %s') % (resolvconf_path,
e.message))
e))

if self.old_dns:
try:
Expand All @@ -484,7 +484,7 @@ def linux_modifylocaldns_ephemeral(self):
except IOError as e:
self.logger.error(('Failed to open %s to modify DNS ' +
'configuration: %s') % (resolvconf_path,
e.message))
e))

def linux_restore_local_dns(self):
resolvconf_path = '/etc/resolv.conf'
Expand All @@ -496,7 +496,7 @@ def linux_restore_local_dns(self):
except IOError as e:
self.logger.error(('Failed to open %s to restore DNS ' +
'configuration: %s') % (resolvconf_path,
e.message))
e))

def linux_find_processes(self, names):
"""But what if a blacklisted process spawns after we call
Expand Down Expand Up @@ -618,7 +618,7 @@ def _linux_find_sock_by_endpoint_unsafe(self, ipver, proto_name, ip, port,
(line.strip()))
except IOError as e:
self.logger.error('No such protocol/IP ver (%s) or error: %s' %
(procfs_path, e.message))
(procfs_path, e))

return inode

Expand Down Expand Up @@ -701,7 +701,7 @@ def linux_get_comm_by_pid(self, pid):
comm = f.read().strip()
except IOError as e:
self.pdebug(DPROCFS, 'Failed to open %s: %s' %
(procfs_path, e.message))
(procfs_path, e))
return comm

def linux_get_pid_comm_by_endpoint(self, ipver, proto_name, ip, port):
Expand Down
4 changes: 2 additions & 2 deletions fakenet/fakenet.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def start(self):
self.logger.error("%s" % e)

else:

listener_config['networkmode'] = self.diverter_config['networkmode']
listener_provider_instance = listener_provider(
listener_config, listener_name, self.logging_level)

Expand Down Expand Up @@ -349,7 +349,7 @@ def main():
| | / ____ \| . \| |____| |\ | |____ | | | |\ | |__| |
|_|/_/ \_\_|\_\______|_| \_|______| |_| |_| \_|\_____|

Version 3.3
Version 3.4
_____________________________________________________________
Developed by FLARE Team
Copyright (C) 2016-2024 Mandiant, Inc. All rights reserved.
Expand Down
2 changes: 1 addition & 1 deletion fakenet/listeners/DNSListener.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class DNSListener(object):

def taste(self, data, dport):

confidence = 1 if dport is 53 else 0
confidence = 1 if dport == 53 else 0

try:
d = DNSRecord.parse(data)
Expand Down
Loading