This demo shows the power of using KeyLines combos with the time bar.
The data1 contains details of the top three ransomware families from January to April 2016. The chart starts with a high-level view of the data, with connections between:
- combos containing malware hosts for each family
- combos containing IP addresses registered in countries from which the attacks originated
Reducing clutter with combos
This is a large, complex dataset, yet the combos feature means the chart remains clean, uncluttered and easy to interact with. The detail is there when you want it, giving immediate insight by revealing malware host details. To compare how much harder it’d be to understand the data without combos, try selecting and then uncombining items.
Filtering time-based data
The histogram shows at a glance the level of ransomware activity at certain points in time. The time bar selection line compares the activity of an item selected in the chart against total activity. You can also zoom in to the time bar to filter the hosts, ransomware families and countries that were active at a particular time.
About ransomware
Ransomware is a type of malware that holds a victim's computer "hostage", typically by encrypting data and then demanding payment to receive a decryption key. The number of attacks continues to grow significantly year on year, with increasingly sophisticated attack vectors and distribution methods.
1 Ransomware Tracker hosted on abuse.ch.
Key functions used:
- chart.filter
- chart.selection
- chart.combo().combine
- chart.combo().isCombo
- chart.combo().uncombine
- chart.graph().neighbours
- timebar.inRange
- Chart Events
- Time bar Events
import KeyLines from "keylines";
import { data, comboData, ransomwareColours } from "./data.js";
let chart;
let timebar;
// Scale the closed combo sizes at slightly less than the square root of their
// node count so that the larger combos (e.g. USA) don't dominate too much
// and the smaller combos aren't too tiny
const scalePower = 0.4;
function isCombo(ids) {
return chart.combo().isCombo(ids, { type: "node" });
}
function showRansomware(item) {
const checked = [
...document.querySelectorAll('input[name="ransomware"]:checked'),
];
return checked.some((c) => item.d.ransomware === c.id);
}
function enableButton(type, enable) {
document.getElementById(`${type}Run`).disabled = !enable;
}
function layout(mode = "full") {
const layoutType = document.getElementById("layoutType").value;
const opts = layoutType === "organic" ? { mode } : {};
chart.layout(layoutType, opts);
}
function timebarFilterCriteria(item) {
// If the ransomware is not checked
if (item.d.ransomware && !showRansomware(item)) {
return false;
}
if (item.d.type === "ip") {
const hosts = item.d.host;
return hosts.some((host) => timebar.inRange(host));
}
if (item.d.type === "host") {
return timebar.inRange(item.id);
}
return false; // Other cases should return false
}
async function timebarChange() {
// filter the chart to show only items in the new range
const changes = await chart.filter(timebarFilterCriteria, {
type: "node",
animate: false,
hideSingletons: true,
});
// update the size of the combo based on the changes object returned by the filter
const visualProperties = changes.combos.nodes.map((comboInfo) => ({
id: comboInfo.id,
e: comboInfo.nodes.length ** scalePower,
}));
// When playing the timebar sometimes it can be helpful to overwrite previous animations
// => queue: false
await chart.animateProperties(visualProperties, { time: 300, queue: false });
}
function isOnlyCombos(items) {
return items.length && items.every((item) => isCombo(item.id));
}
function isOnlyTypeSelected(type, items) {
return items.every((item) => item.d.type === type);
}
function groupByRansomware(items) {
const result = {};
items.forEach((item) => {
const group = item.d.ransomware;
if (result[group]) {
result[group].push(item);
} else {
result[group] = [item];
}
});
return result;
}
function ransomwareSelection(nodes, countrySelected, subsetHost) {
return Object.entries(groupByRansomware(nodes)).map(
([name, group], index) => {
let ids;
const firstItem = group[0];
if (isCombo(firstItem.id)) {
if (countrySelected) {
ids = firstItem.d.lookup[countrySelected].filter((id) =>
subsetHost ? subsetHost.includes(id) : true,
);
} else {
// Selected a ransomware
ids = [];
Object.values(firstItem.d.lookup).forEach((i) => {
ids = ids.concat(i);
});
}
} else {
ids = group.map((item) => item.id);
}
return { id: ids, index, c: ransomwareColours[name] };
},
);
}
function chartSelectionChange() {
// Reset the previous timebar selection
timebar.selection([]);
// Get only the nodes within the selection
const selection = chart.getItem(chart.selection());
// Enable or disable the uncombine button
enableButton("uncombine", isOnlyCombos(selection));
let tbSelection = []; // The new selection of the timebar
// show the trend of the ransomwares for the country combo and ip nodes
if (isOnlyTypeSelected("ip", selection)) {
const neighbours = {};
const hosts = {};
// For each country
selection.forEach((ip) => {
neighbours[ip.d.country] = neighbours[ip.d.country] || [];
neighbours[ip.d.country] = neighbours[ip.d.country].concat(
chart.graph().neighbours(ip.id).nodes,
);
if (ip.d.host) {
hosts[ip.d.country] = hosts[ip.d.country] || [];
hosts[ip.d.country] = hosts[ip.d.country].concat(ip.d.host);
}
});
// For every neighbour to selected countries
Object.entries(neighbours).forEach(([country, nodes]) => {
// Get the timebar selection
const newSelection = ransomwareSelection(
chart.getItem(nodes),
country,
hosts[country],
);
tbSelection = tbSelection.concat(newSelection);
});
}
// Show the trend for the ransomware combos and host nodes
if (isOnlyTypeSelected("host", selection)) {
tbSelection = ransomwareSelection(selection);
}
timebar.selection(tbSelection); // Set the new selection to the timebar
}
function selectionChangeAndLayout() {
chartSelectionChange();
layout("adaptive");
}
async function filterRansomware() {
await timebarChange();
selectionChangeAndLayout();
}
function uncombineAction() {
chart.combo().uncombine(chart.selection(), { animate: false, select: false });
// run the filter of ransomware
filterRansomware();
// Enable the combine button
enableButton("combine", true);
}
async function combineAction() {
// Find combos that have been uncombined
// Filter out ones that are still combos as otherwise, Keylines raises an error
const toBeCombined = comboData.filter(
({ ids }) => chart.combo().find(ids[0]) === null,
);
await chart
.combo()
.combine(toBeCombined, {
select: false,
animate: false,
arrange: "concentric",
});
// run the filter of ransomware
filterRansomware();
// Disable the combine button
enableButton("combine", false);
}
function initialiseEvents() {
chart.on("selection-change", chartSelectionChange); // Align the chart selection to the timebar
timebar.on("change", timebarChange); // Filter the nodes to match the timebar range
document
.getElementById("layoutRun")
.addEventListener("click", () => layout()); // Run the layout
document
.getElementById("layoutType")
.addEventListener("change", () => layout()); // Run the layout when choosing a layout
document
.getElementById("combineRun")
.addEventListener("click", combineAction); // Combine all the nodes
document
.getElementById("uncombineRun")
.addEventListener("click", uncombineAction); // Uncombine selected nodes
document.querySelectorAll('input[name="ransomware"]').forEach((btn) => {
// Filter the ransomwares
btn.addEventListener("change", filterRansomware);
btn.addEventListener("keyup", filterRansomware);
});
}
async function startKeyLines() {
const chartOptions = {
logo: "/public/images/Logo.png",
hover: 100,
marqueeLinkSelection: "off",
imageAlignment: {
"/public/images/icons/virus.svg": { e: 0.9 },
},
selectedNode: {
fb: true,
ha0: {
c: "#555",
r: "31",
w: "3",
},
oc: { bw: 20 },
},
iconFontFamily: "Font Awesome 5 Free",
handMode: true,
};
[chart, timebar] = await KeyLines.create([
{
container: "klchart",
type: "chart",
options: chartOptions,
},
{
container: "kltimebar",
type: "timebar",
options: { showExtend: true },
},
]);
chart.load(data);
timebar.load(data);
// Fit the initial view to the loaded data
chart.zoom("fit", { animate: false });
timebar.zoom("fit", { animate: false });
combineAction();
initialiseEvents();
}
function loadKeyLines() {
document.fonts.load('24px "Font Awesome 5 Free"').then(startKeyLines);
}
window.addEventListener("DOMContentLoaded", loadKeyLines); import KeyLines from "keylines";
export const data = {
type: "LinkChart",
items: [
{
id: "host-cwprfpjtmjb.biz",
type: "node",
t: "Host\ncwprfpjtmjb.biz",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "USA",
},
e: 1,
dt: [1461956160000],
},
{
id: "69.195.129.70",
type: "node",
t: "69.195.129.70",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "USA",
host: [
"host-cwprfpjtmjb.biz",
"host-blxbymhjva.info",
"host-sqrgvbgfyya.org",
"host-dwytqrgblrynsgtew.org",
"host-hmndhdbscgru.pw",
"host-uxvvm.us",
"host-luvenxj.uk",
],
},
e: 1,
g: [
{
u: "/public/images/flags/united-states-of-america.svg",
p: "ne",
},
],
},
{
id: "host-83.217.8.155",
type: "node",
t: "Host\n83.217.8.155",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "Russia",
},
e: 1,
dt: [1461946860000],
},
{
id: "83.217.8.155",
type: "node",
t: "83.217.8.155",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Russia",
host: ["host-83.217.8.155"],
},
e: 1,
g: [
{
u: "/public/images/flags/russia.svg",
p: "ne",
},
],
},
{
id: "host-89.108.84.155",
type: "node",
t: "Host\n89.108.84.155",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "Russia",
},
e: 1,
dt: [1461929940000],
},
{
id: "89.108.84.155",
type: "node",
t: "89.108.84.155",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Russia",
host: ["host-89.108.84.155"],
},
e: 1,
g: [
{
u: "/public/images/flags/russia.svg",
p: "ne",
},
],
},
{
id: "host-gmtuae.com",
type: "node",
t: "Host\ngmtuae.com",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "Brunei",
},
e: 1,
dt: [1461900480000],
},
{
id: "182.50.158.108",
type: "node",
t: "182.50.158.108",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Brunei",
host: ["host-gmtuae.com"],
},
e: 1,
g: [
{
u: "/public/images/flags/brunei.svg",
p: "ne",
},
],
},
{
id: "host-91.234.32.19",
type: "node",
t: "Host\n91.234.32.19",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "Ukraine",
},
e: 1,
dt: [1461876240000],
},
{
id: "91.234.32.19",
type: "node",
t: "91.234.32.19",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Ukraine",
host: ["host-91.234.32.19"],
},
e: 1,
g: [
{
u: "/public/images/flags/ukraine.svg",
p: "ne",
},
],
},
{
id: "host-faenzabike.makkie.com",
type: "node",
t: "Host\nfaenzabike.makkie.com",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "Italy",
},
e: 1,
dt: [1461873060000],
},
{
id: "213.26.174.81",
type: "node",
t: "213.26.174.81",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Italy",
host: ["host-faenzabike.makkie.com"],
},
e: 1,
g: [
{
u: "/public/images/flags/italy.svg",
p: "ne",
},
],
},
{
id: "host-51.254.240.60",
type: "node",
t: "Host\n51.254.240.60",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "France",
},
e: 1,
dt: [1461862800000],
},
{
id: "51.254.240.60",
type: "node",
t: "51.254.240.60",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "France",
host: ["host-51.254.240.60"],
},
e: 1,
g: [
{
u: "/public/images/flags/france.svg",
p: "ne",
},
],
},
{
id: "host-axnemuevqnstqyflb.work",
type: "node",
t: "Host\naxnemuevqnstqyflb.work",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "Rep Czech",
},
e: 1,
dt: [1461858660000],
},
{
id: "31.148.99.188",
type: "node",
t: "31.148.99.188",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Rep Czech",
host: ["host-axnemuevqnstqyflb.work"],
},
e: 1,
g: [
{
u: "/public/images/flags/czech-republic.svg",
p: "ne",
},
],
},
{
id: "host-83.217.26.168",
type: "node",
t: "Host\n83.217.26.168",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "Russia",
},
e: 1,
dt: [1461852600000],
},
{
id: "83.217.26.168",
type: "node",
t: "83.217.26.168",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Russia",
host: ["host-83.217.26.168"],
},
e: 1,
g: [
{
u: "/public/images/flags/russia.svg",
p: "ne",
},
],
},
{
id: "host-bestinghana.com",
type: "node",
t: "Host\nbestinghana.com",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "USA",
},
e: 1,
dt: [1461843480000],
},
{
id: "184.168.51.1",
type: "node",
t: "184.168.51.1",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "USA",
host: ["host-bestinghana.com"],
},
e: 1,
g: [
{
u: "/public/images/flags/united-states-of-america.svg",
p: "ne",
},
],
},
{
id: "host-coolcases.info",
type: "node",
t: "Host\ncoolcases.info",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "USA",
},
e: 1,
dt: [1461820200000],
},
{
id: "72.167.232.144",
type: "node",
t: "72.167.232.144",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "USA",
host: ["host-coolcases.info"],
},
e: 1,
g: [
{
u: "/public/images/flags/united-states-of-america.svg",
p: "ne",
},
],
},
{
id: "host-htankds.info",
type: "node",
t: "Host\nhtankds.info",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "Ukraine",
},
e: 1,
dt: [1461816000000],
},
{
id: "91.219.31.18",
type: "node",
t: "91.219.31.18",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Ukraine",
host: ["host-htankds.info"],
},
e: 1,
g: [
{
u: "/public/images/flags/ukraine.svg",
p: "ne",
},
],
},
{
id: "host-107.170.20.33",
type: "node",
t: "Host\n107.170.20.33",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "USA",
},
e: 1,
dt: [1461784740000],
},
{
id: "107.170.20.33",
type: "node",
t: "107.170.20.33",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "USA",
host: ["host-107.170.20.33"],
},
e: 1,
g: [
{
u: "/public/images/flags/united-states-of-america.svg",
p: "ne",
},
],
},
{
id: "host-runescape-autominer.info",
type: "node",
t: "Host\nrunescape-autominer.info",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "USA",
},
e: 1,
dt: [1461772260000],
},
{
id: "192.185.46.61",
type: "node",
t: "192.185.46.61",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "USA",
host: ["host-runescape-autominer.info"],
},
e: 1,
g: [
{
u: "/public/images/flags/united-states-of-america.svg",
p: "ne",
},
],
},
{
id: "host-www.teacherassist.info",
type: "node",
t: "Host\nwww.teacherassist.info",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "Belgium",
},
e: 1,
dt: [1461768120000],
},
{
id: "94.124.120.61",
type: "node",
t: "94.124.120.61",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Belgium",
host: ["host-www.teacherassist.info"],
},
e: 1,
g: [
{
u: "/public/images/flags/belgium.svg",
p: "ne",
},
],
},
{
id: "host-kortingcodes.be",
type: "node",
t: "Host\nkortingcodes.be",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "USA",
},
e: 1,
dt: [1461690360000],
},
{
id: "108.167.181.253",
type: "node",
t: "108.167.181.253",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "USA",
host: ["host-kortingcodes.be"],
},
e: 1,
g: [
{
u: "/public/images/flags/united-states-of-america.svg",
p: "ne",
},
],
},
{
id: "host-custommerchandisingservices.com",
type: "node",
t: "Host\ncustommerchandisingservices.com",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "USA",
},
e: 1,
dt: [1461647280000],
},
{
id: "45.79.161.27",
type: "node",
t: "45.79.161.27",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "USA",
host: ["host-custommerchandisingservices.com"],
},
e: 1,
g: [
{
u: "/public/images/flags/united-states-of-america.svg",
p: "ne",
},
],
},
{
id: "host-bonjourtablier.com",
type: "node",
t: "Host\nbonjourtablier.com",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "Germany",
},
e: 1,
dt: [1461442680000],
},
{
id: "212.227.247.229",
type: "node",
t: "212.227.247.229",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Germany",
host: ["host-bonjourtablier.com"],
},
e: 1,
g: [
{
u: "/public/images/flags/germany.svg",
p: "ne",
},
],
},
{
id: "host-blackroom.club",
type: "node",
t: "Host\nblackroom.club",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "Russia",
},
e: 1,
dt: [1461370680000],
},
{
id: "81.177.135.232",
type: "node",
t: "81.177.135.232",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Russia",
host: ["host-blackroom.club"],
},
e: 1,
g: [
{
u: "/public/images/flags/russia.svg",
p: "ne",
},
],
},
{
id: "host-artsabc.com",
type: "node",
t: "Host\nartsabc.com",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "USA",
},
e: 1,
dt: [1461274500000],
},
{
id: "204.12.208.74",
type: "node",
t: "204.12.208.74",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "USA",
host: ["host-artsabc.com"],
},
e: 1,
g: [
{
u: "/public/images/flags/united-states-of-america.svg",
p: "ne",
},
],
},
{
id: "host-blessingshealthuk.com",
type: "node",
t: "Host\nblessingshealthuk.com",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "USA",
},
e: 1,
dt: [1461274500000],
},
{
id: "107.180.50.165",
type: "node",
t: "107.180.50.165",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "USA",
host: ["host-blessingshealthuk.com"],
},
e: 1,
g: [
{
u: "/public/images/flags/united-states-of-america.svg",
p: "ne",
},
],
},
{
id: "host-anybug.net",
type: "node",
t: "Host\nanybug.net",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "France",
},
e: 1,
dt: [1461180240000],
},
{
id: "78.217.205.113",
type: "node",
t: "78.217.205.113",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "France",
host: ["host-anybug.net"],
},
e: 1,
g: [
{
u: "/public/images/flags/france.svg",
p: "ne",
},
],
},
{
id: "host-alushtadom.com",
type: "node",
t: "Host\nalushtadom.com",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "Russia",
},
e: 1,
dt: [1461130920000],
},
{
id: "81.177.140.186",
type: "node",
t: "81.177.140.186",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Russia",
host: ["host-alushtadom.com"],
},
e: 1,
g: [
{
u: "/public/images/flags/russia.svg",
p: "ne",
},
],
},
{
id: "host-blxbymhjva.info",
type: "node",
t: "Host\nblxbymhjva.info",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "USA",
},
e: 1,
dt: [1461076140000],
},
{
id: "host-ahsqbeospcdrngfv.info",
type: "node",
t: "Host\nahsqbeospcdrngfv.info",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "Canada",
},
e: 1,
dt: [1461036300000],
},
{
id: "195.22.28.198",
type: "node",
t: "195.22.28.198",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Canada",
host: [
"host-ahsqbeospcdrngfv.info",
"host-jghbktqepe.pw",
"host-gsebqsi.ru",
"host-ywjgjvpuyitnbiw.info",
"host-kypsuw.pw",
"host-kqlxtqptsmys.in",
],
},
e: 1,
g: [
{
u: "/public/images/flags/canada.svg",
p: "ne",
},
],
},
{
id: "host-cxlgwofgrjfoaa.info",
type: "node",
t: "Host\ncxlgwofgrjfoaa.info",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "Canada",
},
e: 1,
dt: [1461036240000],
},
{
id: "195.22.28.197",
type: "node",
t: "195.22.28.197",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Canada",
host: [
"host-cxlgwofgrjfoaa.info",
"host-barjhxoye.info",
"host-glhxgchhfemcjgr.pw",
"host-fitga.ru",
"host-wdvxeval.ru",
"host-bnjhx.eu",
],
},
e: 1,
g: [
{
u: "/public/images/flags/canada.svg",
p: "ne",
},
],
},
{
id: "host-91.234.35.243",
type: "node",
t: "Host\n91.234.35.243",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "Ukraine",
},
e: 1,
dt: [1460970000000],
},
{
id: "91.234.35.243",
type: "node",
t: "91.234.35.243",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Ukraine",
host: ["host-91.234.35.243"],
},
e: 1,
g: [
{
u: "/public/images/flags/ukraine.svg",
p: "ne",
},
],
},
{
id: "host-4turka.com",
type: "node",
t: "Host\n4turka.com",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "TeslaCrypt",
from: "Turkey",
},
e: 1,
dt: [1460953560000],
},
{
id: "185.12.108.138",
type: "node",
t: "185.12.108.138",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Turkey",
host: ["host-4turka.com"],
},
e: 1,
g: [
{
u: "/public/images/flags/turkey.svg",
p: "ne",
},
],
},
{
id: "host-185.14.28.30",
type: "node",
t: "Host\n185.14.28.30",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "Belgium",
},
e: 1,
dt: [1460901960000],
},
{
id: "185.14.28.30",
type: "node",
t: "185.14.28.30",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Belgium",
host: ["host-185.14.28.30"],
},
e: 1,
g: [
{
u: "/public/images/flags/belgium.svg",
p: "ne",
},
],
},
{
id: "host-31.184.196.74",
type: "node",
t: "Host\n31.184.196.74",
fi: {
t: "fas fa-server",
},
d: {
type: "host",
ransomware: "Locky",
from: "Russia",
},
e: 1,
dt: [1460872140000],
},
{
id: "31.184.196.74",
type: "node",
t: "31.184.196.74",
u: "/public/images/icons/ip-address.png",
d: {
type: "ip",
country: "Russia",
host: ["host-31.184.196.74"],
},
e: 1,
g: [
{
u: "/public/images/flags/russia.svg",
p: "ne",
},
],
},
{
id: "host-91.230.211.103",
// ...truncated 17669 lines <!doctype html>
<html lang="en" style="background-color: #2d383f">
<head>
<meta charset="utf-8" />
<title>Ransomware Attacks</title>
<link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/keylines.css" />
<link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/minimalsdk.css" />
<link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/sdk-layout.css" />
<link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/demo.css" />
<link
rel="stylesheet"
type="text/css"
href="@fortawesome/[email protected]/css/fontawesome.css"
/>
<link
rel="stylesheet"
type="text/css"
href="@fortawesome/[email protected]/css/solid.css"
/>
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<div id="klchart" class="klchart klchart-timebar"></div>
<div id="kltimebar" class="kltimebar"></div>
<script type="module" src="./code.js"></script>
</body>
</html> #layoutRun {
margin-top: 0;
}
.checkbox.inline {
vertical-align: middle;
}
.checkbox input[type="checkbox"] {
float: none;
margin-right: 4px;
}
.form-inline * {
margin: 0px;
vertical-align: middle;
}