Nessa postagem eu vou estar falando um pouco sobre Injeção de shellcode em processos (conhecido como Code Injection). Esta técnica é muito utilizada por malware com o objetivo de obter persistência em uma determinada vítima. Code Injection também pode ser utilizado para 'migrar' de um processo para outro (Ex: migrate do meterpreter).
Metodologia
A técnica de Code Injection pode ser dividida nas seguintes etapas:
- Abrir um processo (no qual o seu shellcode será injetado).
- Alocar espaço em memória para o shellcode (Este espaço deve ter permissões de leitura e escrita)
- Escrever o shellcode em um espaço de memória do processo escolhido.
- Criar uma nova thread no processo escolhido (a nova thread vai executar o shellcode).
Para realizar todas essas etapas, vamos precisar utilizar 4 funções específicas da biblioteca Kernel32:
- OpenProcess
- VirtualAllocEx
- WriteProcessMemory
- CreateRemoteThread
Vamos dar uma olhada em cada uma dessas funções!
Função OpenProcess
Primeiro vamos selecionar e abrir um processo de nossa escolha. Para realizar esta tarefa vamos utilizar a função OpenProcess. A figura abaixo apresenta uma descrição da função e seus parâmetros de entrada.
 |
Figura1: http://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx |
Para utilizar esta função vamos precisar de 3 parâmetros:
- dwDesiredAccess: Permissões de acesso ao processo.
- bInheritHandle: Vamos setar o valor como zero.
- dwProcessId: O identificador do processo (conhecido como PID).
A função OpenProcess vai retornar um handler do processo escolhido (o qual será utilizado como parâmetro de entrada nas próximas funções). Em Python podemos fazer dessa forma:
 |
Figura 2: Abrindo o processo |
Função VirtualAllocEx
O segundo passo envolve utilizar a função VirtualAllocEx para alocar espaço na memória do processo escolhido para armazenar o nosso shellcode. A Função VirtualAllocEx e seus parâmetros de entrada são apresentados na figura abaixo:
| |
Figura 3: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366890%28v=vs.85%29.aspx |
Para utilizar esta função vamos precisar de 5 parâmetros:
- hProcess: Handler do processo (obtido através da função OpenProcess).
- lpAddress: Vamos setar o valor como zero.
- dwSize: Total de bytes que serão escritos (Tamanho do shellcode).
- flAllocationType: Tipo de permissão para alocação de memória.
- flProtect: Tipo de permissão para aloção de páginas de memória.
A função
VirtualAllocEx vai retornar o endereço de memória no qual o nosso
shellcode vai ser armazenado. Em Python podemos fazer desta forma:
 |
Figura 4: Alocando memória para o shellcode |
Função WriteProcessMemory
A função WriteProcessMemory vai ser utilizada para escrever o nosso shellcode dentro do espaço de memória obtido através da função VirtualAllocEx (passo anterior). A figura abaixo descreve a função WriteProcessMemory e apresenta os seus parâmetros de entrada.
 |
Figura 5: http://msdn.microsoft.com/en-us/library/windows/desktop/ms681674%28v=vs.85%29.aspx |
A função WriteProcessMemory recebe 5 parâmetros de entrada:
- hProcess: O handler do processo (obtido no passo 1).
- lpBaseAddress: Endereço de memória aonde vai ser escrito o shellcode (obtido pela função VirtualAllocEx).
- lpBuffer: Shellcode.
- nSize: Tamanho do shellcode.
- lpNumberOfBytesWritten: Total de bytes escritos pela função.
Em Python podemos fazer desta forma:
 |
Figura 6: Escrevendo o shellcode no processo |
Função CreateRemoteThread
Agora so falta utilizar a função CreateRemoteThread para iniciar uma nova thread no processo escolhido. Esta nova thread vai rodar o shellcode que foi inserido no espaço de memória do processo através da função WriteProcessMemory. A figura abaixo apresenta uma descrição da função e seus parâmetros de entrada.
 |
Figura 7: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682437%28v=vs.85%29.aspx | |
A função CreateRemoteThread recebe 7 parâmetros de entrada:
- hProcess: handler do processo (obtido no passo 1).
- lpThreadAttributes: vamos setar o valor como nulo.
- dwStackSize: vamos setar o valor como zero.
- lpStartAddress: endereço do shellcode (obtido através da função VirtualAllocEx).
- lpParameter: vamos setar o valor como nulo.
- dwCreationFlags: vamos setar o valor como zero.
- lpThreadId: Id da nova thread criada.
Em Python pode ser feito desta forma:
 |
Figura 8: Criando uma nova thread |
Combinando todos os passos
O ultimo passo de todo o processo é combinar todas as 4 partes em um único
script. Para demonstrar a técnica de
Code Injection, eu gravei um pequeno vídeo para servir como
PoC (
Proof of Concept) e apresentar o funcionamento do script.
O script pode ser encontrado para download em:
https://github.com/pasknel/hacking-com-tapioca/blob/master/CodeInjection/injector.py
Conclusão
Nesta postagem foi apresentada uma técnica básica de injeção de shellcode em processos. Esta técnica funciona em Windows XP e Windows 2003 Server. Para uma futura postagem eu pretendo colocar também a alternativa para realizar esta técnica em Windows 7 e outros. Por favor escrevam suas sugestões e comentários!
Obrigado :)
Keep Hacking!