DLL Injection e Debugging com o Immunity Debugger
Autor: Danilo Kishi | Publicado: 2012-05-03T08:13:00-07:00

Introdução 




DLL,
 Dynamic Link Library, é a forma que o Windows utiliza para compartilhar
 bibliotecas de funções entre múltiplas aplicações. Internamente uma DLL
 é bem semelhante a um EXE, utiliza o formato PE e somente uma simples 
flag diferencia que é uma DLL e não um EXE (essa flag está no 
IMAGE_FILE_HEADER no campo Characteristics do PE Header). Além disso 
DLLs geralmente têm mais Exports que os executáveis.



DLL
 não é um arquivo standalone, se clicarmos duas vezes nela ela não vai 
executar,  necessita de um processo host. Esse processo é o responsável 
por carregar a DLL para seu espaço de memória através da função LoadLibrary. 



Assim
 como os executáveis, as DLLs também possuem seu entry point (é chamado 
de DllMain ou DllEntryPoint), que na teoria é o endereço da primeira 
instrução que será executada pela DLL assim que ela for carregada na 
memória do processo host. Assim que a LoadLibrary carrega uma DLL na 
memória, automaticamente ela executa a DllMain.



Para
 os malwares, as DLLs são ótimos lugares de armazenamento de códigos 
maliciosos, inclusive por sua análise ser um pouco mais complicada que a
 de um executável comum. Imagine uma DLL com um packer, se pretendemos 
retirar a proteção através de debugging temos que carregá-la na memória 
de um processo e colocar um breakpoint bem no entry point da DLL. Como 
fazer isso sabendo que um processo pode ter inúmeras DLLs em seu 
contexto?  



É o que veremos agora através de um passo a passo.



Ambiente de testes



Foi utilizado o Immunity Debugger para injetar uma DLL em um processo e 
colocaremos um Breakpoint no entry point da DLL injetada para realizar o
 debugging desde a primeira instrução como se fosse um executável 
normal.  



Apenas para título de demonstração o autor utilizou arquivos comuns do Windows, o processo host será o IEXPLORE.EXE e a DLL será a p2p.dll, localizada em “C:\windows\system32\”. O software utilizado é o Immunity Debugger que pode ser baixado aqui, e também é necessária a instalação do Python 2.7 que pode ser obtido aqui.



Injeção de DLL em um processo



Segue o passo a passo do procedimento:



1- Execute normalmente o programa que servirá como processo host da DLL, nesse caso foi utilizado o Internet Explorer.



2- Abra o Immunity Debugger e clique em File – Attach
 para selecionar o processo no qual o ImmDbg irá anexar para debugar. 
Será exibida uma janela com todos os processos em execução. Selecione o 
IEXPLORE e clique em Attach.







3-
 O ImmDbg irá abrir o processo IEXPLORE.exe em seu ambiente e irá pausar
 a execução. Queremos injetar uma DLL no processo e parar a execução 
exatamente no Entry Point da DLL.  



Aqui
 temos um problema, a função que faz a injeção da DLL é a LoadLibrary() e
 sabemos que quando ela carregar a DLL na memória do processo ela 
automaticamente executará o entry point da DLL não dando tempo de 
colocar um breakpoint aí.  



Para lidar com isso o ImmDbg possui uma opção, clique em Options – Debugging options e selecione a aba Events. Marque a opção “Break on new module (DLL)”
 e clique em OK. Assim o debugger irá parar a execução bem após ter 
carregado a DLL na memória e antes de executar o entry point.







4- Estamos prontos para injetar a DLL. Clique no segundo botão da barra de tarefas do ImmDbg para a abrir a Python Shell.







5-
 A shell que se abriu nos permite executar comando Python e ter acesso a
 API Python do debugger. Para obter a documentação da API há o menu ImmLib – Help no próprio ImmDbg ou ainda na pasta de instalação do programa: Immunity Debugger\Documentation\Ref\toc.html.



6-
 No momento que injetamos a DLL no processo é criada uma nova Thread 
para essa DLL, então vamos injetar nossa DLL e recuperar e exibir o 
número da Thread. Para isso digite os seguintes comandos na shell:



&gt;&gt;&gt;thread = imm.injectDll("c:\\p2p.dll")

&gt;&gt;&gt;

&gt;&gt;&gt;print "Thread ID: 0x%X" % thread

Thread ID: 0x134



Injetamos a DLL e já recuperamos o número da nova Thread em um variável, depois exibimos esse número no formato hexadecimal.



7-
 A DLL foi injetada na memória do processo mas o módulo ainda não foi 
carregado pela LoadLibrary(). Precisamos executar o programa para que 
nosso módulo seja chamado. Pode ser que ele não seja o próximo módulo a 
ser carregado, talvez precisemos executar o programa (F9) mais de uma 
vez.



Quando pressionarmos F9 para a execução, teremos que ficar de olho na janela de módulos carregados (Window – 3 Executable modules)
 para descobrir se o nosso está lá. Às vezes o ImmDbg nos apresenta essa
 janela assim que o módulo é carregado e ele estará destacado em 
vermelho.



8- Pressione F9
 e observe os resultados, caso não tenha carregado a DLL pressione 
novamente F9 até atingi-la. No momento que carregar o nosso módulo 
injetado será exibida na janela de módulos essa linha em vermelho:







9-
 Nosso módulo foi carregado e o entry point da DLL ainda não foi 
executado. Agora vamos voltar para a Python Shell para colocar um 
breakpoint no entry point da DLL carregada. Utilize os comandos abaixo.



&gt;&gt;&gt;mod = imm.getModule("p2p.dll")

&gt;&gt;&gt;

&gt;&gt;&gt;print "Module ImageBase: 0x%X" % mod.getBase()

Module ImageBase: 0x4EFB0000

&gt;&gt;&gt;

&gt;&gt;&gt;print "Module EntryPoint:   0x%X" % mod.getEntry()

Module EntryPoint: 0x4EFC22E4

&gt;&gt;&gt;

&gt;&gt;&gt;imm.setBreakpoint(mod.getEntry())

0

&gt;&gt;&gt;



Primeiro
 atribuímos para uma variável o módulo carregado, em seguida apenas por 
questões de estudo imprimimos os endereços do ImageBase e EntryPoint do 
módulo, com as funções getBase() e getEntry() 
respectivamente. Por fim colocamos o breakpoint exatamente no EntryPoint
 do módulo. Se olharmos na janela de breakpoint do ImmDbg ele estará lá.







10- Agora retire aquela opção de parar a execução nos módulos e execute o programa novamente com F9 ou com o comando imm.run() no Python Shell. A execução irá parar em nosso breakpoint e a partir daí é só debugar a DLL normalmente.











Conclusão



Essa
 injeção de DLL com o uso do ImmDebugger não é muito conhecida, é 
difícil encontrar documentação a respeito e até em uma fonte mais 
confiável como um livro não apresenta o procedimento de forma 
precisa, são necessários vários testes até atingir os resultados 
esperados.



Fonte: Crimes Ciberneticos

Postado por:
Ronaldo Lima