Olá pessoas, decidi escrever este pequeno artigo para mostrar-lhes como é possível identificar um programa compactado sem a ajuda desses auto-scanners como PEiD, EXEInfoPE e etc...
1º Método - Imports
O executável compactado tem poucos imports, isso acontece porque a IAT (Import Address Table) também foi compactada, e uma nova IAT foi sobreposta à ela. Essa nova IAT tem poucas funções, e quase sempre contém essas duas: LoadLibraryA e GetProcAddress, ambas provenientes da kernel32.dll.
LoadLibraryA é responsável por carregar as dlls da IAT original do programa, assim que ela é reconstruída, e depois disso, a GetProcAddress se responsabiliza por pegar o endereço de cada função usada pelo programa original.
Ou seja, quando um software compactado é executado, a unpacking stub descompacta o executável na memória, reconstrói a IAT original e transfere a execução para o OEP (Original Entry Point).
2º Método - Analisando o Entry Point
EP, ou Entry Point, é o endereço da primeira linha de execução do programa. Esse endereço deve estar sempre localizado na seção .text (a seção que contém o código do executável (não necessariamente ela tem esse nome)). Então, ao vermos o PE Header com algum editor, no campo Optional Header, a flag AddressOfEntryPoint deve apontar para a seção .text. Se ele apontar para outra seção, algo estranho está acontecendo. No exemplo abaixo, o EntryPoint está localizado na seção .aspack (que já nos dá certeza de que ele está compactado com o aspack).
Isso acontece porque o EntryPoint está localizado na Unpacking Stub, que faz a descompressão do arquivo na memória, e depois passa a instrução pro OEP (Original Entry Point, o EP do programa descompactado).
3º Método - Analisando o tamanho das seções
Já aproveitando o embalo nas seções, devemos também olhar as flags Raw Size e Virtual Size da seção .text.
Raw Size se refere ao tamanho em bytes do arquivo no disco rígido.
Virtual Size se refere ao tamanho em bytes do arquivo na memória.
Se o Virtual Size for muito maior que o Raw Size, quer dizer que o programa tem um tamanho maior quando está na memória, do que quando está em disco. Ou seja, o programa se descompacta, ficando bem maior do que realmente é (ou parece ser).
No exemplo acima, o Virtual Size tem tamanho de 2000 (8192 em decimal), enquanto que o Raw Size tem E00 (3584 em decimal). A diferença é bem grande, cerca de 4608 bytes são descompactados na memória.
Apenas resumindo:
1- O programa tem poucos imports, geralmente o LoadLibraryA e GetProcAddress;
2 - O EntryPoint está na seção errada (fora da .text);
3 - Existe alguma seção que denuncia a utilização de packer (como .aspack, .UPXo, etc);
4 - O Virtual Size é bem maior que o Raw Size na seção .text;
Bom, é basicamente isso, é sempre bom usar todos os métodos que citei aqui, pois um complementa o outro. Espero que o texto tenha ficado compreensivo à todos, estou aberto a críticas construtivas e dúvidas. Obrigado e até a próxima =)
Escrito por Nickguitar.dll em 14/01/2015.
1º Método - Imports
O executável compactado tem poucos imports, isso acontece porque a IAT (Import Address Table) também foi compactada, e uma nova IAT foi sobreposta à ela. Essa nova IAT tem poucas funções, e quase sempre contém essas duas: LoadLibraryA e GetProcAddress, ambas provenientes da kernel32.dll.
LoadLibraryA é responsável por carregar as dlls da IAT original do programa, assim que ela é reconstruída, e depois disso, a GetProcAddress se responsabiliza por pegar o endereço de cada função usada pelo programa original.
Ou seja, quando um software compactado é executado, a unpacking stub descompacta o executável na memória, reconstrói a IAT original e transfere a execução para o OEP (Original Entry Point).
2º Método - Analisando o Entry Point
EP, ou Entry Point, é o endereço da primeira linha de execução do programa. Esse endereço deve estar sempre localizado na seção .text (a seção que contém o código do executável (não necessariamente ela tem esse nome)). Então, ao vermos o PE Header com algum editor, no campo Optional Header, a flag AddressOfEntryPoint deve apontar para a seção .text. Se ele apontar para outra seção, algo estranho está acontecendo. No exemplo abaixo, o EntryPoint está localizado na seção .aspack (que já nos dá certeza de que ele está compactado com o aspack).
Isso acontece porque o EntryPoint está localizado na Unpacking Stub, que faz a descompressão do arquivo na memória, e depois passa a instrução pro OEP (Original Entry Point, o EP do programa descompactado).
3º Método - Analisando o tamanho das seções
Já aproveitando o embalo nas seções, devemos também olhar as flags Raw Size e Virtual Size da seção .text.
Raw Size se refere ao tamanho em bytes do arquivo no disco rígido.
Virtual Size se refere ao tamanho em bytes do arquivo na memória.
Se o Virtual Size for muito maior que o Raw Size, quer dizer que o programa tem um tamanho maior quando está na memória, do que quando está em disco. Ou seja, o programa se descompacta, ficando bem maior do que realmente é (ou parece ser).
No exemplo acima, o Virtual Size tem tamanho de 2000 (8192 em decimal), enquanto que o Raw Size tem E00 (3584 em decimal). A diferença é bem grande, cerca de 4608 bytes são descompactados na memória.
Apenas resumindo:
1- O programa tem poucos imports, geralmente o LoadLibraryA e GetProcAddress;
2 - O EntryPoint está na seção errada (fora da .text);
3 - Existe alguma seção que denuncia a utilização de packer (como .aspack, .UPXo, etc);
4 - O Virtual Size é bem maior que o Raw Size na seção .text;
Bom, é basicamente isso, é sempre bom usar todos os métodos que citei aqui, pois um complementa o outro. Espero que o texto tenha ficado compreensivo à todos, estou aberto a críticas construtivas e dúvidas. Obrigado e até a próxima =)
Escrito por Nickguitar.dll em 14/01/2015.
Comment