
Um utilitário para analisar JavaScript malicioso.
Instalação
Simplesmente instale o box-js a partir do npm:
npm install box-js --global
Uso
Olhando para usar box-js com Cuckoo? Use
cuckoo-package.pycomo um pacote de
análise .Digamos que você tenha uma amostra chamada sample.js: para analisá-la, basta executar
box-js sample.js
Provavelmente, você também desejará fazer o download de quaisquer cargas úteis; use a bandeira --downloadpara ativar o download. Caso contrário, o mecanismo simulará um erro 404, para que o script seja levado a pensar que o site de distribuição está inoperante e entrar em contato com os sites de fallback.
O Box.js emulará um ambiente Windows JScript, imprimirá um resumo da emulação no console e criará uma pasta chamada sample.js.results(se ela já existir, será criada sample.js.1.resultse assim por diante). Esta pasta conterá:
analysis.log, um log da análise impressa na tela;- uma série de arquivos identificados por UUIDs;
snippets.json, uma lista de trechos de código executados pela amostra (JavaScript, comandos de shell etc.);urls.json, uma lista de URLs contatados;active_urls.json, uma lista de URLs que parecem eliminar malware ativo;resources.json, os fluxos ADODB (ou seja, os arquivos que o script gravou no disco) com tipos e hashes de arquivo;IOC.json, uma lista de comportamentos identificados como COI (indicadores de compromisso). Isso inclui acessos ao registro, arquivos gravados, solicitações HTTP e assim por diante.
Você pode analisá-las sozinho ou enviá-las automaticamente para o Malwr, VirusTotal ou uma caixa de proteção Cuckoo: para obter mais informações, execute box-export --help.
Para um isolamento adicional, é recomendável executar a análise em um contêiner temporário do Docker. Consulte
integrations/README.mdpara mais informações. Se você deseja automatizar a análise, pode usar os códigos de retorno – documentados em
integrations/README.md– para distinguir entre diferentes tipos de erros.
Uso em lote
Embora o box.js seja normalmente usado em arquivos únicos, ele também pode executar análises em lote. Você pode simplesmente passar uma lista de arquivos ou pastas para analisar:
box-js sample1.js sample2.js /var/data/mySamples ...
Por padrão, o box.js processa amostras em paralelo, executando uma análise por núcleo. Você pode usar uma configuração diferente especificando um valor para --threads: em particular, 0 removerá o limite, fazendo o box-js gerar o maior número possível de threads de análise e resultando em uma análise muito rápida, mas possivelmente sobrecarregando o sistema (observe que as análises geralmente são de CPU -bound , não RAM-bound).
Você pode usar --loglevel=warnpara silenciar mensagens relacionadas à análise e exibir apenas informações de progresso.
Após a conclusão da análise, você pode extrair os URLs ativos assim:
cat ./*.results/active_urls.json | sort | uniq
Bandeiras
NAME DESCRIPTION
-h, --help Show the help text and quit
-v, --version Show the package version and quit
--license Show the license and quit
--debug Die when an emulation error occurs, even in "batch mode", and pass on the exit
code.
--loglevel Logging level (debug, verbose, info, warning, error - default "info")
--threads When running in batch mode, how many analyses to run at the same time (0 =
unlimited, default: as many as the number of CPU cores)
--download Actually download the payloads
--encoding Encoding of the input sample (will be automatically detected by default)
--timeout The script will timeout after this many seconds (default 10)
--output-dir The location on disk to write the results files and folders to (defaults to the
current directory)
--preprocess Preprocess the original source code (makes reverse engineering easier, but takes
a few seconds)
--unsafe-preprocess More aggressive preprocessing. Often results in better code, but can break on
some ed ge cases (eg. redefining prototypes)
--no-kill Do not kill the application when runtime errors occur
--no-echo When the script prints data, do not print it to the console
--no-rewrite Do not rewrite the source code at all, other than for `@cc_on` support
--no-catch-rewrite Do not rewrite try..catch clauses to make the exception global-scoped
--no-cc_on-rewrite Do not rewrite `/*@cc_on <...>@*/` to `<...>`
--no-eval-rewrite Do not rewrite `eval` so that its argument is rewritten
--no-file-exists Return `false` for Scripting.FileSystemObject.FileExists(x)
--no-folder-exists Return `false` for Scripting.FileSystemObject.FileExists(x)
--function-rewrite Rewrite function cal ls in order to catch eval calls
--no-rewrite-prototype Do not rewrite expressions like `function A.prototype.B()` as `A.prototype.B =
function()`
--no-hoist-prototype Do not hoist expressions like `function A.prototype.B()` (implied by
no-rewrite-prototype)
--no-shell-error Do not throw a fake error when executing `WScriptShell.Run` (it throws a fake
error by default to pretend that the distribution sites are down, so that the
script will attempt to poll every site)
--no-typeof-rewrite Do not rewrite `typeof` (e.g. `typeof ActiveXObject`, which must return
'unknown' in the JScript standard and not 'ob ject')
--proxy [experimental] Use the specified proxy for downloads. This is not relevant if
the --download flag is not present.
--windows-xp Emulate Windows XP (influences the value of environment variables)
--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.
Analisando a saída Saída do
console
A primeira fonte de informação é a saída do console. Em uma análise bem-sucedida, normalmente será impresso algo como isto:
Using a 10 seconds timeout, pass --timeout to specify another timeout in seconds
Analyzing sample.js
Header set for http://foo.bar/baz: User-Agent Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
Emulating a GET request to http://foo.bar/baz
Downloaded 301054 bytes.
Saved sample.js.results/a0af1253-597c-4eed-9e8f-5b633ff5f66a (301054 bytes)
sample.js.results/a0af1253-597c-4eed-9e8f-5b633ff5f66a has been detected as data.
Saved sample.js.results/f8df7228-7e0a-4241-9dae-c4e1664dc5d8 (303128 bytes)
sample.js.results/f8df7228-7e0a-4241-9dae-c4e1664dc5d8 has been detected as PE32 executable (GUI) Intel 80386, for MS Windows.
http://foo.bar/baz is an active URL.
Executing sample.js.results/d241e130-346f-4c0c-a698-f925dbd68f0c in the WScript shell
Header set for http://somethingelse.com/: User-Agent Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
Emulating a GET request to http://somethingelse.com/
...
Nesse caso, estamos vendo um conta-gotas que baixa um arquivo http://foo.bar/baz, configurando o cabeçalho HTTP User-Agentpara Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0). Em seguida, ele decodifica e grava o resultado no disco (um executável do PE32). Por fim, ele executa algum comando no shell do Windows.
sample.js.results/a0af1253-597c-4eed-9e8f-5b633ff5f66aconterá a carga como foi baixada em http://foo.bar/baz ;sample.js.results/f8df7228-7e0a-4241-9dae-c4e1664dc5d8conterá a carga útil real (executável PE);sample.js.results/d241e130-346f-4c0c-a698-f925dbd68f0cconterá o comando que foi executado no shell do Windows.
Registros JSON
Toda solicitação HTTP é impressa no terminal e efetuada loginurls.json. URLs duplicados não são inseridos (ou seja, solicitar o mesmo URL duas vezes resultará em apenas uma linhaurls.json). active_urls.jsoncontém a lista de URLs que acabaram resultando em uma carga executável. Esse arquivo é o mais interessante, se você deseja derrubar sites de distribuição. snippets.jsoncontém todos os trechos de códigobox-jsencontrados, JavaScript, um comando cmd.exe ou umscript doPowerShell . resources.jsoncontém todos os arquivos gravados em disco pela amostra. Por exemplo, se o aplicativo tentasse salvarHello world!em$PATH/foo.txt, o conteúdo deresources.jsonseria:
{
"9a24...": {
"path": "(path)\\foo.txt",
"type": "ASCII text, with no line terminators",
"md5": "86fb269d190d2c85f6e0468ceca42a20",
"sha1": "d3486ae9136e7856bc42212385ea797094475802",
"sha256": "c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a"
}
}
O resources.jsonarquivo também é importante: cuidado com qualquer recurso executável (por exemplo, com "type": "PE32 executable (GUI) Intel 80386, for MS Windows").
Correção
Alguns scripts em estado selvagem foram observados para usar new Date().getYear()onde new Date().getFullYear(). Se uma amostra não mostrar nenhum comportamento suspeito, preste atenção nas Dateverificações.
Se você tiver arquivos .JSE, compile o decodificador e execute-o assim:
cc decoder.c -o decoder
./decoder foo.jse bar.js
node run bar.js
Expansão
Ocasionalmente, você pode encontrar componentes não suportados. Nesse caso, você pode registrar um problema no GitHub ou emular o componente se souber JavaScript.
O erro normalmente terá esta aparência (os números de linha podem ser diferentes):
1 Jan 00:00:00 - Unknown ActiveXObject WinHttp.WinHttpRequest.5.1
Trace
at kill (/home/CapacitorSet/box-js/run.js:24:10)
at Proxy.ActiveXObject (/home/CapacitorSet/box-js/run.js:75:4)
at evalmachine.<anonymous>:1:6471
at ContextifyScript.Script.runInNewContext (vm.js:18:15)
at ...
Você pode ver que a exceção foi levantada Proxy.ActiveXObject, assim:
function ActiveXObject(name) {
name = name.toLowerCase();
/* ... */
switch (name) {
case "wscript.shell":
return require("./emulator/WScriptShell");
/* ... */
default:
kill(`Unknown ActiveXObject ${name}`);
break;
}
}
Adicione um novo case "winhttp.winhttprequest.5.1"(observe as minúsculas!) E faça com que ele retorne um Proxyobjeto ES6 (por exemplo ProxiedWinHttpRequest). Isso é usado para capturar recursos não implementados assim que solicitados pela amostra maliciosa:
/* emulator/WinHttpRequest.exe */
const lib = require("../lib");
module.exports = function ProxiedWinHttpRequest() {
return new Proxy(new WinHttpRequest(), {
get: function(target, name, receiver) {
switch (name) {
/* Add here "special" traps with case statements */
default:
if (name in target) return target[name];
else lib.kill(`WinHttpRequest.${name} not implemented!`)
}
}
})
}
function WinHttpRequest() {
}
Execute novamente a análise: ela falhará novamente, informando o que exatamente não foi implementado.
1 Jan 00:00:00 - WinHttpRequest.open not implemented!
Trace
at kill (/home/CapacitorSet/box-js/run.js:24:10)
at Object.ProxiedWinHttpRequest.Proxy.get (/home/CapacitorSet/box-js/run.js:89:7)
Emule WinHttpRequest.openconforme necessário:
function WinHttpRequest() {
this.open = function(method, url) {
URLLogger(method, url);
this.url = url;
}
}
e itere até o código emular sem erros.
Contribuidores
@CapacitorSet : desenvolvedor principal
@daviesjamie :
- embalagem npm
- ajuda da linha de comando
--output-directory- correções de bugs
@ALange :
- suporte para codificações não UTF8
- relatório de erros
- conselhos sobre como integrar o UglifyJS no box-js
- aprimorando os recursos do UglifyJS usados na desofuscação
@psrok :
- correções de bugs
- correções de bugs

