Você pode chamar uma função em qualquer endereço. Portanto, carregue a biblioteca dinâmica em seu espaço de endereço de processo, descubra a base da biblioteca recém-carregada e pegue o deslocamento da base da biblioteca da função que você não deseja chamar e adicione-a.
Então, se o IDA diz que a base do binário é 0x4000
e sua função está no endereço 0x4100
, então você tem um deslocamento de 0x100
. Então, se você carregar sua biblioteca, ela acaba sendo carregada no endereço 0x8000
, você faz um ponteiro de função (com a assinatura correta, é claro) apontando para o endereço 0x8000 + 0x100
e chama isto. Dependendo de sua plataforma, a base que você obtém para sua biblioteca dinâmica do carregador de plataforma pode ser ainda mais deslocada dos shows de base reais do IDA.
Outra opção é, claro, adicionar uma nova definição de exportação para seu sub_xxx ()
função para a biblioteca dinâmica e fazer o carregador realmente lidar com quaisquer relocações. Será muito mais confiável, permitirá que você atribua um nome lógico à função, para que possa lidar com futuras atualizações da biblioteca onde o endereço da função muda, simplesmente adicionando novamente sua nova exportação à nova versão. Use algo como BinDiff para encontrar a nova localização da função.
A terceira opção popular é usar algo semelhante às assinaturas FLIRT de IDAs para escaneie a biblioteca dinâmica carregada para a função diretamente na memória. Geralmente é chamado de verificação de assinatura e aqui está uma explicação mais completa do conceito na plataforma Windows. Muito simplificado, é uma técnica para encontrar uma função baseada no padrão extraído do prólogo da função.
No seu caso, você controla o aplicativo pelo que posso ver e desejo chamar em uma biblioteca dinâmica que não tem a fonte para. Nesse caso, eu provavelmente escolheria a segunda opção ou a primeira se você souber que a biblioteca nunca mudará.