10. Injetando códigos
Neste tutorial vamos ver como injetar novos códigos em um executável já compilado. Vamos modificar o bloco de notas do windows para que exiba uma simples mensagem de texto ( pois é uma das função mais fáceis que o Windows fornece ) quando for iniciado.
Antes de tudo, faça uma cópia do bloco de notas ( C:\WINDOWS\notepad.exe ) para uma pasta qualquer ( vamos usar essa cópia, pra preservar o original ). O que nós vamos fazer é o seguinte: desviar o início do código do notepad para outro local, exibir a mensagem e depois retornar ao ponto original.
Para fazer isso, precisamos encontrar na seção do código do notepad, um local vazio, que não altere a funcionalidade do programa, o que é chamado de "Code-cave". Abra o notepad.exe no Olly e role o código para baixo. Lá pelo offset 8747 você deve encontrar o início da code-cave, uma seção sem código algum, apenas com valores 00:
Essa região a partir de 8747 é a que vamos utilizar para escrever nosso código. Como disse, vamos adicionar uma MessageBox no início da execução. Vamos dar uma olhada na função MessageBoxA para ver o que nós precisamos:
int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
);
Para chamar a função, precisamos passar 4 argumentos. hWnd indica à qual janela a Msgbox pertence. lpText e lpCaption são o texto da mensagem e o título da janela, respectivamente. E por útlimo, uType indica o estilo da janela, como número de botões e ícones.
Precisamos gravar o texto e o título da janela em algum lugar, e esse lugar é a própria code-cave. Vamos ao título primeiro.
A partir do início da code-cave, selecione o número de linhas que você vai usar para armazenar o título, sendo que cada linha que você selecionar vai ocupar o espaco de 1 caractere. Vou usar como título "F3rGO!", que contém 6 caracteres. Então seleciono 6 linhas a partir do início da CV ( code-cave ), usando SHIFT, clico com o botão direito sobre a seleção e em seguida "Binary->Edit". Em seguida, marque a caixa "Keep Size" e digite a sua mensagem no campo ASCII:
Aperte OK. O Olly primeiramente entede o que você digitou como uma sequência de comandos, por isso a sua mensagem não apareceu corretamente na janela de código. Aperte CTRL+A para o Olly analisar o cógido novamente e aí sim você deve ver a sua string corretamente. Repita o mesmo processo para o texto da janela ( selecionando as linhas a partir da linha que contém o seu título ). Eu usei como texto "Notepad modificado!", que contém 19 caracteres ( espaços contam como caracteres ). Selecione as 19 linhas e faça o mesmo que você fez para o título. No final, terá algo assim:
Já temos armazenado as nossas strings, então podemos chamar a função. Lembre-se que os argumentos da função são puxados na ordem inversa, ou seja, devemos usar o comando PUSH partido da uType para o hWnd. Escolha um offset qualquer da CV ( pode ser logo abaixo das strings ). Eu usei o 01008763. Escreva o código da chamda da função ( na hora de puxar o título e texto, indique o endereço de cada um no código ( 01008747 e 0100874E no meu caso )). Para escrever o código, basta dar 2 cliques sobre a linha e entrar com o comando. Seu código deve ficar assim ( os comentários eu adicionei ):
Já temos o código da msgbox, precisamos desviar o ínicio do programa 01008763 para chamar a mensagem e depois retornar à sequência de código original. Ainda não vamos adicionar o JMP de retorno após a chamada por motivos que vou explicar adiante. Memorize o endereço 01008763, pois é para ele que vamos desviar ( ja que é onde tem início a chamada da msgbox ).
Clique com o botão direito em qualquer lugar do código e em seguida "Goto->Origin *". Fomos levado até o EntryPoint ( ponto de entrada ) do programa.
0100739D 6A 70 PUSH 70
0100739F 68 98180001 PUSH NOTEPAD.01001898
010073A4 E8 BF010000 CALL NOTEPAD.01007568
010073A9 33DB XOR EBX,EBX
Vamos ter que alterar o PUSH 70 para um jump até o endereço 01008763. Antes de alterar, anote os comandos desses 2 primeiros offsets ( PUSH 70 e PUSH NOTEPAD... ). Já explico o porquê. Agora dê um duplo clique sobre o PUSH 70 e altere para JMP 01008763 ( marque a opção Fill with NOP's ). Certo, desviamos o nosso código, mas repare que foram perdidos 2 comandos devido a esse jump ( os 2 que você anotou ). Isso se dá ao fato que o comando JMP ocupa o espaço do PUSH 70 e de parte do outro PUSH, completando com NOPs os bytes que sobraram. Não podemos deixar assim, precisamos de alguma maneira adicionar esses 2 comandos perdidos em algum lugar. Onde? Na code-cave após a chamada da MessageBoxA.
Antes de voltar para a MessageBox, anote o offset do CALL NOTEPAD.01007568 ( 010073A4 ), pois depois da msgbox ser exibida, nós vamos ter que pular nesse endereço, para que a execução continue.
Volte para a região da sua MessageBox e adicione os 2 comandos anotados ( quando for adicionar o segundo comando, deixe somente o push com o endereço, remova o texto "NOTEPAD." ). Agora podemos realizar o jump de retorno ao código normal. Basta adicionar um novo JMP após o fim do código injetado para o endereço 010073A4 ( offset que você acabou de anotar ). No final das contas, seu código deve ter ficado semelhante a isso:
Pode salvar seu arquivo ( "Botão Direito->Copy to Exetuable->All Modifications->Copy All->Botão Direito->Save File" ) e testar. Se você fez tudo certo, deve ter visto isso ao iniciar o seu bloco de notas modificado
Até a próxima!
F3rGO!