Ir ao conteúdo
  • Cadastre-se
Entre para seguir isso  
joaoArthur1

C O que essa função faz?

Recommended Posts

Olá, tenho experiencia na linguagem C, mas a meses estou tentando entender o que essa função faz, mas não consigo entender algum poderia me dizer o que ela faz?

 

void* DetourCreate(BYTE* src, CONST BYTE* dst, CONST INT len)
{
    BYTE* jmp = (BYTE*)malloc(len + 5);
    DWORD dwback;
    VirtualProtect(src, len, PAGE_READWRITE, &dwback);
    memcpy(jmp, src, len);
    jmp += len;
    jmp[0] = 0xE9;
    *(DWORD*)(jmp + 1) = (DWORD)(src + len - jmp) - 5;
    src[0] = 0xE9;
    *(DWORD*)(src + 1) = (DWORD)(dst - src) - 5;
    for(INT i = 5; i < len; i++) src[i] = 0x90;
    VirtualProtect(src, len, dwback, &dwback);
    return(jmp - len);
}


 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Essa função é um pouco complexa, pois não envolve apenas a linguagem C, envolve também um pouco da linguagem Assembly, pois ela vai modificar diretamente na memória da aplicação usando instruções assembly(0xE9 = Número do byte equivalente a instrução jmp em x86 Assembly, 0x90 = Número do byte equivalente a instrução nop em x86 Assembly).

 

Basicamente o que essa função faz é modificar a memória da função que vai ser passada por argumento através do endereço(Primeiro argumento, src) para fazer um salto(0xE9 - jmp) para a o endereço de memória da nova função passada pelo segundo argumento(dst) e depois preenche os bytes que sobraram por 0x90(se sobrar obviamente). Esse 0x90 é apenas um nop(No operation, de uma forma traduzida bem simples, apenas não faz nada, seria apenas para preencher os bytes que sobraram para evitar bytes inválidos apos modificados).

 

Está função é bastante usada para fazer cheaters(trapaças/hackers) para jogos online/offline, também é bastante utilizado por Anti Cheats/Anti Hacks(Programas usados por empresas de jogos onlines para bloquear o uso de trapaças em seus jogos onlines), extremamente usado por malwares(No caso um malware poderia usar para desviar uma função de algum antivirus, por exemplo, a função de escaneamente do antivírus poderia ser facilmente desviada para não detectar o malware), também é usado por programas legítimos como: Fraps, OBS Studio, Overlays(Steam, Origin), programas de gravação.

 

Vou ter que fugir um pouco da linguagem C para explicar de uma forma mais clara como ela funciona(Obvio que não vou poder explicar tudo, pois é muita coisa isso você vai ter que pesquisar por conta própria).

 

Considere a seguinte instrução Assembly da função Sleep(Localizada no endereço de memória da dll KERNEL32):

 

Na imagem abaixo temos a função antes de ser desviada, ela apenas pula para a função Sleep da KERNELBASE.DLL

 

VoBvTBG.png

 

 

Apos o uso da função DetourCreate(DetourCreate((BYTE*)Sleep, (BYTE*)meuSleep, 6)) vai ficar da seguinte forma:

 

Bn7Go6r.png

 

Ou seja, como você pode ver nas imagens, ele apenas modifica os bytes da função passada pelo argumento, para fazer um salto para o endereço de memória da sua função.

 

Primeiro argumento: Endereço de memória da função que deseja desviar
Segundo argumento: Nova função que vai ser trocando quando a função Sleep for chamada.


Terceiro argumento: Número de bytes da função que vai ser modificado, o número de bytes na maioria das vezes muda dependendo da função e do sistema operacional.

 

Vou deixar um código bem parecido com esse para caso você queira testar na pratica(Vai ficar bem melhor pra você entender do que eu apenas explicando, recomendo que compile e teste)

O código foi modificado para ficar de forma mais clara, e com um pouco mais de segurança, ainda não está 100% seguro, mas está um pouco mais seguro.

#include <stdio.h>
#include <Windows.h>

// Prototipo da função
typedef VOID(WINAPI* __Sleep)(_In_ DWORD dwMilliseconds);

// Instancia da função
__Sleep SleepOriginal = NULL;

void* Desvio(const void* Endereco, const void* NovaFuncao, const size_t Tamanho)
{
    // Verificação se os argumentos foram passados são validos, se não for retorna 0
    // É necessario que o tamanho(numero de bytes) seja maior ou igual 5
    if (IsBadCodePtr((FARPROC)Endereco) || IsBadCodePtr((FARPROC)NovaFuncao) || Tamanho < 5)
        return NULL;

    DWORD ProtecaoAntiga = NULL;

    // Muda a proteção de memória para PAGE_EXECUTE_READWRITE, por padrão a proteção de memória é PAGE_EXECUTE_READ
    // Se for READ apenas, não é possível modificar, então por isso usamos a função VirtualProtect
    // Se retorna 0 é porque falhou ao modificar a proteção de memória para PAGE_EXECUTE_READWRITE
    // Então saimos da função retornando 0 se falhar, não podemos arriscar continuar sem ter certeza que é possível escrever na memória
    if (!VirtualProtect((void*)Endereco, Tamanho, PAGE_EXECUTE_READWRITE, &ProtecaoAntiga))
        return NULL;

    // Aloca memória na aplicação para poder salvar os bytes que vamos sobreescrever nele
    // Funcionaria da mesma forma que o malloc, porém para fazer Desvio é melhor a VirtualAlloc pois algumas vezes a malloc falha
    // Esse + 5 é o tamanho de um jmp em x86 Assembly, jmp onde vai ser usado para ir para a função depois de executar os bytes que modificamos
    void* InstrucoesAntigas = VirtualAlloc(NULL, Tamanho + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    // Verificação se foi possível alocar memória para salvar as instruções antigas da função Sleep
    // Caso retorne TRUE, é porque não foi possível alocar memória para a função
    // Saimos da função se falhar retornando 0
    if (IsBadCodePtr((FARPROC)InstrucoesAntigas))
        return NULL;

    // Tenta copiar os bytes para o endereço de memória que foi alocado(InstrucoesAntigas)
    // Se retornar 0 é porque falhou, então saimos da função retornando 0
    if (!memcpy(InstrucoesAntigas, Endereco, Tamanho))
        return NULL;

    // Muda o byte da memória alocada + Tamanho para 0xE9
    *(BYTE*)((DWORD_PTR)InstrucoesAntigas + Tamanho) = 0xE9; // jmp

    // Calcula o endereço de destino do jmp
    *(DWORD_PTR*)((DWORD_PTR)InstrucoesAntigas + Tamanho + 1) = ((DWORD_PTR)Endereco + Tamanho - (DWORD_PTR)InstrucoesAntigas) - 5;

    // Agora vamos modificar os bytes da função que queremos desviar
    *(BYTE*)((DWORD_PTR)Endereco + 0) = 0xE9; // jmp

    // Calcula o destino do jmp e depois coloca o endereço de destino no jmp da função que queremos desviar
    *(DWORD_PTR*)((DWORD_PTR)Endereco + 1) = ((DWORD_PTR)NovaFuncao - (DWORD_PTR)Endereco) - 5;

    // Preenche os bytes que sobraram com bytes que não fazem a diferença(nop) para evitar que sobre bytes, deixando a função invalida
    for (size_t i = 5; i < Tamanho; i++)
        *(BYTE*)((DWORD_PTR)Endereco + i) = 0x90;

    // Restaura para a proteção antiga de memória apos escrever os novos bytes
    VirtualProtect((void*)Endereco, Tamanho, ProtecaoAntiga, &ProtecaoAntiga);

    // Retorna o endereço de memória das instruções antigas
    return InstrucoesAntigas;
}

VOID WINAPI meuSleep(_In_ DWORD dwMilliseconds)
{
    printf("A funcao Sleep foi chamada e foi desviada para essa funcao!\n");
    Beep(150, 150); // Para dar um Beep sempre que ela for chamada
    
    // Chama a função do Sleep que foi salva naquela memória que alocamos para que o Sleep seja executado
    SleepOriginal(dwMilliseconds); // Poderia mudar o tempo(dwMiliseconds) para o tanto que eu quisesse ou poderia não fazer nada
}

int main()
{
    // Instala o Desvio no endereço da função Sleep e salva na variável SleepOriginal a função antiga
    SleepOriginal = (__Sleep)Desvio(Sleep, meuSleep, 6); // Esse número pode mudar em alguns sistemas, por isso eu disse que o código está mal feito, mas tem como pegar esse número usando uma outra função

    while (true)
    {
        Sleep(150); // Chama a função Sleep
    }
    return 0;
}

 

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora
Entre para seguir isso  





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×