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) { $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; } } } // 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; }