
Plugins e scripts do IDA para análise de frame de uso de registradores.

"""
Para que serve este registo?
Hmm.. Vou apenas renomeá-lo para veryuniquename, fazer uma pesquisa textual e encontrar todas as referências!
Ok.. À espera que a pesquisa termine.. daqui a nada.. Feito!
Agora só preciso de perceber qual dos resultados da pesquisa é relevante para o quadro de uso atual do registo.
Não deve ser muito difícil, certo?
"""
Se isto lhe aconteceu (talvez mais de uma vez), está com sorte!
Basta Shift-X, e os seus problemas desaparecerão!
Você também pode renomear o registo no quadro de uso. Basta Shift-N e siga as instruções!
Além disso - em vez de alterar os tipos de todos os usos para um certo tipo, basta Shift-T uma vez.
E por último, mas não menos importante - se quiser definir um offset (como fazer Ctrl-R) para todos os usos deste registo, basta pressionar Shift-R.
Nota: Às vezes já existe outro plugin a usar Shift-T. Remova esse plugin - nunca o usou antes de qualquer maneira :-).
Este plugin usa sark para interagir com os scripts do IDA de uma forma confortável, e cachetools para armazenar em cache o scan do quadro, o que torna isto muito mais rápido.
O Oregami suporta tanto IDA 7.x/8.x como IDA 9.0+.
Se estiver a usar IDA 9, certifique-se de que tem uma versão atualizada do sark que suporte IDA 9.
Nota: O IDA 9 introduziu a sua própria funcionalidade Shift-X. Se precisar de usar o Shift-X integrado do IDA em vez do do oregami, deve alterar o atalho do oregami no ficheiro do plugin.
[Para python3]
pip3 install sark
[Para python2]
Se estiver a usar a variante python2 do IDA, deve em vez disso executar:
pip2 install -U git+https://github.com/tmr232/[email protected]#egg=Sark
Note que o python2 não é ativamente suportado (já que o IDA migrou maioritariamente para python3, e eu também), por isso isto pode não funcionar.
git clone https://github.com/shemesh999/oregami
O código base do sark oferece muitos plugins. Um deles é: https://github.com/tmr232/Sark/blob/master/plugins/plugin_loader.py
Recomendamos copiá-lo para o seu diretório de plugins e depois executar o IDA uma vez com privilégios de administrador (para que ele possa criar os ficheiros plugins.list).
Depois de o fazer, pode adicionar novos plugins adicionando o caminho para eles a um dos ficheiros plugins.list criados (ex. um é criado na pasta cfg do IDA)
Agora, adicione a um dos ficheiros plugins.list:
FULLPATH\oregami\oregami_plugin.py
FULLPATH\oregami\regname_plugin.py
FULLPATH\oregami\typeregter_plugin.py
FULLPATH\oregami\offreg_plugin.py
Reinicie o IDA, e os plugins devem funcionar.
Alternativamente:
Copie todos os ficheiros (incluindo a pasta interna oregami, excluindo setup.py) para o diretório de plugins do IDA.
Além de ser usado como plugins, o oregami também pode ser usado para escrever os seus próprios scripts!
Para isso, deve primeiro instalar usando o ficheiro setup.py incluído. Ou seja, deve chamar:
'python setup.py develop', e a partir daí pode usar as classes e funções internas.
Note que recomendamos usar 'develop' e não 'install', para que se fizer pull de uma nova versão do oregami, funcione imediatamente.
Por exemplo:
-- script.py --
def find_func_usage(func_ea, reg='r0'):
"""
Encontra e imprime todos os usos de um registo, incluindo a informação dos operandos específicos
em que se encontra, e que operação realiza no operando.
"""
import oregami
rf = oregami.RegFrame(func_ea, reg)
for insn in rf.get_instructions():
print('Addr:{:x}'.format(insn.ea))
for opnd in insn.operands:
if opnd.uf_is_external:
continue
print('--opnd_idx:{} - {}'.format(opnd.n, oregami.UsageBits(opnd.op_flags)))
Vamos assumir a seguinte sequência de opcodes:
ROM:01000010 e_lis r10, 0x4004 # 0x40040000 # Load Immediate Shifted
ROM:01000014 e_add16i r10, r10, 0x1337 # 0x40041337 # Add Immediate
ROM:01000020 se_mr r30, r31 # Move Register
ROM:01000022 cmplw r11, r10 # Compare Logical Word
ROM:01000026 se_bge loc_1000036 # Branch if greater than or equal
ROM:01000028
ROM:01000028 loc_1000028: # CODE XREF: sub_0100000+144↓j
ROM:01000028 e_stmw r30, 0(r11) # Store Multiple Word
ROM:0100002C e_add16i r11, r11, 8 # Add Immediate
ROM:01000030 cmplw r11, r10 # Compare Logical Word
ROM:01000034 se_blt loc_1000028 # Branch if less than
ROM:01000036
ROM:01000036 loc_1000036: # CODE XREF: sub_0100000+136↑j
ROM:01000036 e_add16i r10, r10, 8 # Add Immediate
ROM:0100003A e_li r11, 0 # Load Immediate
Se fizermos scan do quadro de uso do registo r10, a partir do endereço 01000022, encontraremos três tipos de usos incluídos no quadro de uso.
Isto incluirá as instruções que inicializam o valor do registo.
Podemos querer incluir apenas a última instrução que alterou o valor do registo (endereço 01000014 no exemplo), ou uma sequência de operações usadas para definir o valor inicial do registo (endereços 01000010 e 01000014 no exemplo).
A sequência de operações usada na inicialização do registo pode ser chamada de "init stage".
Pode escolher suportar um init stage, ou não, dependendo do parâmetro init_stage_bool na inicialização do RegFrame.
Isto incluirá as instruções que usam o valor do registo e não o alteram de forma alguma. Estas correspondem às linhas 01000022 e 01000030 no exemplo.
Isto incluirá as instruções que usam o valor do registo, mas depois alteram o seu valor. Estas instruções podem ser vistas como incluídas em dois quadros de uso distintos - o que leva a elas, e o que se origina delas.
Isto corresponde à linha 01000036.
Ao fazer o scan do registo de uso, chegar a uma operação init ou a uma operação break fará com que paremos o scan numa determinada direção.
Mas, também podemos parar o scan por causa de instruções fora do quadro de uso.
Por exemplo, fazer o scan do quadro de uso do registo r11 a partir do endereço 01000030 irá parar na linha 0100003A.
Esta é a classe básica usada no oregami. Ao inicializá-la num endereço e registo específico, ela fará scan do quadro de uso do registo e criará um UFInstruction para todas as instruções relevantes.
get_instruction - obtém a instrução do endereço dado
get_instructions - um gerador que retorna as instruções no quadro de uso.
Também pode pedir subconjuntos específicos das instruções usadas:
get_init_instructions - obtém apenas instruções do tipo init
get_pure_instructions - obtém apenas instruções do tipo pure
get_break_instructions - obtém apenas instruções do tipo break
get_nobreak_instructions - obtém apenas instruções que não são do tipo break (ie. init + pure)
get_noinit_instructions - obtém apenas instruções que não são do tipo init (ie. pure + break)
get_outbreak_instructions - obtém apenas instruções do tipo out break
Por predefinição, esta classe irá armazenar em cache os resultados do scan e evitará rescannear o mesmo quadro de uso. Isto significa que solicitar o RegFrame de qualquer instrução que fez parte do quadro de uso (especificamente dos tipos init + pure. Não breaks, porque iniciar um scan neles deve retornar o quadro de uso que se origina deles) retornará a mesma instância de RegFrame pré-calculada. Para forçar um rescan, use a flag force ao inicializar a classe.
Esta é a classe retornada pelo RegFrame, representando uma instrução no quadro de uso.
Esta classe herda da classe Instruction do sark e, como tal, suporta os mesmos métodos.
Uma diferença principal é que, em vez de conter um array de operandos da classe Operand do sark, conterá um array da classe UFOperand.
Esta classe também contém métodos para perceber o tipo de instrução (init, pure, break, outbreak) e os bits de operação (read, write, explicit e diferentes tipos de implicit)
Esta é a classe no array de operandos dentro de um UFInstruction específico.
Esta classe herda da classe Instruction do sark e, como tal, suporta os mesmos métodos.
Além das operações do sark, contém métodos para obter os bits de operação (read, write, explicit e diferentes tipos de implicit) e para saber se o operando é realmente parte do quadro de uso (útil para saber qual operando numa instrução do tipo break faz parte do quadro de uso)
Esta é uma classe usada para analisar uma instrução específica, para saber o seu uso em relação a registos.
Fá-lo usando conhecimento do IDA, análise textual e detalhes específicos do processador.
A razão para esta classe é que a análise básica do IDA tende a mentir sobre o conjunto de registos usados e a forma como são usados em muitos opcodes.
Esta classe herda da classe Instruction do sark e, como tal, suporta os mesmos métodos.
Uma diferença principal é que, em vez de conter um array de operandos da classe Operand do sark, conterá um array da classe RegOperand.
Esta é uma classe usada para analisar um operando específico, para saber o seu uso em relação a registos.
Fá-lo usando conhecimento do IDA, análise textual e detalhes específicos do processador.
A razão para esta classe é que a análise básica do IDA tende a mentir sobre o conjunto de registos usados e a forma como são usados em muitos opcodes.
Esta classe herda da classe Operand do sark e, como tal, suporta os mesmos métodos.