Building Backdoors with Alternative Socket with lib-nosa (No Socket API)

Alternative implementation of winsock2 using AFD.sys for socket realization. Still improving!

lib-nosa is a minimalist C library designed to facilitate socket connections through AFD driver IOCTL operations on Windows. By bypassing the traditional winsock2.h -> (ws2_dll.dll) header, lib-nosa directly interacts with the internal socket APIs of the AFD (Ancillary Function Driver for WinSock), offering developers a lightweight and low-level alternative for network programming.

Created by ViperX Team

Repository: https://github.com/ViperXSecurity/lib-nosa

Features

  • Establishes socket connections directly through AFD driver IOCTL calls, bypassing the standard Winsock2 interface.

  • Focuses on simplicity and performance, with a small footprint and no unnecessary dependencies.

  • Provides direct access to internal socket APIs, giving developers fine-grained control over network operations.

  • Avoids the overhead and abstraction of the Winsock2 API, making it ideal for performance-critical applications.

Building a Simple Backdoor with lib-nosa

Creating a simple backdoor using the lib-nosa library. We'll explore the core functions provided by lib-nosa, understand their purposes, and see how they integrate to establish a connection, send and receive data, and execute received shellcode.

Overview

The backdoor's primary function is to connect to a Command and Control (C2) server, signal its readiness, receive a shellcode payload, and execute it. Here's the high-level flow:

  1. Establish Connection: Connect to the C2 server using the specified IP and port.

  2. Allocate Memory: Reserve memory to store the incoming shellcode.

  3. Signal Readiness: Inform the server that the client is ready to receive the shellcode.

  4. Receive Shellcode: Receive the shellcode from the server.

  5. Execute Shellcode: Change memory permissions to executable and run the shellcode.

  6. Cleanup: Release allocated resources.

Let's delve into each step, examining the code and the underlying lib-nosa APIs.

The Code

Code Run

"Compiling nosa-rev11.c with x86_64-w64-mingw32-gcc
"Netcat is used to listen on port 4444 and receives a connection from IP 192.168.15.7, with 322 bytes sent and 5 bytes received."
"Execution of nosa-rev11.exe shows successful socket creation and connection to 192.168.15.32:4444, with a detailed hex dump of the data sent."

Detailed Breakdown

1. Establishing a Connection

Function Used: nosa_connect

nosa_connect Function

  • Purpose: Establishes a connection to a specified host and port using the desired socket type (e.g., TCP or UDP).

  • Parameters:

    • hSocket: A pointer to a HANDLE where the function will store the created socket handle upon successful connection.

    • host: The target hostname or IP address.

    • port: The target port number.

    • socketType: The type of socket to use ("TCP" or "UDP").

  • Return Value: Returns an NTSTATUS code indicating success or failure.

Explanation:

  • The function initializes and creates a socket based on the provided socketType.

  • It resolves the host to an IP address, possibly using nosa_dns_lookup if a domain name is provided.

  • It then attempts to establish a connection to the specified host and port.

  • Upon success, it stores the socket handle in hSocket.

2. Allocating Memory

Explanation:

  • Uses the Windows API VirtualAlloc to reserve a memory region of size MAX_RECV_BYTES (4096 bytes in this case) with read/write permissions.

  • This memory will store the incoming shellcode.

  • memset ensures the allocated memory is zeroed out to prevent any residual data.

3. Signaling Readiness

Function Used: nosa_send

nosa_send Function

  • Purpose: Sends data over an established socket connection.

  • Parameters:

    • hSocket: Pointer to the socket handle over which data will be sent.

    • packet_data: Pointer to the data buffer to be sent.

    • packet_data_sz: Size of the data buffer in bytes.

  • Return Value: Returns an NTSTATUS code indicating success or failure.

Explanation:

  • Sends the string "READY" to the server, indicating that the client is prepared to receive the shellcode.

  • Ensures that the entire message is sent successfully.

4. Receiving the Shellcode

Function Used: nosa_recv

nosa_recv Function

  • Purpose: Receives data from an established socket connection.

  • Parameters:

    • hSocket: The socket handle from which data will be received.

    • packet_data_received: Pointer to the buffer where the received data will be stored.

  • Return Value: Returns the number of bytes received or an NTSTATUS code indicating an error.

Explanation:

  • Receives data from the server, which should be the shellcode payload.

  • Checks if the received byte count is greater than zero to ensure data was received successfully.

  • The received data is stored in the previously allocated pktRecv buffer.

5. Executing the Shellcode

Explanation:

  • Changing Memory Permissions: Uses VirtualProtect to modify the memory permissions of the pktRecv buffer, allowing it to be executable.

    • Changes from PAGE_READWRITE to PAGE_EXECUTE_READ.

    • Stores the old protection settings in oldProtect (useful for restoring later if needed).

  • Executing the Shellcode:

    • Casts the pktRecv buffer to a function pointer func.

    • Invokes func(), executing the shellcode.

Safety Note: Executing arbitrary shellcode can be extremely dangerous. Ensure that the shellcode is from a trusted source and that testing occurs in a controlled environment.

6. Cleanup

Explanation:

  • Memory Release: Frees the allocated memory for pktRecv using VirtualFree.

  • Socket Closure: Closes the established socket connection using afd_close.

Understanding Additional lib-nosa APIs

nosa_dns_lookup

  • Purpose: Resolves a domain name to its corresponding IP address.

  • Parameters:

    • hSocket: A socket handle used for the DNS query.

    • domain_name: The domain name to resolve (e.g., "example.com").

    • outBuffer: A pointer to a DOMAIN_INFO structure where the resolved IP address and related information will be stored.

  • Return Value: Returns an NTSTATUS code indicating success or failure.

Explanation:

  • This function is essential when the host parameter in nosa_connect is provided as a domain name rather than an IP address.

  • It performs a DNS lookup to retrieve the IP address associated with the given domain.

  • The resolved information is stored in the outBuffer, which can then be used for establishing connections.

afd_close

While not explicitly defined in the provided context, afd_close appears to be a function responsible for closing the socket handle.

Assumed Function Signature:

  • Purpose: Closes an established socket connection.

  • Parameters:

    • hSocket: The socket handle to be closed.

  • Explanation: Ensures that the socket resources are properly released, preventing resource leaks.

Last updated