segunda-feira, 9 de dezembro de 2013

Injeção de Shellcode em Processos (Parte 1)

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:
  1. Abrir um processo (no qual o seu shellcode será injetado).
  2. Alocar espaço em memória para o shellcode (Este espaço deve ter permissões de leitura e escrita) 
  3. Escrever o shellcode em um espaço de memória do processo escolhido.
  4. 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:
  1. OpenProcess
  2. VirtualAllocEx
  3. WriteProcessMemory
  4. 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:
  1. hProcess: Handler do processo (obtido através da função OpenProcess).
  2. lpAddress: Vamos setar o valor como zero.
  3. dwSize: Total de bytes que serão escritos (Tamanho do shellcode).
  4. flAllocationType: Tipo de permissão para alocação de memória.
  5. 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:
  1. hProcess: O handler do processo (obtido no passo 1).
  2. lpBaseAddress: Endereço de memória aonde vai ser escrito o shellcode (obtido pela função VirtualAllocEx).
  3. lpBuffer: Shellcode.
  4. nSize: Tamanho do shellcode.
  5. 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:
  1. hProcess: handler do processo (obtido no passo 1).
  2. lpThreadAttributes: vamos setar o valor como nulo.
  3. dwStackSize: vamos setar o valor como zero.
  4. lpStartAddress: endereço do shellcode (obtido através da função VirtualAllocEx).
  5. lpParameter: vamos setar o valor como nulo.
  6. dwCreationFlags: vamos setar o valor como zero.
  7. 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!

 

3 comentários: