Tecnologia do Blogger.

Arquivo do blog

Publicidade

Construa seu próprio crypter executável.

Este artigo irá levá-lo através dos passos básicos da construção de um crypter executável. Todas as etapas realizadas neste artigo exigem a configuração manual e integração para preparar a exe para o topo crypter. O foco deste artigo é orientá-lo através da teoria e know-how de como Crypters trabalho e não tentar criar o mais recente ponto de maior e solução do clique.

Para uma formação básica, aqui está como executável trabalho Crypters:

1) Os comandos do processador real de um binário protegidas são 
   crypted / obscurecida / munged qualquer

2) Quando a aplicação protegida inicia pela primeira vez, uma pequena decrypter 
   stub é executado pela primeira vez que restaura todo o processador original 
   comandos para o executável na memória.

3) Finalmente, o topo decrypter extremidades e transfere a execução para o
   ponto de entrada original (OEP) eo programa roda normalmente.

No decorrer deste trabalho, vamos implementar um manual muito simples 'crypter' para mostrar a você todas as técnicas de desenvolvimento, considerações de design, depuração e detalhes necessários para fazer o seu próprio.

Primeiro, deixe-me apresentar-lhe nosso alvo executável. É um aplicativo do mundo 28kb Olá escrito em C. Este aplicativo simples apenas imprime "Olá Mundo" para a tela, espera por uma tecla e então sai.

Para um bom começo, vamos examinar a estrutura de PE do arquivo executável. Abaixo está uma imagem da tabela Seção PE. Você vai notar que a seção de texto. (Onde o código executável real está alojado) tem um tamanho prima de 4000h e um tamanho virtual do 3DCEh. 

A discrepância nos números indica que, no final da seção de texto. Há uma certa quantidade de espaço não utilizado atualmente não mapeadas na memória quando o arquivo é carregado. Este espaço em branco no arquivo executável é bom porque significa que temos uma almofada vazia onde podemos colocar nosso próprio código executável.

Para verificar isso visualmente você pode abrir o arquivo em um editor hexadecimal e procure por um bloco nulo. Para saber para onde olhar você tem que ser capaz de encontrar o arquivo certo deslocamento. Em nossa amostra exe isso é simplificado porque todas as nossas seções têm um tamanho <= sua dimensão virtual primas e cada seção primas offset = seu deslocamento virtual.

Isso é bom porque mantém todos os valores na RVA = PEheader deslocamentos arquivo raw no entanto isso nem sempre é o caso. V.2 das classes editor pe agora levar isso em conta e pode calcular deslocamentos de arquivo a partir de valores RVA corretamente. A hipótese de RVA = deslocamento arquivo será feita durante todo o restante deste artigo, porque vale para este exemplo específico que estamos analisando.

Então ... para ver esta almofada nula abrir o exe original em um editor hexadecimal e verifique a área entre 4DCEh e 5000h (RawOffset + VirtualSize)

Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F

00004DC0 C0 0F 74 06 B6 45 0B 83 C3 C9 C8 C9 FF C3 00 00 E. .. na ÉÃÈÿÉà ..
00004DD0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00004DE0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00004DF0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00004E00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00004E10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00004E20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00004E30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00004E40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00004E50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00004E60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00004E70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00004E80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

Para as nossas necessidades esta será mais do que espaço suficiente para colocar o nosso toco decrypter simples. Nós não necessariamente precisa espremer o nosso código em uma seção já existente. Se tivéssemos sido pequena em espaço, que poderia ter recorrido a adição de uma nova seção PE e colocar nosso código lá.

Ok, temos encontrado um lar para o nosso bloco decrypter, mas primeiro temos que fazer alguns ajustes para as características seção PE, para que:

A) código decrypter nossa é carregado na memória 
B) uma vez mapeados em memória, temos acesso de gravação para o corpo principal do código
C) quando o programa for carregado pela primeira vez, a execução começa com o nosso código decrypter 

Como mencionado acima, o tamanho virtual da seção (o tamanho carregado na memória) não inclui esta almofada nula encontramos no arquivo. Uma vez que vamos estar adicionando código para essa área, precisamos ter certeza de que esta área é carregado na memória também. Isto é conseguido através do aumento do tamanho virtual para esta seção PE usando um editor de PE como LordPE.

A segunda mudança, temos de fazer é certificar-se que a seção de texto. Sinalizado como uma área gravável uma vez mapeados em memória. Isso é necessário porque o nosso toco decrypter precisa dinamicamente reescrever (decodificar) os códigos real do processador para ser executado. Isso também é facilmente feito com LordPE do "editar seção de cabeçalho" diálogo. Abaixo está um gráfico da seqüência de diálogo e manipulações de campo requerida no LordPE. Destacadas em amarelo são os campos que foram alterados.

Nosso próximo objetivo agora passa a ter certeza de que quando as cargas primeiro executável é nossa stub decrypter que é executado pela primeira vez. Como os comandos do processador real para o arquivo executável não presentes no disco, com o início do programa no ponto de entrada inicial teria a máquina tentando executar aquilo que é essencialmente um bloco de dados desordenados.

O ponto de entrada do programa pode ser editado diretamente de LordPEs interface principal. Para a nossa demonstração permite escolher para definir o ponto de entrada na 4E00h. Esse deslocamento fica 32 bytes a partir do final de nosso código de aplicações reais e nos dá um bom lugar fácil de encontrar na hexeditor.

Com as modificações na estrutura do PE do caminho, agora podemos ir para o trabalho real. Aqui está o que nos resta:

D) construir o ramal decrypter
E) os opcodes cripta real executável 
F) integrar o nosso toco decrypter no modificada binário

Vamos começar com algumas visões de design para o nosso mecanismo de codificação. Como este é um demo e um treinador, o mecanismo de codificação vai ser mantido o mais leve e mais simples possível. Por estas razões, uma codificação simples XOR será utilizado.

A consideração próximo projeto é enumerar o tipo de variáveis de um esboço crypter genéricos vai precisar. Basicamente, qualquer esboço crypter vai precisar de três coisas:

1) o que compensar (em memória) para iniciar desencriptar dados
2) comprimento dos dados para decifrar
3 ponto de entrada) para transferir a execução para depois descodificada

Considerando que estamos projetando um esboço muito simples, eu vou tomar um atalho e inicie o direito de rotina de criptografia em programas de ponto de entrada original. Enquanto o EP não está bem no início da seção de código, é geralmente perto o suficiente para que a maioria dos comandos do processador serão criptografados.

Antes de entrar na própria concepção e desenvolvimento de stub decrypter para fora, vamos derrubar a parte mais fácil de XORing os opcodes primeiro original. Esta é uma operação simples, e pode ser feito da maneira que for mais conveniente para o desenvolvedor. A implementação que eu escolhi foi a de criar um programa VB rápido que percorre o binário aplicar o XOR para os bytes apropriado em representação da opcodes aplicações.

Para uma atualização rápida:

Q) Como faço para saber onde o opcodes começar? 
A) para a nossa configuração simples, estamos começando o programa original 
   ponto de entrada encontrado no cabeçalho PE

Q) Como faço para saber quanto tempo de um bloco para codificar?
A) Uma vez que queremos codificar todos os opcodes após o ponto de entrada, 
   comprimento dos dados para criptografar é Original Tamanho Virtual - ponto de entrada

Inline abaixo está o código fonte VB usado para codificar o arquivo executável do opcodes:

  StartAt = & H1048 ponto de "entrada original
  Comprimento = & '3 H2D86 DCE - 1048 (tamanho virtual - entrypoint)
    
  Abra P2 para binário como f
    
  Para i = 1 To comprimento
      offset = startAt + i
      Obter f, offset, b
      b XOR b = & HF
      Coloque f, offset, b
  Seguinte
    
  Fechar f
 

Com isso fora do caminho, estamos agora a desenvolver as nossas stub decrypter. Basicamente o que precisamos é de um pequeno bloco de comandos ASM que podemos colar no binário codificado em nosso novo ponto de entrada.

Abaixo está o bloco decodificador eu vim com escritas em C:

void main (void) (

   int i;
   b char;
   
   char * buffer = 0x400000; / imagebase /  
   comprimento longo 0xBEEF = / / <comprimento de código (espaço reservado)

   buffer + = 0xDEAD / / <- OEP deslocamento (espaço reservado)

   for (i = 0; comprimento <i, i + +) (
      
      Buffer = b ;
      b = b ^ 0xF; 
      buffer = b;  

   )

   buffer jmp _asm
  
)

Deixe-me mencionar alguns pontos e considerações de projeto sobre o código acima.

    * Para fazer o esboço genérico que você vai ter que editar os deslocamentos de ponto de entrada de comprimento e cada vez que você usá-lo. Faça alguns desses valores reconhecidos em hexadecimal para torná-lo mais fácil de encontrá-los no editor hexadecimal.

    buffer * aponta inicialmente para a imagebase, lembre-se que você vai estar trabalhando em endereços de memória. A razão de eu incremento * buffer último ao ponto de entrada de deslocamento é porque eu vou ter que editar este valor de forma independente em um editor hexadecimal.

    * Para transferir a execução para o ponto de entrada original que acabamos de usar um tampão inline asm jmp comando. Neste ponto * buffer já está apontando diretamente para os programas de ponto de entrada original. 

Tudo em tudo é um esboço decodificador muito simples. O truque consiste na depuração e execução. Desde que o decodificador é projetado para trabalhar com dados e deslocamentos não foi encontrado neste aplicativo independente, nós podemos realmente usar apenas o compilador para gerar os opcodes para os comandos que nós precisamos. Depuração ocorre através da integração de códigos de byte real stub em nosso exe crypted e execução que, por meio do depurador.

Agora que temos a nossa fonte C proposto, a necessidade de códigos de byte montador associados a ela. A maneira mais fácil que eu encontrei para obter os códigos asm byte do compilador é definir um break point no topo do código e iniciar o depurador do VC, pressionando F5.

Depois VC compilou o código, ele irá iniciar a construção no depurador interrompe a execução, que em seu ponto de interrupção programada. Agora você pode clicar na janela principal e escolha "desmontagem goto" para ver uma variedade mista de comandos C e ASM.

Abaixo está uma despojado bloco ASM gerado pelo compilador para nós. À esquerda estão os códigos de byte reais associados com os comandos assembler seqüência à direita.

C7 F4 45 00 00 40 00 mov dword ptr [ebp-0Ch], 400000h
C7 45 F0 00 00 BE EF mov dword ptr [ebp-10h], 0BEEFh
8B 45 F4 mov eax, dword ptr [ebp-0Ch]
05 AD DE 00 00 add eax, 0DEADh
89 45 F4 mov dword ptr [ebp-0Ch], eax
C7 FC 45 00 [ebp-4] 00 00 00 mov dword ptr, 0
EB jmp 09 h 43 principais  
8B 4D FC mov ecx, dword ptr [ebp-4]
83 C1 01 add ecx, 1
89 4D FC mov ecx dword ptr [ebp-4],
8B 55 edx mov FC, [ebp-4] dword ptr
3B 55 edx cmp F0, dword ptr [ebp-10h]
7D 22 JGE principal 6 Dh  
8B 45 F4 mov eax, dword ptr [ebp-0Ch]
03 45 FC add eax, dword ptr [ebp-4]
8A 08 cl mov byte ptr [eax]
88 4D F8 mov byte ptr [ebp-8], cl
BE 0F 55 edx MOVSx F8, byte ptr [ebp-8]
83 F2 0F xor edx, 0Fh
88 55 F8 mov byte ptr [ebp-8], dl
8B 45 F4 mov eax, dword ptr [ebp-0Ch]
03 45 FC add eax, dword ptr [ebp-4]
8A 4D F8 cl mov [ebp-8] byte ptr
88 08 mov byte ptr [eax], cl
EB jmp CD principal 3 Ah  
FF 65 F4 dword ptr jmp [ebp-0Ch]

Para podermos inserir isso em nosso executável, devemos ainda tira apenas os códigos de byte e escrever os valores hexadecimais em nosso arquivo executável. Uma boa maneira de fazer isso é eliminar os comandos assembler, remover todos os espaços, e coloque-os em uma seqüência longa como esta:

C745F400004000C745F0EFBE00008B45F405ADDE00008945F4C745FC
00000000EB098B4DFC83C101894DFC8B55FC3B55F07D228B45F40345
FC8A08884DF80FBE55F883F20F8855F88B45F40345FC8A4DF88808EB
CDFF65F4

A partir daqui, você pode copiar a seqüência de texto e escrever os valores hexadecimais associados diretamente no binário usando o editor hexadecimal Winhex, destacando o início de deslocamento (4E00h) pressionando Ctrl-B (escrever clipboard) e então escolher a "ACII Hex" formato de prancheta.

Uma vez feito isto, tudo o que resta é para editar o comprimento de dados e começar a espaços reservados para compensar compilados no topo e vai ser configurado para este binário. Se você escreveu o rascunho de partida no deslocamento 4E00h então você vai encontrar o marcador BEEFh comprimento de dados em 4E0Ah compensação e DEADh marcador de ponto de entrada na 4E12h offset.

Note-se que esses valores estão no formato little endian. Quando você vai para modificá-los com os valores reais, lembre-se também escrever os novos valores no formato little endian.

Abaixo são vistas hexeditor das modificações introduzidas.

Offset 0 1 2 3
00004E10 .. .. ANÚNCIO DE (DEAD)
00004E10 .. .. 48 10 (1048)

Offset 0 1 2 3 4 5 6 7 8 9 A B  
00004E00 .. .. .. .. .. .. .. .. .. .. EF BE (carne)
00004E00 .. .. .. .. .. .. .. .. .. .. 86 2D (2D86)

Com o nosso bloco decrypter no lugar, o nosso código principal crypted, eo ponto de entrada agora visando o decrypter, tudo deve ser definido e pronto para correr!

Abri-lo no Olly, dar-lhe um tiro e ver o que acontece. Antes de iniciar a depuração através de código, olhar ao redor do ponto de entrada original e ver o que a desmontagem parece.

004010DC 12 DB 12
004010DD 05 DB 05
004010DE 0F DB 0F
004010DF 0F DB 0F
AE DB 004010E0 AE
004010E1 53 DB 53
004010E2 63 DB 63
004010E3 4F DB 4F
004010E4 0F DB 0F
004010E5 DB AC
004010E6 DB 6F 6F
004010E7 63 DB 63
004010E8 4F DB 4F

Sim, isso é uma característica bagunça jarbled de um bloco de dados criptografados ou opcodes ... Agora volte para o fim do bloco decrypter e definir um ponto de interrupção na "jmp buffer" final de comando:

00404E55> ^ FF65 F4 JMP DWORD PTR SS: [EBP-C]; final.00401048

Depois de chegar a esse ponto, vá novamente para cima e tomar um outro olhar para o ponto de entrada original 401048. Se você ainda ver um bloco de sucata de comandos, como a confusão acima, é porque Olly ainda não analisou os novos valores de bytes para os comandos do processador. Para corrigir isso, clique direito na janela principal desmontagem e escolha "analisar o código. Agora você deve ver as instruções reais decodificada:

00401048 /. 55 PUSH EBP
00401049 |. MOV 8BEC EBP, ESP
0040104B |. FF 6A PUSH -1
0040104D |. 68 B8504000 PUSH final.004050B8
00401052 |. 68 9C244000 PUSH final.0040249C; SE instalação manipulador
00401057 |. 64: MOV EAX A1 00000000, DWORD PTR FS: [0]
0040105D |. 50 PUSH EAX
0040105E |. 64:8925 000000> MOV DWORD PTR FS: [0], ESP
00401065 |. 83EC ESP SUB 10, 10

Agora você pode clicar no botão executar e Voila! Tudo deve funcionar como esperado!

Parece que tudo está no lugar e funcionando exatamente como deveria ser :)

Observe que usar C para gerar os opcodes podem fazer o decodificador um pouco inchado. Se você quiser escrever directamente no seu decodificador asm você poderia usar um esboço semelhante ao seguinte: (mesmo que isso poderia ser ainda mais otimizados)

00404E3A B8 48104000 MOV EAX, 401.048; compensação inicial
00404E3F B9 862D0000 MOV ECX, 2D86, comprimento
00404E44 8BD0 MOV EDX, EAX; cópia da compensação inicial (OEP)
00404E46 8030 0F XOR BYTE PTR DS: [EAX], 0F; inst decodificar top_of_loop
00404E49 40 INC EAX; próximo byte
00404E4A 49 dezembro ECX; contra dezembro
00404E4B ^ 75 F9 JNZ SHORT 00404E46; contador = 0 top_of_loop goto!                
00404E4D FFE2 EDX JMP; OEP jmp

Como uma pepita passado pouco, deixe-me jogar para fora uma dica rápida você pode usar para restaurar um exe crypted como esta ao seu estado anterior :)

Vamos assumir que o stub decrypter fez algumas criptografia real que nós não queremos tentar fazer engenharia reversa. Se o toco crypter ser operado apenas em um bloco de dados não comprimidos, que foi totalmente presente no exe e não executar qualquer outros truques ou manipulações a restauração do executável pode realmente ser muito simples.

Dê um presente tiro de carga .. a exe em olly e quebram no buffer jmp passado. Aqui o código executável real é totalmente decifrado na memória e pronto para ser executado. Agora o fogo até LordPE e despejar o 401000-405000 intervalo de endereços de memória para agarrar a seção de texto completo da memória.. Você tem agora todos os opcodes descriptografado salvo em disco ;)

Anote o endereço do ponto de entrada original que o comando jmp ia levá-lo e sair olly. Abra o despejo de memória eo exe crypted em Winhex e gravar o despejo de toda a seção de texto. Sobre a seção de texto criptografado. No executável.

Salve-o, em seguida, alterar o ponto de entrada para o original que você anotou e dar-lhe um clique. Tadaahhh meio ..... magia .. bem, não realmente ... mas você sabe. * Dá de ombros *

Enfim, este foi um pouco divertido desenho e descobrir como fazer. Esperemos que isto leva um pouco do "mágico" de como executável Crypters trabalho e deve ser suficiente para ajudar alguém junto.

Eu também cedeu e escreveu um ponto rápido e utilitário, clique em integrar este stub crypter em executáveis arbitrária. Você pode se deparar com o aplicativo mais VB fonte aqui. (Também tem um bom conjunto de classes para a manipulação do cabeçalho PE)

-<dzzie Dzzie na yahoo.com>



Fonte: http://sandsprite.com/CodeStuff/Build_your_own_executable_crypter.html[/ quote]

 
sprintrade network