06. Descompactando UPX
Diversos aplicativos distribuídos por aí vem compactado com algum tipo de compressor, para diminuir o tamanho do executável e dificultar o debug. Um desses compressores, talvez o mais famoso, é o UPX ( Ultimate Packer for eXecutables ). Possui uma otima compressão é descompacta o executável original muito rápidamente. Ele é Open Source e pode-se baixá-lo gratuitamente em http://upx.sourceforge.net
Existem diversas maneiras de decompactar executáveis. Você pode usar o próprio unpacker do UPX, usar um unpacker de terceiros ou descompactar na mão, que é o que vamos fazer nesse tutorial. Antes de tudo, vou explicar como um compressor do tipo do UPX funciona.
Quando você utiliza um packer, como o UPX, o EP ( Entry Point, onde inicia o código do programa ) é desviado para outro endereço, que contem algo que chamamos de Loader. A função do loader é somente descompactar o executável para a memória e depois chamar o OEP ( Original Entry Point, que contém o código verdadeiro e descomprimido ). A sequência é mais ou menos essa:
EP -> Loader -> Descomprime o conteúdo do executável para a memória -> Move o EP para o OEP.
O processo para descompactar o UPX na mão é praticamente sempre o mesmo. É só seguir a mesma sequência que você consegue descompactar sem grandes dificuldades. Eu não vou explicar o que acontece com o loader ou como ele descomprime, nós vamos apenas descobrir onde está o ponto de partida inicial do código ( OEP ) e buscar o executável comprimido da memória. Para isso, vamos usar o OllyDbg e também outro utilitário que remonta a base de Imports dos arquivos executáveis ( se tiver interesse em saber o que é isso, procure pelo file format de arquivos executáveis ) chamado ImportREC
Vamos então iniciar. Antes de tuto, nosso alvo. Um executável simples feito em VB e comprimido com UPX.
-Download: unpackme.zip
Como saber se ele está comprimido? Para ver se o executável contém algum tipo de proteção, eu uso o PEiD, que analisa e detecta quase todos os tipos de compressores. Baixe e descompacte na pasta do Olly a dll do plugin OllyDump, que vamos utilizar mais adiante.
Certo, ele foi comprimido com o UPX ( a versão não interessa, pois o processo é o mesmo para todos ). Abra o Olly e carregue nosso executável. Ele vai dar um aviso de que ele foi comprimido e pergunta se queremos continuar, clique em Yes. O Olly já nos deixa no Entry Point ( do loader ainda ):
0040EA80 60 PUSHAD
Guarde bem essa linha. Ele é TÍPICA de UPX. Todo arquivo comprimido com ele vai iniciar com um PUSHAD. Como eu disse, não vou explicar o porque de estarmos fazendo tal processo, etc, vou apenas indiciar o que você deve fazer.
Aperte F7 para que ele execute a instrução do PUSHAD e passe para a linha seguinte ( EA81 ). Repare que na janela dos registradores ( a direita ), o ESP está colorido, indicando que ele mudou de valor. Nós vamos setar um breakpoint de hardware no conteúdo do primeiro byte do ESP, pois ele é acessado somente no início e no final do loader, assim nós cairemos bem perto do local onde encerra o loader e ele chama pelo OEP, que é o que nós precisamos.
Clique com o botão direito sobre o valor de ESP e vá em "Follow in Dump". Agora nós estamos monitorando o conteúdo do ESP na parte de baixo da tela. Clique com o botão direito sobre o primeiro byte da janela de dump (38 ) e selecione "Breakpoint->Hardware, on access->DWord". Esse breakpoint vai nos levar logo no final do loader, bem perto da chamada para o OEP ( para saber o motivo de setar esses breakpoints, você precisa estudar o comportamento do Loader, que não é o enfoque deste tutorial ).
Aperte F9 para continuar a execução do programa. Quase instantaneamente chegamos no breakpoint setado. O Olly parou aqui:
0040EC06 61 POPAD
0040EC07 8D4424 80 LEA EAX,DWORD PTR SS:\[ESP-80\] ; Paramos aqui
0040EC0B 6A 00 PUSH 0
0040EC0D 39C4 CMP ESP,EAX
0040EC0F 75 FA JNZ SHORT UnpackMe.0040EC0B
0040EC11 83EC 80 SUB ESP,-80
0040EC14 E9 7725FFFF JMP UnpackMe.00401190
Repare no POPAD que apareceu. Como disse, isso é típico de UPX, começando com um PUSHAD e terminando com um POPAD. Repare agora na última linha, um jump obrigatório para o endereço 1190. Esse jump indica que chegamos no final do Loader, o aplicativo descomprimido já está na memória, e esse JMP vai nos levar até o ponto de partida original. ( vendo pelo jump já dá pra saber que o OEP é 00401190 ). Coloque um Breakpoint comum na linha do jump ( 0040EC14 ) apertanto F2. Aperte F9 para continuar até chegarmos no jump. Assim que chegar, aperte F7 uma vez para realizar o pulo para o entry point original.
00401190 68 A09E4000 PUSH UnpackMe.00409EA0
00401195 E8 EEFFFFFF CALL UnpackMe.00401188
0040119A 0000 ADD BYTE PTR DS:\[EAX\],AL
Se você fez tudo certo, agora deve estar no endereço 00401190 que nos mostra o código original do .exe descomprimido. O que nós precisamos fazer é pegar o aplicativo descompactado da memória e remontar um novo executável a partir dele, indicando o ponto de início correto ( 1190 ). Para fazer isso, vamos utilizar o OllyDump. Com o programa ainda congelado na linha 1190, vá em "Plugins->OllyDump->Dump debugged process".
O Olly já calcula tudo sozinho para você, inclusive o OEP, mas se quiser garantir clique em "Get EIP as OEP". Desmarque também a caixa "Rebuild Import", pois nós vamos utilizar outro programa para remontar a base de Imports. Clique em "Dump" e escolha o nome e o local onde você deseja salvar o arquivo descompactado. Eu utilizei o nome "Dumped.exe".
Provavelmente você ficou muito entusiasmado, já executou esse arquivo criado e se deparou com um erro de falha de inicialização. Isso ocorre porque o UPX desroganiza a seção de Imports do executável, e nós precisamos remontá-la. Para isso, vamos usar o ImpRec, que eu falei no inicio do tutorial. Deixe o Olly aberto da maneira que está, não feche ele. Execute também o .exe original ( que veio com o zip, o mesmo que está rodando no Olly ).
Agora inicie o ImpRec e configure da maneira como mostrada na figura:
Em 2, você deve colocar o valor adquirido na caixa de texto "Modify", da janela de Dump do Olly.
Ao clicar em Get Imports ( 4 ), deve aparecer alguns items na lista "Imported Functions Found". Todos os items devem aparecer com um YES no final, caso contrário ele não conseguirá montar a tabela de imports corretamente. A última coisa a fazer é clicar em Fix Dump ( 5 ). Ao clicar, ele pede por um arquivo executável. Selecione aquele que foi criado no Olly, que eu dei o nome de "Dumped.exe". Logo após selecionar o arquivo, ele já vai gerar o executável descompactado definitivo ( contendo um underline no final do nome: Dumped_.exe ) e vai mostrar no Log do ImpRec que o arquivo foi criado com sucesso. Agora sim você já pode fechar o Olly, todo o resto da parafernália e executar o "Dumped_.exe". Se deu tudo certo, você deve ter recebido uma mensagem animadora do unpackme :P
Se quiser comprovar que foi descompactado, faça um novo scan com o PEiD no "Dumped_.exe" e veja ( ou simplesmente compare o tamanho dos arquivos ) ;D
F3rGO!