Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
chivay committed Aug 19, 2020
1 parent 9b48088 commit 3e05d95
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 40 deletions.
24 changes: 24 additions & 0 deletions drakcore/drakcore/frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion drakcore/drakcore/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
"react-d3-tree": "^1.16.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.2.0",
"react-scripts": "^3.4.1"
"react-scripts": "^3.4.1",
"react-virtualized-auto-sizer": "^1.0.2",
"react-window": "^1.8.5",
"react-window-infinite-loader": "^1.0.5"
},
"scripts": {
"start": "react-scripts start",
Expand Down
140 changes: 102 additions & 38 deletions drakcore/drakcore/frontend/src/AnalysisApicall.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React from "react";
import { Component } from "react";
import { FixedSizeList as List } from "react-window";
import OptionPicker from "./OptionPicker";
import AutoSizer from "react-virtualized-auto-sizer";
import "./App.css";
import api from "./api";
import OptionPicker from "./OptionPicker";

class AnalysisApicall extends Component {
constructor(props) {
Expand All @@ -13,9 +15,13 @@ class AnalysisApicall extends Component {
this.state = {
calls: null,
processList: [],
filter: '',
filteredResults: [],
};

this.pidChanged = this.pidChanged.bind(this);
this.filterChanged = this.filterChanged.bind(this);
this.computeFiltered = this.computeFiltered.bind(this);
}

async pidChanged(new_pid) {
Expand All @@ -24,11 +30,33 @@ class AnalysisApicall extends Component {
const res = await api.getApiCalls(this.analysis_id, new_pid);
const calls = res.data.split("\n").map(JSON.parse);
this.setState({ calls });
this.computeFiltered(this.state.filter);
} catch (e) {
this.setState({ calls: [] });
}
}

computeFiltered(filter) {
if (filter === '') {
this.setState({ filteredResults: this.state.calls });
return;
}
try {
let regex = new RegExp(filter, 'gi');
this.setState({
filteredResults: this.state.calls.filter((elem) =>
regex.test(elem.method)
),
});
} catch { }
}

filterChanged(event) {
const newFilter = event.target.value;
this.setState({filter: newFilter});
this.computeFiltered(newFilter);
}

async componentDidMount() {
const analysis = this.props.match.params.analysis;
const process_tree = await api.getProcessTree(analysis);
Expand All @@ -37,14 +65,11 @@ class AnalysisApicall extends Component {
let result = [];

process_tree.forEach((proc) => {
result.push({
key: proc.pid,
value: `${proc.pid}${proc.procname || "unnamed process"}`,
});
result.push({ key: proc.pid, value: `${proc.pid}${proc.procname || "unnamed process"}` });
result.push(...treeFlatten(proc.children));
});

result.sort((a, b) => a.pid - b.pid);
result.sort((a, b) => a.key - b.key);

return result;
}
Expand Down Expand Up @@ -82,33 +107,62 @@ class AnalysisApicall extends Component {
</div>
);
} else {
let tableContent = this.state.calls.map((entry, i) => (
<tr key={i}>
<td>{entry.timestamp}</td>
<td>
<code>{entry.method}</code>
</td>
<td>
{entry.arguments.map((arg, i) => (
<div key={i} className="badge-outline-primary badge mr-1">
{arg}
</div>
))}
</td>
</tr>
));
content = (
<table className="table table-centered apicallTable">
<thead>
<tr>
<th>Timestamp</th>
<th>Method</th>
<th>Arguments</th>
</tr>
</thead>
<tbody>{tableContent}</tbody>
</table>
// let tableContent = this.state.calls.map((entry, i) => (
// <tr key={i}>
// <td>{entry.timestamp}</td>
// <td>
// <code>{entry.method}</code>
// </td>
// <td>
// {entry.arguments.map((arg, i) => (
// <div key={i} className="badge-outline-primary badge mr-1">
// {arg}
// </div>
// ))}
// </td>
// </tr>
// ));

const Row = ({ data, index, style }) => {
const entry = data[index];
const args = entry.arguments.join(", ");
return (
<div style={style} className="d-flex flex-row align-content-stretch">
<div className="p-1 d-none d-md-block">{entry.timestamp}</div>
<div className="p-1">
<code>
{entry.method}({args}) = ?
</code>
</div>
</div>
);
};

let tableContent = (
<List
itemData={this.state.filteredResults}
height={600}
itemCount={this.state.filteredResults ? this.state.filteredResults.length : 0}
itemSize={28}
>
{Row}
</List>
);

content = tableContent;

// content = (
// <table className="table table-centered apicallTable">
// <thead>
// <tr>
// <th>Timestamp</th>
// <th>Method</th>
// <th>Arguments</th>
// </tr>
// </thead>
// <tbody>{tableContent}</tbody>
// </table>
// );
}

return (
Expand All @@ -119,12 +173,22 @@ class AnalysisApicall extends Component {

<div className="card tilebox-one">
<div className="card-body">
<OptionPicker
defaultSelection={url_pid}
data={this.state.processList}
onChange={this.pidChanged}
className="mb-1"
/>
<div className="row mb-2">
<div className="col-9">
<OptionPicker
defaultSelection={url_pid}
data={this.state.processList}
onChange={(pid) => this.pidChanged(parseInt(pid))}
/>
</div>
<input
type="text"
className="form-control col-3"
placeholder="Search API calls..."
value={this.state.filter}
onChange={this.filterChanged}
/>
</div>
{content}
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion drakcore/drakcore/frontend/src/AnalysisMain.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ class AnalysisMain extends Component {
try {
const res_graph = await api.getGraph(this.analysisID);
if (res_graph.data) {
this.setState({ graphState: "loaded", graph: res_graph.data });
//this.setState({ graphState: "loaded", graph: res_graph.data });
} else {
this.setState({ graphState: "missing" });
}
Expand Down
1 change: 1 addition & 0 deletions drakcore/drakcore/frontend/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ import React from "react";
import ReactDOM from "react-dom";
import App from "./App";


ReactDOM.render(<App />, document.getElementById("root"));
43 changes: 43 additions & 0 deletions drakrun/drakrun/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import zipfile
import json
import re
import functools
from typing import Optional, List
from stat import S_ISREG, ST_CTIME, ST_MODE, ST_SIZE

Expand Down Expand Up @@ -78,6 +79,47 @@ def start_dnsmasq(vm_id: int, dns_server: str) -> Optional[subprocess.Popen]:
])


def local_logs(method):
class LocalBuffer(logging.Handler):
FIELDS = (
"levelname",
"message",
"created",
)

def __init__(self):
super().__init__()
self.buffer = []

def emit(self, record):
entry = {k: v for (k, v) in record.__dict__.items() if k in self.FIELDS}
self.buffer.append(entry)

@functools.wraps(method)
def wrapper(self: Karton, *args, **kwargs):
handler = LocalBuffer()
try:
# Register new log handler
self.log.addHandler(handler)
method(self, *args, **kwargs)
except Exception:
self.log.exception("Analysis failed")
finally:
# Unregister local handler
self.log.removeHandler(handler)
try:
res = LocalResource("analysis_log.json",
json.dumps(handler.buffer),
bucket="drakrun")
task_uid = self.current_task.payload.get('override_uid') or self.current_task.uid
res._uid = f"{task_uid}/{res.name}"
res.upload(self.minio)
except Exception:
self.log.exception("Failed to upload analysis logs")

return wrapper


class DrakrunKarton(Karton):
identity = "karton.drakrun-prod"
filters = [
Expand Down Expand Up @@ -269,6 +311,7 @@ def get_profile_list() -> List[str]:

return out

@local_logs
def process(self):
sample = self.current_task.get_resource("sample")
self.log.info("hostname: {}".format(socket.gethostname()))
Expand Down

0 comments on commit 3e05d95

Please sign in to comment.