Skip to content

Commit 9dadd85

Browse files
committed
Some changes
- Switch over to [pyyed] [1] library instead of networkx for generating GraphML - Migrate Python 2 code to Python 3 - Stick to one casing style (lowercase) for node labels (HarmJ0y#1) - Add more trust attributes (HarmJ0y#2) [1]: https://github.com/jamesscottbrown/pyyed
1 parent b905170 commit 9dadd85

File tree

3 files changed

+101
-84
lines changed

3 files changed

+101
-84
lines changed

README.md

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,36 @@
11
TrustVisualizer
22
====================
33

4-
Simple Python script that takes the output from [PowerView's](https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1) `Get-DomainTrustMapping | Export-CSV -NoTypeInformation trusts.csv` and transforms it to GraphMl. This output can be visualized in any number of ways, including with the [yEd](https://www.yworks.com/products/yed) project.
4+
Simple Python script that takes the output from [PowerView's](https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1) `Get-DomainTrustMapping` and transforms it to GraphML. This output can be visualized in any number of ways, including with the [yEd](https://www.yworks.com/products/yed) project:
5+
6+
```
7+
PS > Get-DomainTrustMapping | Export-CSV -NoTypeInformation trusts.csv
8+
```
59

610
The graph output will represent the access direction (opposite of trust direction).
711

8-
Heaily adapted from @sixdub's [DomainTrustExplorer](https://github.com/sixdub/DomainTrustExplorer/) project.
9-
Python script for analyis of the "Trust.csv" file generated by Veil PowerView. Provides graph based analysis and output.
12+
Heaily adapted from @sixdub's [DomainTrustExplorer](https://github.com/sixdub/DomainTrustExplorer/) project. Python script for analyis of the "trust.csv" file generated by Veil PowerView. Provides graph based analysis and output.
1013

11-
yEd intstructions from [DomainTrustExplorer](https://github.com/sixdub/DomainTrustExplorer/blob/master/README.md):
14+
yEd intstructions from [DomainTrustExplorer](https://github.com/sixdub/DomainTrustExplorer/blob/master/README.md) (tested on Mac OSX with yEd for visualization). Parsing colors and labels in yEd (GraphML):
1215

13-
Tested on Mac OSX with yEd for visualization.
14-
Parsing colors and labels in yEd (GraphML):
15-
-Edit->Properties Mapper
16-
-Add a configuration for node
17-
-Add a mapping for label/Label Text
18-
-Add a configuration for edge
19-
-Add a mapping for color/Line Color
16+
1. Edit → Properties Mapper
17+
2. Add a configuration for node with a mapping for label, map to "Label Text"
18+
3. Apply
19+
4. Add a configuration for edge with a mapping for color, map to "Line Color"
20+
5. Apply, Ok
21+
6. Tools → Fit Node to Label, Ok
22+
7. Layout → Hierarchical
2023

2124
Setup & Requirements
2225
====================
2326

24-
pip install networkx
27+
* [pyyed](https://github.com/jamesscottbrown/pyyed)
28+
29+
```
30+
$ pip3 install -r requirements.txt
31+
```
32+
33+
References
34+
====================
35+
36+
* [Domain Trusts: Why You Should Care – harmj0y](http://www.harmj0y.net/blog/redteaming/domain-trusts-why-you-should-care/)

TrustVisualizer.py

Lines changed: 76 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,90 @@
1-
#!/usr/bin/python
1+
#!/usr/bin/env python3
22

33
##############################################################################
44
# Author: @harmj0y
55
#
66
# Based on: https://github.com/sixdub/DomainTrustExplorer by @sixdub
77
#
8-
# Description: Usesnetworkx library to transform PowerView's updated
8+
# Description: Uses pyyed (yEd) library to transform PowerView's updated
99
# Get-DomainTrustMapping functionality output to graphml
1010
#
1111
# License: BSD 3-clause
1212
##############################################################################
1313

14-
import networkx as nx
15-
import sys, csv
14+
import csv
15+
from os.path import basename, splitext
16+
from argparse import ArgumentParser
1617

17-
if __name__ == '__main__':
18-
19-
if (len(sys.argv) != 2):
20-
print "usage: ./TrustVisualizer.py <trust_file.csv>"
21-
exit()
22-
23-
graph = nx.DiGraph()
24-
intputFile = sys.argv[1]
25-
26-
with open(intputFile, 'rb') as csvfile:
27-
28-
reader = csv.reader(csvfile, delimiter=',')
29-
30-
for row in reader:
31-
32-
# if we have the header row, skip
33-
if row[0] == 'SourceName':
34-
continue
18+
import pyyed
3519

36-
# csv format:
37-
# SourceName,TargetName,TrustType,TrustAttributes,TrustDirection,WhenCreated,WhenChanged
38-
ecolor = ''
39-
sourceName = row[0].strip()
40-
targetName = row[1].strip()
41-
trustType = row[2].strip()
42-
trustAttributes = row[3].strip()
43-
trustDirection = row[4].strip()
20+
parser = ArgumentParser()
21+
parser.add_argument('trust_file', help='trust file in .csv format (generate with PowerView)')
22+
args = parser.parse_args()
4423

45-
# if the source and destination domains are the same, skip
46-
if (sourceName == targetName):
47-
continue
48-
49-
if (trustType == 'MIT'):
50-
# black label for MIT trusts
51-
ecolor ='#000000'
52-
53-
else:
54-
if "WITHIN_FOREST" in trustAttributes:
55-
# green label for intra-forest trusts
56-
ecolor = '#009900'
57-
elif (trustAttributes == "FOREST_TRANSITIVE"):
58-
# blue label for inter-forest trusts
59-
ecolor = '#0000CC'
60-
elif ((trustAttributes == "") or (trustAttributes == "TREAT_AS_EXTERNAL") or (trustAttributes == "FILTER_SIDS")):
61-
# red label for external trusts
62-
ecolor = '#FF0000'
63-
else:
64-
# violet label for unknown
65-
print "[-] Unrecognized trust attributes between %s and %s : %s" % (sourceName, targetName, trustAttributes)
66-
ecolor = '#EE82EE'
67-
68-
# add the domain nodes to the internal graph
69-
graph.add_node(sourceName, label=sourceName)
70-
graph.add_node(targetName, label=targetName)
71-
72-
# add the edges to the graph
73-
if "Bidirectional" in trustDirection:
74-
graph.add_edge(sourceName, targetName, color=ecolor)
75-
graph.add_edge(targetName, sourceName, color=ecolor)
76-
elif "Outbound" in trustDirection:
77-
graph.add_edge(targetName, sourceName, color=ecolor)
78-
elif "Inbound" in trustDirection:
79-
graph.add_edge(sourceName, targetName, color=ecolor)
80-
else:
81-
print "[-] Unrecognized relationship direction between %s and %s : %s" % (sourceName, targetName, trustDirection)
82-
83-
outputFile = intputFile + ".graphml"
84-
nx.write_graphml(graph, outputFile)
85-
print "\n[+] Graphml writte to '%s'" % (outputFile)
86-
print "\n[*] Note: green = within forest, red = external, blue = forest to forest, black = MIT, violet = unrecognized\n"
24+
if __name__ == '__main__':
25+
graph = pyyed.Graph()
26+
27+
with open(args.trust_file, 'r', encoding='utf-8') as fd:
28+
reader = csv.reader(fd, delimiter=',')
29+
next(reader, None)
30+
31+
for row in reader:
32+
# csv format:
33+
# "SourceName","TargetName","TrustType","TrustAttributes","TrustDirection","WhenCreated","WhenChanged"
34+
sourceName = row[0].strip().lower()
35+
targetName = row[1].strip().lower()
36+
trustType = row[2].strip()
37+
trustAttributes = row[3].strip()
38+
trustDirection = row[4].strip()
39+
40+
# if the source and destination domains are the same, skip
41+
if sourceName == targetName:
42+
continue
43+
44+
if trustType == 'MIT':
45+
# black label for MIT trusts
46+
ecolor = '#000000'
47+
else:
48+
if 'WITHIN_FOREST' in trustAttributes:
49+
# green label for intra-forest trusts
50+
ecolor = '#009900'
51+
elif 'FOREST_TRANSITIVE' in trustAttributes:
52+
# blue label for inter-forest trusts
53+
ecolor = '#0000CC'
54+
elif trustAttributes == '' or any(attr in trustAttributes for attr in ('TREAT_AS_EXTERNAL', 'FILTER_SIDS', 'CROSS_ORGANIZATION')):
55+
# red label for external trusts
56+
ecolor = '#FF0000'
57+
else:
58+
# violet label for unknown
59+
print(f'[-] Unrecognized trust attributes between {sourceName} and {targetName} : {trustAttributes}')
60+
ecolor = '#EE82EE'
61+
62+
try:
63+
# add source node to the internal graph
64+
graph.add_node(sourceName, label=sourceName, shape_fill='#FFCC00')
65+
# node exists
66+
except RuntimeWarning:
67+
pass
68+
69+
try:
70+
# add target node to the internal graph
71+
graph.add_node(targetName, label=targetName, shape_fill='#FFCC00')
72+
# node exists
73+
except RuntimeWarning:
74+
pass
75+
76+
# add the edges to the graph
77+
if 'Bidirectional' in trustDirection:
78+
graph.add_edge(sourceName, targetName, color=ecolor)
79+
elif 'Outbound' in trustDirection:
80+
graph.add_edge(targetName, sourceName, color=ecolor)
81+
elif 'Inbound' in trustDirection:
82+
graph.add_edge(sourceName, targetName, color=ecolor)
83+
else:
84+
print(f'[-] Unrecognized relationship direction between {sourceName} and {targetName} : {trustDirection}' % (sourceName, targetName, trustDirection))
85+
86+
outputFile = splitext(basename(args.trust_file))[0] + '.graphml'
87+
graph.write_graph(outputFile)
88+
89+
print(f'[+] Graphml writte to "{outputFile}"')
90+
print('[*] Note: green = within forest, red = external, blue = forest to forest, black = MIT, violet = unrecognized')

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pyyed

0 commit comments

Comments
 (0)