PE cryptor - přidání nové sekce do souboru - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:

Soutěž

Sponzorem soutěže je:

IDIF

 

Kdo je autorem fotografií z výstavy " Tiché krajiny "?

V dnešní soutěži hrajeme o:



Assembler

PE cryptor - přidání nové sekce do souboru

5. prosince 2001, 00.00 | Dnešním článkem pokračujeme v seriálu Cracker proof, konkrétně rozborem zaměřeným na tvorbu vlastního PE cryptoru. V tomto díle přidáme novou sekci do souboru.

V minulém díle jsem uvedl základní problematiku PE cryptorů a také objasnil, jak takový PE cryptor pracuje. Nyní se budeme věnovat jednotlivým problémům pěkně zvlášť. 
Jak už bylo řečeno minule, nejdříve přidáme do souboru novou sekci, kde bude později uložen náš režijní kód. Jak na to?

Přidání sekce do souboru



Základem všeho je načtení souboru do paměti a získání struktury IMAGE_NT_HEADERS:

HANDLE File;
PIMAGE_NT_HEADERS pImageNT;
DWORD NOBR;

File = CreateFile("pokus.exe",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL); //získáme HANDLE souboru
DWORD Size = GetFileSize(File,NULL)+0x1000/*SizeOfRawData*/;
BYTE *pMem = new BYTE[Size]; // alokujeme paměť
ReadFile(File,pMem, GetFileSize(File,NULL),&NOBR,NULL); //načtení souboru do paměti
pImageNT = ImageNtHeader((VOID*)pMem); // získání struktury IMAGE_NT_HEADERS

V prvé řadě musíme zjistit, jestli je v tabulce sekcí dostatek místa na přidání nové sekce. To uděláme tak, že sečteme velikosti hlaviček v souboru, připočítáme novou sekci (respektive její deklaraci v tabulce sekcí) a porovnáme s hodnotou SizeOfHeaders.

DWORD SecNum = pImageNT->FileHeader.NumberOfSections;
DWORD velsekce = sizeof IMAGE_SECTION_HEADER;
DWORD velikost = SecNum * velsekce + velsekce;
DWORD celkvelikost = (DWORD)(pImageNT) - (DWORD)(pMem) + velikost + 0x0F8/*velikost PE hlavičky*/;
DWORD velhlavicek = pImageNT->OptionalHeader.SizeOfHeaders;

if (celkvelikost > velhlavicek)
{
   //…chyba - nedostatek místa v tabulce sekcí
}

Novou sekci přidáme za poslední sekci v souboru, proto o ní potřebujeme znát nějaké informace. 
Protože víme, že do většiny sekcí budeme později zapisovat (kódování/dekódování), nastavíme jejich charakteristiku na "writeable", tedy možnost zápisu:

DWORD vaddr,AdrOfSecTable;

for (int i = 0;i < dwSecNum;i++)
{
    AdrOfSecTable = (DWORD)pImageNT + (sizeof IMAGE_NT_HEADERS)+i*(sizeof IMAGE_SECTION_HEADER);
    memcpy(&vaddr,(VOID*)(AdrOfSecTable+12),sizeof vaddr);
    pSection = ImageRvaToSection(pImageNT,pMem_,vaddr);
    if (pSection != 0)
    {
        pSection->Characteristics = pSection->Characteristics | 0x80000000;//writeable flag
    }
}

Pokud nechcete použít funkci ImageRvaToSection, musíte jednotlivé proměnné nahrávat manuálně (např. již použitou funkcí memcpy).

Nyní použijeme informace o poslední sekci v souboru k výpočtu důležitých dat naší nové sekce:

VirtualAddress = PEAlign(pSection->VirtualAddress + pSection->Misc.VirtualSize, pImageNT->OptionalHeader.SectionAlignment);
VirtualSize = 0x100;
SizeOfRawData = 0x1000;
Characteristics = 0xE00000E0;
PointerToRawData = pSection->PointerToRawData + pSection->SizeOfRawData;

Vše je více než jasné, akorát bych rád upozornil na funkci PEAlign - ta má za úkol výpočet nejbližšího možného násobku zadaných čísel. Použijeme ji k tomu, abychom řádně zarovnali sekci v paměti (viz. seriál PE file format). Správně bychom ji měli použít také při výpočtu SizeOfRawData (se zarovnáním na FileAlignment), ale tím si teď komplikovat situaci nebudeme.

Nyní už stačí jen upravit několik hodnot ve struktuře IMAGE_NT_HEADERS, aby zůstal soubor funkční. Samozřejmě musíme zvýšit NumberOfSections o jedna. Hodnoty SizeOfImage, SizeOfCode a SizeOfInitializedData zvětšíme o velikost přidaných dat.

pImageNT->FileHeader.NumberOfSections += 1;
pImageNT->OptionalHeader.SizeOfImage += SizeOfRawData;
pImageNT->OptionalHeader.SizeOfCode += SizeOfRawData;
pImageNT->OptionalHeader.SizeOfInitializedData += SizeOfRawData;

Obsah paměti uložíme do souboru a dílo je dokonáno. Ukázkový příklad, který do souboru pokus.exe přidá novou sekci si můžete stáhnout zde.

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » Assembler  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: