Olá pessoal,
Nesse post vou falar um pouco sobre códigos que se auto modificam em tempo de execução. (Também conhecidos como códigos auto-mutáveis, auto-mutantes e etc). Espero que gostem.
Como surgiram os códigos que se auto modificam?
Bom...ao contrário do que muita gente pensa, os SMCs (a partir de agora vou usar essa sigla, que significa Self-Modifying Code, para me referir aos códigos auto-mutantes) não surgiram na área de segurança da informação.
Antigamente, as máquinas possuiam pouca memória RAM e, as vezes o programa que iria ser executado não cabia em memória. Como tais máquinas geralmente usavam métodos sequenciais de armazenamento físico de dados, era complicado ficar carregando partes do programa. Pense bem, imagine um computador com fita magnética, agora imagine um programa que começa na posição 10 e termina na posição 900 dessa fita....Agora imgine que esse programa grava informações na posição 1000 da fita. Bom...o sistema carregaria uma parte de programa, essa parte iria escrever na posição 1000, então a fita andava pra frente, quando acabasse essa parte do programa, o sistema teria que ir na fita buscar mais uma parte e pra isso a fita teria que voltar, então ela ficaria ficar indo e voltando...e isso demora.
Então surgiram os SMCs. Conforme o código ia sendo executado, ele sobrescrevia as partes do código que não seriam mais usadas por instruções úteis, e assim se aproveitava melhor o pouco espaço que se tinha...
Os SMCs Hoje...
Hoje em dia os SMCs, depois de um tempo desaparecidos, voltaram a aparecer em grande escala, porém, com um propósito diferente: Segurança. As melhores proteções anti-cracking atuais usam SMCs para esconder partes do programa. Conforme o programa vai sendo executado, o sistema de proteção vai escrevendo o código que deveria estar lá em um determinado lugar, e quando o programa termina de usar, algumas proteções escrevem outros códigos em cima e outras deixam o código lá. (não confunda SMC com stolen bytes). Dada a complexidade e o tamanho dos programas atuais, fica relativamente difícil achar os locais onde os códigos estão mudando.
Finalmente vamos à prática...
Existe mais de um método para se modificar o código. Vou colocar um exemplo de como utilizar o WriteProcessMemory + inline Assembly para fazer isso.
Vou colocar o código e comentar depois...
OBS.: O código foi feito no VC++ (visual C++), mas é fácil traduzir para o GNU C++...
Bom... a função mudaBytes recebe o endereço do byte que ela deve alterar e o novo valor do byte. Após isso ela altera o byte usando o WriteProcessMemory.
As linhas do inline Assembly estão comentadas...o que é importante observar é a última linha:
Isso basicamente significa: "chegando no LoopInf, pule para LoopInf", ou seja, ele vai ficar sempre pulando, formando aí um loop infinito.
Porém, o assembly antes do LoopInf chama a função mudaByte com o endereço de LoopInf e com o novo valor 0x74 (74 em hexa). Ou seja, ele está dizendo pra função mudaByte que ela deve ir no endereço de LoopInf, e mudar o byte do JMP para 0x74...
Mas por que 0x74? Acontece que toda instrução possui um código, no caso a função mudaByte vai tirar o código da instrução JMP de lá e vai colocar o código 74 que é a instrução JZ (só pula se a flag zero estiver setada).
Ou seja: ele não vai mais pular pra LoopInf e vai seguir reto no código, imprimindo a mensagem "Saiu do JUMP" na tela e finalizando o programa.
"Mas...Black-Hat...como eu sei se vc tá falando a verdade?" Simplesmente comente a parte do código que chama a função mudaByte, assim, ela não será chamada e você vai ver que seu programa vai ficar num loop infinito...
Para comentar alguma linha, coloque um ; (ponto e vírgula) na frente da linha, assim:
ORIGINAL:
COMENTADA:
"Os Finalmentes..."
Finalmente chegamos ao fim do tópico...esse não ficou tão grande igual ao de Assembly xD
Espero que tenham gostado e se gostaram cliquem em Obrigado, não dói nada e não paga tbm =)
Até mais...
Nesse post vou falar um pouco sobre códigos que se auto modificam em tempo de execução. (Também conhecidos como códigos auto-mutáveis, auto-mutantes e etc). Espero que gostem.
Como surgiram os códigos que se auto modificam?
Bom...ao contrário do que muita gente pensa, os SMCs (a partir de agora vou usar essa sigla, que significa Self-Modifying Code, para me referir aos códigos auto-mutantes) não surgiram na área de segurança da informação.
Antigamente, as máquinas possuiam pouca memória RAM e, as vezes o programa que iria ser executado não cabia em memória. Como tais máquinas geralmente usavam métodos sequenciais de armazenamento físico de dados, era complicado ficar carregando partes do programa. Pense bem, imagine um computador com fita magnética, agora imagine um programa que começa na posição 10 e termina na posição 900 dessa fita....Agora imgine que esse programa grava informações na posição 1000 da fita. Bom...o sistema carregaria uma parte de programa, essa parte iria escrever na posição 1000, então a fita andava pra frente, quando acabasse essa parte do programa, o sistema teria que ir na fita buscar mais uma parte e pra isso a fita teria que voltar, então ela ficaria ficar indo e voltando...e isso demora.
Então surgiram os SMCs. Conforme o código ia sendo executado, ele sobrescrevia as partes do código que não seriam mais usadas por instruções úteis, e assim se aproveitava melhor o pouco espaço que se tinha...
Os SMCs Hoje...
Hoje em dia os SMCs, depois de um tempo desaparecidos, voltaram a aparecer em grande escala, porém, com um propósito diferente: Segurança. As melhores proteções anti-cracking atuais usam SMCs para esconder partes do programa. Conforme o programa vai sendo executado, o sistema de proteção vai escrevendo o código que deveria estar lá em um determinado lugar, e quando o programa termina de usar, algumas proteções escrevem outros códigos em cima e outras deixam o código lá. (não confunda SMC com stolen bytes). Dada a complexidade e o tamanho dos programas atuais, fica relativamente difícil achar os locais onde os códigos estão mudando.
Finalmente vamos à prática...
Existe mais de um método para se modificar o código. Vou colocar um exemplo de como utilizar o WriteProcessMemory + inline Assembly para fazer isso.
Vou colocar o código e comentar depois...
OBS.: O código foi feito no VC++ (visual C++), mas é fácil traduzir para o GNU C++...
Código:
#include <windows.h> int mudaByte(void* end, int b){ HANDLE h=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE,true, GetCurrentProcessId()); return WriteProcessMemory(h,end,&b,1,NULL); } int _tmain(int argc, _TCHAR* argv[]) { _asm{ push 0x74 ;Empilha o novo valor do byte push offset LoopInf ;Empilha o endereço call mudaByte ;Muda o byte add esp, 8 ;Desempilha LoopInf: JMP LoopInf ;Normalmente esse loop seria infinito } printf("Saiu do JUMP!\n"); system("pause"); return 0; }
As linhas do inline Assembly estão comentadas...o que é importante observar é a última linha:
Código:
LoopInf: JMP LoopInf
Porém, o assembly antes do LoopInf chama a função mudaByte com o endereço de LoopInf e com o novo valor 0x74 (74 em hexa). Ou seja, ele está dizendo pra função mudaByte que ela deve ir no endereço de LoopInf, e mudar o byte do JMP para 0x74...
Mas por que 0x74? Acontece que toda instrução possui um código, no caso a função mudaByte vai tirar o código da instrução JMP de lá e vai colocar o código 74 que é a instrução JZ (só pula se a flag zero estiver setada).
Ou seja: ele não vai mais pular pra LoopInf e vai seguir reto no código, imprimindo a mensagem "Saiu do JUMP" na tela e finalizando o programa.
"Mas...Black-Hat...como eu sei se vc tá falando a verdade?" Simplesmente comente a parte do código que chama a função mudaByte, assim, ela não será chamada e você vai ver que seu programa vai ficar num loop infinito...
Para comentar alguma linha, coloque um ; (ponto e vírgula) na frente da linha, assim:
ORIGINAL:
Código:
call mudaByte ;Muda o byte
Código:
; call mudaByte ;Muda o byte
Finalmente chegamos ao fim do tópico...esse não ficou tão grande igual ao de Assembly xD
Espero que tenham gostado e se gostaram cliquem em Obrigado, não dói nada e não paga tbm =)
Até mais...
Comment