Jump to content

Metin2 Web API - Registration | Ranklist | User Online


Recommended Posts

  • Bot

Open input.cpp

Make your Analyze function like mine:

int CInputHandshake::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
{

	//YOUR THINGS
  
	if (bHeader == 10)
		return 0;
	if (bHeader == HEADER_CG_TEXT)// HEADER_CG_TEXT = 64 -> 64 IN HEXADECIMAL = 0x40
	{
		++c_pData;
		const char * c_pSep;
		if (!(c_pSep = strchr(c_pData, '\n'))) return -1;
		if (*(c_pSep - 1) == '\r') --c_pSep;
		std::string stResult;
		std::string stBuf;
		stBuf.assign(c_pData, 0, c_pSep - c_pData);

		//sys_log(0, "SOCKET_CMD: FROM(%s) CMD(%s)", d->GetHostName(), stBuf.c_str());

		if (!stBuf.compare("PLAYER_ONLINE"))
		{
			std::string risultato="";
			if (!IsInList(inet_ntoa(d->GetAddr().sin_addr))) {
				risultato += "[WebPanel::OnlineCounter] Access Denied.";
				//sys_err("[WebPanel] %s has tried to connect in the web panel.", inet_ntoa(d->GetAddr().sin_addr));
			}else{
				int iTotal;
				int *paiEmpireUserCount;
				int iLocal;
				DESC_MANAGER::instance().GetUserCount(iTotal, &paiEmpireUserCount, iLocal);
				risultato += format("Player Online: %d\nShinsoo: %d\nChunjo: %d\nJinno: %d", iTotal, paiEmpireUserCount[1], paiEmpireUserCount[2], paiEmpireUserCount[3]);
			}
			stResult += risultato;
		}
      
		else if (!stBuf.compare("PLAYER_RANKLIST"))
		{
			std::string risultato="";
			if (!IsInList(inet_ntoa(d->GetAddr().sin_addr))) {
				risultato += "[WebPanel::Ranklist] Access Denied.";
				//sys_err("[WebPanel] %s has tried to connect in the web panel.", inet_ntoa(d->GetAddr().sin_addr));
			}else{
				std::string Ranklist="";
				char classifica[1024]={0};
				snprintf(classifica, sizeof(classifica), "SELECT name, level FROM player.player%s WHERE account_id=(SELECT id FROM account.account%s WHERE status='OK' AND id=account_id) ORDER BY level DESC LIMIT 10;", get_table_postfix(), get_table_postfix());
				SQLMsg * res = DBManager::instance().DirectQuery(classifica);
				if (res->Get()->uiNumRows == 0) {
					M2_DELETE(res);
					risultato += "Players not found.";
				}
				Ranklist+="<Top 10 Player>\n\n";
				int pos=0;
				for (uint i=0; i<res->Get()->uiNumRows; i++) {
					MYSQL_ROW rows=mysql_fetch_row(res->Get()->pSQLResult);
					std::string name=std::string(rows[0]);
					if (name[0] != '[') {
						pos=i+1;
						std::string space="";
						for (unsigned s=0; s<=(25 - (int)name.length()); s++) space+=" ";
						Ranklist+=format("%d | %s%s | Lv.%s\n", pos, name.c_str(), space.c_str(), rows[1]);
					}else{
						pos=i-1;
					}
				}
				M2_DELETE(res);
				risultato += Ranklist;
			}
			stResult += risultato;			
		}
      
		else if (stBuf.find("ACCOUNT_REGISTER") != std::string::npos)
		{
			std::string risultato="";
			if (!IsInList(inet_ntoa(d->GetAddr().sin_addr))) {
				risultato += "[WebPanel::RegisterAccount] Access Denied.";
				//sys_err("[WebPanel] %s has tried to connect in the web panel.", inet_ntoa(d->GetAddr().sin_addr));
			}else{
				std::vector<std::string> args;
				std::string status;
				boost::split(args, stBuf, boost::is_any_of(","));
				if (args.size() > 0 && args[0].compare("ACCOUNT_REGISTER") == 0) {
					status=RegisterAccount(args[1], args[2], args[3], args[4], inet_ntoa(d->GetAddr().sin_addr));
				}else{
					status="[RegisterAccount] Syntax Error.";
				}
				risultato += status;
			}
			stResult += risultato;			
		}
		else if (stBuf.find("ACCOUNT_CHANGEPSW") != std::string::npos)
		{
			std::string risultato="";
			if (!IsInList(inet_ntoa(d->GetAddr().sin_addr))) {
				risultato += "[WebPanel::ChangePassword] Access Denied.";
				//sys_err("[WebPanel] %s has tried to connect in the web panel.", inet_ntoa(d->GetAddr().sin_addr));
			}else{
				std::vector<std::string> args;
				std::string status;
				boost::split(args, stBuf, boost::is_any_of(","));
				if (args.size() > 0 && args[0].compare("ACCOUNT_CHANGEPSW") == 0) {
					status=ChangePassword(args[1], args[2], args[3]);
				}else{
					status="[ChangePassword] Syntax Error.";
				}
				risultato += status;
			}
			stResult += risultato;			
		}
		stResult += "\n";
		d->Packet(stResult.c_str(), stResult.length());
		return (c_pSep - c_pData) + 1;
	}
  
 	//CONTINUE YOUR THINGS
	

NOW, THE FUNCTIONS:

//REMEMBER AT THE TOP OF FILE:
//#include <fstream>
//#include <boost/algorithm/string.hpp>

inline std::string format(const char* fmt, ...)
{
    int size = 512;
    char* buffer = 0;
    buffer = new char[size];
    va_list vl;
    va_start(vl, fmt);
    int nsize = vsnprintf(buffer, size, fmt, vl);
    if(size<=nsize){
        delete[] buffer;
        buffer = 0;
        buffer = new char[nsize+1];
        nsize = vsnprintf(buffer, size, fmt, vl);
    }
    std::string ret(buffer);
    va_end(vl);
    delete[] buffer;
    return ret;
}

inline bool IsInList(const char *ip)
{
	bool ritorno=false;
	std::ifstream ifs("locale/pannello_web_ip.txt", std::ifstream::in);
	if (ifs.fail()) {
		sys_err("[Web Panel] The file [locale/pannello_web_ip.txt] was not found.");
		return ritorno;
	}
	char c=ifs.get();
	std::string read;
	while (ifs.good()) {
		read += c;
		c=ifs.get();
	}
	ifs.close();
	if (strstr(read.c_str(), std::string(std::string(ip)+std::string("\n")).c_str()) != NULL) ritorno=true;
	return ritorno;
}

bool is_email(std::string const& address) {
    size_t at_index = address.find_first_of('@', 0);
    return at_index != std::string::npos && address.find_first_of('.', at_index) != std::string::npos;
}

std::string RegisterAccount(std::string login, std::string password, std::string email, std::string social_id, const char *ip)
{
	char EscapedLogin[255]={0};
	char EscapedPassword[255]={0};
	char EscapedSocialID[255]={0};
	char EscapedEmail[255]={0};

	DBManager::instance().EscapeString(EscapedLogin, sizeof(EscapedLogin), login.c_str(), strlen(login.c_str()));
	DBManager::instance().EscapeString(EscapedPassword, sizeof(EscapedPassword), password.c_str(), strlen(password.c_str()));
	DBManager::instance().EscapeString(EscapedSocialID, sizeof(EscapedSocialID), social_id.c_str(), strlen(social_id.c_str()));
	DBManager::instance().EscapeString(EscapedEmail, sizeof(EscapedEmail), email.c_str(), strlen(email.c_str()));

	if (strlen(EscapedLogin)<2) return "[RegisterAccount] Login can't be < 2 chars.";
	if (strlen(EscapedPassword)<3) return "[RegisterAccount] Password can't be < 3 chars.";
	if (strlen(EscapedEmail)<5) return "[RegisterAccount] Email can't be < 5 chars.";
	if (strlen(EscapedLogin)>20) return "[RegisterAccount] Login can't be > 20 chars.";
	if (strlen(EscapedPassword)>30) return "[RegisterAccount] Password can't be > 30 chars.";
	if (strlen(EscapedEmail)>50) return "[RegisterAccount] Email can't be > 50 chars.";
	if (strlen(EscapedSocialID)<3) return "[RegisterAccount] Social id can't be < 3 chars.";
	if (strlen(EscapedSocialID)>7) return "[RegisterAccount] Social id can't be > 7 chars.";
	if (!is_email(std::string(EscapedEmail))) return "[RegisterAccount] Email is not valid.";

	char iscrizione[1024]={0};
	snprintf(iscrizione, sizeof(iscrizione), 
	"INSERT INTO account.account%s (login, password, social_id, email, create_time, status, gold_expire, silver_expire, safebox_expire, autoloot_expire, fish_mind_expire, marriage_fast_expire, money_drop_rate_expire, web_ip) "
	"VALUES ('%s', password('%s'), '%s', '%s', NOW(), 'OK', '2025-01-01 00:00:00', '2025-01-01 00:00:00', '2025-01-01 00:00:00', '2025-01-01 00:00:00', '2025-01-01 00:00:00', '2025-01-01 00:00:00', '2025-01-01 00:00:00', '%s')",
	get_table_postfix(), EscapedLogin, EscapedPassword, EscapedSocialID, EscapedEmail, ip);

	std::auto_ptr<SQLMsg> res(DBManager::instance().DirectQuery(iscrizione));
	if (res->Get()->uiAffectedRows == 0 || res->Get()->uiAffectedRows == (uint32_t)-1) return "[RegisterAccount] The account name already exists, try with another account name.";
	return "[RegisterAccount] Registration done!";
}

std::string ChangePassword(std::string login, std::string password, std::string password2)
{
	char EscapedLogin[255]={0};
	char EscapedPassword[255]={0};
	char EscapedPassword2[255]={0};

	DBManager::instance().EscapeString(EscapedLogin, sizeof(EscapedLogin), login.c_str(), strlen(login.c_str()));
	DBManager::instance().EscapeString(EscapedPassword, sizeof(EscapedPassword), password.c_str(), strlen(password.c_str()));
	DBManager::instance().EscapeString(EscapedPassword2, sizeof(EscapedPassword2), password2.c_str(), strlen(password2.c_str()));

	if (!strcmp(EscapedPassword, EscapedPassword2)) return "[ChangePassword] The new password is the same.";
	if (strlen(EscapedLogin)<2) return "[ChangePassword] Login can't be < 2 chars.";
	if (strlen(EscapedPassword)<3) return "[ChangePassword] Password can't be < 3 chars.";
	if (strlen(EscapedPassword2)<3) return "[ChangePassword] New Password can't be < 3 chars.";
	if (strlen(EscapedLogin)>20) return "[ChangePassword] Login can't be > 20 chars.";
	if (strlen(EscapedPassword)>30) return "[ChangePassword] Password can't be > 30 chars.";
	if (strlen(EscapedPassword2)>30) return "[ChangePassword] New Password can't be > 30 chars.";

	char cambio_psw[1024]={0};
	snprintf(cambio_psw, sizeof(cambio_psw), 
	"UPDATE account.account%s SET password=password('%s') WHERE login='%s' AND password=password('%s')",
	get_table_postfix(), EscapedPassword2, EscapedLogin, EscapedPassword);

	std::auto_ptr<SQLMsg> res(DBManager::instance().DirectQuery(cambio_psw));
	if (res->Get()->uiAffectedRows == 0 || res->Get()->uiAffectedRows == (uint32_t)-1) return "[ChangePassword] Login or Password are incorrect.";
	return "[ChangePassword] Password changed successfully!";
}

PYTHON EXAMPLE:

def __Try(ip, port):
	try:
		import socket
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		s.connect((ip, port))
		s.send("\x40PLAYER_ONLINE\n")
		s.recv(100)
 		s.send("\x40PLAYER_ONLINE\n")
		print s.recv(1024)
		s.send("\x40PLAYER_RANKLIST\n")
		print s.recv(1024)
		s.send("\x40ACCOUNT_REGISTER,Raffa123,pass123,[email protected],1234567\n")
		print s.recv(1024)
		s.send("\x40ACCOUNT_CHANGEPSW,Raffa123,pass123,pass456\n")
		print s.recv(1024)
		s.close()
	except (socket.gaierror, socket.error, socket.herror, socket.timeout):
		print "[Server] Server is not online. [%s:%d]" % (ip, port)

__Try("IP_CH1", PORT_CH1)
import os
os.system("pause")

 

BE SAFE YOUR PANEL:

 

Open packet.h find HEADER_CG_TEXT = 64, and change the 64 with another number of packet, but remember that the number must be unused by other packet.

And replace in your scripts the \x40 with the other number in HEXADECIMAL, because 64 in hexadecimal is 0x40, use google to find the hexadecimal of a number ;) and put the escape char, final RESULT: \0x40MYCOMMAND

REMEMBER TO create the pannello_web_ip.txt into your locale folder.

IN THAT FILE PUT THE IP ADDRESS OF YOUR HOST OF THE WEBSITE, for any errors or log, just check the syserr.txt.

 

You can use your SOCKET API in PHP or Other languages ;)

With this you can insert your registration or ranklist or status or others and others without PUT THE "CREDENTIAL of Database".

  • Love 1

english_banner.gif

Link to comment
Share on other sites

  • Premium
25 minutes ago, Johnny69 said:

		import socket
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		s.connect((ip, port))
		for i in xrange(1000):
			s.send("\x40ACCOUNT_REGISTER,test%d,password,[email protected],1234567\n", i)
			print s.recv(1024)
		s.close()

What happen if i make that ?

They should rename they`re guides like: how to do a superuseless things that will open vulnerabilities to your server

 

 

  • Love 1
Link to comment
Share on other sites

  • Bot
3 hours ago, Johnny69 said:

		import socket
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		s.connect((ip, port))
		for i in xrange(1000):
			s.send("\x40ACCOUNT_REGISTER,test%d,password,[email protected],1234567\n", i)
			print s.recv(1024)
		s.close()

What happen if i make that ?

 

2 hours ago, Fleon said:

They should rename they`re guides like: how to do a superuseless things that will open vulnerabilities to your server

 

 

*** HOW TO DON'T READ THE TUTORIAL ***

if (!IsInList(inet_ntoa(d->GetAddr().sin_addr))) {
		risultato += "[Web Panel] Access Denied.";
		sys_err("[Web Panel] %s has tried to connect in the web panel.", inet_ntoa(d->GetAddr().sin_addr));
}
inline bool IsInList(const char *ip)
{
	bool ritorno=false;
	std::ifstream ifs("locale/pannello_web_ip.txt", std::ifstream::in);
	if (ifs.fail()) {
		sys_err("[Web Panel] The file [locale/pannello_web_ip.txt] was not found.");
		return ritorno;
	}
	char c=ifs.get();
	std::string read;
	while (ifs.good()) {
		read += c;
		c=ifs.get();
	}
	ifs.close();
	if (strstr(read.c_str(), std::string(std::string(ip)+std::string("\n")).c_str()) != NULL) ritorno=true;
	return ritorno;
}

MY EXAMPLE OF PYTHON IS ONLY FOR TEST, YOU NEED PUT THIS APP IN YOUR WEBSITE, AND PUT THE IP OF YOUR APP IN THE LIST, THE IPs THAT AREN'T IN THE LIST THEY CAN'T DO NOTHING!

"They should rename they`re guides like: how to do a superuseless things that will open vulnerabilities to your server"

HOW TO INSULT AND TELL SHIT ABOUT RELEASES OF PEOPLE.

UPDATES:

 

UPDATED CHANGE PASSWORD TOOL ADDED!

  • Love 1

english_banner.gif

Link to comment
Share on other sites

  • Active Member
3 hours ago, HiiPower said:

This is cancer for your server.

A web api built with PHP would have more sense than this.

Some webhosting providers have problems with php sockets so you can't use php api(Example: gazduirejocuri.ro)

  • Love 1
Link to comment
Share on other sites

  • Bot
On 1/7/2017 at 3:28 AM, metin2team said:

one word. "useless".

One word, go away from this topic if you don't like the content.

8 hours ago, Exygo said:

Some webhosting providers have problems with php sockets so you can't use php api(Example: gazduirejocuri.ro)

Yes is true, is true that you need a good php hosting

english_banner.gif

Link to comment
Share on other sites

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.