[Help] Disconect account from website

omFg!

Member
Joined
Feb 12, 2013
Messages
51
Reaction score
15
Здравейте, да ви попитам за някаква информация относно това, по какъв начин мога да дискънектна акаунт през уеб сайта.
А ако не дискънект, то поне да форсна някък датасървъра да ъпдейтне информацията за чарактъра в базата данни.

До тук открих, че при Switch character и при вдигален на левел се ъпдейтват данните, но има ли някакъв начин да го правя когато аз искам това сейване.
 
Не мисля че има безопасен начин през сайта директно, защото ще трябва да разрешиш на PHP библиотеки, които не са за препоръчване ит.н.

Доколкото си спомням сървъра четеше записите от базата при логин и ти както каза може би при switch, както и прави всички записи след logout. Ти в базата каквито и записи да правиш по акаунта, докато той е онлайн сървъра не ги чете. Което означава, че ти трябва да симулираш logout, не че не е възможно през сайта но това е все едно да имаш шел на сайта който да контролира сървъра физически, което не ми се вижда разумно. По-скоро си го представям с връзка с някакъв посредник (програма), която след проверка да изпраща команда към сървъра за дисконект. Това ми се струва по-логично. Иначе е възможно, разбира се.
 
Last edited:
  • Like
Reactions: omFg!
Хм помня че имаше скрипт за да пишеш админски съобщения през сайта, някой ако го има я да го постне? Може да е нещо подобно и за диск.. Дарка ще каже най-добре де..
Иначе за онзи скрипт не мисля че трябваха някакви странични библиотеки.. (think)
 
  • Like
Reactions: omFg!
И аз да дам малко акъл, да не остана по-назад.

Както каза @Dea7h, имаше скриптове и за админ съобщения и за disconnect. Обаче са за специфична версия на GS/DS (не помня с кое беше комуникацията).

Накратко, трябва да симулираш пакета, който се изпраща при натискане на “log out” в играта и да го изпратиш с PHP. Най-вероятно този пакет може да се проследи с packet sniffing програма (сещам се за WireShark).

https://www.php.net/manual/en/ref.sockets.php - работата със сокети

Коментара ми е изграден основно на теория. Ако някой се е опитвал да прави такова нещо, може да сподели и на практика.
 
  • Like
Reactions: omFg! and Dea7h
Не трябва да е възможно да се снифват пакетите и да се репликират, ако е възможно това си е дупка. Една от основните задачи на антихаковете е да капсуловат комуникацията.
 
Disconnect на акаунт: 0xC1, 0x05 (JoinServer : 55970)
Code:
struct PBMSG_HEAD
{
    BYTE c;
    BYTE size;
    BYTE headcode;
};

struct SDHP_USERCLOSE_ID
{
    PBMSG_HEAD h;
    char szId[10];
#if(VERSION > 97D)
    char szName[10];
    WORD Level;
    BYTE DbClass;
#endif
};

Информацията за героите се записва при:
- Излизане от игра
- Вдигане на level
- На всеки 60 минути прекарани в игра
 
Аз скрипта за инпращане на съобщения го ползвам за Auto bring me евента ни и той бачка точно като изпраща пакет на локално ниво.
Предполагам това с дискънект ще е същото, от няколко часа дебъгвам с Wireshark да открия пакета който изпраща JS когато дискънектвам акаунт през него, но за в момента без успех.
 
Ако говорите за този скрипт не знам кои версии го подрържат и дали не праща само съобщения:
PHP:
////////////////////////////////////////////////////////////////////////////
// PHP Script to Send a public message inside the game from the website.  //
// It will appear just like the Golden Invasion text                      //
// Made by: Sandbird                                                      //
////////////////////////////////////////////////////////////////////////////

function ascii2hex($ascii) {
    $hex = '';
    for ($i = 0; $i < strlen($ascii); $i++) {
        $byte = strtoupper(dechex(ord($ascii{$i})));
        $byte = str_repeat('0', 2 - strlen($byte)).$byte;
        $hex.=$byte." ";
        }
        $hex=str_replace(" ", "", $hex);
        return $hex;
}

function hex2ascii($hex){
    $ascii='';
    $hex=str_replace(" ", "", $hex);
    for($i=0; $i<strlen($hex); $i=$i+2) {
        $ascii.=chr(hexdec(substr($hex, $i, 2)));
        }
        return($ascii);
}
function int_int_divide($x, $y) {
//Returns the integer division of $x/$y.
    if ($x == 0) return 0;
    if ($y == 0) return FALSE;
    return ($x % $y >= $y / 2) ?
        (($x - ($x % $y)) / $y) + 1 : ($x - ($x % $y)) / $y;
}

function send_msg($host, $port, $msg)
{ 
    $header = "C144A10024000000";   // Starting header of the message
    $msglength = strlen($msg);    // Length of message

if ($msglength < 34 && $msglength != 0){    // Starting calculations to divide the message box so the message looks centerd
    $divisor = (34 - $msglength);
    $start_space = int_int_divide($divisor , 2);
    
    for ($i=0;$i<=$start_space;$i++){
        $header .= "20";
        }
        $header .= ascii2hex($msg);   // Insert the message in the packet
            
       for ($j=0;$j<=($divisor-$start_space);$j++){
       $header .= "20";
       }
}else{                        // If the message is longer that 64 chars no need for spaces
        $header .= ascii2hex($msg);   // Insert the message in the packet if msg > 34
        }

    $header .= "00BED3410000F8BBB90400000000FCBBB904A4FF1A06F8F04100FFFFFFFF"; // Remainding header
    $packet = hex2ascii($header);                                // Convert the whole string to ascii
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    
        if (!$x = @socket_connect($socket, $host, $port))             // attempt to connect
        {
            echo "No access to the Joinserver or Server is down.";
        }
        else
       {
            socket_write($socket, $packet , strlen($packet));             // Send the packet to the Joinserver
            socket_close($socket);                 // Close connection (i dont know if this is needed or not).
      }

}
// If you want to post the message from another page then remove the // from the line below
// and add them on the other line. If you dont know how to do that then if your page is
// located for example at http://website.com/shout.php
// just write this at the header: http://website.com/shout.php?msg=And put your msg here.

// send_msg("127.0.0.1", "55970", $msg);
send_msg("127.0.0.1", "55970", "Insert your text here. It can fit in one message up to here.");
 
Ако говорите за този скрипт не знам кои версии го подрържат и дали не праща само съобщения:
PHP:
////////////////////////////////////////////////////////////////////////////
// PHP Script to Send a public message inside the game from the website.  //
// It will appear just like the Golden Invasion text                      //
// Made by: Sandbird                                                      //
////////////////////////////////////////////////////////////////////////////

function ascii2hex($ascii) {
    $hex = '';
    for ($i = 0; $i < strlen($ascii); $i++) {
        $byte = strtoupper(dechex(ord($ascii{$i})));
        $byte = str_repeat('0', 2 - strlen($byte)).$byte;
        $hex.=$byte." ";
        }
        $hex=str_replace(" ", "", $hex);
        return $hex;
}

function hex2ascii($hex){
    $ascii='';
    $hex=str_replace(" ", "", $hex);
    for($i=0; $i<strlen($hex); $i=$i+2) {
        $ascii.=chr(hexdec(substr($hex, $i, 2)));
        }
        return($ascii);
}
function int_int_divide($x, $y) {
//Returns the integer division of $x/$y.
    if ($x == 0) return 0;
    if ($y == 0) return FALSE;
    return ($x % $y >= $y / 2) ?
        (($x - ($x % $y)) / $y) + 1 : ($x - ($x % $y)) / $y;
}

function send_msg($host, $port, $msg)
{
    $header = "C144A10024000000";   // Starting header of the message
    $msglength = strlen($msg);    // Length of message

if ($msglength < 34 && $msglength != 0){    // Starting calculations to divide the message box so the message looks centerd
    $divisor = (34 - $msglength);
    $start_space = int_int_divide($divisor , 2);

    for ($i=0;$i<=$start_space;$i++){
        $header .= "20";
        }
        $header .= ascii2hex($msg);   // Insert the message in the packet
      
       for ($j=0;$j<=($divisor-$start_space);$j++){
       $header .= "20";
       }
}else{                        // If the message is longer that 64 chars no need for spaces
        $header .= ascii2hex($msg);   // Insert the message in the packet if msg > 34
        }

    $header .= "00BED3410000F8BBB90400000000FCBBB904A4FF1A06F8F04100FFFFFFFF"; // Remainding header
    $packet = hex2ascii($header);                                // Convert the whole string to ascii
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

        if (!$x = @socket_connect($socket, $host, $port))             // attempt to connect
        {
            echo "No access to the Joinserver or Server is down.";
        }
        else
       {
            socket_write($socket, $packet , strlen($packet));             // Send the packet to the Joinserver
            socket_close($socket);                 // Close connection (i dont know if this is needed or not).
      }

}
// If you want to post the message from another page then remove the // from the line below
// and add them on the other line. If you dont know how to do that then if your page is
// located for example at http://website.com/shout.php
// just write this at the header: http://website.com/shout.php?msg=And put your msg here.

// send_msg("127.0.0.1", "55970", $msg);
send_msg("127.0.0.1", "55970", "Insert your text here. It can fit in one message up to here.");
От архивите:
PHP:
function dc_user($host, $port, $user)
{
    $mystring = "C11405";
    $mystring .= ascii2hex($user);
    $zeros = strlen($mystring);

    for ($i = 0; $i <= 39 - $zeros; $i++) {
        $mystring .= "0";
    }

    $packet = hex2ascii($mystring);
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

    if (!$x = @socket_connect($socket, $host, $port)) {
        echo "An unexpected error occurred, please try again later.";
    } else {
        socket_write($socket, $packet, strlen($packet));
        socket_close($socket);
    }
}
Ще внедрите необходимите промени според структурите, които съм предоставил по-горе.
Имайте предвид, че през JoinServer-а могат да се изпълняват и други команди, като например блокиране на акаунт. Съветвам достъпа до него да бъде ограничен.
 
Аз вчера стигнах до тук:

PHP:
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

         $request = "c10d056f6d666731310000000014f312";

        $requestPacket = $serverMessageService->hex2ascii($request);
        if (!$x = @socket_connect($socket, '127.0.0.1', '55970'))
        {
            throw new \Exception("No access to the Joinserver or Server is down.");
        } else {
            @socket_write($socket, $requestPacket, strlen($requestPacket));
            @socket_close($socket);
        }

Чрез този код успявам да дискънекта акаунта от JoinServer, но самият акаунт остава онлайн в GameServer и не го известява, че е офлайн вече.

14f312 - червената част от хекса забелязах, че се генерира поредно при всеки следващ дискънект от JoinServer.

От менюто User в JS-a, когато селектирам потребителя и след това натисна Disconnect User то го дискънектва само от JS, но ако 1-во въведа името на акаунта, след това Search и след това селектирам и Disconnect User го дискънектва и от GS и от JS, затова предполагам, че последните 6 символа от хекс-а се връщат от GS като някакъв вид автентикация.

@DarkMaster кода който си прикачил ти прави същото което и моят, дискънектва от JS само.

Продължавам с опитите и ще ъпдейтвам като имам развитие.

PS: това го правя на 97d+99i DarksTeam

1611396796073.png

PS2: Ето това изписва JoinServer когато опитам да дискънектна през PHP-то:

1611397260937.png
 
Last edited:
  • Like
Reactions: RaFa and hater
Какво значи че не е дискънектнат от гейм сървъра? Не е ли само да упдейтнеш МЕМБ_СТАТ таблицата? Или самия гейм сървър си има някакъв стейт на онлайн юзърите 🔌 🤔
 
Ами не го дискънектва от играта, в Joinserver-a, го премахва от листа и когато след това изляза по нормален начин, той пак си изписва грешката User not found, но трябва нещо допълнително да се направи, за да започне да му отброява времето 5,4,3,2,1 и да го дискънектне от GameServer.

Това което намемерих е, че когато играч се логне в GS той получава нещо като уникален ключ който го пише навсякъде в лога за текущата му сесеия, и когато става disconnect от Joinserver, той изпраща заедно към хекса този ключ който си го взема от GS предполагам при Search, но в същото време явно когато го изискаш този ключ уведомевящ GS, че предстои операция за този потребител и той чака да му се подаде хедъра.

1611408494117.png

1611408521371.png

Обаче не мога да прехвана пакета който извършва тази операция..

ЕДИТ: c110096f6d666731310000000014e212 - червеното ако е 12e2 е равно на 4834 децимал, това ме води на мистлта, че този ключ е от значение и се изисква от GS..
 
Last edited:
До колкото знам, GS държи 1 огромен обект за всички monsters и players. Обикновенно players започват от ID 6000 (player objects). В този player object се държи всичката информация за героя, включително дали е он или не. Попринцип е отговорност на joinserver-a да се обръща към GS при disconnect, за да се промени player object-a и да се извика WZ_DISCONNECT в SQL. Според мен най-добре се опитай да прихванеш пакета, който се праща към GS при logout и ползвай него