Skip to content

Commit 1851ce0

Browse files
committed
Initial
1 parent 80366dd commit 1851ce0

17 files changed

+235
-2
lines changed

LICENSE.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ZFG license: just do whatever you want with this code.

README.md

+37-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,37 @@
1-
# stackstorm-forensics
2-
Forensics and CTF automation pack to use with StackStorm. Actions and ChatOps aliases.
1+
# StackStorm Forensics
2+
3+
## Marceline
4+
5+
An automation pack for [https://github.com/StackStorm|StackStorm]: various actions and ChatOps aliases for file/stream forensics and CTFs challenges.
6+
7+
Although this pack was meant to power Randoms' own CTF helper, Marceline, it can also be reused as a set of independent StackStorm actions or as code somewhere else. Whatever you want, really.
8+
9+
## Commands
10+
11+
So far the list of things Marceline does is really small:
12+
```
13+
base64 decode {{ string }} - Do a base64 decode of a string.
14+
base64 encode {{ string }} - Do a base64 encode of a string.
15+
crack substitution {{ ciphertext }} - Try to crack a substitution cipher.
16+
rot13 {{ string }} - Apply rot13 to a string.
17+
what.s next? - Look for upcoming CTFs.
18+
when is {{ query }}? - Look for upcoming CTFs.
19+
```
20+
21+
However, I'm planning to extend it in the nearest future, and you're more than welcome to contribute.
22+
23+
![](http://i.imgur.com/xxnIghW.gifv)
24+
25+
## Todo
26+
27+
* File analysis: `file`, `hachoir-subfile`
28+
* Metadata extraction: `hachoir-metadata`
29+
* Output from `strings`
30+
* Hash lookups
31+
* Hex/bin/dec/ascii/unicode conversions
32+
* Basic steganographic analysis
33+
* Nmap scanning
34+
35+
Suggestions are always appreciated.
36+
37+
— Ed.

actions/base64-decode.yaml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
name: "base64decode"
3+
runner_type: "local-shell-cmd"
4+
description: "Do a base64 decode of a string."
5+
enabled: true
6+
parameters:
7+
string:
8+
type: "string"
9+
description: "String to decode."
10+
required: true
11+
cmd:
12+
description: "Command to run"
13+
type: "string"
14+
immutable: true
15+
default: "echo \"{{ string }}\" | base64 -d"

actions/base64-encode.yaml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
name: "base64encode"
3+
runner_type: "local-shell-cmd"
4+
description: "Do a base64 encode of a string."
5+
enabled: true
6+
parameters:
7+
string:
8+
type: "string"
9+
description: "String to encode."
10+
required: true
11+
cmd:
12+
description: "Command to run"
13+
type: "string"
14+
immutable: true
15+
default: "echo \"{{ string }}\" | base64"

actions/ctfsearch.py

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/python
2+
3+
import ics
4+
import requests
5+
import arrow
6+
import re
7+
8+
from st2actions.runners.pythonrunner import Action
9+
10+
__all__ = [
11+
'CTFSearchAction'
12+
]
13+
14+
15+
class CTFSearchAction(Action):
16+
def run(self, query):
17+
calendar = 'https://www.google.com/calendar/ical/ctftime%40gmail.com/public/basic.ics'
18+
contents = requests.get(calendar).text
19+
contents = re.sub(r'(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z',
20+
r'\1-\2-\3T\4:\5',
21+
contents)
22+
ctfs = ics.Calendar(contents)
23+
for event in ctfs.events[arrow.utcnow():]:
24+
if not query or (query.lower() in event.name.lower()):
25+
url = re.search('URL: (.*?)\n', event.description)
26+
return "%s starts %s%s" % (
27+
event.name,
28+
event.begin.humanize(),
29+
" (%s)" % (url.group(1)) if url else "",
30+
)
31+
return "can't find upcoming CTFs matching \"%s\" :(" % (query)

actions/ctfsearch.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
name: "ctfsearch"
3+
runner_type: "python-script"
4+
description: "Searches CTFTime.org calendar for events."
5+
enabled: true
6+
entry_point: "ctfsearch.py"
7+
parameters:
8+
query:
9+
type: "string"
10+
description: "Query for CTF title."
11+
required: false

actions/rot13.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/python
2+
3+
import codecs
4+
from st2actions.runners.pythonrunner import Action
5+
6+
__all__ = [
7+
'Rot13Action'
8+
]
9+
10+
11+
class Rot13Action(Action):
12+
def run(self, string):
13+
return codecs.encode(string, 'rot_13')

actions/rot13.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
name: "rot13"
3+
runner_type: "python-script"
4+
description: "Shift a string 13 chars."
5+
enabled: true
6+
entry_point: "rot13.py"
7+
parameters:
8+
string:
9+
type: "string"
10+
description: "String to rotate."
11+
required: true

actions/substitution.py

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/python
2+
3+
import requests
4+
import re
5+
from st2actions.runners.pythonrunner import Action
6+
7+
__all__ = [
8+
'SubstitutionAction'
9+
]
10+
11+
12+
class SubstitutionAction(Action):
13+
def run(self, ciphertext):
14+
page = requests.post("http://quipqiup.com/index.php", {
15+
'mode': '3',
16+
'clues': '',
17+
'action': 'Solve',
18+
'ciphertext': ciphertext
19+
})
20+
expression = '\<script\>solsum.*?\"(.*?)\"'
21+
result = re.search(expression, page.text)
22+
return result.group(1)

actions/substitution.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
name: "substitution"
3+
runner_type: "python-script"
4+
description: "Crack a substitution cipher."
5+
enabled: true
6+
entry_point: "substitution.py"
7+
parameters:
8+
ciphertext:
9+
type: "string"
10+
description: "Ciphertext to crack."
11+
required: true

aliases/base64-decode.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
name: "forensics_base64decode"
3+
action_ref: "forensics.base64decode"
4+
description: "Do a base64 decode of a string."
5+
formats:
6+
- "base64 decode {{ string }}"
7+
ack:
8+
disabled: true
9+
execution:
10+
output: "{{ result }}"

aliases/base64-encode.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
name: "forensics_base64encode"
3+
action_ref: "forensics.base64encode"
4+
description: "Do a base64 encode of a string."
5+
formats:
6+
- "base64 encode {{ string }}"
7+
ack:
8+
disabled: true
9+
execution:
10+
output: "{{ result }}"

aliases/ctfsearch.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
name: "forensics_ctfsearch"
3+
action_ref: "forensics.ctfsearch"
4+
description: "Look for upcoming CTFs."
5+
formats:
6+
- "what.s next\\?"
7+
- "when is {{ query }}\\?"
8+
ack:
9+
disabled: true
10+
execution:
11+
output: "{{ result }}"

aliases/rot13.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
name: "forensics_rot13"
3+
action_ref: "forensics.rot13"
4+
description: "Apply rot13 to a string."
5+
formats:
6+
- "rot13 {{ string }}"
7+
ack:
8+
disabled: true
9+
execution:
10+
output: "{{ result }}"

aliases/substitution.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
name: "forensics_substitution"
3+
action_ref: "forensics.substitution"
4+
description: "Try to crack a substitution cipher."
5+
formats:
6+
- "crack substitution {{ ciphertext }}"
7+
ack:
8+
disabled: true
9+
execution:
10+
output: "here's the best I could come up with: ```{{ result }}``` I used http://quipqiup.com/ by Edwin Olson to crack the cipher, and you should consider buying him a beer or at least visiting the website. :)"

pack.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
name : forensics
3+
description : st2 action pack for basic forensics and file analysis
4+
keywords:
5+
- cipher
6+
- steganography
7+
- forensics
8+
version : 0.1
9+
author : emedvedev
10+

requirements.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
requests
2+
arrow
3+
ics
4+
binwalk
5+
hachoir-core
6+
hachoir-parser
7+
hachoir-metadata

0 commit comments

Comments
 (0)