├── BloodHoundExampleDB.graphdb ├── store_lock ├── logs │ └── debug.log ├── neostore.id ├── schema │ └── index │ │ └── lucene │ │ ├── 13 │ │ └── 1 │ │ │ ├── write.lock │ │ │ ├── _0.cfe │ │ │ ├── _0.cfs │ │ │ ├── _0.si │ │ │ └── segments_4 │ │ ├── 18 │ │ └── 1 │ │ │ ├── write.lock │ │ │ ├── _0.cfe │ │ │ ├── _0.cfs │ │ │ ├── _0.si │ │ │ └── segments_4 │ │ ├── 23 │ │ └── 1 │ │ │ ├── write.lock │ │ │ ├── _0.cfe │ │ │ ├── _0.cfs │ │ │ ├── _0.si │ │ │ └── segments_4 │ │ ├── 28 │ │ └── 1 │ │ │ ├── write.lock │ │ │ ├── _0.cfe │ │ │ ├── _0.cfs │ │ │ ├── _0.si │ │ │ └── segments_4 │ │ ├── 33 │ │ └── 1 │ │ │ ├── write.lock │ │ │ └── segments_4 │ │ └── 38 │ │ └── 1 │ │ ├── write.lock │ │ └── segments_4 ├── neostore.labeltokenstore.db.id ├── neostore.nodestore.db.labels.id ├── neostore.labeltokenstore.db.names.id ├── neostore.propertystore.db.arrays.id ├── neostore.propertystore.db.strings.id ├── neostore.relationshiptypestore.db.id ├── neostore.propertystore.db.index.id ├── neostore.propertystore.db.index.keys.id ├── neostore.relationshiptypestore.db.names.id ├── neostore.nodestore.db.id ├── neostore ├── data │ └── dbms │ │ └── auth ├── neostore.schemastore.db.id ├── neostore.counts.db.a ├── neostore.counts.db.b ├── neostore.nodestore.db ├── neostore.schemastore.db ├── neostore.labelscanstore.db ├── neostore.propertystore.db ├── neostore.transaction.db.0 ├── neostore.propertystore.db.id ├── neostore.relationshipstore.db ├── neostore.labeltokenstore.db.names ├── neostore.propertystore.db.arrays ├── neostore.propertystore.db.strings ├── neostore.relationshipgroupstore.db ├── neostore.relationshipstore.db.id ├── neostore.propertystore.db.index.keys ├── neostore.relationshipgroupstore.db.id ├── neostore.relationshiptypestore.db.names ├── certificates │ ├── neo4j.cert │ └── neo4j.key ├── neostore.labeltokenstore.db ├── neostore.nodestore.db.labels ├── neostore.propertystore.db.index └── neostore.relationshiptypestore.db ├── .gitignore ├── src ├── img │ ├── icon.icns │ ├── icon.ico │ ├── icon.png │ ├── favicon.ico │ ├── icon@2x.png │ ├── loading.gif │ ├── loading_new.gif │ ├── logo-white-transparent.png │ └── logo-white-transparent-full.png ├── fonts │ ├── roboto-v15-latin-regular.eot │ ├── roboto-v15-latin-regular.ttf │ ├── roboto-v15-latin-regular.woff │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ ├── roboto-v15-latin-regular.woff2 │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── components │ ├── edgeTooltip.html │ ├── SearchContainer │ │ ├── Tabs │ │ │ ├── NoNodeData.jsx │ │ │ ├── PrebuiltQueryNode.jsx │ │ │ ├── LoadLabel.jsx │ │ │ ├── NodeALink.jsx │ │ │ ├── NodeCypherNoNumberLink.jsx │ │ │ ├── SelectedImage.jsx │ │ │ ├── NodePropItem.jsx │ │ │ ├── NodeProps.jsx │ │ │ ├── NodeCypherLinkComplex.jsx │ │ │ ├── NodeCypherLink.jsx │ │ │ ├── PrebuiltQueriesDisplay.jsx │ │ │ └── DatabaseDataDisplay.jsx │ │ └── TabContainer.jsx │ ├── Float │ │ ├── QueryNodeSelectHeader.jsx │ │ ├── Alert.jsx │ │ ├── LoadingContainer.jsx │ │ ├── QueryNodeSelectItem.jsx │ │ ├── ExportContainer.jsx │ │ ├── QueryNodeSelect.jsx │ │ └── NodeEditorRow.jsx │ ├── Icon.jsx │ ├── stageTooltip.html │ ├── Modals │ │ ├── ClearingModal.jsx │ │ ├── DeleteEdgeModal.jsx │ │ ├── DeleteNodeModal.jsx │ │ ├── CancelUploadModal.jsx │ │ ├── SessionClearModal.jsx │ │ ├── LogoutModal.jsx │ │ ├── ClearWarnModal.jsx │ │ ├── ClearConfirmModal.jsx │ │ ├── About.jsx │ │ └── AddNodeModal.jsx │ ├── GlyphiconSpan.jsx │ ├── Zoom │ │ └── ZoomContainer.jsx │ ├── Menu │ │ ├── MenuButton.jsx │ │ └── ProgressBarMenuButton.jsx │ ├── RawQuery.jsx │ ├── Spotlight │ │ ├── SpotlightRow.jsx │ │ └── SpotlightContainer.jsx │ └── nodeTooltip.html ├── css │ ├── simple-slider.css │ ├── simple-slider-volume.css │ └── tooltip.css ├── js │ ├── sigma.helpers.graph.min.js │ ├── simple-slider.min.js │ └── worker.js └── AppContainer.jsx ├── Ingestors ├── SharpHound.exe └── DebugBuilds │ ├── SharpHound.exe │ └── SharpHound.pdb ├── renderer.js ├── webpack.config.production.js ├── server.js ├── webpack.config.development.js ├── appveyor.yml ├── index.html ├── .travis.yml ├── README.md ├── deploy.sh ├── package.json ├── main.js └── LICENSE-3RD-PARTY.md /BloodHoundExampleDB.graphdb/store_lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/logs/debug.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.id: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/13/1/write.lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/18/1/write.lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/23/1/write.lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/28/1/write.lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/33/1/write.lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/38/1/write.lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.labeltokenstore.db.id: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.nodestore.db.labels.id: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.labeltokenstore.db.names.id: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.propertystore.db.arrays.id: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.propertystore.db.strings.id: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.relationshiptypestore.db.id: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.propertystore.db.index.id: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.propertystore.db.index.keys.id: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.relationshiptypestore.db.names.id: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | Bloodhound-* 3 | dist/ 4 | npm-debug.log 5 | *.bin 6 | *.csv 7 | -------------------------------------------------------------------------------- /src/img/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/img/icon.icns -------------------------------------------------------------------------------- /src/img/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/img/icon.ico -------------------------------------------------------------------------------- /src/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/img/icon.png -------------------------------------------------------------------------------- /src/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/img/favicon.ico -------------------------------------------------------------------------------- /src/img/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/img/icon@2x.png -------------------------------------------------------------------------------- /src/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/img/loading.gif -------------------------------------------------------------------------------- /Ingestors/SharpHound.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/Ingestors/SharpHound.exe -------------------------------------------------------------------------------- /src/img/loading_new.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/img/loading_new.gif -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.nodestore.db.id: -------------------------------------------------------------------------------- 1 | IVIGIDIJIKIHIIILIM -------------------------------------------------------------------------------- /src/img/logo-white-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/img/logo-white-transparent.png -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore -------------------------------------------------------------------------------- /Ingestors/DebugBuilds/SharpHound.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/Ingestors/DebugBuilds/SharpHound.exe -------------------------------------------------------------------------------- /Ingestors/DebugBuilds/SharpHound.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/Ingestors/DebugBuilds/SharpHound.pdb -------------------------------------------------------------------------------- /src/fonts/roboto-v15-latin-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/fonts/roboto-v15-latin-regular.eot -------------------------------------------------------------------------------- /src/fonts/roboto-v15-latin-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/fonts/roboto-v15-latin-regular.ttf -------------------------------------------------------------------------------- /src/fonts/roboto-v15-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/fonts/roboto-v15-latin-regular.woff -------------------------------------------------------------------------------- /src/img/logo-white-transparent-full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/img/logo-white-transparent-full.png -------------------------------------------------------------------------------- /src/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/fonts/roboto-v15-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/fonts/roboto-v15-latin-regular.woff2 -------------------------------------------------------------------------------- /src/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/src/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/data/dbms/auth: -------------------------------------------------------------------------------- 1 | neo4j:SHA-256,40E0ECEC46CF97B7DD31D296AA2462D3C690908FB852D2D6A788086FE70FC730,D0357E62D8B042914C64937C9D9AB9F8: 2 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.schemastore.db.id: -------------------------------------------------------------------------------- 1 | + 2 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.counts.db.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.counts.db.a -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.counts.db.b: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.counts.db.b -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.nodestore.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.nodestore.db -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.schemastore.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.schemastore.db -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.labelscanstore.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.labelscanstore.db -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.propertystore.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.propertystore.db -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.transaction.db.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.transaction.db.0 -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.propertystore.db.id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.propertystore.db.id -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.relationshipstore.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.relationshipstore.db -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/13/1/_0.cfe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/13/1/_0.cfe -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/13/1/_0.cfs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/13/1/_0.cfs -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/13/1/_0.si: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/13/1/_0.si -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/18/1/_0.cfe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/18/1/_0.cfe -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/18/1/_0.cfs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/18/1/_0.cfs -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/18/1/_0.si: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/18/1/_0.si -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/23/1/_0.cfe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/23/1/_0.cfe -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/23/1/_0.cfs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/23/1/_0.cfs -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/23/1/_0.si: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/23/1/_0.si -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/28/1/_0.cfe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/28/1/_0.cfe -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/28/1/_0.cfs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/28/1/_0.cfs -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/28/1/_0.si: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/28/1/_0.si -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.labeltokenstore.db.names: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.labeltokenstore.db.names -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.propertystore.db.arrays: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.propertystore.db.arrays -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.propertystore.db.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.propertystore.db.strings -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.relationshipgroupstore.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.relationshipgroupstore.db -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.relationshipstore.db.id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.relationshipstore.db.id -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.propertystore.db.index.keys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.propertystore.db.index.keys -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/13/1/segments_4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/13/1/segments_4 -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/18/1/segments_4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/18/1/segments_4 -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/23/1/segments_4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/23/1/segments_4 -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/28/1/segments_4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/28/1/segments_4 -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/33/1/segments_4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/33/1/segments_4 -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/schema/index/lucene/38/1/segments_4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/schema/index/lucene/38/1/segments_4 -------------------------------------------------------------------------------- /renderer.js: -------------------------------------------------------------------------------- 1 | // This file is required by the index.html file and will 2 | // be executed in the renderer process for that window. 3 | // All of the Node.js APIs are available in this process. 4 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.relationshipgroupstore.db.id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.relationshipgroupstore.db.id -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/neostore.relationshiptypestore.db.names: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrismaddalena/BloodHoundLegacy/master/BloodHoundExampleDB.graphdb/neostore.relationshiptypestore.db.names -------------------------------------------------------------------------------- /webpack.config.production.js: -------------------------------------------------------------------------------- 1 | var config = require('./webpack.config.development.js'); 2 | config.entry.shift(); 3 | config.plugins.shift(); 4 | config.output.publicPath = './dist/'; 5 | module.exports = config; -------------------------------------------------------------------------------- /src/components/edgeTooltip.html: -------------------------------------------------------------------------------- 1 |
2 | {{label}} 3 |
4 | -------------------------------------------------------------------------------- /src/components/SearchContainer/Tabs/NoNodeData.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export default class NoNodeData extends Component { 5 | render() { 6 | return ( 7 |
8 |

Node Properties

9 |

Select a node for more information

10 |
11 | ); 12 | } 13 | } 14 | 15 | NoNodeData.propTypes = { 16 | visible: PropTypes.bool.isRequired 17 | }; 18 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import webpack from 'webpack'; 3 | import webpackDevMiddleware from 'webpack-dev-middleware'; 4 | import webpackHotMiddleware from 'webpack-hot-middleware'; 5 | 6 | import config from './webpack.config.development'; 7 | 8 | const compiler = webpack(config); 9 | const app = express(); 10 | 11 | app.use(webpackDevMiddleware(compiler, { 12 | publicPath: config.output.publicPath, 13 | stats: { 14 | colors: true 15 | } 16 | })); 17 | 18 | app.use(webpackHotMiddleware(compiler)); 19 | 20 | app.listen(9000); -------------------------------------------------------------------------------- /src/components/Float/QueryNodeSelectHeader.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class QueryNodeSelectHeader extends Component { 4 | render() { 5 | var title = this.props.length > 0 ? this.props.title : "Loading..."; 6 | return ( 7 |
8 | {title} 9 | 12 |
13 | ); 14 | } 15 | } -------------------------------------------------------------------------------- /src/components/Icon.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export default class Icon extends Component { 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render() { 10 | return ( 11 | 19 | ); 20 | } 21 | } 22 | 23 | Icon.propTypes = { 24 | glyph: PropTypes.string.isRequired, 25 | extraClass: PropTypes.string 26 | }; 27 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/certificates/neo4j.cert: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBoTCCAQqgAwIBAgIIG1tfOzLnQa0wDQYJKoZIhvcNAQENBQAwEjEQMA4GA1UE 3 | AwwHMC4wLjAuMDAgFw0xNTA2MTMwMzA3NDhaGA85OTk5MTIzMTIzNTk1OVowEjEQ 4 | MA4GA1UEAwwHMC4wLjAuMDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAoA7y 5 | JBzmyXXbVvQV/96YuqC9VYH76rBPpajJMcZi4ROeTXpBnL392f9C+VefHokCHlqm 6 | vFN7dC5g8ZSypZ1fNErm50gkXnofvp4wk3K696rXmJJApGKSMQkEXamteu4z0eAF 7 | 443IIVbh/sQtz9UBGbycE5iHtnx/F1IH2OnD280CAwEAATANBgkqhkiG9w0BAQ0F 8 | AAOBgQBW0y3Uo7zYFik4F9z25weyemT9yA2Yf0185LnAT5D8prCjxWpQH0OxvYf8 9 | dGxrQGN+PFAjqKAvmbp1G0lUgALdS1PGRAQKuVux55lMnd8ESrzs1b6b/oyv/ysn 10 | exlv2VNxFSb2ZaFyFkpSWCIsQ3SB/HGb7GLnP1nxRD1BvH/PWA== 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /src/components/SearchContainer/Tabs/PrebuiltQueryNode.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | export default class PrebuiltQueryNode extends Component { 4 | render() { 5 | var c; 6 | 7 | c = function() { 8 | if (appStore.prebuiltQuery.length === 0) { 9 | appStore.prebuiltQuery = JSON.parse( 10 | JSON.stringify(this.props.info.queryList) 11 | ); 12 | emitter.emit("prebuiltQueryStart"); 13 | } 14 | }.bind(this); 15 | 16 | return ( 17 |
18 | 19 | {this.props.info.name} 20 | 21 |
22 |
23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/components/stageTooltip.html: -------------------------------------------------------------------------------- 1 |
2 | Graph Options 3 |
4 | -------------------------------------------------------------------------------- /BloodHoundExampleDB.graphdb/certificates/neo4j.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKAO8iQc5sl121b0 3 | Ff/emLqgvVWB++qwT6WoyTHGYuETnk16QZy9/dn/QvlXnx6JAh5aprxTe3QuYPGU 4 | sqWdXzRK5udIJF56H76eMJNyuveq15iSQKRikjEJBF2prXruM9HgBeONyCFW4f7E 5 | Lc/VARm8nBOYh7Z8fxdSB9jpw9vNAgMBAAECgYBQQe5NCWj4D+7iFRaK7LUsr7kA 6 | jWMidTIa4R2xpcajEdFJDEqmK+aETyjoGnWhPBYh3lbJDBtVUIQv3t4NiXHY3clO 7 | 28KM/UGU/o8LyvNlk70N1AKVDEDw9lI8161rat3vzdjF8KfBUOK/CewnF3yLqzYP 8 | 5UsZr5YDTX+GiTZaAQJBAMzsY+Ggo9c+bIflp4ERUt1HTQ2TW7N6sCoTT0/GwdjE 9 | 92Y1dtAUsb3OqP0wa9PamzESEAOxkQxnFA9z3t0pEEECQQDH89cC+gJGp+fAGiMR 10 | MBz/BrVsxgRnkA3o12Lf/7iJQxVHEIoVS7fSwNqALwGKLpZKlkBhed8+RTRLi7wI 11 | q+iNAkEAxpKizvatDVyOKrndsPIqjAYVonwStj7DCmKfzjxZh0aGPeK8+TG0cqsZ 12 | kg8jzazeCZTpM8sTNSOFitvLMCAkgQJBAIKYLDJxf9MODztU1tp/BjE6/HvSyUWq 13 | vKr7IkUTDD/6ZIdJsiY+kg1AkHVwPh02WErW363Kn5hYMtO0rFctkHECQQCNsAZ9 14 | ScwIeDtmgSIPNn+xXToSUExkKZjMs+HfZljFE9P7IKop6WGd2MEt6wjbH5W8nM0+ 15 | USv34xhBt8Z86dLz 16 | -----END PRIVATE KEY----- 17 | -------------------------------------------------------------------------------- /src/components/SearchContainer/Tabs/LoadLabel.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { If, Then, Else } from "react-if"; 3 | import PropTypes from "prop-types"; 4 | 5 | export default class LoadLabel extends Component { 6 | constructor(props) { 7 | super(props); 8 | } 9 | render() { 10 | return ( 11 | 12 | 13 |
{this.props.value}
14 |
15 | 16 | {() => ( 17 |
18 |
19 |
20 |
21 |
22 | )} 23 | 24 | 25 | ); 26 | } 27 | } 28 | 29 | LoadLabel.propTypes = { 30 | ready: PropTypes.bool.isRequired, 31 | value: PropTypes.number 32 | }; 33 | -------------------------------------------------------------------------------- /src/components/SearchContainer/Tabs/NodeALink.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { If, Then, Else } from "react-if"; 3 | import PropTypes from "prop-types"; 4 | 5 | export default class NodeALink extends Component { 6 | constructor(props) { 7 | super(props); 8 | } 9 | render() { 10 | return ( 11 | 12 | 13 | 14 | {this.props.value} 15 | 16 | 17 | 18 | {() => ( 19 |
20 |
21 |
22 |
23 |
24 | )} 25 | 26 | 27 | ); 28 | } 29 | } 30 | 31 | NodeALink.propTypes = { 32 | ready: PropTypes.bool.isRequired, 33 | click: PropTypes.func, 34 | value: PropTypes.number 35 | }; 36 | -------------------------------------------------------------------------------- /webpack.config.development.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path') 3 | 4 | var config = { 5 | target: 'electron-renderer', 6 | externals: [{ 7 | 'electron-config': 'electron-config' 8 | }], 9 | entry: [ 10 | 'webpack-hot-middleware/client?reload=true&path=http://localhost:9000/__webpack_hmr', 11 | './src/index', 12 | ], 13 | module: { 14 | rules: [ 15 | { 16 | test: /\.jsx?$/, 17 | exclude: /(node_modules)/, 18 | use: { 19 | loader: 'babel-loader', 20 | options: { 21 | } 22 | } 23 | } 24 | ] 25 | }, 26 | output: { 27 | path: __dirname + '/dist', 28 | publicPath: 'http://localhost:9000/dist/', 29 | filename: 'bundle.js' 30 | }, 31 | resolve: { 32 | extensions: ['.js', '.jsx'], 33 | alias: { 34 | utils: path.resolve(__dirname, 'src', 'js', 'utils.js'), 35 | modals: path.resolve(__dirname, 'src', 'components', 'Modals') 36 | } 37 | }, 38 | plugins: [ 39 | new webpack.HotModuleReplacementPlugin(), 40 | ], 41 | node: { 42 | __dirname: false, 43 | __filename: false 44 | } 45 | }; 46 | module.exports = config; -------------------------------------------------------------------------------- /src/components/Modals/ClearingModal.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { Modal } from "react-bootstrap"; 3 | 4 | export default class ClearingModal extends Component { 5 | constructor() { 6 | super(); 7 | this.state = { 8 | open: false 9 | }; 10 | } 11 | 12 | openModal() { 13 | this.setState({ open: true }); 14 | } 15 | 16 | closeModal() { 17 | this.setState({ open: false }); 18 | } 19 | 20 | componentDidMount() { 21 | emitter.on("openClearingModal", this.openModal.bind(this)); 22 | emitter.on("hideDBClearModal", this.closeModal.bind(this)); 23 | } 24 | render() { 25 | return ( 26 | 31 | 32 | 33 | Clearing Data 34 | 35 | 36 | 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/components/SearchContainer/Tabs/NodeCypherNoNumberLink.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component, Fragment } from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export default class NodeCypherNoNumberLink extends Component { 5 | constructor(props) { 6 | super(props); 7 | } 8 | 9 | render() { 10 | let c = function() { 11 | emitter.emit( 12 | "query", 13 | this.props.query, 14 | { name: this.props.target }, 15 | this.props.start, 16 | this.props.end 17 | ); 18 | }.bind(this); 19 | 20 | return ( 21 | 22 |
23 | 24 | {this.props.property} 25 | 26 |
27 |
28 | 29 | ); 30 | } 31 | } 32 | 33 | NodeCypherNoNumberLink.propTypes = { 34 | target: PropTypes.string.isRequired, 35 | property: PropTypes.string.isRequired, 36 | query: PropTypes.string.isRequired, 37 | start: PropTypes.string, 38 | end: PropTypes.string 39 | }; 40 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # Install scripts. (runs after repo cloning) 2 | install: 3 | # Get the latest stable version of Node.js or io.js 4 | - ps: Install-Product node $env:nodejs_version 5 | # install modules 6 | - npm install -g npm@5.2 7 | - npm install 8 | - npm install -g electron-packager 9 | 10 | # Post-install test scripts. 11 | test_script: 12 | # Output useful info for debugging. 13 | - node --version 14 | - npm --version 15 | - npm run winbuild 16 | - 7z a -tzip -mx9 BloodHound-win32-ia32.zip BloodHound-win32-ia32 17 | - 7z a -tzip -mx9 BloodHound-win32-x64.zip BloodHound-win32-x64 18 | 19 | artifacts: 20 | - path: BloodHound-win32-ia32.zip 21 | name: BloodHound-win32-ia32 22 | - path: BloodHound-win32-x64.zip 23 | name: BloodHound-win32-x64 24 | 25 | deploy: 26 | - provider: GitHub 27 | release: BloodHound Rolling 28 | description: 'Rolling release of BloodHound compiled from source ($(APPVEYOR_REPO_COMMIT)). Not necessarily stable. Automatically kept up to date with master, so ignore the commits since tag' 29 | artifact: BloodHound-win32-ia32,BloodHound-win32-x64 30 | force_update: true 31 | auth_token: 32 | secure: 9E4/AX+ecgXB482XLGCgpdLL5hlWJOUywGKREcRL0iD+YBU/ABXJOGXYHLeKQIgv 33 | 34 | 35 | # Don't actually build. 36 | build: off 37 | 38 | branches: 39 | only: 40 | - master -------------------------------------------------------------------------------- /src/components/SearchContainer/Tabs/SelectedImage.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | const {clipboard} = require('electron') 3 | 4 | export default class SelectedImage extends Component { 5 | constructor(){ 6 | super() 7 | } 8 | 9 | componentDidMount(){ 10 | } 11 | 12 | click(e, del){ 13 | let o = { 14 | index: this.props.index, 15 | photo: this.props.photo 16 | } 17 | 18 | if (del){ 19 | emitter.emit("deletePhoto", o); 20 | }else{ 21 | emitter.emit("clickPhoto", o); 22 | } 23 | } 24 | 25 | render(){ 26 | let style = { 27 | margin: this.props.margin, 28 | cursor: "pointer", 29 | height: this.props.photo.height, 30 | width: this.props.photo.width, 31 | position: "relative" 32 | }; 33 | 34 | return (
35 | {emitter.emit("showAlert", "Copied file path to clipboard");clipboard.writeText(this.props.photo.src)}} /> 36 | this.click(e, true)} /> 37 | this.click(e, false)} {...this.props.photo} style={style} /> 38 |
); 39 | } 40 | } -------------------------------------------------------------------------------- /src/components/Float/Alert.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { Alert } from "react-bootstrap"; 3 | 4 | 5 | export default class GenericAlert extends Component { 6 | constructor() { 7 | super(); 8 | this.state = { 9 | visible: false, 10 | text: "No data returned from query", 11 | timeout: null 12 | }; 13 | 14 | emitter.on("showAlert", this._show.bind(this)); 15 | emitter.on("hideAlert", this._dismiss.bind(this)); 16 | } 17 | 18 | _dismiss() { 19 | this.setState({ visible: false }); 20 | } 21 | 22 | _show(val) { 23 | clearTimeout(this.state.timeout); 24 | var t = setTimeout( 25 | _ => { 26 | this._dismiss(); 27 | }, 28 | 2500 29 | ); 30 | 31 | this.setState({ 32 | visible: true, 33 | text: val, 34 | timeout: t 35 | }); 36 | } 37 | 38 | render() { 39 | if (this.state.visible) { 40 | return ( 41 | this._dismiss} 45 | > 46 | {this.state.text} 47 | 48 | ); 49 | } else { 50 | return null; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/components/Float/LoadingContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | export default class LoadingContainer extends Component { 4 | constructor() { 5 | super(); 6 | 7 | this.state = { 8 | text: "Loading", 9 | darkMode: false 10 | }; 11 | 12 | emitter.on( 13 | "updateLoadingText", 14 | payload => { 15 | this.setState({ text: payload }); 16 | }); 17 | 18 | 19 | emitter.on( 20 | "showLoadingIndicator", 21 | payload => { 22 | if (payload) { 23 | jQuery(this.refs.load).fadeIn(); 24 | } else { 25 | jQuery(this.refs.load).fadeOut(); 26 | } 27 | } 28 | ); 29 | } 30 | 31 | componentDidMount() { 32 | jQuery(this.refs.load).fadeToggle(0); 33 | 34 | emitter.on("toggleDarkMode", this.toggleDarkMode.bind(this)); 35 | this.toggleDarkMode(appStore.performance.darkMode); 36 | } 37 | 38 | toggleDarkMode(enabled){ 39 | this.setState({darkMode: enabled}); 40 | } 41 | 42 | render() { 43 | return ( 44 |
45 |
{this.state.text}
46 | 47 |
48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/components/GlyphiconSpan.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { If, Then, Else } from "react-if"; 3 | import PropTypes from "prop-types"; 4 | 5 | export default class GlyphiconSpan extends Component { 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | render() { 11 | return ( 12 | 13 | 14 | 21 | {this.props.children} 22 | 23 | 24 | 25 | {() => ( 26 | 30 | {this.props.children} 31 | 32 | )} 33 | 34 | 35 | ); 36 | } 37 | } 38 | 39 | GlyphiconSpan.propTypes = { 40 | classes: PropTypes.string, 41 | tooltipDir: PropTypes.string, 42 | tooltipTitle: PropTypes.string, 43 | tooltip: PropTypes.bool.isRequired, 44 | click: PropTypes.func 45 | }; 46 | -------------------------------------------------------------------------------- /src/components/SearchContainer/Tabs/NodePropItem.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | export default class NodePropItem extends Component { 4 | constructor(props) { 5 | super(props); 6 | } 7 | 8 | isArray(object) { 9 | return ( 10 | object && typeof object === "object" && object.constructor === Array 11 | ); 12 | } 13 | 14 | render() { 15 | var val; 16 | var obj = this.props.keyValue; 17 | if (obj.hasOwnProperty("low")) { 18 | return [
{this.props.keyName}
,
{obj.low}
]; 19 | } else if (this.isArray(obj)) { 20 | console.log(obj); 21 | if (obj.length === 0) { 22 | return [
{this.props.keyName}
,
None
]; 23 | } else { 24 | var elements = []; 25 | $.each(obj, function(_, prop) { 26 | elements.push(
); 27 | elements.push(
{prop}
); 28 | }); 29 | elements[0] =
Service Principal Names
; 30 | } 31 | 32 | return elements; 33 | } else if (typeof obj === "boolean") { 34 | return [ 35 |
{this.props.keyName}
, 36 |
{this.props.keyValue.toString().toTitleCase()}
37 | ]; 38 | } else { 39 | return [ 40 |
{this.props.keyName}
, 41 |
{this.props.keyValue.toString()}
42 | ]; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/css/simple-slider.css: -------------------------------------------------------------------------------- 1 | .slider { 2 | width: 300px; 3 | } 4 | 5 | .slider > .dragger { 6 | background: #8DCA09; 7 | background: -webkit-linear-gradient(top, #8DCA09, #72A307); 8 | background: -moz-linear-gradient(top, #8DCA09, #72A307); 9 | background: linear-gradient(top, #8DCA09, #72A307); 10 | -webkit-box-shadow: inset 0 2px 2px rgba(255, 255, 255, 0.5), 0 2px 8px rgba(0, 0, 0, 0.2); 11 | -moz-box-shadow: inset 0 2px 2px rgba(255, 255, 255, 0.5), 0 2px 8px rgba(0, 0, 0, 0.2); 12 | box-shadow: inset 0 2px 2px rgba(255, 255, 255, 0.5), 0 2px 8px rgba(0, 0, 0, 0.2); 13 | -webkit-border-radius: 10px; 14 | -moz-border-radius: 10px; 15 | border-radius: 10px; 16 | border: 1px solid #496805; 17 | width: 16px; 18 | height: 16px; 19 | } 20 | 21 | .slider > .dragger:hover { 22 | background: -webkit-linear-gradient(top, #8DCA09, #8DCA09); 23 | } 24 | 25 | .slider > .track, 26 | .slider > .highlight-track { 27 | background: #ccc; 28 | background: -webkit-linear-gradient(top, #bbb, #ddd); 29 | background: -moz-linear-gradient(top, #bbb, #ddd); 30 | background: linear-gradient(top, #bbb, #ddd); 31 | -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1); 32 | -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1); 33 | box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1); 34 | -webkit-border-radius: 8px; 35 | -moz-border-radius: 8px; 36 | border-radius: 8px; 37 | border: 1px solid #aaa; 38 | height: 4px; 39 | } 40 | 41 | .slider > .highlight-track { 42 | background-color: #8DCA09; 43 | background: -webkit-linear-gradient(top, #8DCA09, #72A307); 44 | background: -moz-linear-gradient(top, #8DCA09, #72A307); 45 | background: linear-gradient(top, #8DCA09, #72A307); 46 | border-color: #496805; 47 | } 48 | -------------------------------------------------------------------------------- /src/components/Float/QueryNodeSelectItem.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { ListGroupItem } from "react-bootstrap"; 3 | 4 | export default class QueryNodeSelectItem extends Component { 5 | convertToDisplayProp() { 6 | var str = ""; 7 | $.each( 8 | Object.keys(this.props.extraProps), 9 | function(_, prop) { 10 | if (prop === "name") { 11 | return; 12 | } 13 | 14 | let obj = this.props.extraProps[prop]; 15 | var type = typeof obj; 16 | let val = null; 17 | if (type === "undefined") { 18 | val = null; 19 | } else if (type === "number") { 20 | if (obj === 0) { 21 | val = "Never"; 22 | } else { 23 | val = new Date(obj * 1000).toUTCString(); 24 | } 25 | } else if (type === "boolean") { 26 | val = obj.toString().toTitleCase(); 27 | } else if (obj === "") { 28 | val = null; 29 | } else { 30 | val = obj; 31 | } 32 | if (val !== null) { 33 | str += prop + ": " + val + "\n"; 34 | } 35 | }.bind(this) 36 | ); 37 | return str; 38 | } 39 | 40 | render() { 41 | let c = function() { 42 | emitter.emit("prebuiltQueryStep", this.props.label); 43 | }.bind(this); 44 | let str = this.convertToDisplayProp(); 45 | return ( 46 | 52 | {str} 53 | 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/components/Modals/DeleteEdgeModal.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { Modal } from "react-bootstrap"; 3 | 4 | export default class DeleteEdgeModal extends Component { 5 | constructor() { 6 | super(); 7 | this.state = { 8 | open: false 9 | }; 10 | } 11 | 12 | closeModal() { 13 | this.setState({ open: false }); 14 | } 15 | 16 | confirmDelete() { 17 | this.closeModal(); 18 | emitter.emit("deleteEdgeConfirm", this.state.id); 19 | } 20 | 21 | openModal(id) { 22 | closeTooltip() 23 | this.setState({ open: true, id: id }); 24 | } 25 | 26 | componentDidMount() { 27 | emitter.on("deleteEdge", this.openModal.bind(this)); 28 | } 29 | 30 | render() { 31 | return ( 32 | 37 | 38 | Delete Edge 39 | 40 | 41 | 42 |

Are you sure you want to delete this edge?

43 |
44 | 45 | 46 | 53 | 60 | 61 |
62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/components/Modals/DeleteNodeModal.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { Modal } from "react-bootstrap"; 3 | 4 | export default class DeleteNodeModal extends Component { 5 | constructor() { 6 | super(); 7 | this.state = { 8 | open: false 9 | }; 10 | } 11 | 12 | closeModal() { 13 | this.setState({ open: false }); 14 | } 15 | 16 | confirmDelete() { 17 | this.closeModal(); 18 | emitter.emit("deleteNodeConfirm", this.state.id); 19 | } 20 | 21 | openModal(id) { 22 | closeTooltip() 23 | 24 | this.setState({ open: true, id: id }); 25 | } 26 | 27 | componentDidMount() { 28 | emitter.on("deletenode", this.openModal.bind(this)); 29 | } 30 | 31 | render() { 32 | return ( 33 | 38 | 39 | Delete Node 40 | 41 | 42 | 43 |

Are you sure you want to delete this node?

44 |
45 | 46 | 47 | 54 | 61 | 62 |
63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/components/Modals/CancelUploadModal.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | import { Modal } from "react-bootstrap"; 4 | 5 | export default class CancelUploadModal extends Component { 6 | constructor() { 7 | super(); 8 | this.state = { 9 | open: false 10 | }; 11 | } 12 | 13 | closeModal() { 14 | this.setState({ open: false }); 15 | } 16 | 17 | closeAndCancel() { 18 | this.setState({ open: false }); 19 | emitter.emit("cancelUpload"); 20 | } 21 | 22 | openModal() { 23 | this.setState({ open: true }); 24 | } 25 | 26 | componentDidMount() { 27 | emitter.on("showCancelUpload", this.openModal.bind(this)); 28 | } 29 | 30 | render() { 31 | return ( 32 | 37 | 38 | 39 | Cancel Upload 40 | 41 | 42 | 43 | 44 |

Are you sure you want to cancel the upload?

45 |
46 | 47 | 48 | 55 | 62 | 63 |
64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/components/Zoom/ZoomContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | export default class ZoomContainer extends Component { 4 | constructor(){ 5 | super(); 6 | 7 | this.state = { 8 | darkMode: false 9 | } 10 | } 11 | 12 | componentDidMount(){ 13 | emitter.on("toggleDarkMode", this.toggleDarkMode.bind(this)); 14 | this.toggleDarkMode(appStore.performance.darkMode); 15 | } 16 | 17 | toggleDarkMode(enabled){ 18 | this.setState({darkMode: enabled}); 19 | } 20 | 21 | render() { 22 | return ( 23 |
24 |
25 | 33 |
34 |
35 | 43 |
44 |
45 | 53 |
54 |
55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | BloodHound 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 |
26 | 37 | 38 | 39 | 43 | 44 | -------------------------------------------------------------------------------- /src/components/Modals/SessionClearModal.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { clearSessions } from "utils"; 3 | 4 | import { Modal } from "react-bootstrap"; 5 | 6 | export default class SessionClearModal extends Component { 7 | constructor() { 8 | super(); 9 | 10 | this.state = { 11 | open: false 12 | }; 13 | } 14 | 15 | closeModal() { 16 | this.setState({ open: false }); 17 | } 18 | 19 | openModal() { 20 | this.setState({ open: true }); 21 | } 22 | 23 | closeAndClear() { 24 | this.setState({ open: false }); 25 | clearSessions(); 26 | } 27 | 28 | componentDidMount() { 29 | emitter.on("openSessionClearModal", this.openModal.bind(this)); 30 | } 31 | 32 | render() { 33 | return ( 34 | 39 | 40 | 41 | Clear Sessions 42 | 43 | 44 | 45 | 46 |

Are you sure you want to clear sessions?

47 |
48 | 49 | 50 | 57 | 64 | 65 |
66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/components/Modals/LogoutModal.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | import { Modal } from "react-bootstrap"; 4 | 5 | export default class LogoutModal extends Component { 6 | constructor() { 7 | super(); 8 | this.state = { 9 | open: false 10 | }; 11 | } 12 | 13 | closeModal() { 14 | this.setState({ open: false }); 15 | } 16 | 17 | closeAndLogout() { 18 | conf.delete("databaseInfo"); 19 | appStore.databaseInfo = null; 20 | this.setState({ open: false }); 21 | emitter.emit("doLogout"); 22 | driver.close(); 23 | renderEmit.emit("logout"); 24 | } 25 | 26 | openModal() { 27 | this.setState({ open: true }); 28 | } 29 | 30 | componentDidMount() { 31 | emitter.on("showLogout", this.openModal.bind(this)); 32 | } 33 | 34 | render() { 35 | return ( 36 | 41 | 42 | Logout 43 | 44 | 45 | 46 |

Are you sure you want to logout?

47 |
48 | 49 | 50 | 57 | 64 | 65 |
66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/components/SearchContainer/Tabs/NodeProps.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | export default class componentName extends Component { 4 | constructor(props) { 5 | super(props); 6 | } 7 | 8 | convertToDisplayProp(propName) { 9 | var obj = this.props.properties[propName]; 10 | var type = typeof obj; 11 | if (type === "undefined") { 12 | return null; 13 | } else if (type === "number") { 14 | if (obj === 0 || obj === -1) { 15 | return "Never"; 16 | } else { 17 | return new Date(obj * 1000).toUTCString(); 18 | } 19 | } else if (type === "boolean") { 20 | return obj.toString().toTitleCase(); 21 | } else if (obj === "") { 22 | return null; 23 | } else { 24 | return obj; 25 | } 26 | } 27 | 28 | render() { 29 | let l = []; 30 | let count = 0; 31 | 32 | $.each( 33 | this.props.displayMap, 34 | function(key, value) { 35 | let val = this.convertToDisplayProp(key); 36 | 37 | if (val !== null) { 38 | l.push(
{value}
); 39 | l.push(
{val}
); 40 | } 41 | }.bind(this) 42 | ); 43 | 44 | if (this.props.ServicePrincipalNames && this.props.ServicePrincipalNames.length > 0) { 45 | l.push(
Service Principal Names
); 46 | $.each(this.props.ServicePrincipalNames, function(_, value) { 47 | l.push(
{value}
); 48 | count++; 49 | }); 50 | } 51 | 52 | if (this.props.AllowedToDelegate && this.props.AllowedToDelegate.length > 0){ 53 | l.push(
Allowed To Delegate
); 54 | $.each(this.props.AllowedToDelegate, function(_, value) { 55 | l.push(
{value}
); 56 | count++; 57 | }); 58 | } 59 | 60 | return l; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | 5 | env: 6 | matrix: 7 | secure: hDK5HxOqtKBOTL8PbBOVN8Rl3JeySb0L7bn7X/ZhkpRsakwoj8Y2YfWZz8tb31W3yViGVAa1FpaJzphze4E+d48pNoV6220yTv5gjJHhtybWzTGNS/FOEUPKYQrDFBk3Ve3l5rIcBZhX6KEJg5r8O27JpJkhrCEqkDj+9SQHWEzLJHaW6HYwMlR0+CNQYSd8+siLsjITYiUn49TnD0f6Ou6PkpMym1q95TGmA+DNmg4iXud4FCdlWPiNVuML3Sl+zBakQd8sosgiGCp5k0qQSFu3l8G20oUoWs0iKmdgJZSdWkZupsrXDoWCmmvC+rHVsxKwQ7YrLgGejLUD7N1uDKO28sfOgPzOGNzSwFO+dZf6RKoyMn/WiudpwFW0/KV/bhv7Uklb5qd4O2nl8yKeoz5o5qCG4Pw7qXsJn8rSY1ytyCU6hCX8dVnN8aQ+MgfSyXPr7rEeeVQkOiNHrI5XLc1Dmiu4khoDf2yn1d/A61fgEwCMClLihOXyc+Qcw4bBgKTcJA5JeMuD39jTmFOLbipIHrFrLpTHOAi1G48uS1o2VWKFOgsA+QphVwdT0zo84oeLminykXxBtGB6YUuiWxLVXbLNET5t6BxskQcMKfCYy5+6Y1TCf3yzYlkqmFvoq/Tu8Z9IAxrT3Bx6IgGOV+njgGszm7PWIy9Doi84sic= 8 | 9 | os: 10 | - linux 11 | - osx 12 | 13 | before_install: 14 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi 15 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install p7zip; fi 16 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update; fi 17 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y p7zip-full; fi 18 | 19 | install: 20 | - npm install 21 | - npm install -g electron-packager 22 | 23 | script: 24 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then npm run macbuild; fi 25 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then npm run linuxbuild; fi 26 | 27 | before_deploy: 28 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 7z a -tzip -mx9 BloodHound-darwin-x64-$TRAVIS_COMMIT.zip BloodHound-darwin-x64 > /dev/null; fi 29 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 7z a -tzip -mx9 BloodHound-linux-ia32-$TRAVIS_COMMIT.zip BloodHound-linux-ia32 > /dev/null; fi 30 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 7z a -tzip -mx9 BloodHound-linux-x64-$TRAVIS_COMMIT.zip BloodHound-linux-x64 > /dev/null; fi 31 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 7z a -tzip -mx9 BloodHound-linux-armv7l-$TRAVIS_COMMIT.zip BloodHound-linux-armv7l > /dev/null; fi 32 | 33 | deploy: 34 | provider: script 35 | script: /bin/bash deploy.sh 36 | skip_cleanup: true 37 | on: 38 | branch: master 39 | 40 | notifications: 41 | email: false 42 | 43 | branches: 44 | only: 45 | - master -------------------------------------------------------------------------------- /src/components/Modals/ClearWarnModal.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { Modal } from "react-bootstrap"; 3 | 4 | export default class ClearWarnModal extends Component { 5 | constructor() { 6 | super(); 7 | 8 | this.state = { 9 | open: false 10 | }; 11 | } 12 | 13 | closeModal() { 14 | this.setState({ open: false }); 15 | } 16 | 17 | openModal() { 18 | this.setState({ open: true }); 19 | } 20 | 21 | closeAndOpenStep() { 22 | this.setState({ open: false }); 23 | emitter.emit("openDBConfirm"); 24 | } 25 | 26 | componentDidMount() { 27 | emitter.on("openDBWarnModal", this.openModal.bind(this)); 28 | } 29 | 30 | render() { 31 | return ( 32 | 37 | 38 | 39 | Clear Database 40 | 41 | 42 | 43 | 44 |

45 | Are you sure you want to clear the database? This is 46 | irreversible and may take some time! 47 |

48 |
49 | 50 | 51 | 58 | 65 | 66 |
67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/css/simple-slider-volume.css: -------------------------------------------------------------------------------- 1 | .slider-volume { 2 | width: 300px; 3 | } 4 | 5 | .slider-volume > .dragger { 6 | width: 16px; 7 | height: 16px; 8 | margin: 0 auto; 9 | border: 1px solid rgba(255, 255, 255, 0.6); 10 | -moz-box-shadow: 0 0px 2px 1px rgba(0, 0, 0, 0.5), 0 2px 5px 2px rgba(0, 0, 0, 0.2); 11 | -webkit-box-shadow: 0 0px 2px 1px rgba(0, 0, 0, 0.5), 0 2px 5px 2px rgba(0, 0, 0, 0.2); 12 | box-shadow: 0 0px 2px 1px rgba(0, 0, 0, 0.5), 0 2px 5px 2px rgba(0, 0, 0, 0.2); 13 | -moz-border-radius: 10px; 14 | -webkit-border-radius: 10px; 15 | border-radius: 10px; 16 | background: #c5c5c5; 17 | background: -moz-linear-gradient(90deg, rgba(180, 180, 180, 1) 20%, rgba(230, 230, 230, 1) 50%, rgba(180, 180, 180, 1) 80%); 18 | background: -webkit-radial-gradient( 50% 0%, 12% 50%, hsla(0, 0%, 100%, 1) 0%, hsla(0, 0%, 100%, 0) 100%), -webkit-radial-gradient( 50% 100%, 12% 50%, hsla(0, 0%, 100%, .6) 0%, hsla(0, 0%, 100%, 0) 100%), -webkit-radial-gradient( 50% 50%, 200% 50%, hsla(0, 0%, 90%, 1) 5%, hsla(0, 0%, 85%, 1) 30%, hsla(0, 0%, 60%, 1) 100%); 19 | } 20 | 21 | .slider-volume > .track, 22 | .slider-volume > .highlight-track { 23 | height: 11px; 24 | background: #787878; 25 | background: -moz-linear-gradient(top, #787878, #a2a2a2); 26 | background: -webkit-linear-gradient(top, #787878, #a2a2a2); 27 | background: linear-gradient(top, #787878, #a2a2a2); 28 | -moz-box-shadow: inset 0 2px 5px 1px rgba(0, 0, 0, 0.15), 0 1px 0px 0px rgba(230, 230, 230, 0.9), inset 0 0 1px 1px rgba(0, 0, 0, 0.2); 29 | -webkit-box-shadow: inset 0 2px 5px 1px rgba(0, 0, 0, 0.15), 0 1px 0px 0px rgba(230, 230, 230, 0.9), inset 0 0 1px 1px rgba(0, 0, 0, 0.2); 30 | box-shadow: inset 0 2px 5px 1px rgba(0, 0, 0, 0.15), 0 1px 0px 0px rgba(230, 230, 230, 0.9), inset 0 0 1px 1px rgba(0, 0, 0, 0.2); 31 | -moz-border-radius: 5px; 32 | -webkit-border-radius: 5px; 33 | border-radius: 5px; 34 | } 35 | 36 | .slider-volume > .highlight-track { 37 | background-color: #c5c5c5; 38 | background: -moz-linear-gradient(top, #c5c5c5, #a2a2a2); 39 | background: -webkit-linear-gradient(top, #c5c5c5, #a2a2a2); 40 | background: linear-gradient(top, #c5c5c5, #a2a2a2); 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Downloading BloodHound Binaries 2 | Pre-Compiled BloodHound binaries can be found [here](https://github.com/BloodHoundAD/BloodHound/releases). 3 | 4 | The rolling release will always be updated to the most recent source. Tagged releases are considered "stable" but will likely not have new features or fixes. 5 | 6 | # About BloodHound 7 | 8 | To get started with BloodHound, check out the [BloodHound Github Wiki.](https://github.com/BloodHoundAD/Bloodhound/wiki) 9 | 10 | BloodHound is a single page Javascript web application, built on top of [Linkurious](http://linkurio.us/), compiled with [Electron](http://electron.atom.io/), with a [Neo4j](https://neo4j.com/) database fed by a PowerShell ingestor. 11 | 12 | BloodHound uses graph theory to reveal the hidden and often unintended relationships within an Active Directory environment. Attackers can use BloodHound to easily identify highly complex attack paths that would otherwise be impossible to quickly identify. Defenders can use BloodHound to identify and eliminate those same attack paths. Both blue and red teams can use BloodHound to easily gain a deeper understanding of privilege relationships in an Active Directory environment. 13 | 14 | BloodHound is developed by [@_wald0](https://www.twitter.com/_wald0), [@CptJesus](https://twitter.com/CptJesus), and [@harmj0y](https://twitter.com/harmj0y). 15 | 16 | # License 17 | 18 | BloodHound uses graph theory to reveal hidden relationships and 19 | attack paths in an Active Directory environment. 20 | Copyright (C) 2016 Andrew Robbins, Rohan Vazarkar, Will Schroeder 21 | 22 | This program is free software: you can redistribute it and/or modify 23 | it under the terms of the GNU General Public License as published by 24 | the Free Software Foundation, either version 3 of the License, or 25 | (at your option) any later version. 26 | 27 | This program is distributed in the hope that it will be useful, 28 | but WITHOUT ANY WARRANTY; without even the implied warranty of 29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 | GNU General Public License for more details. 31 | 32 | You should have received a copy of the GNU General Public License 33 | along with this program. If not, see . 34 | -------------------------------------------------------------------------------- /src/components/Modals/ClearConfirmModal.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { clearDatabase } from "utils"; 3 | 4 | import { Modal } from "react-bootstrap"; 5 | 6 | export default class ClearConfirmModal extends Component { 7 | constructor() { 8 | super(); 9 | this.state = { 10 | open: false 11 | }; 12 | } 13 | 14 | openModal() { 15 | this.setState({ open: true }); 16 | } 17 | 18 | closeModal() { 19 | this.setState({ open: false }); 20 | } 21 | 22 | closeModalAndClearDB() { 23 | this.setState({ open: false }); 24 | emitter.emit("clearDB"); 25 | clearDatabase(); 26 | } 27 | 28 | componentDidMount() { 29 | emitter.on("openDBConfirm", this.openModal.bind(this)); 30 | } 31 | 32 | render() { 33 | return ( 34 | 39 | 40 | 41 | Clear Database 42 | 43 | 44 | 45 | 46 |

47 | Are you ABSOLUTELY sure you want to clear the database? 48 |

49 |
50 | 51 | 52 | 59 | 66 | 67 |
68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/components/Menu/MenuButton.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export default class MenuButton extends Component { 5 | constructor(){ 6 | super() 7 | 8 | this.state = { 9 | darkMode: false 10 | } 11 | } 12 | 13 | componentDidMount() { 14 | $(this.refs.btn).html( 15 | ''.format(this.props.glyphicon) 16 | ); 17 | 18 | emitter.on("toggleDarkMode", this.toggleDarkMode.bind(this)) 19 | this.toggleDarkMode(appStore.performance.darkMode); 20 | } 21 | 22 | toggleDarkMode(enabled){ 23 | this.setState({darkMode: enabled}); 24 | } 25 | 26 | _leave(e) { 27 | var target = $(e.target); 28 | target.css("width", "auto"); 29 | var oldWidth = target.width(); 30 | target.html(''.format(this.props.glyphicon)); 31 | var newWidth = target.outerWidth(); 32 | target.width(oldWidth); 33 | target.animate( 34 | { 35 | width: newWidth + "px" 36 | }, 37 | 100 38 | ); 39 | } 40 | 41 | _enter(e) { 42 | var target = $(e.target); 43 | target.css("width", "auto"); 44 | var oldWidth = target.width(); 45 | target.html( 46 | '{} '.format( 47 | this.props.hoverVal, 48 | this.props.glyphicon 49 | ) 50 | ); 51 | var newWidth = target.outerWidth(); 52 | target.width(oldWidth); 53 | target.animate( 54 | { 55 | width: newWidth + "px" 56 | }, 57 | 100 58 | ); 59 | } 60 | 61 | render() { 62 | var c = "glyphicon glyphicon-" + this.props.glyphicon; 63 | return ( 64 | 73 | ); 74 | } 75 | } 76 | 77 | MenuButton.propTypes = { 78 | hoverVal: PropTypes.string.isRequired, 79 | glyphicon: PropTypes.string.isRequired, 80 | click: PropTypes.func.isRequired 81 | }; 82 | -------------------------------------------------------------------------------- /src/components/SearchContainer/Tabs/NodeCypherLinkComplex.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component, Fragment } from "react"; 2 | import PropTypes from "prop-types"; 3 | import NodeALink from "./NodeALink"; 4 | 5 | export default class NodeCypherLinkComplex extends Component { 6 | constructor(props) { 7 | super(props); 8 | } 9 | 10 | componentWillMount() { 11 | this.setState({ 12 | ready: false, 13 | value: 0 14 | }); 15 | } 16 | 17 | componentWillReceiveProps(newProps) { 18 | if (this.props.target !== newProps.target) { 19 | var session = driver.session(); 20 | if (typeof this.state.session !== "undefined") { 21 | this.state.session.close(); 22 | } 23 | 24 | this.setState({ 25 | session: session, 26 | ready: false 27 | }); 28 | let query = this.props.countQuery; 29 | let domain = "@" + newProps.target.split("@").last(); 30 | session.run(query, { name: newProps.target, domain: domain }).then( 31 | function(result) { 32 | this.setState({ 33 | value: result.records[0]._fields[0].low, 34 | ready: true 35 | }); 36 | }.bind(this) 37 | ); 38 | } 39 | } 40 | 41 | render() { 42 | return ( 43 | 44 |
{this.props.property}
45 |
46 | 59 |
60 |
61 | ); 62 | } 63 | } 64 | 65 | NodeCypherLinkComplex.propTypes = { 66 | target: PropTypes.string.isRequired, 67 | property: PropTypes.string.isRequired, 68 | countQuery: PropTypes.string.isRequired, 69 | graphQuery: PropTypes.string.isRequired, 70 | start: PropTypes.string, 71 | end: PropTypes.string 72 | }; 73 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # DO NOT RUN THIS SCRIPT, THIS IS A SCRIPT FOR TRAVIS TO DO STUFF 3 | response="$(curl -s --user "${GH_USER}" https://api.github.com/repos/BloodHoundAD/BloodHound/releases/4033842/assets)" 4 | 5 | iad32id="$(echo "$response" | grep -B 2 \"BloodHound-linux-ia32 | head -n1 | cut -d ":" -f 2 | cut -c 2- | sed 's/.$//')" 6 | x64id="$(echo "$response" | grep -B 2 \"BloodHound-linux-x64 | head -n1 | cut -d ":" -f 2 | cut -c 2- | sed 's/.$//')" 7 | armv7lid="$(echo "$response" | grep -B 2 \"BloodHound-linux-armv7l | head -n1 | cut -d ":" -f 2 | cut -c 2- | sed 's/.$//')" 8 | macid="$(echo "$response" | grep -B 2 \"BloodHound-darwin-x64 | head -n1 | cut -d ":" -f 2 | cut -c 2- | sed 's/.$//')" 9 | 10 | if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 11 | if [[ ! $iad32id == "" ]]; then 12 | curl -s -X DELETE --user "${GH_USER}" https://api.github.com/repos/BloodHoundAD/BloodHound/releases/assets/$iad32id 13 | fi 14 | 15 | if [[ ! $x64id == "" ]]; then 16 | curl -s -X DELETE --user "${GH_USER}" https://api.github.com/repos/BloodHoundAD/BloodHound/releases/assets/$x64id 17 | fi 18 | 19 | if [[ ! $armv7lid == "" ]]; then 20 | curl -s -X DELETE --user "${GH_USER}" https://api.github.com/repos/BloodHoundAD/BloodHound/releases/assets/$armv7lid 21 | fi 22 | 23 | curl -X POST -# --header 'Content-Type:application/zip' --data-binary @BloodHound-linux-ia32-$TRAVIS_COMMIT.zip --user "${GH_USER}" https://uploads.github.com/repos/BloodHoundAD/BloodHound/releases/4033842/assets?name=BloodHound-linux-ia32-$TRAVIS_COMMIT.zip 24 | curl -X POST -# --header 'Content-Type:application/zip' --data-binary @BloodHound-linux-x64-$TRAVIS_COMMIT.zip --user "${GH_USER}" https://uploads.github.com/repos/BloodHoundAD/BloodHound/releases/4033842/assets?name=BloodHound-linux-x64-$TRAVIS_COMMIT.zip 25 | curl -X POST -# --header 'Content-Type:application/zip' --data-binary @BloodHound-linux-armv7l-$TRAVIS_COMMIT.zip --user "${GH_USER}" https://uploads.github.com/repos/BloodHoundAD/BloodHound/releases/4033842/assets?name=BloodHound-linux-armv7l-$TRAVIS_COMMIT.zip 26 | fi 27 | 28 | if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 29 | if [[ ! $macid == "" ]]; then 30 | curl -s -X DELETE --user "${GH_USER}" https://api.github.com/repos/BloodHoundAD/BloodHound/releases/assets/$macid 31 | fi 32 | 33 | curl -X POST -# --header 'Content-Type:application/zip' --data-binary @BloodHound-darwin-x64-$TRAVIS_COMMIT.zip --user "${GH_USER}" https://uploads.github.com/repos/BloodHoundAD/BloodHound/releases/4033842/assets?name=BloodHound-darwin-x64-$TRAVIS_COMMIT.zip 34 | fi 35 | -------------------------------------------------------------------------------- /src/components/RawQuery.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | export default class RawQuery extends Component { 4 | constructor() { 5 | super(); 6 | this.state = { 7 | val: "", 8 | open: false, 9 | darkMode: false 10 | }; 11 | } 12 | 13 | componentWillMount() { 14 | emitter.on("setRawQuery", this._setQueryFromEvent.bind(this)); 15 | emitter.on("toggleDarkMode", this.toggleDarkMode.bind(this)); 16 | } 17 | 18 | componentDidMount() { 19 | $(this.refs.input).slideToggle(0); 20 | this.toggleDarkMode(appStore.performance.darkMode); 21 | } 22 | 23 | toggleDarkMode(enabled){ 24 | this.setState({darkMode: enabled}); 25 | } 26 | 27 | _onChange(event) { 28 | this.setState({ 29 | val: event.target.value 30 | }); 31 | } 32 | 33 | _onKeyUp(e) { 34 | var key = e.keyCode ? e.keyCode : e.which; 35 | 36 | if (key === 13) { 37 | emitter.emit("query", this.state.val); 38 | } 39 | } 40 | 41 | _toggle() { 42 | $(this.refs.input).slideToggle(); 43 | this.setState({ 44 | open: !this.state.open 45 | }); 46 | } 47 | 48 | _setQueryFromEvent(query) { 49 | this.setState({ val: query }); 50 | } 51 | 52 | render() { 53 | return ( 54 |
55 | 75 | 85 |
86 | ); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/components/Menu/ProgressBarMenuButton.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | export default class ProgressBarMenuButton extends Component { 5 | constructor() { 6 | super(); 7 | 8 | this.state = { 9 | expanded: false 10 | }; 11 | } 12 | 13 | componentDidMount() { 14 | $(this.refs.btn).html("{}%".format(this.props.progress)); 15 | $(this.refs.btn).css("padding", "6px 0px 6px 0px"); 16 | $(this.refs.btn).css("width", "41px"); 17 | } 18 | 19 | componentWillReceiveProps(nextProps) { 20 | if (this.state.expanded) { 21 | var template = `
22 |
23 |
24 | 25 | {}% 26 | 27 |
`.formatAll(nextProps.progress); 28 | $(this.refs.btn).html(template); 29 | } else { 30 | $(this.refs.btn).html("{}%".format(nextProps.progress)); 31 | } 32 | 33 | this.forceUpdate(); 34 | } 35 | 36 | shouldComponentUpdate(_nextProps, _nextState) { 37 | return true; 38 | } 39 | 40 | _leave(e) { 41 | this.setState({ expanded: false }); 42 | var target = $(e.target); 43 | target.html("{}%".format(this.props.progress)); 44 | target.animate( 45 | { 46 | width: "41px" 47 | }, 48 | 100 49 | ); 50 | } 51 | 52 | _enter(e) { 53 | this.setState({ expanded: true }); 54 | var target = $(e.target); 55 | var template = ` 56 |
57 |
58 |
59 | 60 | {}% 61 | 62 |
63 | `.formatAll(this.props.progress); 64 | 65 | target.html(template); 66 | target.animate( 67 | { 68 | width: "150px" 69 | }, 70 | 100 71 | ); 72 | } 73 | 74 | render() { 75 | return ( 76 | 53 |
54 | 55 | 103 |
104 | ); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/components/nodeTooltip.html: -------------------------------------------------------------------------------- 1 |
2 | {{label}} 3 |
4 |
    5 | {{#type_ou}} 6 |
  • 7 | Set as Starting Node 8 |
  • 9 |
  • 10 | Set as Ending Node 11 |
  • 12 | {{/type_ou}} 13 | {{^type_ou}} 14 |
  • 15 | Set as Starting Node 16 |
  • 17 |
  • 18 | Set as Ending Node 19 |
  • 20 | {{/type_ou}} 21 | {{#type_user}} 22 |
  • 23 | Shortest Paths to Here 24 |
  • 25 | {{/type_user}} {{#type_computer}} 26 |
  • 27 | Shortest Paths to Here 28 |
  • 29 | {{/type_computer}} {{#type_group}} 30 |
  • 31 | Shortest Paths to Here 32 |
  • 33 | {{/type_group}} {{#type_gpo}} 34 |
  • 35 | Shortest Paths to Here 36 |
  • 37 | {{/type_gpo}} {{#type_ou}} 38 |
  • 39 | Shortest Paths to Here 40 |
  • 41 | {{/type_ou}} {{#type_domain}} 42 |
  • 43 | Shortest Paths to Here 44 |
  • 45 | {{/type_domain}} 46 | {{#type_ou}} 47 |
  • 48 | Edit Node 49 |
  • 50 | {{/type_ou}} 51 | {{^type_ou}} 52 |
  • 53 | Edit Node 54 |
  • 55 | {{/type_ou}} 56 | {{#owned}} 57 |
  • 58 | Unmark {{type}} as Owned 59 |
  • 60 | {{/owned}} 61 | {{#notowned}} 62 |
  • 63 | Mark {{type}} as Owned 64 |
  • 65 | {{/notowned}} 66 | {{#highvalue}} 67 |
  • 68 | Unmark {{type}} as High Value 69 |
  • 70 | {{/highvalue}} 71 | {{^highvalue}} 72 |
  • 73 | Mark {{type}} as High Value 74 |
  • 75 | {{/highvalue}} 76 |
  • 77 | Delete Node 78 |
  • 79 | {{#expand}} 80 |
  • 81 | Expand 82 |
  • 83 | {{/expand}} {{#collapse}} 84 |
  • 85 | Collapse 86 |
  • 87 | {{/collapse}} {{#groupedNode}} 88 |
  • 89 | Expand 90 |
  • 91 | {{/groupedNode}} 92 |
-------------------------------------------------------------------------------- /src/components/Spotlight/SpotlightContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import GlyphiconSpan from "../GlyphiconSpan"; 3 | import Icon from "../Icon"; 4 | import SpotlightRow from "./SpotlightRow"; 5 | 6 | export default class SpotlightContainer extends Component { 7 | constructor(props) { 8 | super(props); 9 | 10 | this.state = { 11 | data: appStore.spotlightData, 12 | searchVal: "", 13 | rex: new RegExp("", "i") 14 | }; 15 | 16 | emitter.on( 17 | "spotlightUpdate", 18 | function() { 19 | this.setState({ data: appStore.spotlightData }); 20 | }.bind(this) 21 | ); 22 | 23 | emitter.on( 24 | "spotlightClick", 25 | function() { 26 | $(this.refs.spotlight).fadeToggle(false); 27 | }.bind(this) 28 | ); 29 | 30 | emitter.on( 31 | "resetSpotlight", 32 | function() { 33 | this.setState({ 34 | searchVal: "", 35 | rex: new RegExp("", "i") 36 | }); 37 | }.bind(this) 38 | ); 39 | } 40 | 41 | _searchChanged(event) { 42 | this.setState({ 43 | searchVal: event.target.value, 44 | rex: new RegExp(event.target.value, "i") 45 | }); 46 | } 47 | 48 | render() { 49 | return ( 50 |
51 |
52 | 56 | 57 | 58 | 67 |
68 | 69 |
70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | {Object.keys(this.state.data).map( 79 | function(key) { 80 | var d = this.state.data[key]; 81 | var nid = parseInt(key); 82 | var x = this.state.rex.test(d[0]) ? ( 83 | 92 | ) : null; 93 | return x; 94 | }.bind(this) 95 | )} 96 | 97 |
Node LabelCollapsed Into
98 |
99 |
100 | ); 101 | } 102 | 103 | componentDidMount() { 104 | jQuery(this.refs.spotlight).fadeToggle(0); 105 | 106 | $(window).on( 107 | "keyup", 108 | function(e) { 109 | var key = e.keyCode ? e.keyCode : e.which; 110 | 111 | if (document.activeElement === document.body && key === 32) { 112 | $(this.refs.spotlight).fadeToggle(); 113 | } 114 | }.bind(this) 115 | ); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/components/SearchContainer/Tabs/PrebuiltQueriesDisplay.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import PrebuiltQueryNode from "./PrebuiltQueryNode"; 3 | import { If, Then, Else } from "react-if"; 4 | import { remote } from "electron"; 5 | const { app } = remote; 6 | import { join } from "path"; 7 | import { platform } from "process"; 8 | import { exec } from "child_process"; 9 | 10 | export default class PrebuiltQueriesDisplay extends Component { 11 | constructor() { 12 | super(); 13 | 14 | this.state = { 15 | queries: [], 16 | custom: [] 17 | }; 18 | } 19 | 20 | componentWillMount() { 21 | $.ajax({ 22 | url: join(app.getPath("userData"), "/customqueries.json"), 23 | type: "GET", 24 | success: function(response) { 25 | var x = JSON.parse(response); 26 | var y = []; 27 | 28 | $.each(x.queries, function(_, el) { 29 | y.push(el); 30 | }); 31 | 32 | this.setState({ custom: y }); 33 | }.bind(this) 34 | }); 35 | 36 | $.ajax({ 37 | url: "src/components/SearchContainer/Tabs/PrebuiltQueries.json", 38 | type: "GET", 39 | success: function(response) { 40 | var x = JSON.parse(response); 41 | var y = []; 42 | 43 | $.each(x.queries, function(_, el) { 44 | y.push(el); 45 | }); 46 | 47 | this.setState({ queries: y }); 48 | }.bind(this) 49 | }); 50 | } 51 | 52 | getCommandLine() { 53 | switch (platform) { 54 | case "darwin": 55 | return "open"; 56 | case "win32": 57 | return ""; 58 | case "win64": 59 | return ""; 60 | default: 61 | return "xdg-open"; 62 | } 63 | } 64 | 65 | editCustom() { 66 | exec( 67 | this.getCommandLine() + 68 | ' "' + 69 | join(app.getPath("userData"), "/customqueries.json") + 70 | '"' 71 | ); 72 | } 73 | 74 | refreshCustom() { 75 | $.ajax({ 76 | url: join(app.getPath("userData"), "/customqueries.json"), 77 | type: "GET", 78 | success: function(response) { 79 | var x = JSON.parse(response); 80 | var y = []; 81 | 82 | $.each(x.queries, function(index, el) { 83 | y.push(el); 84 | }); 85 | 86 | this.setState({ custom: y }); 87 | }.bind(this) 88 | }); 89 | } 90 | 91 | render() { 92 | return ( 93 |
94 |

Pre-Built Analytics Queries

95 |
96 | {this.state.queries.map(function(a) { 97 | return ; 98 | })} 99 |
100 |

101 | Custom Queries 102 | 108 | 115 |

116 |
117 | 118 | 119 |
No user defined queries.
120 |
121 | 122 | {() => ( 123 |
124 | {this.state.custom.map(function(a) { 125 | return ( 126 | 130 | ); 131 | })} 132 |
133 | )} 134 |
135 |
136 |
137 |
138 | ); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/components/Modals/About.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | import { Modal } from "react-bootstrap"; 4 | import { join } from "path"; 5 | import { readFileSync, readFile } from "fs"; 6 | import { remote } from "electron"; 7 | const { app, shell } = remote; 8 | 9 | export default class About extends Component { 10 | constructor() { 11 | super(); 12 | 13 | var json = JSON.parse( 14 | readFileSync(join(app.getAppPath(), "package.json")) 15 | ); 16 | 17 | readFile( 18 | join(app.getAppPath(), "LICENSE.md"), 19 | "utf8", 20 | function(err, data) { 21 | this.setState({ 22 | license: data 23 | }); 24 | }.bind(this) 25 | ); 26 | 27 | this.state = { 28 | open: false, 29 | version: json.version 30 | }; 31 | } 32 | 33 | closeModal() { 34 | this.setState({ open: false }); 35 | } 36 | 37 | openModal() { 38 | this.setState({ open: true }); 39 | } 40 | 41 | componentDidMount() { 42 | emitter.on("showAbout", this.openModal.bind(this)); 43 | } 44 | 45 | render() { 46 | return ( 47 | 52 | 53 | About BloodHound 54 | 55 | 56 | 57 |
58 | Version: {this.state.version} 59 |
60 |
61 | GitHub:{" "} 62 | 70 | https://www.github.com/BloodHoundAD/BloodHound 71 | 72 |
73 |
74 | BloodHound Slack:{" "} 75 | 83 | https://bloodhoundgang.herokuapp.com/ 84 | 85 |
86 |
87 | Authors:{" "} 88 | 96 | @harmj0y 97 | ,{" "} 98 | 106 | @_wald0 107 | ,{" "} 108 | 116 | @cptjesus 117 | 118 |
119 |
120 |
121 | License 122 |
123 |
{this.state.license}
124 |
125 | 126 | 127 | 134 | 135 |
136 | ); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/components/Modals/AddNodeModal.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { Modal } from "react-bootstrap"; 3 | 4 | export default class AddNodeModal extends Component { 5 | constructor() { 6 | super(); 7 | this.state = { 8 | open: false 9 | }; 10 | } 11 | 12 | componentDidMount() { 13 | emitter.on("addNode", this.openModal.bind(this)); 14 | } 15 | 16 | closeModal() { 17 | this.setState({ open: false }); 18 | } 19 | 20 | validate() { 21 | let name = jQuery(this.refs.name).val(); 22 | let type = jQuery(this.refs.type).val(); 23 | let validate = jQuery(this.refs.validate); 24 | let error = jQuery(this.refs.error); 25 | let complete = jQuery(this.refs.complete); 26 | 27 | if (name === ""){ 28 | validate.addClass("has-error") 29 | error.html("Name cannot be blank!"); 30 | error.show(); 31 | return; 32 | } 33 | 34 | if (type === "Computer"){ 35 | if (!name.includes('.') || name.split('.').length < 3){ 36 | validate.addClass("has-error") 37 | error.html("Computer name must be similar to COMPUTER.DOMAIN.COM"); 38 | error.show(); 39 | return; 40 | } 41 | }else{ 42 | if (!name.includes('@') || name.split('@').length > 2){ 43 | validate.addClass("has-error") 44 | error.html("Name must be similar to NAME@DOMAIN.COM"); 45 | error.show(); 46 | return; 47 | } 48 | 49 | let dpart = name.split('@')[1]; 50 | if (!dpart.includes('.')){ 51 | validate.addClass("has-error") 52 | error.html("Name must be similar to NAME@DOMAIN.COM"); 53 | error.show(); 54 | return; 55 | } 56 | } 57 | 58 | //initial validation done, check for duplicate 59 | name = name.toUpperCase(); 60 | if (type !== "OU"){ 61 | let q = driver.session(); 62 | let statement = "MATCH (n:{} {name:{name}}) RETURN n".format(type); 63 | q.run(statement, {name: name}).then(x => { 64 | q.close(); 65 | if (x.records.length > 0){ 66 | validate.addClass("has-error") 67 | error.html("Node with name already exists!"); 68 | error.show(); 69 | return; 70 | } 71 | 72 | emitter.emit("addNodeFinal", name, type) 73 | complete.show(); 74 | setTimeout(x => {this.closeModal()}, 500); 75 | }); 76 | }else{ 77 | complete.show(); 78 | emitter.emit("addNodeFinal", name, type); 79 | setTimeout(x => {this.closeModal();}, 500); 80 | } 81 | 82 | //this.closeModal(); 83 | } 84 | 85 | openModal() { 86 | closeTooltip() 87 | this.setState( {open: true }); 88 | jQuery(this.refs.name).focus() 89 | jQuery(this.refs.error).hide() 90 | jQuery(this.refs.complete).hide(); 91 | } 92 | 93 | clearFocus(){ 94 | let validate = jQuery(this.refs.validate); 95 | let error = jQuery(this.refs.error); 96 | 97 | validate.removeClass("has-error"); 98 | error.hide(); 99 | } 100 | 101 | render() { 102 | return ( 103 | 108 | 109 | Add Node 110 | 111 | 112 | 113 |
{x.preventDefault();this.validate()}} className="needs-validation" noValidate> 114 |
115 | 116 | 117 | 118 | Looks good! 119 | 120 |
121 |
122 | 123 | 131 |
132 |
133 |
134 | 135 | 136 | 140 | 147 | 154 | 155 |
156 | ); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/js/simple-slider.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery Simple Slider: Unobtrusive Numerical Slider 3 | * Version 1.0.0 4 | * 5 | * Copyright (c) 2014 James Smith (http://loopj.com) 6 | * 7 | * Licensed under the MIT license (http://mit-license.org/) 8 | * 9 | */ 10 | 11 | var __slice=[].slice,__indexOf=[].indexOf||function(e){for(var t=0,n=this.length;t").addClass("slider"+(this.settings.classSuffix||"")).css({position:"relative",userSelect:"none",boxSizing:"border-box"}).insertBefore(this.input),this.input.attr("id")&&this.slider.attr("id",this.input.attr("id")+"-slider"),this.track=this.createDivElement("track").css({width:"100%"}),this.settings.highlight&&(this.highlightTrack=this.createDivElement("highlight-track").css({width:"0"})),this.dragger=this.createDivElement("dragger"),this.slider.css({minHeight:this.dragger.outerHeight(),marginLeft:this.dragger.outerWidth()/2,marginRight:this.dragger.outerWidth()/2}),this.track.css({marginTop:this.track.outerHeight()/-2}),this.settings.highlight&&this.highlightTrack.css({marginTop:this.track.outerHeight()/-2}),this.dragger.css({marginTop:this.dragger.outerHeight()/-2,marginLeft:this.dragger.outerWidth()/-2}),this.track.mousedown(function(e){return i.trackEvent(e)}),this.settings.highlight&&this.highlightTrack.mousedown(function(e){return i.trackEvent(e)}),this.dragger.mousedown(function(e){if(e.which!==1)return;return i.dragging=!0,i.dragger.addClass("dragging"),i.domDrag(e.pageX,e.pageY),!1}),e("body").mousemove(function(t){if(i.dragging)return i.domDrag(t.pageX,t.pageY),e("body").css({cursor:"pointer"})}).mouseup(function(t){if(i.dragging)return i.dragging=!1,i.dragger.removeClass("dragging"),e("body").css({cursor:"auto"})}),this.pagePos=0,this.input.val()===""?(this.value=this.getRange().min,this.input.val(this.value)):this.value=this.nearestValidValue(this.input.val()),this.setSliderPositionFromValue(this.value),r=this.valueToRatio(this.value),this.input.trigger("slider:ready",{value:this.value,ratio:r,position:r*this.slider.outerWidth(),el:this.slider})}return t.prototype.createDivElement=function(t){var n;return n=e("
").addClass(t).css({position:"absolute",top:"50%",userSelect:"none",cursor:"pointer"}).appendTo(this.slider),n},t.prototype.setRatio=function(e){var t;return e=Math.min(1,e),e=Math.max(0,e),t=this.ratioToValue(e),this.setSliderPositionFromValue(t),this.valueChanged(t,e,"setRatio")},t.prototype.setValue=function(e){var t;return e=this.nearestValidValue(e),t=this.valueToRatio(e),this.setSliderPositionFromValue(e),this.valueChanged(e,t,"setValue")},t.prototype.trackEvent=function(e){if(e.which!==1)return;return this.domDrag(e.pageX,e.pageY,!0),this.dragging=!0,!1},t.prototype.domDrag=function(e,t,n){var r,i,s;n==null&&(n=!1),r=e-this.slider.offset().left,r=Math.min(this.slider.outerWidth(),r),r=Math.max(0,r);if(this.pagePos!==r)return this.pagePos=r,i=r/this.slider.outerWidth(),s=this.ratioToValue(i),this.valueChanged(s,i,"domDrag"),this.settings.snap?this.setSliderPositionFromValue(s,n):this.setSliderPosition(r,n)},t.prototype.setSliderPosition=function(e,t){t==null&&(t=!1);if(t&&this.settings.animate){this.dragger.animate({left:e},200);if(this.settings.highlight)return this.highlightTrack.animate({width:e},200)}else{this.dragger.css({left:e});if(this.settings.highlight)return this.highlightTrack.css({width:e})}},t.prototype.setSliderPositionFromValue=function(e,t){var n;return t==null&&(t=!1),n=this.valueToRatio(e),this.setSliderPosition(n*this.slider.outerWidth(),t)},t.prototype.getRange=function(){return this.settings.allowedValues?{min:Math.min.apply(Math,this.settings.allowedValues),max:Math.max.apply(Math,this.settings.allowedValues)}:this.settings.range?{min:parseFloat(this.settings.range[0]),max:parseFloat(this.settings.range[1])}:{min:0,max:1}},t.prototype.nearestValidValue=function(t){var n,r,i,s;return i=this.getRange(),t=Math.min(i.max,t),t=Math.max(i.min,t),this.settings.allowedValues?(n=null,e.each(this.settings.allowedValues,function(){if(n===null||Math.abs(this-t)this.settings.step/2&&s=0?(s=e(this).data("slider-object"),s[i].apply(s,t)):(o=i,e(this).data("slider-object",new n(e(this),o)))})}}),e(function(){return e("[data-slider]").each(function(){var t,n,r,i;return t=e(this),r={},n=t.data("slider-values"),n&&(r.allowedValues=function(){var e,t,r,s;r=n.split(","),s=[];for(e=0,t=r.length;e { 37 | this.refreshDBData(); 38 | }, 39 | 60000 40 | ); 41 | this.setState({ 42 | interval: x 43 | }); 44 | } 45 | 46 | toggleLogoutModal() { 47 | emitter.emit("showLogout"); 48 | } 49 | 50 | toggleDBWarnModal() { 51 | emitter.emit("openDBWarnModal"); 52 | } 53 | 54 | toggleSessionClearModal() { 55 | emitter.emit("openSessionClearModal"); 56 | } 57 | 58 | refreshDBData() { 59 | var s1 = driver.session(); 60 | var s2 = driver.session(); 61 | var s3 = driver.session(); 62 | var s4 = driver.session(); 63 | var s5 = driver.session(); 64 | var s6 = driver.session(); 65 | 66 | s1.run( 67 | "MATCH (n:User) WHERE NOT n.name ENDS WITH '$' RETURN count(n)" 68 | ).then( 69 | result => { 70 | this.setState({ num_users: result.records[0]._fields[0].low }); 71 | s1.close(); 72 | } 73 | ); 74 | 75 | s2.run("MATCH (n:Group) RETURN count(n)").then( 76 | result => { 77 | this.setState({ num_groups: result.records[0]._fields[0].low }); 78 | s2.close(); 79 | } 80 | ); 81 | 82 | s3.run("MATCH (n:Computer) RETURN count(n)").then( 83 | result => { 84 | this.setState({ 85 | num_computers: result.records[0]._fields[0].low 86 | }); 87 | s3.close(); 88 | } 89 | ); 90 | 91 | s4.run("MATCH ()-[r:HasSession]->() RETURN count(r)").then( 92 | result => { 93 | this.setState({ 94 | num_sessions: result.records[0]._fields[0].low 95 | }); 96 | s4.close(); 97 | } 98 | ); 99 | 100 | s6.run("MATCH ()-[r {isacl: true}]->() RETURN count(r)").then( 101 | result => { 102 | this.setState({ num_acls: result.records[0]._fields[0].low }); 103 | s6.close(); 104 | } 105 | ); 106 | 107 | s5.run("MATCH ()-[r]->() RETURN count(r)").then( 108 | result => { 109 | this.setState({ 110 | num_relationships: result.records[0]._fields[0].low 111 | }); 112 | s5.close(); 113 | } 114 | ); 115 | } 116 | 117 | render() { 118 | return ( 119 |
120 |

Database Info

121 |
122 |
DB Address
123 |
{this.state.url}
124 |
DB User
125 |
{this.state.user}
126 |
Users
127 |
{this.state.num_users}
128 |
Computers
129 |
{this.state.num_computers}
130 |
Groups
131 |
{this.state.num_groups}
132 |
Sessions
133 |
{this.state.num_sessions}
134 |
ACLs
135 |
{this.state.num_acls}
136 |
Relationships
137 |
{this.state.num_relationships}
138 |
139 | 140 |
141 |
142 | 151 | 158 |
159 |
160 | 167 | 174 |
175 |
176 |
177 | ); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/components/SearchContainer/TabContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import DatabaseDataDisplay from "./Tabs/DatabaseDataDisplay"; 3 | import PrebuiltQueriesDisplay from "./Tabs/PrebuiltQueriesDisplay"; 4 | import NoNodeData from "./Tabs/NoNodeData"; 5 | import UserNodeData from "./Tabs/UserNodeData"; 6 | import GroupNodeData from "./Tabs/GroupNodeData"; 7 | import ComputerNodeData from "./Tabs/ComputerNodeData"; 8 | import DomainNodeData from "./Tabs/DomainNodeData"; 9 | import GpoNodeData from "./Tabs/GpoNodeData"; 10 | import OuNodeData from "./Tabs/OuNodeData"; 11 | import { Tabs, Tab } from "react-bootstrap"; 12 | import { openSync, readSync, closeSync } from "fs"; 13 | import imageType from "image-type"; 14 | 15 | export default class TabContainer extends Component { 16 | constructor(props) { 17 | super(props); 18 | 19 | this.state = { 20 | userVisible: false, 21 | computerVisible: false, 22 | groupVisible: false, 23 | domainVisible: false, 24 | gpoVisible: false, 25 | ouVisible: false, 26 | selected: 1 27 | }; 28 | } 29 | 30 | componentDidMount() { 31 | emitter.on("userNodeClicked", this._userNodeClicked.bind(this)); 32 | emitter.on("groupNodeClicked", this._groupNodeClicked.bind(this)); 33 | emitter.on("computerNodeClicked", this._computerNodeClicked.bind(this)); 34 | emitter.on("domainNodeClicked", this._domainNodeClicked.bind(this)); 35 | emitter.on("gpoNodeClicked", this._gpoNodeClicked.bind(this)); 36 | emitter.on("ouNodeClicked", this._ouNodeClicked.bind(this)); 37 | emitter.on("imageupload", this.uploadImage.bind(this)); 38 | } 39 | 40 | uploadImage(event){ 41 | let files = []; 42 | $.each(event.dataTransfer.files, (_, f) => { 43 | let buf = Buffer.alloc(12); 44 | let file = openSync(f.path, 'r') 45 | readSync(file,buf, 0, 12, 0); 46 | closeSync(file) 47 | let type = imageType(buf); 48 | if (type !== null && type.mime.includes("image")){ 49 | files.push({path: f.path, name: f.name}) 50 | }else{ 51 | emitter.emit("showAlert", `${f.name} is not an image`); 52 | } 53 | }) 54 | emitter.emit("imageUploadFinal", files); 55 | } 56 | 57 | _userNodeClicked() { 58 | this.setState({ 59 | userVisible: true, 60 | computerVisible: false, 61 | groupVisible: false, 62 | domainVisible: false, 63 | gpoVisible: false, 64 | ouVisible: false 65 | }); 66 | this.setState({ selected: 2 }); 67 | } 68 | 69 | _groupNodeClicked() { 70 | this.setState({ 71 | userVisible: false, 72 | computerVisible: false, 73 | groupVisible: true, 74 | domainVisible: false, 75 | gpoVisible: false, 76 | ouVisible: false 77 | }); 78 | this.setState({ selected: 2 }); 79 | } 80 | 81 | _computerNodeClicked() { 82 | this.setState({ 83 | userVisible: false, 84 | computerVisible: true, 85 | groupVisible: false, 86 | domainVisible: false, 87 | gpoVisible: false, 88 | ouVisible: false 89 | }); 90 | this.setState({ selected: 2 }); 91 | } 92 | 93 | _domainNodeClicked() { 94 | this.setState({ 95 | userVisible: false, 96 | computerVisible: false, 97 | groupVisible: false, 98 | domainVisible: true, 99 | gpoVisible: false, 100 | ouVisible: false 101 | }); 102 | this.setState({ selected: 2 }); 103 | } 104 | 105 | _gpoNodeClicked() { 106 | this.setState({ 107 | userVisible: false, 108 | computerVisible: false, 109 | groupVisible: false, 110 | domainVisible: false, 111 | gpoVisible: true, 112 | ouVisible: false 113 | }); 114 | this.setState({ selected: 2 }); 115 | } 116 | 117 | _ouNodeClicked() { 118 | this.setState({ 119 | userVisible: false, 120 | computerVisible: false, 121 | groupVisible: false, 122 | domainVisible: false, 123 | gpoVisible: false, 124 | ouVisible: true 125 | }); 126 | this.setState({ selected: 2 }); 127 | } 128 | 129 | _handleSelect(index, last) { 130 | this.setState({ selected: index }); 131 | } 132 | 133 | render() { 134 | return ( 135 |
136 | 142 | 143 | 144 | 145 | 146 | 147 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 |
170 | ); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /LICENSE-3RD-PARTY.md: -------------------------------------------------------------------------------- 1 | PapaParse 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2015 Matthew Holt 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | Simple Slider 24 | The MIT License (MIT) 25 | 26 | Copyright (c) 2012 James Smith (http://loopj.com) 27 | 28 | Permission is hereby granted, free of charge, to any person obtaining a copy of 29 | this software and associated documentation files (the "Software"), to deal in 30 | the Software without restriction, including without limitation the rights to 31 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 32 | the Software, and to permit persons to whom the Software is furnished to do so, 33 | subject to the following conditions: 34 | 35 | The above copyright notice and this permission notice shall be included in all 36 | copies or substantial portions of the Software. 37 | 38 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 39 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 40 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 41 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 42 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 43 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 44 | 45 | jQuery-UI 46 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 47 | 48 | This software consists of voluntary contributions made by many 49 | individuals. For exact contribution history, see the revision history 50 | available at https://github.com/jquery/jquery-ui 51 | 52 | The following license applies to all parts of this software except as 53 | documented below: 54 | 55 | ==== 56 | 57 | Permission is hereby granted, free of charge, to any person obtaining 58 | a copy of this software and associated documentation files (the 59 | "Software"), to deal in the Software without restriction, including 60 | without limitation the rights to use, copy, modify, merge, publish, 61 | distribute, sublicense, and/or sell copies of the Software, and to 62 | permit persons to whom the Software is furnished to do so, subject to 63 | the following conditions: 64 | 65 | The above copyright notice and this permission notice shall be 66 | included in all copies or substantial portions of the Software. 67 | 68 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 69 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 70 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 71 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 72 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 73 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 74 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 75 | 76 | ==== 77 | 78 | Copyright and related rights for sample code are waived via CC0. Sample 79 | code is defined as all source code contained within the demos directory. 80 | 81 | CC0: http://creativecommons.org/publicdomain/zero/1.0/ 82 | 83 | ==== 84 | 85 | All files located in the node_modules and external directories are 86 | externally maintained libraries used by this software which have their 87 | own licenses; we recommend you read them, as their terms may differ from 88 | the terms above. 89 | 90 | 91 | stream-json 92 | This library is available under the terms of the modified BSD license. No external contributions 93 | are allowed under licenses which are fundamentally incompatible with the BSD license that this library is distributed under. 94 | 95 | The text of the BSD license is reproduced below. 96 | 97 | ------------------------------------------------------------------------------- 98 | The "New" BSD License: 99 | ********************** 100 | 101 | Copyright (c) 2005-2018, Eugene Lazutkin 102 | All rights reserved. 103 | 104 | Redistribution and use in source and binary forms, with or without 105 | modification, are permitted provided that the following conditions are met: 106 | 107 | * Redistributions of source code must retain the above copyright notice, this 108 | list of conditions and the following disclaimer. 109 | * Redistributions in binary form must reproduce the above copyright notice, 110 | this list of conditions and the following disclaimer in the documentation 111 | and/or other materials provided with the distribution. 112 | * Neither the name of Eugene Lazutkin nor the names of other contributors 113 | may be used to endorse or promote products derived from this software 114 | without specific prior written permission. 115 | 116 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 117 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 118 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 119 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 120 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 121 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 122 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 123 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 124 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 125 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /src/components/Float/QueryNodeSelect.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { ListGroup, Panel } from "react-bootstrap"; 3 | import { If, Then, Else } from "react-if"; 4 | import QueryNodeSelectItem from "./QueryNodeSelectItem"; 5 | 6 | export default class QueryNodeSelect extends Component { 7 | constructor() { 8 | super(); 9 | 10 | this.state = { 11 | data: [], 12 | currentQueryTitle: "" 13 | }; 14 | 15 | emitter.on("prebuiltQueryStart", this.getEventInfo.bind(this)); 16 | emitter.on("prebuiltQueryStep", this.doQueryStep.bind(this)); 17 | } 18 | 19 | componentDidMount() { 20 | $(this.refs.outer).fadeToggle(0); 21 | } 22 | 23 | getEventInfo() { 24 | var query = appStore.prebuiltQuery.shift(); 25 | if (query.final) { 26 | emitter.emit( 27 | "query", 28 | query.query, 29 | query.props, 30 | null, 31 | null, 32 | query.allowCollapse 33 | ); 34 | } else { 35 | this.setState({ 36 | currentQueryTitle: query.title 37 | }); 38 | $(this.refs.outer).fadeToggle(true); 39 | var session = driver.session(); 40 | session.run(query.query, query.props).then( 41 | results => { 42 | var y = $.map(results.records, x => { 43 | let a = x.keys.map((e, i) => { 44 | let obj = {}; 45 | obj[e.split(".")[1]] = x._fields[i]; 46 | return obj; 47 | }); 48 | let b = {}; 49 | $.each(a, (_, o) => { 50 | Object.assign(b, o); 51 | }); 52 | 53 | return b; 54 | }); 55 | this.setState({ data: y }); 56 | session.close(); 57 | } 58 | ); 59 | } 60 | } 61 | 62 | doQueryStep(querydata) { 63 | var query = appStore.prebuiltQuery.shift(); 64 | if (query.final) { 65 | let start = 66 | typeof query.startNode !== "undefined" 67 | ? query.startNode.format(querydata) 68 | : ""; 69 | let end = 70 | typeof query.endNode !== "undefined" 71 | ? query.endNode.format(querydata) 72 | : ""; 73 | emitter.emit( 74 | "query", 75 | query.query, 76 | { result: querydata }, 77 | start, 78 | end, 79 | query.allowCollapse 80 | ); 81 | appStore.prebuiltQuery = []; 82 | this._dismiss(); 83 | } else { 84 | this.setState({ 85 | currentQueryTitle: query.title 86 | }); 87 | var session = driver.session(); 88 | session.run(query.query, { result: querydata }).then( 89 | function(results) { 90 | var y = $.map(results.records, function(x) { 91 | let a = x.keys.map(function(e, i) { 92 | let obj = {}; 93 | obj[e.split(".")[1]] = x._fields[i]; 94 | return obj; 95 | }); 96 | let b = {}; 97 | $.each(a, function(index, o) { 98 | Object.assign(b, o); 99 | }); 100 | 101 | return b; 102 | }); 103 | if (y.length === 0) { 104 | emitter.emit( 105 | "showAlert", 106 | "No data returned from query" 107 | ); 108 | appStore.prebuiltQuery = []; 109 | this._dismiss(); 110 | } else { 111 | this.setState({ data: y }); 112 | } 113 | session.close(); 114 | }.bind(this) 115 | ); 116 | } 117 | } 118 | 119 | _dismiss() { 120 | $(this.refs.outer).fadeToggle(false); 121 | } 122 | 123 | handleClick(event) { 124 | emitter.emit( 125 | "query", 126 | this.state.queryData.onFinish.formatAll(event.target.text), 127 | { result: event.target.text }, 128 | this.state.queryData.start.format(event.target.text), 129 | this.state.queryData.end.format(event.target.text), 130 | this.state.queryData.allowCollapse 131 | ); 132 | $(this.refs.outer).fadeToggle(false); 133 | } 134 | 135 | render() { 136 | return ( 137 |
138 | 139 | 140 | {/* ; */} 141 | {this.state.currentQueryTitle} 142 | 143 | 144 | 0}> 145 | 146 | 147 | {this.state.data.map( 148 | function(key) { 149 | var x = ( 150 | 155 | ); 156 | return x; 157 | }.bind(this) 158 | )} 159 | 160 | 161 | 162 | {() => } 163 | 164 | 165 | 166 | 167 |
168 | ); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/components/Float/NodeEditorRow.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | export default class NodeEditorRow extends Component { 4 | constructor() { 5 | super(); 6 | } 7 | 8 | componentDidMount() { 9 | let type = typeof this.props.val; 10 | if (type === "object") { 11 | type = "array"; 12 | } 13 | this.setState({ 14 | editing: false, 15 | val: this.props.val, 16 | deleting: false, 17 | valtype: type 18 | }); 19 | } 20 | 21 | componentWillReceiveProps(nextProps) { 22 | if (nextProps.val !== this.props.val && nextProps.val !== this.state.val) { 23 | let type = typeof nextProps.val; 24 | if (type === "object") { 25 | type = "array"; 26 | } 27 | this.setState({ 28 | val: nextProps.val, 29 | editing: false, 30 | deleting: false, 31 | valtype: type 32 | }); 33 | } 34 | } 35 | 36 | saveDelete() { 37 | this.setState({ deleting: false }); 38 | this.props.deleteHandler(this.props.attributeName); 39 | } 40 | 41 | cancelDelete() { 42 | this.setState({ deleting: false }); 43 | } 44 | 45 | enableDelete() { 46 | this.setState({ deleting: true }); 47 | } 48 | 49 | changeVal() { 50 | let val = this.state.val; 51 | val = !val; 52 | this.setState({ val: val }); 53 | } 54 | 55 | cancelEdit() { 56 | let input = jQuery(this.refs.input); 57 | let val = this.props.val; 58 | 59 | if (input.is("div")) { 60 | input.html(val); 61 | input.removeAttr("contenteditable"); 62 | } else if (input.is("textarea")){ 63 | let tempval = val.join("\n"); 64 | input.attr("disabled", ""); 65 | input.val(tempval); 66 | }else { 67 | input.attr("disabled", ""); 68 | } 69 | this.setState({ editing: false, val: val }); 70 | } 71 | 72 | saveEdit() { 73 | let input = jQuery(this.refs.input); 74 | let val; 75 | if (input.is("div")) { 76 | val = input.html(); 77 | input.removeAttr("contenteditable"); 78 | } else if (input.is("textarea")){ 79 | let tempval = input.val(); 80 | val = tempval.split("\n"); 81 | input.attr("disabled", ""); 82 | } else { 83 | val = this.state.val; 84 | input.attr("disabled", ""); 85 | } 86 | if (this.state.valtype === "number"){ 87 | val = parseInt(val); 88 | } 89 | this.setState({editing: false}); 90 | this.props.updateHandler(this.props.attributeName, val) 91 | } 92 | 93 | enableEdit() { 94 | let input = jQuery(this.refs.input); 95 | 96 | if (input.is("div")) { 97 | input.attr("contenteditable", true); 98 | } else { 99 | input.removeAttr("disabled"); 100 | } 101 | 102 | this.setState({ editing: true }); 103 | } 104 | 105 | render() { 106 | let type = this.state ? this.state.valtype : typeof this.props.val; 107 | let valcolumn; 108 | 109 | if (type === "boolean") { 110 | valcolumn = ( 111 | 119 | ); 120 | } else if (type === "string") { 121 | valcolumn = ( 122 |
123 | {!this.state ? this.props.val : this.state.val} 124 |
125 | ); 126 | } else if (type === "number") { 127 | valcolumn = ( 128 |
129 | {!this.state ? this.props.val : this.state.val} 130 |
131 | ); 132 | } else if (type === "object" || type === "array") { 133 | valcolumn = ( 134 |