Pergunta

Imagine que eu estou fazendo algo parecido com isto:

void *p = malloc (1000);
*((char*)p) = some_opcode;
*((char*)p+1) = another_opcode; // for the sake of the example: the opcodes are ok

....
etc...

Como posso definir um ponteiro de função para chamar p como se fosse uma função? (Estou usando VC ++ 2008 Express).

Graças

Foi útil?

Solução

Um comentário não havia espaço suficiente. Joe_Muc está correto. Você não deve codificar o material na memória obtido por malloc ou new. Você vai ter problemas se você alterar as propriedades da página de páginas que aloca Windows.

Este não é um problema becuase usando VirtualAlloc () e do Win32 APIs relacionados é cada fácil: chamada VirtualAlloc () e definir o flProtect para [PAGE_EXECUTE_READWRITE][2]

Note, você provavelmente deve fazer três alocações, uma página de proteção, as páginas que você precisa para o seu código, em seguida, outra página de proteção. Isto lhe dará um pouco de proteção contra o mau código.

Além disso embrulhar as chamadas para o código gerado com tratamento de exceção estruturada .

Em seguida, o Windows x86 ABI (convenções de chamada) não estão bem documentados (eu sei, eu olhei). Há algumas informações aqui , aqui , aqui a melhor maneira de ver como as coisas trabalho é olhar para o código gerado pelo compilador. Isso é fácil de fazer com o \FA muda ( existem quatro deles).

Você pode encontrar o 64-bit chamando convenções aqui .

Além disso, você ainda pode obter Macro Assembler da Microsoft MASM aqui . Eu recomendo escrever o seu código de máquina em MASM e olhar para a sua saída, em seguida, ter o seu código de máquina gerador de fazer coisas semelhantes.

e da Intel manuais processador da AMD são boas referências -. obtê-los se você não tê-los

Outras dicas

Na verdade, malloc provavelmente não vai cortá-la. No Windows, você provavelmente precisará chamada algo como [VirtualAlloc] ( http://msdn.microsoft.com/en-us/library/aa366887 (VS.85) .aspx) a fim de obter uma página executável da memória.

Começar pequeno:

void main(void)
{
    char* p = (char*)VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    p[0] = (char)0xC3;  // ret

    typedef void (*functype)();
    functype func = (functype)p;
    (*func)();
}

O próximo passo para jogar bonito com o seu código é preservar o registo EBP. Isso é deixado como um exercício. : -)

Depois de escrever isso, eu corri com malloc e também trabalhou. Isso pode ser porque eu estou correndo uma conta de administrador no Windows 2000 Server. Outras versões do Windows pode realmente precisa a chamada VirtualAlloc. Quem sabe.

Se você tem os opcodes no lugar certo, chamando pode ser tão simples como lançando a um ponteiro de função e chamá-lo.

typedef void (*voidFunc)();

char *p = malloc (1000);
p[0] = some_opcode;
p[1] = another_opcode; // for the sake of the example: the opcodes are ok
p[n] = // return opcode...

((voidFunc)p)();

Note que embora a menos que você marcar a página como executável, o processador não pode deixá-lo executar código gerado na pilha.

Estou também investigando a execução de código gerado, e enquanto as respostas aqui não me deu exatamente o que eu precisava, vocês me enviou no caminho certo.

Se você precisa para marcar uma página como executável em sistemas POSIX (Linux, BSD, etc.), consulte a mmap (2) função .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top