Skip to content

Commit

Permalink
Merge pull request #82 from kirk-sayre-work/master
Browse files Browse the repository at this point in the history
1.19.20 Release
  • Loading branch information
kirk-sayre-work authored Feb 15, 2023
2 parents fa6b298 + 393e5ad commit bdca8ea
Show file tree
Hide file tree
Showing 23 changed files with 1,727 additions and 4,156 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ Box.js will emulate a Windows JScript environment, print a summary of the emulat
>If you wish to automate the analysis, you can use the return codes - documented in `integrations/README.md` - to distinguish between different types of errors.
## Analysis Fails Due to Missing 'document' Object
## Analysis Fails Due to Missing 'document' Object or Other Objects/Functions

The box-js repository from git includes a `boilerplate.js` file. This file defines some stubbed versions of common browser objects such as document. Try rerunning your analysis with the `--prepended-code=DIR/boilerplate.js` option, where `DIR` is the directory of the cloned box-js repository. The `--prepended-code` option tells box-js to prepend the JavaScript in the given file to the sample being analyzed.

Note that you can copy boilerplate.js and add your own stubbed classes, objects, etc. as needed.

## Batch usage

While box.js is typically used on single files, it can also run batch analyses. You can simply pass a list of files or folders to analyse:
Expand Down Expand Up @@ -88,6 +90,8 @@ cat ./*.results/active_urls.json | sort | uniq
--preprocess Preprocess the original source code (makes reverse engineering easier, but takes
a few seconds)
--prepended-code Prepend the JavaScript in the given file to the sample prior to sandboxing
--fake-script-engine The script engine to report in WScript.FullName and WScript.Name (ex.
'cscript.exe' or 'wscript.exe'). Default is wscript.exe.
--unsafe-preprocess More aggressive preprocessing. Often results in better code, but can break on
some edge cases (eg. redefining prototypes)
--no-kill Do not kill the application when runtime errors occur
Expand All @@ -114,6 +118,8 @@ cat ./*.results/active_urls.json | sort | uniq
--dangerous-vm Use the `vm` module, rather than `vm2`. This sandbox can be broken, so **don't
use this** unless you're 100% sure of what you're doing. Helps with debugging by
giving correct stack traces.
--rewrite-loops Rewrite some types of loops to make analysis faster
--throttle-writes Throttle reporting and data tracking of file writes that write a LOT of data
<!--END_FLAGS-->

# Analyzing the output
Expand Down
17 changes: 17 additions & 0 deletions RELEASE_NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Version 1.19.20, 2/15/2023
--------------------------

* Added anti-emulation loop rewriting functionality.
* Added functionality for faking being run with cscript.exe or wscript.exe.
* Added functionality for throttling lots of small file writes.
* Added support for WMI.GetObject.Run().
* Added support for ADODBStream.flush().
* Added support for InternetExplorer.Application.
* Added support for XMLHttpRequest.
* Added some stubbed JQuery functionality.
* Added support for ScheduleService.
* Track IOCs being passed through the '|' operator in analyzed JS code.
* Added support for WindowsInstaller.installer.



48 changes: 39 additions & 9 deletions _run.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ const path = require("path");
const walk = require("walk-sync");
const argv = require("./argv.js").run;

function list_delete(arr, item) {
for( var i = 0; i < arr.length; i++){

if ( arr[i] === item) {
arr.splice(i, 1);
i--;
}
}
return arr;
}

// Track whether we should return an error shell code or not.
var single_sample = false;

// Read and format JSON flag documentation
if (argv.help || process.argv.length === 2) {
const columnify = require("columnify");
Expand Down Expand Up @@ -72,7 +86,13 @@ const [targets, options] = args.functionalSplit(fs.existsSync);
// Array of {filepath, filename}
const tasks = [];

const [folders, files] = targets.functionalSplit(path => fs.statSync(path).isDirectory());
var [folders, files] = targets.functionalSplit(path => fs.statSync(path).isDirectory());

// The output dir does not have samples to analyze.
const outputDir = argv["output-dir"] || "./";
if (outputDir != "./") {
folders = list_delete(folders, outputDir);
}

files
.map(filepath => ({
Expand Down Expand Up @@ -105,14 +125,16 @@ if (argv.threads === 0) q.concurrency = Infinity;
else if (argv.threads) q.concurrency = argv.threads;
else q.concurrency = require("os").cpus().length;

if (tasks.length > 1) // If batch mode
if (argv.threads)
if (tasks.length > 1) { // If batch mode
if (argv.threads) {
console.log(`Analyzing ${tasks.length} items with ${q.concurrency} threads`)
else
console.log(`Analyzing ${tasks.length} items with ${q.concurrency} threads (use --threads to change this value)`)

}
else {
console.log(`Analyzing ${tasks.length} items with ${q.concurrency} threads (use --threads to change this value)`)
}
}

// queue the input files for analysis
const outputDir = argv["output-dir"] || "./";
tasks.forEach(({filepath, filename}) => q.push(cb => analyze(filepath, filename, cb)));

let completed = 0;
Expand All @@ -123,6 +145,10 @@ q.on("success", () => {
console.log(`Progress: ${completed}/${tasks.length} (${(100 * completed/tasks.length).toFixed(2)}%)`);
});

// Exit with a meaningful return code if we are only analyzing 1 sample.
single_sample = (q.length == 1);

// Start analyzing samples.
q.start();

function analyze(filepath, filename, cb) {
Expand All @@ -142,7 +168,8 @@ function analyze(filepath, filename, cb) {
if (!argv.preprocess)
console.log("Hint: if the script is heavily obfuscated, --preprocess --unsafe-preprocess can speed up the emulation.");
worker.kill();
if (argv.debug) process.exit(2);
// Useful analysis may have occurred.
process.exit(0);
cb();
}, timeout * 1000);

Expand All @@ -169,9 +196,12 @@ function analyze(filepath, filename, cb) {
* If the error is about a weird \"Unknown ActiveXObject\", try --no-kill.
* Otherwise, report a bug at https://github.com/CapacitorSet/box-js/issues/ .`);
}
if (code != 0) {
final_code = code;
}
clearTimeout(killTimeout);
worker.kill();
if (argv.debug) process.exit(code);
if (argv.debug || single_sample) process.exit(code);
cb();
});

Expand Down
Loading

0 comments on commit bdca8ea

Please sign in to comment.