Introdução
No último post eu mostrei como transformar a saída do objdump em shellcode utilizando somente comandos do sistema. Após publicar o material, percebi que seria útil envolver todos aqueles comandos em um arquivo e criar um script, e foi isso que fiz.
Problemas
Percebi também que a solução do post anterior contém alguns problemas. O maior deles é que se ocorre um jump relativo, por exemplo, o endereço de salto é casado pelo sed que irá colocar um \x nele. O script postado aqui hoje resolve esse problema fazendo uma leitura somente dos bytes da shellcode, sem casar com o endereço das instruções de salto.
Uma coisa que deixei de falar foi em relação a plataforma. Eu considerei uma máquina x86-32 bits e por isso fiz algumas considerações exclusivas a essa plataforma, como o tamanho máximo das instruções (parâmetro do cut).
Sabendo disso, o script só funcionará para a plataforma x86-32 porque é necessário saber de antemão o tamanho máximo das instruções. Entretanto, se você programa em shell script ou tem uma pequena noção, ficará fácil alterar o script para que ele funcione em uma plataforma específica.
O script
Segue o código:
#!/bin/bash #[obj2s.sh] # Transforma a saída do objdump em shellcode # OBS: Script testado em uma máquina IA-32 # # [Autor] # Marcos Paulo Ferreira (Daemonio) # undefinido gmail com # daemoniolabs.wordpress.com # # [Como usar] # $ objdump -d programa | ./objs # ou # $ objdump -d programa | ./objs -1 # A opção '-1' gera somente a shellcode, # excluindo as instruções em assembly. # # Versão 1.0, by daemonio @ Sun Mar 18 15:07:21 BRT 2012 # Versão 1.1, by daemonio @ Sun Aug 12 14:04:29 BRT 2012 # - Corrigido o erro que ignorava alguns endereços. # O erro estava no primeiro grep da linha 48. # # Se '1', gera shellcode com comentário COMM=1 # Função de conversão function obj2s { if [ "$COMM" = "0" ] then cut -f1-7 -d' ' | tr -d ' ' | sed 's/../\\x&/g;1s/^/"/;$s/$/"/' | paste -s -d '' else sed 's/\([0-9a-f][0-9a-f] \)\{1,7\}/&\n/;' | sed 's/ //g;s/../\\x&/g;N;s,\(.*\)\n *\(.*\),"\1" /* \2 */,' | column -t fi } # # Main # # Testa linha de comando [ "$1" = "-1" ] && COMM=0 # Nome do vetor echo 'char shellcode[] = ' # Shellcode grep '[0-9a-f]:' | grep -v file | cut -f2 -d: | tr -d '\t' | obj2s # Dois pontos do fim da declaração echo ';' #EOF
Uso
Usá-lo é simples, basta passar a saída do objdump para ele:
$ objdump -d shellexecve | ./obj2s.sh char shellcode[] = "\x6a\x0b" /* push $0xb */ "\x58" /* pop %eax */ "\x99" /* cltd */ "\x52" /* push %edx */ "\x68\x2f\x2f\x73\x68" /* push $0x68732f2f */ "\x68\x2f\x62\x69\x6e" /* push $0x6e69622f */ "\x89\xe3" /* mov %esp,%ebx */ "\x31\xc9" /* xor %ecx,%ecx */ "\xcd\x80" /* int $0x80 */ ; $ objdump -d shellexecve | ./obj2s.sh -1 char shellcode[] = "\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80" ;
Conclusão
Até então esse script tem funcionado perfeitamente em meus testes. Qualquer erro ou dica de implementação fique livre para comentar.