Skip to content

Client API Reference

SightHouseAnalysis

SightHouseAnalysis(url: str, username: str, password: str, logger: LoggingSighthouse, verify_host: bool = True, force_submission: bool = False, options: AnalysisOptions = None)

Parameters:

  • url

    (str) –

    URL of Sighthouse server

  • username

    (str) –

    username to connect to server

  • password

    (str) –

    password to connect to server

  • logger

    (LoggingSighthouse) –

    A Sighthouse Logging linked to SRE

  • verify_host

    (bool, default: True ) –

    Option to enable or disable certificate verification

  • force_submission

    (bool, default: False ) –

    Delete cached information on the server side if any before starting a new analysis

  • options

    (AnalysisOptions | None, default: None ) –

    Options for the analysis

Methods:

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
def __init__(
    self,
    url: str,
    username: str,
    password: str,
    logger: LoggingSighthouse,
    verify_host: bool = True,
    force_submission: bool = False,
    options: AnalysisOptions = None,
) -> None:
    """Initialize SightHouseAnalysis

    Args:
        url (str): URL of Sighthouse server
        username (str): username to connect to server
        password (str): password to connect to server
        logger (LoggingSighthouse): A Sighthouse Logging linked to SRE
        verify_host (bool): Option to enable or disable certificate verification
        force_submission (bool): Delete cached information on the server side if any
                                 before starting a new analysis
        options (AnalysisOptions | None): Options for the analysis
    """
    self._username = username
    self._password = password
    self._logger = logger
    self._client = SightHouseClient(url, self._logger, verify_host=verify_host)
    self._force_submission = force_submission
    self._processor = self.get_current_arch()
    if self._processor is None:
        self._logger.error("architecture not found or not supported yet")
        return None

    self._options = options or AnalysisOptions()

add_tag

add_tag(address: int, tag: str, message: str) -> None

Add a tag on the SRE

Parameters:

  • address

    (int) –

    address where put the tag

  • tag

    (str) –

    tag of message

  • message

    (str) –

    message to show

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
727
728
729
730
731
732
733
734
735
def add_tag(self, address: int, tag: str, message: str) -> None:
    """Add a tag on the SRE

    Args:
        address (int): address where put the tag
        tag (str): tag of message
        message (str): message to show
    """
    raise NotImplementedError("add_tag")

get_current_arch

get_current_arch() -> None

get current architecture and translate to ghidra one

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
707
708
709
def get_current_arch(self) -> None:
    """get current architecture and translate to ghidra one"""
    raise NotImplementedError("get_current_arch")

get_current_binary

get_current_binary() -> bytes

Retrieve the current binaries in bytes

Returns:

  • bytes ( bytes ) –

    the content in bytes of the current binaries

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
719
720
721
722
723
724
725
def get_current_binary(self) -> bytes:
    """Retrieve the current binaries in bytes

    Returns:
        bytes: the content in bytes of the current binaries
    """
    raise NotImplementedError("get_current_binary")

get_functions

get_functions(section: Section) -> List[Function]

get functions

Parameters:

Returns:

  • List[Function]

    List[Function]: list of function inside the section

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
753
754
755
756
757
758
759
760
761
762
def get_functions(self, section: Section) -> List[Function]:
    """get functions

    Args:
        section (Section): section

    Returns:
        List[Function]: list of function inside the section
    """
    raise NotImplementedError("get_functions")

get_hash_program

get_hash_program() -> str

get hash of program

Returns:

  • str ( str ) –

    sha256 string

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
764
765
766
767
768
769
770
def get_hash_program(self) -> str:
    """get hash of program

    Returns:
        str: sha256 string
    """
    raise NotImplementedError("get_hash_program")

get_program_name

get_program_name() -> str

Get program name

Returns:

  • str ( str ) –

    the program name

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
737
738
739
740
741
742
743
def get_program_name(self) -> str:
    """Get program name

    Returns:
        str: the program name
    """
    raise NotImplementedError("get_program_name")

get_sections

get_sections() -> List[Section]

Get sections

Returns:

  • List[Section]

    List[Section]: list sections

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
745
746
747
748
749
750
751
def get_sections(self) -> List[Section]:
    """Get sections

    Returns:
        List[Section]: list sections
    """
    raise NotImplementedError("get_sections")

run

run() -> bool

Run the complete analysis

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
def run(self) -> bool:
    """Run the complete analysis"""
    try:
        self.update_progress("Logging in to the signature server...")
        if not self._client.login(self._username, self._password):
            return False

        binary = self.get_current_binary()
        if binary == b"":
            return False

        self.update_progress("Uploading current binary...")
        # potentially check if file already upload
        program_name = self.get_program_name()
        if not self._client.upload(program_name, binary):
            return False

        self.update_progress("Importing current binary...")
        # Check for previous program
        program_id = self._client.get_program(program_name)
        do_import = True
        if program_id is None:
            # No program found, create a new one
            if not self._client.create_program(program_name, self._processor):
                return False

        elif self._force_submission:
            self._client.delete_program(program_id)
            self._client.create_program(program_name, self._processor)
        else:
            # Program exists and force_submission is false -> use cache
            do_import = False

        if do_import:
            self.update_progress("Importing sections binary...")
            if not self._client.delete_sections():
                return False

            sections = self.get_sections()
            for section in sections:
                if not self._client.create_section(section):
                    return

                if section.perms[-1] == "X":
                    functions = self.get_functions(section)
                    if not self._client.add_functions(functions, section):
                        return False

            self.update_progress("Analyzing the binary file...")
            if not self._client.start_analysis(options=self._options):
                return False

            self.update_progress("Analysis started.")

            # Poll periodically
            while self._client.is_analyzing():
                self.wait()

        self.update_progress("Request for matches...")
        signatures = self._client.get_matches()
        if isinstance(signatures, list):
            self.update_progress(f"Got {len(signatures)} potential signatures!")
            for signature in signatures:
                self.add_tag(
                    signature.address, "SightHouse matches", "\n" + str(signature)
                )

            return True
    except Exception as e:
        self._logger.error(str(e))
        raise e

    return False

update_progress

update_progress(message: str) -> None

show an update progress

Parameters:

  • message

    (str) –

    message to show

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
711
712
713
714
715
716
717
def update_progress(self, message: str) -> None:
    """show an update progress

    Args:
        message (str): message to show
    """
    raise NotImplementedError("update_progress")

wait

wait(seconds: int = 10) -> None

Some analyzers will need to handle sleeping differently. The default implementation rely on time.sleep.

Parameters:

  • seconds

    (int, default: 10 ) –

    The number of seconds to wait for

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
772
773
774
775
776
777
778
779
def wait(self, seconds: int = 10) -> None:
    """Some analyzers will need to handle sleeping differently.
       The default implementation rely on time.sleep.

    Args:
        seconds (int): The number of seconds to wait for
    """
    time.sleep(seconds)

Section

Section(name: str, start: int, end: int, fileoffset: int, perms: str, kind: str, id: int = -1)

Bases: object

Manipulate Section object

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
def __init__(
    self,
    name: str,
    start: int,
    end: int,
    fileoffset: int,
    perms: str,
    kind: str,
    id: int = -1,
):
    self.name: str = name
    self.start: int = start
    self.end: int = end
    self.perms: str = perms
    self.kind: str = kind
    self.fileoffset = fileoffset
    self.id: int = id

Function

Function(name: str, offset: int, details: dict = None)

Bases: object

Manipulate Function object

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
82
83
84
85
86
87
def __init__(self, name: str, offset: int, details: dict = None):
    self.name: str = name
    self.offset: int = offset
    self.id: int = -1
    # Details are architecture/SRE dependent information
    self.details: dict = details or {}

Match

Match(executable: str, function: str, score: float, nb_match: int)

Bases: object

Show match

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
35
36
37
38
39
40
41
42
43
44
45
def __init__(self, executable: str, function: str, score: float, nb_match: int):
    self.executable = json.loads(executable)
    self.metadatas = self.executable.get("metadata", None)
    if self.metadatas is None:
        self.metadatas = [
            (self.executable.get("name"), self.executable.get("version"))
        ]
    self.origin = self.executable["origin"]
    self.function = function
    self.score = score
    self.nb_match = nb_match

Signature

Signature(function: str, address: int, matches: list[Match])

Bases: object

show signature

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
93
94
95
96
def __init__(self, function: str, address: int, matches: list[Match]):
    self.function = function
    self.address = address
    self.matches = matches

LoggingSighthouse

LoggingSighthouse()

Bases: object

Initialize logging class

Methods:

  • error

    Show an error message

  • info

    Show an info message

  • warning

    Show an warning message

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
642
643
644
def __init__(self) -> None:
    """Initialize logging class"""
    raise NotImplementedError("LoggingSighthouse")

error

error(message: str)

Show an error message

Parameters:

  • message

    (str) –

    The message to show

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
646
647
648
649
650
651
652
def error(self, message: str):
    """Show an error message

    Args:
        message (str): The message to show
    """
    raise NotImplementedError("error")

info

info(message: str)

Show an info message

Parameters:

  • message

    (str) –

    The message to show

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
662
663
664
665
666
667
668
def info(self, message: str):
    """Show an info message

    Args:
        message (str): The message to show
    """
    raise NotImplementedError("info")

warning

warning(message: str)

Show an warning message

Parameters:

  • message

    (str) –

    The message to show

Source code in venv/lib/python3.12/site-packages/sighthouse/client/SightHouseClient.py
654
655
656
657
658
659
660
def warning(self, message: str):
    """Show an warning message

    Args:
        message (str): The message to show
    """
    raise NotImplementedError("warning")