Ghidra é ótimo, e eu gosto de roteirizar o máximo possível do meu RE. Mas o Script Python de Ghidra é baseado em Jython, que não está em um grande estado hoje em dia. A instalação de novos pacotes é um aborrecimento, se eles podem até correr em um ambiente de Jython, e isso só vai piorar à medida que o Python 2 é desligado lentamente.
Portanto, a Ghidra Bridge é um esforço para evitar esse problema-em vez de ficar preso em Jython, configure um proxy de RPC para objetos Python, para que possamos chamar a Ghidra/Jython-Land para obter os dados de que precisamos e, em seguida, trazê-lo de volta a um python mais atualizado com todos os pacotes que você precisa fazer o seu trabalho.
O objetivo é ser o mais transparente possível; portanto, quando você estiver configurado, você não precisa saber se um objeto é local ou do ghidra remoto - a ponte deve lidar perfeitamente com a obtenção/configuração/chamada contra ele.
Se você gosta disso, também pode estar interessado nos equivalentes para outras ferramentas de engenharia reversa:
Se você realmente gosta disso, fique à vontade para me comprar um café: https://ko-fi.com/justfoxing
pip install ghidra_bridge
python -m ghidra_bridge.install_server ~/ghidra_scripts
Para um shell interativo melhor, como o IPython ou se você precisar de bibliotecas Python 3 em seu ambiente interativo, poderá iniciar a ponte no contexto de uma sessão interativa da GUI.
De outra forma:
Você pode executar a Ghidra Bridge como um script de pós -análise para uma análise sem cabeça e, em seguida, executar algumas análises adicionais do cliente. Use o ghidra_bridge_server.py (não _background.py) para este, para que ele não saia até você fechar a ponte.
$ghidraRoot/support/analyzeHeadless <path to directory to store project> <name for project> -import <path to file to import> -scriptPath <install directory for the server scripts> -postscript ghidra_bridge_server.py
Consulte o AnalyZehefetelleadReadme.html no diretório/ diretório da Ghidra para obter mais informações sobre como executar o comando Analyzeheheadlehead, se necessário.
Você pode iniciar a ponte em um ambiente sem nenhum programa carregado, por exemplo, se você deseja acessar algumas APIs como o DatatyManager que não exige um programa que seja analisado
$ghidraRoot/support/pythonRun <install directory for the server scripts>/ghidra_bridge_server.py
Do ambiente Python Client:
import ghidra_bridge
with ghidra_bridge . GhidraBridge ( namespace = globals ()):
print ( getState (). getCurrentAddress (). getOffset ())
ghidra . program . model . data . DataUtilities . isUndefinedData ( currentProgram , currentAddress )ou
import ghidra_bridge
b = ghidra_bridge . GhidraBridge ( namespace = globals ()) # creates the bridge and loads the flat API into the global namespace
print ( getState (). getCurrentAddress (). getOffset ())
# ghidra module implicitly loaded at the same time as the flat API
ghidra . program . model . data . DataUtilities . isUndefinedData ( currentProgram , currentAddress )Aviso: se você estiver executando no modo não background, evite clicar no botão "Cancelar" no pop-up do script, pois isso deixará o soquete do servidor em um estado ruim e você terá que fechar completamente o Ghidra para corrigi-lo.
Para desligar o servidor de maneira limpa, se você fez a Etapa 3 nas instruções de instalação acima, clique em Ferramentas-> Ghidra Bridge-> Desligamento. Caso contrário, execute o script ghidra_bridge_server_shutdown.py na pasta da ponte.
Como alternativa, você pode ligar para o REMOTE_SHUTDOWN de qualquer cliente conectado.
import ghidra_bridge
b = ghidra_bridge . GhidraBridge ( namespace = globals ())
b . remote_shutdown ()Esteja ciente de que, ao executar, um servidor Ghidra Bridge fornece efetivamente a execução de código como um serviço. Se um invasor puder conversar com a ponte Port Ghidra, ele poderá obter trivialmente a execução com os privilégios que Ghidra é executada.
Esteja ciente de que o protocolo usado para enviar e receber mensagens de Ghidra Bridge não é criptografado e não verificado-um ataque de pessoa no meio permitiria o controle completo dos comandos e respostas, fornecendo novamente a execução de código trivial no servidor (e com um pouco mais de trabalho, no cliente).
Por padrão, o servidor Ghidra Bridge apenas ouve o host localhost para reduzir levemente a superfície de ataque. Somente ouça em endereços de rede externos se você está confiante de que está em uma rede onde é seguro fazê -lo. Além disso, ainda é possível que os invasores enviem mensagens para localhost (por exemplo, via javascript malicioso no navegador ou explorando um processo diferente e atacando a ponte Ghidra para elevar privilégios). Você pode mitigar esse risco executando a ponte ghidra de um servidor Ghidra com permissões reduzidas (um usuário não administrado ou dentro de um contêiner), executando-o apenas quando necessário ou executando em sistemas conectados sem rede.
A Ponte Ghidra foi projetada para ser transparente, para permitir a fácil porte de scripts sem pontes sem muitas alterações. However, if you're happy to make changes, and you run into slowdowns caused by running lots of remote queries (eg, something like for function in currentProgram.getFunctionManager().getFunctions(): doSomething() can be quite slow with a large number of functions as each function will result in a message across the bridge), you can make use of the remote_eval() function to ask for the result to be evaluated on the bridge server all at once, which exigirá apenas uma única mensagem de ida e volta.
O exemplo a seguir demonstra obter uma lista de todos os nomes de todas as funções em um binário:
import ghidra_bridge
b = ghidra_bridge . GhidraBridge ( namespace = globals ())
name_list = b . remote_eval ( "[ f.getName() for f in currentProgram.getFunctionManager().getFunctions(True)]" )Se sua avaliação levar algum tempo, talvez seja necessário usar o argumento timeout_override para aumentar quanto tempo a ponte esperará antes de decidir que as coisas dão errado.
Se você precisar fornecer um argumento para a avaliação remota, poderá fornecer argumentos de palavras -chave arbitrárias à função REMOTE_EVAL, que será transmitida para o contexto de avaliação como variáveis locais. O argumento a seguir passa em uma função:
import ghidra_bridge
b = ghidra_bridge . GhidraBridge ( namespace = globals ())
func = currentProgram . getFunctionManager (). getFunctions ( True ). next ()
mnemonics = b . remote_eval ( "[ i.getMnemonicString() for i in currentProgram.getListing().getInstructions(f.getBody(), True)]" , f = func )Como simplificação, observe também que o contexto de avaliação tem os mesmos globais carregados no __main__ do script que iniciou o servidor - no caso do servidor Ghidra Bridge, inclui a API plana e os valores como o programa Current.
Se você tiver uma chamada particularmente lenta no seu script, ele pode atingir o tempo limite de resposta que a ponte usa para garantir que a conexão não tenha quebrado. Se isso acontecer, você verá algo como Exception: Didn't receive response <UUID> before timeout .
Existem duas opções para aumentar o tempo limite. Ao criar a ponte, você pode definir um valor de tempo limite em segundos com o argumento Response_timeout (por exemplo, b = ghidra_bridge.GhidraBridge(namespace=globals(), response_timeout=20) ), que se aplicarão a todos os comandos atravessados pela ponte. Como alternativa, se você deseja alterar o tempo limite para um comando, poderá usar o REMOTE_EVAL como mencionado acima, com o argumento timeout_override (por exemplo, b.remote_eval("[ f.getName() for f in currentProgram.getFunctionManager().getFunctions(True)]", timeout_override=20) Se você usar o valor -1 para qualquer um desses argumentos, o tempo limite da resposta será desativado e a ponte aguardará para sempre que sua resposta volte - observe que isso pode fazer com que seu script pendure se a ponte entrar em problemas.
Se você deseja importar módulos do lado de Ghidra (por exemplo, Ghidra, Java, Docking Namespaces), você tem duas opções.
remote_module = b.remote_import("java.math.BigInteger") ). Isso tem a vantagem de que você tem controle exato sobre obter o módulo remoto (e pode obter módulos remotos com o mesmo nome dos módulos locais) e quando é lançado, mas é preciso um pouco mais de trabalho.b = ghidra_bridge.GhidraBridge(namespace=globals(), hook_import=True) ). Isso adicionará um gancho à máquina de importação de modo que, se nada mais puder preencher a importação, a ponte tentará lidar com isso. Isso permite que você use apenas a sintaxe import ghidra.framework.model.ToolListener depois de conectar a ponte. Isso tem a vantagem de que pode ser um pouco mais fácil de usar (você ainda precisa garantir que as importações aconteçam depois que a ponte estiver conectada), mas não permite que você importe módulos remotos com o mesmo nome que os módulos locais (as importações locais têm precedência) e coloca os módulos remotos até os sistemas de sistema. Além disso, várias pontes com hook_import = true tentarão resolver as importações na ordem em que estavam conectadas, o que pode não ser o comportamento que você deseja.Normalmente, os scripts Ghidra recebem uma instância do estado de Ghidra e das variáveis atuais* (CurrentProgram, CurrentAddress, etc.) quando iniciadas pela primeira vez, e não se atualiza enquanto o script é executado. No entanto, se você executar o intérprete de Ghidra Python, isso atualiza seu estado com todos os comando, para que o CurrentDredress sempre corresponda à GUI.
Para refletir isso, o Ghidrabridge tentará automaticamente determinar se você está executando o cliente em um ambiente interativo (por exemplo, o intérprete Python, ipython) ou apenas a partir de um script. Se for um ambiente interativo, ele registrará um ouvinte de eventos com Ghidra e realizará algumas travessuras duvidosas nos bastidores para garantir que o estado seja atualizado com alterações na GUI para se comportar como o entreteador de Ghidra Python. Ele também substituirá help() por um que estende a mão para usar a ajuda de Ghidra do outro lado da ponte, se você lhe der um objeto em ponte.
Você não deve se preocupar com isso, mas se, por algum motivo, a detecção automática não fornecer o resultado que você precisa, você poderá especificar o argumento booleano interactive_mode ao criar o seu cliente Ghidrabridge para forçá-lo a entrar ou desligar, conforme necessário.
O código RPC da ponte real é implementado em JFX-Bridge. Verifique por aí e arquive questões específicas não-Ghidra relacionadas à ponte lá.