ShellCode com chamada de funcao ???

1. ShellCode com chamada de funcao ???

???
gokernel

(usa Linux Mint)

Enviado em 19/01/2013 - 21:14h

Olá pessoal !!!

estou tentando fazer um ShellCode com funcao.

Alguem sabe fazer um ShellCode funcionar com uma chamada de funcao ???



#include <stdio.h>
#include <time.h>

int i, x;

/*
void func (void)
{
for (i = 0; i < 100000000; i++)
x++;
}
*/

//-------------------------------------------------------------------
// esse ShellCode abaixo na verdade eh a funcao ( func ) compilada ...
//
// gerado pelo programa: objdump
//
// objdump.exe -d execute.exe > saida.c
//
//-------------------------------------------------------------------
char code[] = {
0x55, // push %ebp
0x89, 0xe5, // mov %esp,%ebp
0xc7, 0x05, 0x70, 0x40, 0x40, 0x00, 0x00, // movl $0x0,0x404070
0x00, 0x00, 0x00, //
0xa1, 0x80, 0x40, 0x40, 0x00, // mov 0x404080,%eax
0xba, 0x00, 0x00, 0x00, 0x00, // mov $0x0,%edx
0x40, // inc %eax
0x42, // inc %edx
0x81, 0xfa, 0xff, 0xe0, 0xf5, 0x05, // cmp $0x5f5e0ff,%edx
0x7e, 0xf6, // jle 4012a7 <_func+0x17>
0x89, 0x15, 0x70, 0x40, 0x40, 0x00, // mov %edx,0x404070
0xa3, 0x80, 0x40, 0x40, 0x00, // mov %eax,0x404080
0x5d, // pop %ebp
0xc3 // ret
};

int main (int argc, char *argv[])
{
clock_t clock_start = clock ();
#ifdef __WIN32__
asm ("call _code");
#endif
#ifdef __linux__
asm ("call code");
#endif
clock_t clock_end = clock ();

float time_used = ((float)(clock_end - clock_start)) / CLOCKS_PER_SEC;
printf("CLOCK TIME: %4.3f - x: %d\n", time_used, x);

return 0;
}


esse programa funciona perfeitamente, mas se eu colocar uma chamada de uma funcao no ShellCode ele quebra ... ou seja, nao sei fazer um ShellCode com uma chamada de funcao ...


espero que tenha sido entendido.



  


2. Re: ShellCode com chamada de funcao ???

???
gokernel

(usa Linux Mint)

Enviado em 20/01/2013 - 07:41h


complementando:

a funcao que tentei executar no shellcode foi essa:


void hello (void)
{
printf ("Hello World\n");
}


e não funcionou.


3. Re: ShellCode com chamada de funcao ???

Paulo
paulo1205

(usa Ubuntu)

Enviado em 20/01/2013 - 09:05h

O que falhou? Saber o endereço da função, ou seguir a sequência certa de passos para realizar a chamada? Que sintomas você teve?


4. Re: ShellCode com chamada de funcao ???

???
gokernel

(usa Linux Mint)

Enviado em 20/01/2013 - 17:46h


olá "paulo" grato por participar !

por execplo, o proximo código ao compilar e executar quebra:
http://codepad.org/OeCsHGFs

simplesmente quebra sem nenhum aviso .

OBS: só aumentei o codigo com: hello ();



5. Re: ShellCode com chamada de funcao ???

Paulo
paulo1205

(usa Ubuntu)

Enviado em 20/01/2013 - 22:56h

Aborta de modo totalmente silencioso, sem dar SIGSEGV/"Operação Ilegal"?

Não tenho como testar no Windows. No Linux, pelo que constatei com o gdb, ele dá SIGSEGV na própria instrução em Assembly "call code". E realmente é uma falha de segmentação, pois o array global code fica na seção chamada ".data", que é marcada para alocar segmentos que não contêm código executável (não tem o atributo "CODE", ao contrério da seção ".text" -- rode um "objdump -x" para ver aí na sua máquina).

Talvez algo como o que você tentou fazer até funcionasse em processadores mais antigos, mesmo com o SO marcando os segmentos de dados como não-executáveis. Os processadores modernos, porém, têm um controle que alguns chamam de "W^X" (uma notação de ou-exclusivo para dizer que o segmento não pode ser Writable e eXecutable ao mesmo tempo).

Eu peguei o seu código e troquei o tipo de code para const char[]. Com isso, numa máquina com sistema de 32 bits (Celeron antigo), ele conseguiu entrar na falsa função, mas deu erro (SIGSEGV) mais a diante, porque os endereços das variáveis i e x ficaram em locais muito diferentes do que na sua compilação, logo os bytes contidos no array precisariam ser reescritos para funcionar nessa máquina. Quando eu fiz isso, o objdump indicou que a variável foi movida da seção ".data" para a ".rodata" (de read-only).

Na máquina de 64 bits (Core i5) com sistema de 64 bits, a instrução "call code" aparentemente funcionou mesmo com o código originalmente postado por você, mas dava erro logo no "push %rbp" (sim, virou "%rbp" no disassembler de 64 bits). Trocando o tipo de code para const char[], foi um pouco além, e o erro se manifestou na hora de aceder às variáveis, como ocorrera na máquina de 32 bits. Isso me surpreendeu, pois eu esperava que, com o bit NX (not-executable) separado do bit de escrita, as páginas da seção ".rodata" fossem marcadas como read-only e not-executable simultaneamente, o que aparentemente não ocorreu.

(Continua...)


6. Re: ShellCode com chamada de funcao ???

???
gokernel

(usa Linux Mint)

Enviado em 20/01/2013 - 23:26h

@paulo: "Aborta de modo totalmente silencioso, sem dar SIGSEGV/"Operação Ilegal"?"

testei só no windows e aparece somente a janela para fechar o programa.

sei que essa parada é complicada mas vou tentar fazer funcionar depois ... arquivar...

mesmo assim, grato pela ajuda !


7. (Continuação)

Paulo
paulo1205

(usa Ubuntu)

Enviado em 21/01/2013 - 00:09h

Como eu vi que os endereços para as variáveis eram diferentes, resolvi adaptar o código, colocando os endereços das variáveis que tenho aqui (na máquina de 32 bits). Funcionou, mas apenas mais ou menos: eu vi pelo gdb que o programa entrava no loop indexado em i que alterava o valor de x (tive de reduzir ou loop de 1M iterações para apenas 10 -- mas deveria ter reduzido para apenas 2), mas dava erro no "call hello".

Logo vi o motivo: esse call usa endereçamento relativo (i.e. em lugar de usar o endereço absoluto da função hello() dentro da função func(), o compilador contou quantos bytes esse endereço estaria a partir do valor previsto para o ponteiro de instrução na hora em que o programa estivesse executando, e usou essa diferença). Isso obviamente não pode ser transposto diretamente para a sua pseudo-função dentro do array, pois ela estará noutra região bem diferente de memória.

Na máquina de 64 bits foi pior ainda: TODAS as operações usavam endereços relativos ao ponteiro de instrução, inclusive as instruções mov. Assim, por exemplo, para gravar o valor inicial de i, a instrução gerada foi "movl $0x0,0x200ad2(%rip)", e para ler esse valor para testar pelo final do loop, a instrução foi "mov 0x200aac(%rip),%eax". O valor do endereço de i obviamente era constante -- no meu caso, 0x000000000060103c, o que implica que o valor de %rip na primeira instrução era 0x000000000040056a, e 0x0000000000400590 para a segunda.

Assim sendo, o seu shell code não seria um mero copy'n'paste, mas teria de ter fazer algumas contas, usando a informação sobre a disposição em memória de cada item que usar. Nada muito difícil, mas deixa de ser, como vimos, absolutamente trivial.

No caso da versão 64 bits, esses acessos relativos tem uma justificativa clara para mim, que é a de ter instruções que requeiram menos bytes (os offsets de 32 bits em relação ao %rip consomem quatro bytes, deixando o tamanho total da segunda instrução mov, mostrada acima, com seis bytes, ao passo que o uso de endereços absolutos requer oito bytes só para o endereço, sem contar o(s) byte(s) de opcode).

Já uso de memória marcada como read-only é algo que faz sentido do ponto de vista de segurança. Ele torna o uso de shellcode via exploit imprevisto muito mais difícil, se não impossível.


8. Re: ShellCode com chamada de funcao ???

???
gokernel

(usa Linux Mint)

Enviado em 21/01/2013 - 11:18h

ok "paulo".

depois vou tentar gerar o ShellCode(char code[]) em tempo real de execuçao usando um "MICRO ASSEMBLY", pegando os endereços em tempo real ...

minha teoria é:
acho que não estou informando o endereço real da funcao (hello) em tempo de execução.

é a diversão da semana nas horas vagas. ;)



9. Re: ShellCode com chamada de funcao ???

Enzo de Brito Ferber
EnzoFerber

(usa FreeBSD)

Enviado em 23/01/2013 - 08:05h

Olá,

Shellcodes não podem ter caracteres nulos, newlines, etc.

Quando mexia com buffer overflows, agente sempre tinha que escrever toda a função em Assembly, usando registradores menores e evitando instruções grandes.

Em C, acho que você consegue executar mesmo com os nulos. Usando funções e ponteiros.


NULL bytes are string delimeters and kill shellcode. If you created shellcode
that contains such bytes: Don't bother using it and try to fix the problem.
So since you cannot have NULL bytes in the shellcode you will have to add them
at runtime. Now that we have seen in the above example how to get the location
of bytes in our string:

jmp short stuff
code:

pop esi
xor eax,eax ; doing this will make eax NULL
mov byte [esi + 17],al ; put a null byte byte on [esi + 17]

stuff:
call code
db 'This is my string#'

In the above example we replace '#' with a NULL byte and terminate the string
'This is my string' at run time. For clean coding purposes it I find it the best
to alter you strings at the beginning of you assembly code.

Please note that NULL bytes are not the only problem! Other bytes such as newlines
and special characters can also cause problems !.


Link: http://www.safemode.org/files/zillion/shellcode/doc/Writing_shellcode.html


char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";

void main() {
int *ret;

ret = (int *)&ret + 2;
(*ret) = (int)shellcode;

}



10. Re: ShellCode com chamada de funcao ???

???
gokernel

(usa Linux Mint)

Enviado em 25/01/2013 - 20:50h

Glória a DEUS, conseguimos fazer funcionar o ShellCode ...

depois de praticamente o dia(sabado) inteiro tentando funcionar, finalmente funcionou.

neste momento(19:38) estou com( fome, grude, fedendo, alegre, dor de cabeça, ), por hoje eh so. ;).

e o resultado/base pode ser visto aqui:
http://codepad.org/akQC6LzI


OBS: falta ainda implementar algo mais, isto eh somente a base do gerador de funcoes compiladas ...

EDITADO...

em linux, a funcao assembly seria assim:

void assembly (void)
{
asm ("movl $hello, %ebp");
asm ("movl %ebp, %eax");
asm ("call *%eax");
}



11. Re: ShellCode com chamada de funcao ???

Paulo
paulo1205

(usa Ubuntu)

Enviado em 26/01/2013 - 08:48h

Na linha em que você faz *(long *)p = func;, você assume que o tamanho de um inteiro longo é igual ao tamanho de um ponteiro genérico, e atribui o valor de um ponteiro a um lvalue cujo tipo é long. A assunção não necessariamente é sempre verdadeira, e a confusão com os tipos, que decorre certamente da assunção sobre os tamanhos, é um tipo de coisa temerária que um compilador configurado corretamente não deveria deixar passar sem pelo menos dar uma mensagem de aviso.

Não só filosoficamente, mas até em termos práticos, seria melhor você fazer da seguinte forma: *(void **)p=func;, até porque func já é do tipo void *.


12. Re: ShellCode com chamada de funcao ???

???
gokernel

(usa Linux Mint)

Enviado em 26/01/2013 - 11:15h

ok "paulo", anotado.

sugestões/críticas são bem vindas, assim conseguiremos melhorar essa pequena biblioteca que usarei para substituir o meu bytecode(JBC) por funçoes mais rapidas e reais.



01 02



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts