Ultima modifica da un moderatore:
Dal titolo sembra chissa che cosa... ma è un semplice packer che verifica se all'apertura del programma è presente un Debbugger. In caso positivo continua con un eccezione.
E' possibile packare un programma trascinandolo sul Packer o aprendo il programma e inserendo il nome del file.
Oltre al programma verrà scritto un file di Log contenente le informazioni principali come i byte liberi.
Il packer è stato testato con programmi compilati con
E' in fase di sviluppo una versione totalmente compatibile con
Per questi motivi sto cercando qualcuno che mi dia una mano ( oltre a retr0 che non è mai on su MSN!)
Essendo un progetto Open Suorce ho optato per iniziare con la licenza GPL.
Bug Conosciuti
DOWNLOAD
Link Diretto
MultiUpload
SCREEN
Programma:
Eccezione di Olly
SUORCE
Download
Il suorce è commentato e comprensibile. So che è scritto un po' male.. e soprattutto indentato male.
Ci sono dei commenti sulle prossime funzioni del programma e delle cose da correggere.
Crediti
E' possibile packare un programma trascinandolo sul Packer o aprendo il programma e inserendo il nome del file.
Oltre al programma verrà scritto un file di Log contenente le informazioni principali come i byte liberi.
Il packer è stato testato con programmi compilati con
- Dev-C++
- Borland Dephi 4.0
- Visual Studio 8 (in alcuni casi)
E' in fase di sviluppo una versione totalmente compatibile con
- Visual Studio 8
- Visual Basic 6.0
- Borland C++ for Win32
Per questi motivi sto cercando qualcuno che mi dia una mano ( oltre a retr0 che non è mai on su MSN!)
Essendo un progetto Open Suorce ho optato per iniziare con la licenza GPL.
Bug Conosciuti
Codice:
1. Il packer non controlla quanti sono i byte liberi tra le sezioni (anche se 18 byte ci sono sempre)
2. Funziona solo su alcuni programmi
3. Se viene attaccato il processo, quando il programma è già aperto, il debugger non viene detectato.
DOWNLOAD
Link Diretto
MultiUpload
SCREEN
Programma:
Eccezione di Olly
SUORCE
Download
Il suorce è commentato e comprensibile. So che è scritto un po' male.. e soprattutto indentato male.
Ci sono dei commenti sulle prossime funzioni del programma e delle cose da correggere.
PHP:
/*
GabriPr0 Packer Alpha Version!
With this program you can "pack" your own .exe file.
This packer may not work with all exe files.
I decline any responsability if you damage your program.
Copyright (C) 2010 Gabriele Serra ( GabriPr0 )
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <windows.h>
#include <iostream>
#include <fstream>
using namespace std;
//Le tre strutture di cui avrò bisogno:
//l'header delle sezioni, le varie caratteristiche (come entrypoint o imagebase) e il DOS header.
//Per un corretto approccio a questo suorce consiglio di studiare un guida sul formato PE
IMAGE_SECTION_HEADER *ImageSectionHeader;
IMAGE_NT_HEADERS *ImageNtHeaders;
IMAGE_DOS_HEADER *ImageDosHeader;
DWORD VaPartenza = 0;
DWORD FileOffset;
//Inizializzo a 0 perchè ne avrò bisogno.. capirete dopo!
BYTE Op[] = { 0x00 , 0x00 , 0x00 , 0x00 };
//La variabile VA conterrà il valore da sotrarre (insieme all'imagebase) al VA per ottenere il FileOffset
DWORD VA;
//Funzione per calcolare i byte di una funzione CALL
void CalcoloCode(DWORD VAPartenza , DWORD VADestinazione);
//Bè il nome della funz dice già tutto!
bool FileExist(LPSTR Filename);
//Per chi non ricordassi argc = numero argomenti , argv = i vari argomenti
int main(int argc, char* argv[])
{
cout << "GabriPr0 Packer Alpha Version." << endl;
cout << "This is an Open Suorce project!" << endl;
//Stream per scrivere su un file, in questo caso Log.txt
ofstream* Log;
//Se non esiste
if(!FileExist("Log.txt"))
{
Log = new ofstream("Log.txt");
//Verrà creato
cout << "Log File don't exist... it will be create now!" << endl;
} else {
//altrimenti lo apre in moalità append
Log = new ofstream("Log.txt" , ios::app);
//e scrive un barra di separazione
*Log << "---------------------------------------" << endl;
}
if(!Log){cout << "Unable to Create Log file!" << endl;}
HANDLE HandleFile;
//Max Path = 260 ..
char Filename[MAX_PATH];
//Se gli argomenti passati al cmd sono diversi da 2
if(argc != 2) {
//Inserisci il nome file da input
cout << "Insert file name..." << endl;
cin >> Filename;
//Ottengo l'handle del file
HandleFile = CreateFile(Filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0 ,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
cout << "Scanning... \nPacking " << Filename << endl;
*Log << "Packing: " << Filename << endl;
} else {
//altrimenti usa il secondo argomento passato al cmd come nome file
//(il primo argomento è il programma stesso)
HandleFile = CreateFile(argv[1], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0 ,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
cout << "Scanning... \nPacking " << argv[1] << endl;
*Log << "Packing: " << argv[1] << endl;
}
//Errore impossibile aprire il file
if (HandleFile == INVALID_HANDLE_VALUE )
{
cout << "Error: Unable to open File" << endl;
cin.get();
return -1;
}
//Crea una mappatura del file
HANDLE MpObj = CreateFileMapping(HandleFile, NULL, PAGE_READONLY, 0, 0, 0);
//Errore: Impossibile Mappare il file
if (!MpObj)
{
CloseHandle(HandleFile);
cout << "Unable to create MapFile" << endl;
cin.get();
return -1;
}
//Mappa il file e restituisce l'address dell'inizio della mappatura
DWORD BaseAddress = (DWORD)MapViewOfFile(MpObj, FILE_MAP_READ, 0, 0, 0);
//se BaseAddress = 0 Errore: Impossibile...
if (!BaseAddress)
{
CloseHandle(HandleFile);
CloseHandle(MpObj);
cout << "Unable to view mapping file" << endl;
cin.get();
return -1;
}
*Log << hex << "Base Address of Mapping Object: " << BaseAddress << endl;
//Per utilizzare la struttura DosHeader basta farla puntare al BaseAddress del file mappato
ImageDosHeader = (IMAGE_DOS_HEADER*)BaseAddress;
//Se e_magic (i primi 2 byte in poche parole) diversi da IMAGE_DOS_SIGNATURE ( MZ [ 4D , 5A ] )
//Errore: Dos Header invalido.. non è un eseguibile!
if (ImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
cout << "Invalid DOS Header" << endl;
CloseHandle(HandleFile);
CloseHandle(MpObj);
cin.get();
return -1;
}
//Per riempire la struttura NtHeaders basta farla puntare all'inizio del PE + e_lfanew
ImageNtHeaders = (IMAGE_NT_HEADERS *)(ImageDosHeader->e_lfanew +(DWORD)ImageDosHeader);
//Se i primi due byte della struttura dopo il DosHeader diversi da IMAGE_NT_SIGNATURE (PE [ 50 , 45 , 00 , 00 ] )
//Errore: il file che stiamo "esaminando" non è un PE!
if (ImageNtHeaders->Signature != IMAGE_NT_SIGNATURE)
{
cout << "Invalid PE Format" << endl;
CloseHandle(HandleFile);
CloseHandle(MpObj);
cin.get();
return -1;
}
//Ottengo l'imagebase ( o baseaddress) del PE che sto packando
DWORD ImageBase = ImageNtHeaders->OptionalHeader.ImageBase;
*Log << "Base Address of file: " << ImageBase << endl;
//Riempo la struttura section header grazie alla macro fornita da winnt.h
ImageSectionHeader = IMAGE_FIRST_SECTION(ImageNtHeaders);
//Per ogni sezione del file
for (int x = 0; x < ImageNtHeaders->FileHeader.NumberOfSections; x++)
{
//trova i byte liberi in fondo alla sezione
DWORD BaseByte = ImageSectionHeader[x].Misc.VirtualSize + ImageSectionHeader[x].PointerToRawData;
//Correggere
if ( BaseByte > 0 ){
/*
DWORD LOL = SetFilePointer(HandleFile, BaseByte, NULL, FILE_BEGIN);
if(LOL == INVALID_SET_FILE_POINTER)
{
cout << "Error: Unable to Set File Pointer" << endl;
CloseHandle(HandleFile);
CloseHandle(MpObj);
cin.get();
return -1 ;
}
BYTE NumeroByteNecessari[17];
DWORD nByteRead;
BOOL Read = ReadFile(HandleFile , NumeroByteNecessari , sizeof(NumeroByteNecessari) , &nByteRead , NULL);
if(!Read)
{
cout << "Error: Unable to Read Byte!" << endl;
}
Read = FALSE;
for(int Loop = 0; Loop < sizeof(NumeroByteNecessari); Loop++){
if(NumeroByteNecessari[x] != 0x00)
{
Read = TRUE;
}
}
if(Read)
{
cout << "I Byte nn sono liberi!" << endl;
cin.get();
return 0;
}
if(!RvaPartenza)
{
VA = ImageSectionHeader[x].VirtualAddress - ImageSectionHeader[x].PointerToRawData;
//Forse inutile magari Log
cout << "BaseByte " << BaseByte << " VA " << VA << " Imagebase " << ImageBase << endl;
RvaPartenza = BaseByte + VA + ImageBase;
FileOffset = BaseByte;
}
*/
//Per ora lascio così
if(!VaPartenza){
VA = ImageSectionHeader[x].VirtualAddress - ImageSectionHeader[x].PointerToRawData;
VaPartenza = BaseByte + VA + ImageBase;
FileOffset = BaseByte;
}
*Log << "Free Byte, Starting at Offset: " << BaseByte << endl;
}else{
cout << "Error!" << endl;
CloseHandle(HandleFile);
CloseHandle(MpObj);
cin.get();
return -1 ;
}//fine if
} //Fine for
cout << "End Scanning: Calculating Code and Write!" << endl;
//Sposto il FilePointer al FileOffset dei byte liberi
DWORD Ris = SetFilePointer(HandleFile, FileOffset, NULL, FILE_BEGIN);
//Se ris = INVALID_SET_FILE_POINTER allora
//Errore: Impossibile spostare il file pointer
if(Ris == INVALID_SET_FILE_POINTER)
{
cout << "Error: Unable to Set File Pointer" << endl;
CloseHandle(HandleFile);
CloseHandle(MpObj);
cin.get();
return -1 ;
}
//Dichiaro i Byte del packer
//copiati da Kernel32 o.O
//64:A1 18000000 MOV EAX,DWORD PTR FS:[18]
//8B40 30 MOV EAX,DWORD PTR DS:[EAX+30]
//0FB640 02 MOVZX EAX,BYTE PTR DS:[EAX+2]
//85C0 TEST EAX,EAX
//75 01 JNZ SHORT "ADDRESS SOTTO RETN" OVVERO ECCEZIONE
//C3 RETN
BYTE IsDbgPresent[] = { 0x64 , 0xA1 , 0x18 , 0x00 , 0x00 , 0x00 , 0x8B , 0x40 , 0x30 , 0x0F ,0xB6 , 0x40, 0x02 , 0x85 , 0xC0 , 0x75 , 0x01 , 0xC3};
//Scrivo i byte sul File..
DWORD lpNumberOfBytesWritten;
if(!WriteFile(HandleFile, IsDbgPresent, sizeof(IsDbgPresent), &lpNumberOfBytesWritten, NULL))
{
//Se ritorna 0 ( FALSE ) allora:
cout << "Error: Unable to write file" << endl;
CloseHandle(HandleFile);
CloseHandle(MpObj);
cin.get();
return -1;
}
//Ottengo l'entrypoint del file
DWORD RvaEntryPoint = ImageNtHeaders->OptionalHeader.AddressOfEntryPoint;
//Calcolo i byte da scrivere per la Call che parte dal VA dell'entrypoint + 1 (lascio il PUSH EBP che avvolte genera errore se lo levo )
// e che ha come destinazione il VA dei byte che ho scritto prima
CalcoloCode(RvaEntryPoint+ImageBase+1 , VaPartenza);
//Sposto il file pointer alla seconda istruzione del programma
Ris = SetFilePointer(HandleFile, RvaEntryPoint - VA +1, NULL, FILE_BEGIN);
//se Ris = INVALID_SET_FILE_POINTER
//allora Errore..
if(Ris == INVALID_SET_FILE_POINTER)
{
cout << "Error: Unable to Set File Pointer" << endl;
CloseHandle(HandleFile);
CloseHandle(MpObj);
cin.get();
return -1 ;
}
//Scrivo i Byte che compongono la CALL
if(!WriteFile(HandleFile, Op, sizeof(Op) + 1, &lpNumberOfBytesWritten, NULL))
{
//e se ritorna 0 errore:
cout << "Error: Unable to write file" << endl;
CloseHandle(HandleFile);
CloseHandle(MpObj);
cin.get();
return -1;
}
//Tutto è andato bene, il file è stato packato con successo!
cout << "File Succesfully Packed!" << endl;
*Log << "File Succesfully Packed!" << endl;
CloseHandle(HandleFile);
CloseHandle(MpObj);
system("pause");
//cancello il puntatore allo stream
delete Log;
return 0;
}
//Funzione per calcolare i byte che compongono un istruzione CALL
void CalcoloCode(DWORD VAPartenza , DWORD VADestinazione){
//Destinazione CALL - Partenza CALL - 5 (ovvero i byte che compongono la call)
VADestinazione = VADestinazione - VAPartenza -5;
//Conversione Big Endian -> Little Endian
//inverto i byte dato i processori Intel usano questa "notazione"
//nelle CALL e nei JMP infatti il byte più significativo è l'ultimo e quello meno
//il primo.
//Se ad esempio il risultato della sottrazione è 00006765 la call sarà
//E8 65670000 .. per questo ho inizializzato a 0 l'array!
unsigned char *ptr = (unsigned char *)&VADestinazione;
//il primo byte è E8 CALL
Op[0] = 0xE8;
Op[1] = ptr[0];
Op[2] = ptr[1];
Op[3] = ptr[2];
Op[4] = ptr[3];
return;
}
//Funzione per accertare se un file esiste..
bool FileExist(LPSTR Filename){
//apro il file Filename con permesso di lettura
FILE* File = fopen(Filename , "r");
//se File è nonzero esiste
if (File)
{
//chiudo e ritorno True
fclose(File);
return true;
}
//altrimenti ritorno false
return false;
}
- Il mio grande amico retr0bot per la base (il suorce del codicecavo ) e che mi deve dare una mano su MSN
- D4n13le che mi sopporta su skype e mi ha risolto il problema della conversione Big -> Little endian