UNPKG

browser-node-virustotal

Version:

An implementation of the Virustotal API for client js

314 lines (310 loc) 8.27 kB
"use strict"; const speedconcat = require("speedconcat"); const request = require("browser-request-fix"); const privateAPI = require("./privateAPI.js"); const formatConverter = require("./formatConverter.js"); const intelAPI = require("./intelligenceAPI.js"); const QB = require("./queryBuilder.js"); const commentSender = require("./commentSender.js"); var apiKey = "e2513a75f92a4169e8a47b4ab1df757f83ae45008b4a8a49903450c8402add4d"; const PublicConnection = function(){ var key = apiKey; var jobDelay = 15000; const internalPrivateAPI = privateAPI.makePrivateAPI(); internalPrivateAPI.setKey(key); this.setKey = function(replacement){ key = replacement; internalPrivateAPI.setKey(key); return; }; this.getKey = function() { return key; }; this.setDelay = function(replacement){ jobDelay = replacement; return; }; this.getDelay = function() { return jobDelay; }; var jobQueue = null; var tail = null; const performNextJob = function(){ if (jobQueue != null) { const workingJob = jobQueue; jobQueue = jobQueue.next; if (jobQueue == null) { tail = null; } else { setTimeout(performNextJob, jobDelay); } workingJob.proc(); } return; }; var fireNow = true; const addJob = function(proc) { if ((fireNow == true)&&(jobQueue == null)) { fireNow = false; setTimeout(function(){ fireNow = true; }, jobDelay); proc(); return; } if (jobQueue == null) { jobQueue = { proc: proc, next: null }; tail = jobQueue; setTimeout(performNextJob, jobDelay); } else { tail.next = { proc: proc, next: null }; tail = tail.next; } return; }; const makeGet = function (URL) { return function(addr, responseProc, errProc){ const checkURL = (URL + addr) + ("&apikey=" + key); const checkProc = function(){ request({ url:checkURL, gzip: true, headers: { "User-Agent": "gzip" }}, function(error, response, body) { if (error) { errProc(error); return; } if(response.statusCode > 399) { errProc(response.statusCode + ""); return; } try { const data = JSON.parse(body); switch (data.response_code) { case -2: addJob(checkProc); return; case 0: case 1: responseProc(data); return; case -1: default: errProc(data); return; } } catch (e) { errProc(e); return; } }); }; addJob(checkProc); }; }; const PostWithoutBody = function(rawURL, mode) { return function(resource, responseProc, errProc){ const fullURL = (rawURL+encodeURIComponent(resource)) + ("&apikey="+key); const jobProc = function(){ request({ method: "POST", url: fullURL, gzip: true, headers: { "User-Agent": "gzip" } },function(error, response, body){ if (error) { errProc(error); return; } try{ const result = JSON.parse(body); switch (result.response_code) { case -2: if (-2==mode) { addJob(jobProc); return; } if (-1==mode) { errProc(result); return; } if (0==mode) { responseProc(result); return; } return; case 1: case 0: responseProc(result); return; case -1: default: errProc(result); return; } } catch (e) { if(response.statusCode == 204){ errProc(204); } else errProc(e); return; } }); }; addJob(jobProc); }; }; const publishUrlComment = function(resource, comment, resultProc, errProc){ if (errProc==null) { errProc = function(e) { publishUrlComment(resource, comment, resultProc, null); return; } } const workingSender = new commentSender(resource, comment, key, resultProc, errProc); addJob(workingSender.attempt); return; }; const sendFile = function(filename, filetype, filecontent, responseProc, errProc){ const sendOptions = { url: "https://www.virustotal.com/vtapi/v2/file/scan?apikey=" + key, form: { file: { value: filecontent, mimeType: filetype, fileName: filename } }, encoding: 'multipart/form-data', gzip: true, headers: { "User-Agent": "gzip" } }; //console.log("sendOptions", JSON.stringify(sendOptions)); const sendFileProc = function(){ request.post(sendOptions, function(error, response, body){ if (error) { errProc(error); return; } try{ const data = JSON.parse(body); switch (data.response_code) { case 1: responseProc(data); return; case 0: case -1: case -2: default: errProc(data); return; } } catch (e) { if(response.statusCode == 204){ errProc(204); } else errProc(e); return; } }); }; addJob(sendFileProc); }; const rescanFile = function(resourceID, responseProc, errProc) { const rescanObject = internalPrivateAPI.makeRescan(resourceID); const pending = function(){ rescanObject.sendRequest(responseProc, errProc); return; }; addJob(pending); return; }; const getFileReport = function(scanID, responseProc, errProc) { const fileResourceURL = ("https://www.virustotal.com/vtapi/v2/file/report?apikey=" + key) + ("&resource=" + scanID); const retrieveProc = function(){ request({url: fileResourceURL, method: "POST", gzip: true, headers: { "User-Agent": "gzip" }}, function(error, response, body){ if (error) { errProc(error); return; } try { const data = JSON.parse(body); switch (data.response_code){ case 1: responseProc(data); return; case -2: addJob(retrieveProc); return; case 0: case -1: default: errProc(data); return; } } catch (e) { errProc(e); return; } }); }; addJob(retrieveProc) }; this.getFileReport = getFileReport; this.rescanFile = rescanFile; this.submitFileForAnalysis = sendFile; this.publishFileComment = publishUrlComment; this.publishUrlComment = publishUrlComment; this.retrieveUrlAnalysis = PostWithoutBody("https://www.virustotal.com/vtapi/v2/url/report?resource=", -2); this.retrieveUrlAnalysisWithRescan = PostWithoutBody("https://www.virustotal.com/vtapi/v2/url/report?scan=1&resource=", -2); this.submitUrlForScanning = PostWithoutBody("https://www.virustotal.com/vtapi/v2/url/scan?url=", 0); this.checkIPv4 = makeGet("https://www.virustotal.com/vtapi/v2/ip-address/report?ip="); this.getDomainReport = makeGet("https://www.virustotal.com/vtapi/v2/domain/report?domain="); const self = this; const UrlEvaluation = function(target, resultProc, errProc){ self.submitUrlForScanning(target, function(data){ self.retrieveUrlAnalysis(target, resultProc, errProc); }, errProc); }; this.UrlEvaluation = UrlEvaluation; const FileEvaluation = function(filename, filetype, filecontent, responseProc, errProc){ self.submitFileForAnalysis(filename, filetype, filecontent, function(responseData){ self.getFileReport(responseData.scan_id, responseProc, errProc); }, errProc); }; this.FileEvaluation = FileEvaluation; return; }; var features = {}; features.MakePublicConnection = function(){ return new PublicConnection(); }; features.MakeHoneypot2Connection = function(){ const workingConnection = new PublicConnection(); workingConnection.setDelay(1000); return workingConnection; }; features.makeIapiConnection = intelAPI.makeIapiConnection; features.queryBuilder = QB; features.makePrivateConnection = privateAPI.makePrivateAPI; features.formatConverter = formatConverter; module.exports = exports = features; /*Still need to add a feature to make Yara files, and upload them.*/