Skip to content

Commit ff8873c

Browse files
committed
first commit
0 parents  commit ff8873c

File tree

9 files changed

+404
-0
lines changed

9 files changed

+404
-0
lines changed

.gitignore

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
temp.txt
2+
temp.py
3+
downloads/
4+
logs/
5+
*.config
6+
*.log
7+
8+
9+
# Byte-compiled / optimized / DLL files
10+
__pycache__/
11+
*.py[cod]
12+
*$py.class
13+
14+
# C extensions
15+
*.so
16+
17+
# Distribution / packaging
18+
.Python
19+
build/
20+
develop-eggs/
21+
dist/
22+
downloads/
23+
eggs/
24+
.eggs/
25+
lib/
26+
lib64/
27+
parts/
28+
sdist/
29+
var/
30+
wheels/
31+
*.egg-info/
32+
.installed.cfg
33+
*.egg
34+
MANIFEST
35+
36+
# PyInstaller
37+
# Usually these files are written by a python script from a template
38+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
39+
*.manifest
40+
*.spec
41+
42+
# Installer logs
43+
pip-log.txt
44+
pip-delete-this-directory.txt
45+
46+
# Unit test / coverage reports
47+
htmlcov/
48+
.tox/
49+
.coverage
50+
.coverage.*
51+
.cache
52+
nosetests.xml
53+
coverage.xml
54+
*.cover
55+
.hypothesis/
56+
.pytest_cache/
57+
58+
# Translations
59+
*.mo
60+
*.pot
61+
62+
# Django stuff:
63+
*.log
64+
local_settings.py
65+
db.sqlite3
66+
67+
# Flask stuff:
68+
instance/
69+
.webassets-cache
70+
71+
# Scrapy stuff:
72+
.scrapy
73+
74+
# Sphinx documentation
75+
docs/_build/
76+
77+
# PyBuilder
78+
target/
79+
80+
# Jupyter Notebook
81+
.ipynb_checkpoints
82+
83+
# pyenv
84+
.python-version
85+
86+
# celery beat schedule file
87+
celerybeat-schedule
88+
89+
# SageMath parsed files
90+
*.sage.py
91+
92+
# Environments
93+
.env
94+
.venv
95+
env/
96+
venv/
97+
ENV/
98+
env.bak/
99+
venv.bak/
100+
101+
# Spyder project settings
102+
.spyderproject
103+
.spyproject
104+
105+
# Rope project settings
106+
.ropeproject
107+
108+
# mkdocs documentation
109+
/site
110+
111+
# mypy
112+
.mypy_cache/

README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Icarus
2+
**Goal:**
3+
4+
SMTP honeypot for collecting malware and automatically uploading to virustotal.
5+
6+
There are many awesome SMTP honeypots but they are for spam. https://github.com/paralax/awesome-honeypots
7+
8+
**Future Features:**
9+
10+
1. Log to ELK or Splunk
11+
2. Log IP addresses.
12+
3. Log email addresses To and From
13+
3. Report IP addresses to an antispam api service.
14+
4. Improve my skills significantly in Git and Python.
15+
5. More than 1 attachment at a time.
16+
6. Database statistics
17+
6.1. Seen Count
18+
6.2. Timestamps for longevity / lifetime tracking
19+
7. Cleanup process for logs and downloads.
20+
8. Cuckoo API?
21+
9. Config file the IP choice.
22+
10. Chroot or nobody:nobody.
23+
24+
**Raspbian from scratch:**
25+
Raspbian 9 has Python 3.5.3 by default. Which should work.
26+
27+
git clone https://github.com/tbiens/icarus.git
28+
29+
cd icarus
30+
31+
pip3 install --upgrade pip
32+
33+
pip3 install requests aiosmtpd
34+
35+
python3 setup.py
36+
37+
38+
**Setup:**
39+
40+
Minimum Python seems to be 3.5. I made this in 3.7.
41+
42+
apt-get install python3-requests python3-aiosmtpd
43+
44+
or
45+
>#Python3 requests module is for uploading to virus total; aiosmtpd for the smtp protocol.
46+
47+
pip3 install requests aiosmtpd
48+
49+
>#Enter your virustotal API Key in.
50+
51+
nano icarus.config
52+
53+
**To run it:**
54+
55+
python3 setup.py
56+
57+
A copy of the attachments are kept in the ./downloads/ folder.
58+
59+
The virustotal links are stored in ./logs/virustotal.log

__init__.py

Whitespace-only changes.

downloads/.gitignore

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
*.egg-info/
24+
.installed.cfg
25+
*.egg
26+
MANIFEST
27+
28+
# PyInstaller
29+
# Usually these files are written by a python script from a template
30+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
31+
*.manifest
32+
*.spec
33+
34+
# Installer logs
35+
pip-log.txt
36+
pip-delete-this-directory.txt
37+
38+
# Unit test / coverage reports
39+
htmlcov/
40+
.tox/
41+
.coverage
42+
.coverage.*
43+
.cache
44+
nosetests.xml
45+
coverage.xml
46+
*.cover
47+
.hypothesis/
48+
.pytest_cache/
49+
50+
# Translations
51+
*.mo
52+
*.pot
53+
54+
# Django stuff:
55+
*.log
56+
local_settings.py
57+
db.sqlite3
58+
59+
# Flask stuff:
60+
instance/
61+
.webassets-cache
62+
63+
# Scrapy stuff:
64+
.scrapy
65+
66+
# Sphinx documentation
67+
docs/_build/
68+
69+
# PyBuilder
70+
target/
71+
72+
# Jupyter Notebook
73+
.ipynb_checkpoints
74+
75+
# pyenv
76+
.python-version
77+
78+
# celery beat schedule file
79+
celerybeat-schedule
80+
81+
# SageMath parsed files
82+
*.sage.py
83+
84+
# Environments
85+
.env
86+
.venv
87+
env/
88+
venv/
89+
ENV/
90+
env.bak/
91+
venv.bak/
92+
93+
# Spyder project settings
94+
.spyderproject
95+
.spyproject
96+
97+
# Rope project settings
98+
.ropeproject
99+
100+
# mkdocs documentation
101+
/site
102+
103+
# mypy
104+
.mypy_cache/

icarus.config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[APIKEY]
2+
APIKEY = PUT API KEY HERE

logs/logging.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
IP Address:, From:, To:, Date

memoryfile.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import io #https://docs.python.org/3/library/allos.html
2+
#import shutil
3+
import os #for os.path.isfile
4+
import hashlib #https://docs.python.org/3/library/hashlib.html
5+
#import sqlite3 #https://docs.python.org/3/library/sqlite3.html
6+
from virustotal import virustotalfile #Check out virustotal.py
7+
from datetime import datetime
8+
9+
10+
def inmemoryfile(filecontents):
11+
memoryfile = io.StringIO()
12+
memoryfile.write(filecontents)
13+
#This stores the file in memory. We limit email size to 30MB or so.
14+
email = memoryfile.getvalue()
15+
if 'Content-Disposition: attachment;' in filecontents: #Checking if there's an attachment
16+
beforeboundary = email.split('Content-Disposition: attachment;')[1]
17+
18+
#emails have a bunch of stuff in it, I'm splitting the attachment off.
19+
attachment = beforeboundary.split('--boundary')[0]
20+
21+
#there was a tiny bit of text after the attachment that was screwing up the sha256
22+
shahash = hashlib.sha256(attachment.encode()).hexdigest() # read() the file, then you need to convert it to bytes with encode, then hexdigest cleans up
23+
if os.path.isfile("./downloads/" + shahash):
24+
print("Already have this attachment") #checking if I have already received that file
25+
else:
26+
filename = open("downloads/" + shahash,"w+") # open sha256 named file
27+
filename.write(attachment) #Reading the memoryfile into the actual file being written to disk.
28+
filename.close() #closing is important.
29+
# shutil.move(shahash, "downloads/" + shahash) #moving the file from . to ./downloads/
30+
virustotalfile(shahash) #Send the file to my virustotal script
31+
memoryfile.close() #closing is important.
32+
33+
else:
34+
print("No attachment?")
35+
36+
37+
def loggingaddresses(sessionpeer, mailfrom, mailto): #Logging connections to a csv file
38+
39+
nowdate = datetime.now(tz=None) #What date and time.
40+
41+
loggingfile = open("logs/logging.csv","a+")
42+
#Opening logs/logging.csv in append mode.
43+
loggingfile.write(sessionpeer + "," + mailfrom + "," + mailto + "," + nowdate + "\n")
44+
#Logging, IP, From, To, and the Date
45+
loggingfile.close()
46+
47+

setup.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
#import asyncio # https://aiosmtpd.readthedocs.io/en/latest/aiosmtpd/docs/controller.html
3+
#import aiosmtpd # the smtp library
4+
import socket #To get your IP address for the server to run on.
5+
#from sha256 import sha256temp #My sha256.py file.
6+
from aiosmtpd.controller import Controller #the controller that handles async smtp?
7+
from memoryfile import inmemoryfile
8+
from memoryfile import loggingaddresses
9+
10+
def get_ip_address():
11+
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
12+
s.connect(("8.8.8.8", 80))
13+
return s.getsockname()[0]
14+
15+
IP = get_ip_address()
16+
print (IP)
17+
#Found socket at https://docs.python.org/3/library/socket.html mostly just their code.
18+
19+
class smtphoney:
20+
async def handle_RCPT(self, server, session, envelope, address, rcpt_options):
21+
loggingaddresses(session.peer[0], envelope.mail_from, address)
22+
envelope.rcpt_tos.append(address)
23+
return '250 OK'
24+
#straight out of documentation
25+
26+
async def handle_DATA(self, server, session, envelope):
27+
28+
print ('New Email \n')
29+
# loggingaddresses(envelope.content.decode('utf8', errors='replace'))
30+
inmemoryfile(envelope.content.decode('utf8', errors='replace')) #A function I made in memoryfile.py
31+
32+
print('End of message')
33+
34+
return '250 Message accepted for delivery'
35+
36+
37+
controller = Controller(smtphoney(), hostname = IP,port=25)
38+
#It calls the class above as my handler, the hostname sets the ip, I set the SMTP port to 25 obviously
39+
40+
controller.start()
41+
input("Server started. Press Return to quit.")
42+
controller.stop()
43+
44+
45+
46+

0 commit comments

Comments
 (0)