Pergunta

Estou no processo de engenharia reversa de um executável do Windows.Encontrei uma classe que quero usar de algum código que injeto no executável (thread diferente, pilha própria).Como eu declararia tal classe, dados os endereços dos métodos e a estrutura das variáveis ​​​​de membros?

Por exemplo, digamos que encontrei uma classe chamada foo, com seu construtor @ 0x4012D30 e uma função doTheMario @ 40125D4.Também sei que contém três DWORDs de dados privados.Como ambos os métodos são _thiscalls, declaro uma classe assim no meu código:

class GuessedFoo {
    private:
        int bar;
        char *cafebabe;
        float deadbeef;
    public:
        GuessedFoo(int a, int b);
        void doTheMario();
};

Agora, esta é uma classe perfeitamente elegante, mas agora existe alguma maneira de fazer o compilador/vinculador vincular os métodos da classe aos dois endereços anteriores que afirmei?É claro que posso escrever um wrapper asm para converter um stdcall em thiscall para cada método que preciso usar e, em seguida, usar estruturas em vez de classes, mas deve haver uma maneira melhor.

Eu uso gcc/g++ no momento, mas posso mudar para VC++ (já que o conjunto embutido do gcc me dá dores de cabeça de qualquer maneira).

Foi útil?

Solução

Se a classe não tiver vtable, você poderá, em princípio, criar tal classe em seu próprio código, onde todas as chamadas de função invocam as implementações reais apropriadas.Você pode fazer isso torcendo as funções-membro como funções nuas contendo uma instrução de salto de montagem para a implementação real.

Se a classe tiver uma tabela v, as coisas provavelmente ficarão muito mais complexas;você provavelmente precisará criar explicitamente a vtable como uma estrutura de ponteiros de função e fazer com que seus stubs de função os chamem.Isso significa funções de correção mais complexas;uma simples função nua com um salto pode não ser suficiente, e pode ser melhor optar por uma função real.Lembre-se, porém, de que as funções-membro no win32 usam um convenção de chamada diferente;isso significa que uma chamada de função de membro comum não funcionará.Você poderia ser capaz de construir ponteiros para funções de membro, mas tenha em mente que eles têm um estrutura bastante estranha para eles, e você precisará combiná-lo com algo que tenha a mesma representação que os ponteiros vtable.Boa sorte!

Outras dicas

Você está fazendo engenharia reversa aqui, portanto (quase, provavelmente) forçado a diminuir quando se trata de interagir com o código existente.

Eu chamaria essa função usando código assembly puro.
Se o endereço base do EXE for corrigido fica ainda mais fácil.
Código de exemplo:

void main()
{
    int bar = 5;
    int * cafebabe = &bar;
    __asm
    {
        push [bar];
        push [cafebabe];
        mov eax, 123456; // address of the function
        call eax;
    }
}

Basta verificar como esta função está sendo chamada pelo código original para ver em que ordem você precisa enviar os argumentos.Não esqueça que alguns argumentos podem precisar ser passados ​​através de registradores!

Não tenho certeza se entendi corretamente, mas de qualquer forma:Acho que o caminho mais fácil para métodos de "localização manual" é usar ponteiros de função.

C++ não define nenhum tipo de interface binária, tornando praticamente impossível implementar qualquer tipo de ligação dinâmica para classes C++.

o melhor que você pode fazer é declarar duas estruturas - uma contendo typedefs de função c para cada método, a outra espelha o layout de dados da classe.

Claro - porque __thiscall em um método de classe passa 'this' através do registro ecs, eu não acredito que você possa realmente fazer uma declaração explícita de função c que terá o mesmo efeito, então você pode precisar executar todas as chamadas através de um personalizado "CallThisCallMethodWithParameters" que você escreveu em assembly.

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