domenica 20 febbraio 2022

Alan c2 Framework v6.0: Alan + JavaScript = ♡

Twitter: @s4tan

Alan v6.0 was release with a new cool feature: JavaScript execution. The scripts are executed in memory and do not depend on any third party program. The scripts source code can be downloaded from the GitHub Alan repository.

Being able to extend the framework is a mandatory feature in today red-team tools. Each team has its own methodology to perform a red-team activity and being able to customize or extend the tool capabilities is mandatory. One of the main goal with Alan was to provide a framework that can be easily adapted to vairous modus-operandi. Alan v6.0 adds a new feature to support an easy extension, it allows the operator to execute JavaScript file directly in memory. This feature is implemented inside an Alan core module and does not depend on any third party program.

In other tools, this kind of feature requires the operator to compile C code by following a specific process. This might be overhelming and unecessary complex. Javascript is an easy language and even novices can become proficient in a short time.

However, being able to execute JavaScript code is not enough, since in most cases the operator needs to interact with native Windows function to perform a given action. Alan provides an interface to call native Windows functions by using the handy JavaScript syntax. This blog post explores the details of this feature and how to use it to extend the Alan capabilities.

Gettin Started

Executing a JavaScript file in Alan is extremyl easy, just use the run command and specify a file with .js extension. In order to call a Windwos function, Alan implements the Win32 module that exposes two methods: GetProcAddress and LoadLibrary. These are the basic methods to call virtually any Windows functions. Let's try to write a simple file that prints the process ID.

import * as win32 from 'Win32';

var kernel32 = win32.LoadLibrary("kernel32.dll");
var GetCurrentProcessId = win32.GetProcAddress(kernel32, "GetCurrentProcessId");
var IsWow64Process = win32.GetProcAddress(kernel32, "IsWow64Process");
var GetCurrentProcess = win32.GetProcAddress(kernel32, "GetCurrentProcess");

var my_pid = GetCurrentProcessId();
var is_wow64 = new Array(4);
IsWow64Process(GetCurrentProcess(), is_wow64);

var msg = "Hello world from Javascript executed in process: " + my_pid;
if (is_wow64[0] == 1)
	msg += " - I'm running under Wow64 :)";
The script opens the Win32 module in order to load the Kernel32 DLL by calling the LoadLibrary function. Using the obtained handle, the GetCurrentProcessId function address is resolved by using the GetProcAddress function. The other functions are resolved in the same way. You can now use the resolved functions by calling them as standard JavaScript functions. As final step, the script prints a string showing a message containing information extracted from the Windows APIs.

A fundamental step of the entire process is being able to easily test the script during the development stage. In this new Alan version, a new folder named tools was added to the Alan package. It contains the files cqjsx86.exe and cqjsx64.exe. These files are JavaScript interpreters in x86 and x64 version. Let's try to run our script with both files to see what result is produced (the --file option is used to specify the file path).

C:\Alan.v6.0.511.24\tools>cqjsx64.exe --file test.js
Hello world from Javascript executed in process: 15532

If we use the wqjsx86.exe program, we obtain the following result (I'm running my test in a x64 OS).
C:\Alan.v6.0.511.24\tools>cqjsx86.exe --file test.js
Hello world from Javascript executed in process: 30844 - I'm running under Wow64 :)

As can be noticed, the result is different according to the used version.
Once that the script works as expected, we can run it in the Alan agent by simply using the run command and specifying the full path of the script.

Windows API Data Structure Interoperation

The GetProcAddress and the LoadLibrary should provide the basic functionality to call every Wind32 APIs. However, interacting with a native API might requires further information. A typical example are parameters that are used as buffer (both in input and output). When this is the case, the following rules apply:
  • Each JavaScript Array is considered as an array of bytes when passed to a Win32 function. Each byte is casted to uint8_t (this causes a data truncation and a potential data corruption). If the array contains other complex data types (such as a String) its value is converted to NULL.
  • Boolean values are converted to 1 if true and 0 if false.
  • Each number is converted to a 32-bit interger on x86 process, and to 64-bit integer on x64 process.
  • Each JavaScript String is converted to an ascii string when passed to a Win32 function.
  • You can not call functions with more than 20 parameters.

The rules above imply that:
  • Each parameter passed by address to a Win32 function needs to be converted to an array (eg. to pass a LPDWORD you have to create an Array(4) parater if running in 32-bit or an Array(8) if running in 64-bit).
  • If a Win32 function accept a structure, it needs to be converted to an Array too. For example, a PROCESSENTRY32 structure must be represented as an Array and then parsed by refercing the fields by their offset (an example using this structure is presented later with some helper function to simplify the job).

All these rules might be quite annoying during the development of a not trivial script. In the next section I'll show how to easier the development task by implementing an lsass process memory dumper.

Implementing a simple lsass.exe process memory dumper

This is a perfect case to explore more in-depth this new feature. Being able to dump the process memory of the lsass process is very import to further compromise an host. There are various techniques to achieve this goal, but for the sake of simplicity I'll go for the simpler one, by using the MiniDumpWriteDump function. I'll put the script on GitHub so you can have a look at its full source code.

Let's suppose that our Agent is running as Administrator, then the following points have to be considered to write the dumper:
  • Enable SE_DEBUG_NAME privilege.
  • Scan all processes to identify the lsass.exe process.
  • Create a mini dump of the lsass.exe process.

As first step we have to load all the needed functions. This is a trivial task and already demonstrated in the previous example. Enabling SE_DEBUG_NAME is the next step. To perform this action we have to use a TOKEN_PRIVILEGES structure. This structure is quite simple, so for this task we will just create an array of 0x10 bytes and reference the sTP.Privileges[0].Luid, the sTP.PrivilegeCount and the sTP.Privileges[0].Attributes by their array offset. After calling the AdjustTokenPrivileges function we are now reayd to proceed with the next and probably most complex step.

We have to identify the lsass.exe process. To achieve this goal we use the CreateToolhelp32Snapshot function to obtain a snapshot and loop through all processes untile we find a process whose name is lsass.exe. This implies the usage of a PROCESSENTRY32 structure which is not that simple. To easies the task I created various JavaScript functions helper that serialize an object to a JavaScript array. The serialization function inspects the prefix of each field name and according to its value a specific serialization action is performed. For example, field names that start dw_ are serializated as DWORD. Field names that start with p_ are serializated to a four bytes array or eigth bytes array according to the value of a global variable that I defined at the start of the script (this step can be more dynamic by using the IsWow64Process function). Thanks to these functions, working with structures is now a lot easier (see the script source code for full details).

The final step is to create a file and call the MiniDumpWriteDump function to create a file dump that you can now download to your machine for post-processing.


Now that we have create our script to dump the lsass.exe process memory, let's use it. The video below provides a demonstration about how to dump the lsass.exe process memory by running our JavaScript script in the agent.

Nessun commento:

Posta un commento

Nota. Solo i membri di questo blog possono postare un commento.