Здравствуйте, гость ( Вход | Регистрация )
Дата поста: | В теме: | За сообщение: | Спасибо сказали: | ||
---|---|---|---|---|---|
20.8.2010, 13:00 |
Хаблисты |
Итак, по порядку. Как было справделиво замеченно, можно отсекать по команде не MyINFO, после MyINFO, но не все тут гладко. Можно довольно долго висеть на хабе из 5 человек ожидая другой команды. Вообще говоря, по протоколу, список MyINFO, должен заканчиваться MyINFO хаблиста, но, к сожалению, так поступают не все хабы. Дальше. Есть такое расширение протокола как Zon. Которое предполагает сжатие gzip дл передаваемых данных. проблема состоит в том, что некоторые хабы в любом случае включат это сжатие не смотря поддерживается оно клиентом или нет. Эта команда может появляться где угодно и, обычно, список пользователей передается в сжатом виде, что означает, что ее нужно игнорировать и не разрывать соединение, так как процесс входа на хаб может быть не завершен. Также следует отслеживать команды ValidateDenide и ForceMove. Первая означает что ник занят или не является допустимым, а вторая - дает редирект, при переполнении или других причинах. Четкой команды, свидетельствующей о бане не существует, обычно это сообщение от бота со словом ban, но не обязательно. 100% алгоритма определения окончания инициализации не существует или мне он не известен. Пользуюсь набором правил следующего вида:
Как вариант, можно еще пытаться отлавливать MOTD, но оно может отсылаться в ЛС. По поводу дубликатов, проблема решается просто, все это дело заноситься в ассциативный массив по ключу ника, а потом из массива и считается шара и число пользователей. Также необходимо отслеживать свой ник и его игнорировать. Еще. Хаб может не поддерживать BotINFO/HubINFO, тогда с текущим алгоритмом вы будете ждать вечность команды HubINFO. Чтобы этого не произошло, необходимо, после указания поддержки данных команд в отсылаемом Supports, проверить наличие поддержи в полученном Supports. |
dro | ||
20.8.2010, 1:38 |
Хаблисты |
Пингом - быстрей, но пинг предоставляет недостаточно информации. С другой стороны, он виден админу, и если часто пинговать, то вас попросту забанят. Поэтому у меня раз в 5 минут хаблист заходит как клиент и раз в час - как пингер, т. е. каждый 12 раз из тех, что по 5 минут. В целом пингер неплох. Критика по коду:
Чтобы бота пускали на все хабы, не нужно передавать специфический тэг клиента. Да и число хабов онлайн можно не 21 ставить. "H:21/0/1" - 21 хаб 1 и на одном админ. UPD: И да, я тут увидел зачатки работы как клиента (Подсчет MyINFO). Вам предстоит нетривиальная задача определения когда заканчивается процесс инициализации хаба. Также вам необходимо отсевать свой собственный MyINFO, так как он вносит погрешность в ваши измерения. В дополнение к этому есть скрипты манипулирующие MyINFO, из-за них оно может приходить несколько раз для одного пользователя, что вызовет искажение размера шары и числа пользователей. Так что работы тут еще много. |
dro | ||
29.7.2010, 1:10 |
lock2key для hublist'а Код для работы с хаблистом. |
Итак, по порядку. Известно что хаблисты используют схему $Lock-$Key. Основная проблема заключаеться в том, что этот алгоритм чуть-чуть отличается от обычного. Если быть точным, ровно на первый байт. В интернете видел информацию, что большинство хаблистов благополучно игнорируют правильность этого кода и есть там один, особо задиристый. Однако, чем черт не шутит. Поэтому наваял свою реализацию на PHP. Но, буду последователен. Исходником послужил код из исходников PtokaX хаба: Код uint16_t lport = (uint16_t)ntohs(addr.sin_port); char cMagic = (char) ((lport&0xFF)+((lport>>8)&0xFF)); // strip the Lock data char *temp; if((temp = strchr(sBuffer+6, ' ')) != NULL) { temp[0] = '\0'; } // Compute the key memcpy(sMsg, "$Key ", 5); sMsg[5] = '\0'; size_t iLen = temp-sBuffer; char v; // first make the crypting stuff for(size_t i = 6; i < iLen; i++) { if(i == 6) { v = sBuffer[i] ^ sBuffer[iLen] ^ sBuffer[iLen-1] ^ cMagic; } else { v = sBuffer[i] ^ sBuffer[i-1]; } // Swap nibbles (0xF0 = 11110000, 0x0F = 00001111) v = (char)(((v << 4) & 0xF0) | ((v >> 4) & 0x0F)); switch(v) { case 0: strcat(sMsg, "/%DCN000%/"); break; case 5: strcat(sMsg, "/%DCN005%/"); break; case 36: strcat(sMsg, "/%DCN036%/"); break; case 96: strcat(sMsg, "/%DCN096%/"); break; case 124: strcat(sMsg, "/%DCN124%/"); break; case 126: strcat(sMsg, "/%DCN126%/"); break; default: strncat(sMsg, (char *)&v, 1); break; } } На старте задается lport как локальный порт хаба, в подключении к хаблисту. У хаблиста порт, естественно, 2501. У нас же, тот что назначит система, а значит случайный. sBuffer - содержит исходный $Lock код. sMsg - по завершении будет содержать нужный $Key код. Теперь собственно код на PHP: Код function lock2key($_LOCK, $port) { $lockLength = strlen($_LOCK); $LockToKey = ''; for ($j = 0; $j < strlen($_LOCK); $j++) { if($j == 0) { $h = ord($_LOCK{0}) ^ 0 ^ ord( $_LOCK{ $lockLength - 1} ) ^ ($port % 256 + ($port>>8) % 256); } else { $h = ord($_LOCK{$j}) ^ ord($_LOCK{$j-1}); } $h = $h % 256; $a = (($h<<4) & 240) | (($h>>4) & 15); if($a == '126' or $a == '124' or $a == '96' or $a == '36' or $a == '5' or $a == '0') { $LockToKey .= "/%DCN"; if ($a < 100) $LockToKey .= "0"; if ($a < 10) $LockToKey .= "0"; $LockToKey .= $a; $LockToKey .= "%/"; } else { $LockToKey .= chr($a); } } return $LockToKey; } Из заметных отличий от стандартного следующие: Код $h = ord($_LOCK{0}) ^ 0 ^ ord( $_LOCK{ $lockLength - 1} ) ^ ($port % 256 + ($port>>8) % 256); Используется связка первого символа с нулем (вместо последнего символа), а затем с последним символом (вместо предпоследнего). Также, вместо константы 5, используется магический байт вычисляемый как сумма верхнего и нижнего байта шестнадцетиричного представления номера порта. Все остальные "отличия" - экономия "на спичках" + изменения форматирования, не меняющие алгоритма работы. Функция принимает два параметра, строку $Lock и номер порта. Было бы неплохо этот код обосновать в соответствующей теме, описания протокола. |
Nickolya, Setuper, Saymon21 | ||
20.4.2010, 17:34 |
Хаблисты |
Полный код я давать не буду. Дам часть, только боюсь что он вырван из контекста и многое не будет понятно. К слову программу я определяю именно через $BotInfo, а шару через получение списка. Код case '$HubINFO': $hubinfo = explode(' ', $linie[$i], 2); $tmp = explode('$', $hubinfo[1]); $hub['online'] = 2; $hub['name'] = $tmp[0]; $hub['address'] = $tmp[1]; $hub['description'] = $tmp[2]; $hub['maxusers'] = $tmp[3]; $hub['minshare'] = $tmp[4]; $hub['minslots'] = $tmp[5]; $hub['maxhubs'] = $tmp[6]; $hub['type'] = $tmp[7]; $hub['admin'] = $tmp[8]; Код case '$MyINFO': $hub['MyINFO'] = true; if ($user[2] != $hub['me']->nick) { $tmp = explode('$', $linie[$i]); if(!isset($hub['users'][$user[2]])) $hub['share'] += $tmp[count($tmp) - 2]; $hub['users'][$user[2]] = ''; } break; |
Accelerator | ||
4.11.2009, 15:18 |
Хаблисты |
Код <?php function lock2key($_LOCK) { $lockLength = strlen ($_LOCK); $h = ord($_LOCK{0}) ^ ord( $_LOCK{ $lockLength - 1} ) ^ ord( $_LOCK{ $lockLength - 2} ) ^ 5; while ($h > 255) {$h = $h - 256;} $h = (($h<<4) & 240) | (($h>>4) & 15); $a = $h; if ($a == '126' || // '~' $a == '124' || // '|' $a == '96' || // '`' $a == '36' || // '$' $a == '5' || // '^E' $a == '0') // NUL { $LockToKey = "/%DCN"; if ($a < 100) $LockToKey .="0"; if ($a < 10) $LockToKey .="0"; $LockToKey .= $a; $LockToKey .= "%/"; } else { $LockToKey = chr ($a); } for ($j = 1; $j < strlen($_LOCK); $j++) { $h = ord($_LOCK{$j}) ^ ord($_LOCK{$j-1}); while ($h > 255) {$h = $h - 256;} $h = (($h<<4) & 240) | (($h>>4) & 15); $a = $h; if ($a == '126' || // '~' $a == '124' || // '|' $a == '96' || // '`' $a == '36' || // '$' $a == '5' || // '^E' $a == '0') // NUL { $LockToKey .= "/%DCN"; if ($a < 100) $LockToKey .="0"; if ($a < 10) $LockToKey .="0"; $LockToKey .= $a; $LockToKey .= "%/"; } else { $LockToKey .= chr ($a); } } return $LockToKey; } function process($sock, $str) { // echo "A: ".$str.'|'.PHP_EOL; socket_send($sock, $str.'|', strlen($str) + 1, NULL); } function checkHub($address, $port) { $nick = substr(md5(mt_rand(0, 100000)), 0, 10); $description = substr(md5(mt_rand(0, 100000)), 0, 10); $email = substr(md5(mt_rand(0, 100000)), 0, 10); $sharesize = mt_rand(10*1024, 20*1024)*mt_rand(1024*1024,2*1024*1024); $status = new stdClass(); if ($fp=@fsockopen(htmlentities($address, ENT_QUOTES),$port,$ERROR_NO,$ERROR_STR,5)) { fclose($fp); $status->online = true; $status->users = 0; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (!socket_connect($socket, gethostbyname($address), $port)) { echo 'Ошибка: '.socket_strerror(socket_last_error()); return; } $end = ''; while ($buffer = socket_read($socket, 2048, PHP_BINARY_READ)) { $linie = explode('|', $end.$buffer); $size = sizeof($linie); for ($i = 0; $i < $size; ++$i) { if ($i + 1 == $size) { $end = $linie[$i]; break; } $user = explode(' ', $linie[$i]); // echo "Q: ".$linie[$i].PHP_EOL; switch($user[0]) { case '$Hello': // echo "Q: ".$linie[$i].PHP_EOL; if ($user[1] == $nick) { process($socket, '$Version 1,0091'); process($socket, '$GetNickList'); process($socket, '$MyINFO $ALL '.$nick.' '.$description.'<++ V:0.674,M:A,H:1/0/1,S:20>$ $LAN(T3).$'.$email.'$'.$sharesize.'$'); } break; case '$HubTopic': // echo "Q: ".$linie[$i].PHP_EOL; $tmp = explode(' ', $linie[$i], 2); $status->topic = $tmp[1]; break; case '$HubName': // echo "Q: ".$linie[$i].PHP_EOL; $hubinfo = explode(' ', $linie[$i], 2); $tmp = explode(' - ', $hubinfo[1], 2); $status->name = $tmp[0]; $status->topic = (count($tmp) > 1) ? $tmp[1] : ''; break; case '$Lock': // echo "Q: ".$linie[$i].PHP_EOL; // process($socket, '$Supports NoGetINFO NoHello UserIP2 '); process($socket, '$Key '.lock2key($user[1])); process($socket, '$ValidateNick '.$nick); break; case '$NickList': // echo "Q: ".$linie[$i].PHP_EOL; $tmp = explode(' ', $linie[$i], 2); $nicks = explode('$$', $tmp[1]); $status->users = count($nicks); break 3; break; case '$MyINFO': // echo "Q: ".$linie[$i].PHP_EOL; if ($user[2] != $nick) { $status->users++; } else { break 3; } break; default: // echo "Q: ".$linie[$i].PHP_EOL; break; } } } socket_close($socket); } else { $status->online = false; } return $status; } Простейший пингер на php. По сути полноценный ДС клиент, обрезаный не хило. Интересует специфиакация общения хабпингер - хаб. Ибо после $BotINFO мне рвут соединение без какого-либо ответа. |
Accelerator | ||
|
Сейчас: 23.11.2024, 1:09 |