# frozen_string_literal: true require "zoomeye" module Mihari module Analyzers class ZoomEye < Base attr_reader :title, :description, :query, :tags, :type def initialize(query, title: nil, description: nil, tags: [], type: "host") super() @query = query @title = title || "ZoomEye lookup" @description = description || "query = #{query}" @tags = tags @type = type end def artifacts case type when "host" host_lookup when "web" web_lookup else raise InvalidInputError, "#{type} type is not supported." unless valid_type? end end private PAGE_SIZE = 10 def valid_type? %w[host web].include? type end def config_keys %w[zoomeye_password zoomeye_username] end def api @api ||= ::ZoomEye::API.new(username: Mihari.config.zoomeye_username, password: Mihari.config.zoomeye_password) end def convert_responses(responses) responses.map do |res| matches = res["matches"] || [] matches.map do |match| match["ip"] end end.flatten.compact.uniq end def _host_lookup(query, page: 1) api.host.search(query, page: page) rescue ::ZoomEye::Error => _e nil end def host_lookup responses = [] (1..Float::INFINITY).each do |page| res = _host_lookup(query, page: page) break unless res total = res["total"].to_i responses << res break if total <= page * PAGE_SIZE end convert_responses responses.compact end def _web_lookup(query, page: 1) api.web.search(query, page: page) rescue ::ZoomEye::Error => _e nil end def web_lookup responses = [] (1..Float::INFINITY).each do |page| res = _web_lookup(query, page: page) break unless res total = res["total"].to_i responses << res break if total <= page * PAGE_SIZE end convert_responses responses.compact end end end end