mirror of
https://github.com/rajkosto/mxoemu
synced 2026-08-14 02:26:05 -04:00
389 lines
No EOL
11 KiB
C++
389 lines
No EOL
11 KiB
C++
// *************************************************************************************************
|
|
// --------------------------------------
|
|
// Copyright (C) 2006-2010 Rajko Stojadinovic
|
|
//
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2.1 of the License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
//
|
|
// *************************************************************************************************
|
|
|
|
#include <pcap.h>
|
|
|
|
#define LINE_LEN 16
|
|
#include "Util.h"
|
|
#include "Internets.h"
|
|
|
|
CryptoPP::CBC_Mode<CryptoPP::Twofish>::Decryption *TFDecryptGTC;
|
|
CryptoPP::CBC_Mode<CryptoPP::Twofish>::Decryption *TFDecryptCTG;
|
|
|
|
DWORD WINAPI InstanceThread(LPVOID lpvParam)
|
|
{
|
|
HANDLE hPipe = CreateNamedPipe(
|
|
"\\\\.\\pipe\\MxoTwofishKey", // pipe name
|
|
PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE, // read/write access
|
|
PIPE_TYPE_BYTE | // byte type pipe
|
|
PIPE_READMODE_BYTE | // byte-read mode
|
|
PIPE_WAIT, // blocking mode
|
|
1, // max. instances
|
|
0x10, // output buffer size
|
|
0x10, // input buffer size
|
|
NMPWAIT_USE_DEFAULT_WAIT, // client time-out
|
|
NULL); // default security attribute
|
|
|
|
if (hPipe == INVALID_HANDLE_VALUE)
|
|
{
|
|
cout << "CreatePipe failed" << endl;
|
|
exit(0);
|
|
}
|
|
|
|
for (;;)
|
|
{
|
|
|
|
BOOL bResult = ConnectNamedPipe (hPipe, NULL);
|
|
|
|
if ( (FALSE == bResult) && ( ERROR_PIPE_CONNECTED != GetLastError() ) )
|
|
{
|
|
cout << "HAXXXX CANT CONNECT TO PIPEZ" << endl;
|
|
}
|
|
|
|
byte buffar[16];
|
|
DWORD hax;
|
|
|
|
BOOL ok = ReadFile(
|
|
hPipe, // handle to pipe
|
|
buffar, // buffer to receive data
|
|
sizeof(buffar), // size of buffer
|
|
&hax, // number of bytes read
|
|
NULL); // not overlapped I/O
|
|
|
|
if (!ok || hax != 0x10)
|
|
{
|
|
cout << "HAX !! GET AWAY ZE BOMB IS GONNA BLOWZ ! " << hax << endl;
|
|
goto end;
|
|
}
|
|
else
|
|
{
|
|
std::string data= std::string((char*)buffar,sizeof(buffar));
|
|
std::string password;
|
|
ConvertBytesintoHex((byte*)data.c_str(),&password,sizeof(buffar));
|
|
cout << "TwoFish passkey: " << password << endl;
|
|
byte hax[16];
|
|
memset(hax,0,sizeof(hax));
|
|
|
|
if (TFDecryptGTC != NULL)
|
|
delete TFDecryptGTC;
|
|
if (TFDecryptCTG != NULL)
|
|
delete TFDecryptCTG;
|
|
|
|
TFDecryptGTC=new CryptoPP::CBC_Mode<CryptoPP::Twofish>::Decryption(buffar, CryptoPP::Twofish::DEFAULT_KEYLENGTH, hax);
|
|
TFDecryptCTG=new CryptoPP::CBC_Mode<CryptoPP::Twofish>::Decryption(buffar, CryptoPP::Twofish::DEFAULT_KEYLENGTH, hax);
|
|
}
|
|
end:
|
|
FlushFileBuffers(hPipe);
|
|
DisconnectNamedPipe(hPipe);
|
|
}
|
|
CloseHandle(hPipe);
|
|
return 0;
|
|
}
|
|
|
|
typedef struct ServerSeq
|
|
{
|
|
unsigned server_sequence: 12;
|
|
unsigned client_sequence: 12;
|
|
unsigned flags: 8;
|
|
} ServerSequence;
|
|
|
|
std::string IP2String(ip_address ip)
|
|
{
|
|
std::ostringstream hax;
|
|
|
|
hax << (int)ip.byte1 << "." << (int)ip.byte2 << "." << (int)ip.byte3 << "." << (int)ip.byte4;
|
|
hax.flush();
|
|
return hax.str();
|
|
}
|
|
|
|
#include "Config.h"
|
|
|
|
void ProcessPacket(u_char type,ip_address sip,ip_address dip,u_short sport,u_short dport,u_char *data,unsigned int lenght)
|
|
{
|
|
if (!lenght)
|
|
return;
|
|
|
|
if (type==IPPROTO_TCP && (sport != MARGIN_PORT && dport != MARGIN_PORT))
|
|
return;
|
|
else if (type==IPPROTO_UDP && (sport != WORLD_PORT && dport != WORLD_PORT))
|
|
return;
|
|
|
|
std::string sourceIP = IP2String(sip);
|
|
std::string destIP = IP2String(dip);
|
|
|
|
std::string FileName="Unknown";
|
|
|
|
if (sourceIP == RECURSION || destIP == RECURSION)
|
|
FileName="Recursion";
|
|
else if (sourceIP == SYNTAX || destIP == SYNTAX)
|
|
FileName="Syntax";
|
|
else if (sourceIP == VECTOR || destIP == VECTOR)
|
|
FileName="Vector";
|
|
else if (sourceIP == LOCALHOST || destIP == LOCALHOST)
|
|
FileName="LocalHost";
|
|
|
|
FileName+=".log";
|
|
|
|
char dateStr [9];
|
|
char timeStr [9];
|
|
_strdate_s(dateStr,9);
|
|
_strtime_s(timeStr,9);
|
|
|
|
std::string location = "error";
|
|
|
|
bool encrypted = false;
|
|
unsigned char flags = 0;
|
|
unsigned short client_sequence = 0;
|
|
unsigned short server_sequence = 0;
|
|
CryptoPP::CBC_Mode<CryptoPP::Twofish>::Decryption *Decryptor;
|
|
Decryptor = NULL;
|
|
|
|
std::string display;
|
|
|
|
if (type==IPPROTO_TCP)
|
|
{
|
|
if (sport==MARGIN_PORT)
|
|
location="MRGN->Client";
|
|
else if (dport==MARGIN_PORT)
|
|
location="Client->MRGN";
|
|
|
|
display=std::string((const char*)data,lenght);
|
|
}
|
|
else if (type==IPPROTO_UDP)
|
|
{
|
|
if (data[0] == 0x01)
|
|
encrypted = true;
|
|
|
|
if (sport==WORLD_PORT)
|
|
{
|
|
if (encrypted)
|
|
Decryptor = TFDecryptGTC;
|
|
|
|
location="GAME->Client";
|
|
}
|
|
else if (dport==WORLD_PORT)
|
|
{
|
|
if (encrypted)
|
|
Decryptor = TFDecryptCTG;
|
|
|
|
location="Client->GAME";
|
|
}
|
|
|
|
if (encrypted && Decryptor == NULL)
|
|
return;
|
|
|
|
if (encrypted)
|
|
{
|
|
std::string vector((const char*)data+1,16);
|
|
Decryptor->Resynchronize((const byte *)vector.c_str());
|
|
std::string input((const char*)data+17,lenght-17);
|
|
std::string output;
|
|
CryptoPP::StringSource(input, true, new CryptoPP::StreamTransformationFilter(*Decryptor, new CryptoPP::StringSink(output)));
|
|
|
|
memcpy(&flags,output.c_str()+10,sizeof(flags));
|
|
|
|
if (sport==WORLD_PORT)
|
|
{
|
|
memcpy(&client_sequence,output.c_str()+11,sizeof(client_sequence));
|
|
memcpy(&server_sequence,output.c_str()+12,sizeof(server_sequence));
|
|
client_sequence = (client_sequence >> 4);
|
|
client_sequence = (client_sequence & 0xFF0F);
|
|
client_sequence = ntohs(client_sequence);
|
|
server_sequence = (server_sequence & 0xFF0F);
|
|
server_sequence = ntohs(server_sequence);
|
|
}
|
|
else if (dport==WORLD_PORT)
|
|
{
|
|
memcpy(&server_sequence,output.c_str()+11,sizeof(server_sequence));
|
|
memcpy(&client_sequence,output.c_str()+12,sizeof(client_sequence));
|
|
server_sequence = (server_sequence >> 4);
|
|
server_sequence = (server_sequence & 0xFF0F);
|
|
server_sequence = ntohs(server_sequence);
|
|
client_sequence = (client_sequence & 0xFF0F);
|
|
client_sequence = ntohs(client_sequence);
|
|
}
|
|
|
|
display = std::string(output.c_str()+14,output.size()-14); // remove first 14 bytes
|
|
}
|
|
else
|
|
display=std::string((const char*)data,lenght);
|
|
}
|
|
|
|
std::ofstream File;
|
|
File.open(FileName.c_str(),std::ios::app);
|
|
File << location << " " << "[" << timeStr << " " << dateStr << "]" << " " << "packet size: " << display.size();
|
|
if (encrypted)
|
|
File << " CRYPTED, Flags: " << std::hex << (int)flags << " ServerSeq: " << std::dec << server_sequence << " ClientSeq: " << client_sequence;
|
|
File << endl;
|
|
string text;
|
|
ConvertBytesintoHex((byte *)display.c_str(),&text,(unsigned int)display.size());
|
|
File << text << endl;
|
|
int j = 0;
|
|
for (unsigned int i = 0;i < display.size();i++)
|
|
{
|
|
j++;
|
|
if (j == 97)
|
|
{
|
|
File << endl;
|
|
j = 1;
|
|
}
|
|
if (display.c_str()[i] > 31 && display.c_str()[i] < 127)
|
|
File << display.c_str()[i];
|
|
else
|
|
File << ".";
|
|
}
|
|
File << endl << endl;
|
|
File.close();
|
|
}
|
|
|
|
int main()
|
|
{
|
|
srand ( (unsigned int)time(NULL) );
|
|
TFDecryptGTC=NULL;
|
|
TFDecryptCTG=NULL;
|
|
|
|
DWORD dwThreadId;
|
|
|
|
CreateThread(
|
|
NULL, // no security attribute
|
|
0, // default stack size
|
|
InstanceThread, // thread proc
|
|
(LPVOID) NULL, // thread parameter
|
|
0, // not suspended
|
|
&dwThreadId); // returns thread ID
|
|
|
|
pcap_if_t *alldevs;
|
|
pcap_if_t *d;
|
|
int inum;
|
|
int i=0;
|
|
pcap_t *adhandle;
|
|
int res;
|
|
char errbuf[PCAP_ERRBUF_SIZE];
|
|
struct pcap_pkthdr *header;
|
|
const u_char *pkt_data;
|
|
|
|
if (pcap_findalldevs(&alldevs, errbuf) == -1)
|
|
{
|
|
cout << "Error in pcap_findalldevs: "<< errbuf << endl;
|
|
exit(1);
|
|
}
|
|
|
|
for(d=alldevs; d; d=d->next)
|
|
{
|
|
cout << ++i << ". ";
|
|
|
|
if (d->description)
|
|
cout << d->description << endl;
|
|
else
|
|
cout << "No description available" << endl;
|
|
}
|
|
|
|
if (!i)
|
|
{
|
|
cout << endl << "No interfaces found! Make sure WinPcap is installed." << endl;
|
|
return -1;
|
|
}
|
|
|
|
cout << "Enter the interface number (1-"<<i<<"):";
|
|
cin >> inum;
|
|
|
|
if (inum < 1 || inum > i)
|
|
{
|
|
cout << endl << "Interface number out of range." << endl;
|
|
|
|
pcap_freealldevs(alldevs);
|
|
return -1;
|
|
}
|
|
for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
|
|
|
|
if ((adhandle= pcap_open_live(d->name, // name of the device
|
|
65536, // portion of the packet to capture.
|
|
// 65536 grants that the whole packet will be captured on all the MACs.
|
|
1, // promiscuous mode (nonzero means promiscuous)
|
|
1000, // read timeout
|
|
errbuf // error buffer
|
|
)) == NULL)
|
|
{
|
|
cout << endl << "Unable to open the adapter. " << d->description << " is not supported by WinPcap"<<endl;
|
|
pcap_freealldevs(alldevs);
|
|
return -1;
|
|
}
|
|
|
|
printf("\nlistening on %s...\n", d->description);
|
|
|
|
/* At this point, we don't need any more the device list. Free it */
|
|
pcap_freealldevs(alldevs);
|
|
|
|
/* Retrieve the packets */
|
|
while((res = pcap_next_ex( adhandle, &header, &pkt_data)) >= 0)
|
|
{
|
|
if(res == 0)
|
|
/* Timeout elapsed */
|
|
continue;
|
|
|
|
ip_header *ip;
|
|
u_int size_ip;
|
|
|
|
ip = (ip_header*)(pkt_data + SIZE_ETHERNET);
|
|
size_ip = (ip->ver_ihl & 0xf) * 4; //Gets length of IP header with options
|
|
if (size_ip < 20)
|
|
continue;
|
|
|
|
if (ip->proto == IPPROTO_TCP)
|
|
{
|
|
tcp_header *tcp;
|
|
tcp = (tcp_header*)(pkt_data + SIZE_ETHERNET + size_ip); //TCP header
|
|
u_int size_tcp = tcp->th_off/4;
|
|
if (size_tcp < 20)
|
|
{
|
|
cout << "Invalid TCP header length: " << size_tcp << " bytes" << endl;
|
|
continue;
|
|
}
|
|
|
|
ProcessPacket(IPPROTO_TCP,ip->saddr,ip->daddr,htons(tcp->sport),htons(tcp->dport),
|
|
(u_char *)(pkt_data + SIZE_ETHERNET + size_ip + size_tcp),
|
|
(header->caplen - SIZE_ETHERNET - size_ip - size_tcp));
|
|
}
|
|
else if (ip->proto == IPPROTO_UDP)
|
|
{
|
|
udp_header *udp;
|
|
udp = (udp_header*)(pkt_data + SIZE_ETHERNET + size_ip); //UDP header
|
|
|
|
ProcessPacket(IPPROTO_UDP,ip->saddr,ip->daddr,htons(udp->sport),htons(udp->dport),
|
|
(u_char *)(pkt_data + SIZE_ETHERNET + size_ip + SIZE_UDP),(htons(udp->len)-SIZE_UDP));
|
|
}
|
|
}
|
|
|
|
if(res == -1)
|
|
{
|
|
cout << "Error reading the packets: " << pcap_geterr(adhandle) << endl;
|
|
return -1;
|
|
}
|
|
|
|
pcap_close(adhandle);
|
|
|
|
if (TFDecryptGTC != NULL)
|
|
delete TFDecryptGTC;
|
|
if (TFDecryptCTG != NULL)
|
|
delete TFDecryptCTG;
|
|
|
|
return 0;
|
|
} |