Ochrana před debuggingem - detekce hardwarových breakpointů 2 - 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

 

Jaký fotograf/ka získal/a cenu za nejpopulárnější příspěvek v Nikon Photo Contest?

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



Assembler

Ochrana před debuggingem - detekce hardwarových breakpointů 2

2. července 2001, 00.00 | Pokračování povídání o detekci hardwarových berakpointů. Dnes se podrobněji vrátíme k příkladu z minulého dílu..


V dnešním díle podrobně rozeberu kód příkladu z minulého dílu:

__try 
{
   ……………………. 


__except(MyHandler(GetExceptionInformation(), check, Adresa, mybreak)) 
{



Do bloku __try umístíme kód, o kterém si myslíme, že může způsobit chybu (ten náš ji způsobí zcela určitě) a do hlavičky bloku __except funkci, která zajistí opravení případné chyby (tzv. Handler).

Náš Handler je hlavní částí celého programu - opraví záměrně vyvolanou chybu v programu a struktury zaplněné při vzniku této chyby využije při nastavení breakpointů do aplikace. Vzhledem k tomu, že nastavené breakpointy způsobí další chyby, o které se opět postará Handler, stačí je jen spočítat a zkontrolovat, jestli opravdu došlo ke všem.

DWORD MyHandler(EXCEPTION_POINTERS *pexcept_point, int &check, DWORD Adresa, int mybreak)
{
  pexcept_point->ContextRecord->Eip +=1; //zde se posuneme o 1 bajt dál při zpracovávání instrukcí, tím odstraníme vzniklou chybu
  pexcept_point->ContextRecord->Dr0 = Adresa+18; //nastavíme breakpointy do všech registrů, které SoftIce používá
  pexcept_point->ContextRecord->Dr1 = Adresa+16; //"Adresa+X" je umístění bezvýznamných instrukcí v __try bloku, na které můžeme breakpointy nastavit
  pexcept_point->ContextRecord->Dr2 = Adresa+14;
  pexcept_point->ContextRecord->Dr3 = Adresa+12; //breakpointy umístíme tak, aby v Dr3 byl první a v Dr0 poslední
  pexcept_point->ContextRecord->Dr6 = 0;

  if (mybreak == 0) 
  { // registr Dr7 musíme poprvé zaplnit taktéž 
     pexcept_point->ContextRecord->Dr7 = 0x255;
  }
  else
  { // znovu již to není třeba
     pexcept_point->ContextRecord->Dr7 = 0;
  }
  if (pexcept_point->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
    {
    //zde se zpracuje naše první chyba vyvolaná v __try bloku
    //pokud zvolíte jinou chybu, musíte upravit ExceptionCode na správnou hodnotu - vše najdete v nápovědě

     return EXCEPTION_CONTINUE_EXECUTION; //vše je opraveno, takže můžeme pokračovat v průběhu programu
  }
  if (pexcept_point->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP)
    {
    //zde se zpracují nastavené breakpointy (vlastně jsou to jen další chyby..)
     check++; //zvýší se počet úspěšných breakpointů
     return EXCEPTION_CONTINUE_EXECUTION;
  }

  //pokud vznikne jiná chyba, než na kterou je náš Handler připraven, necháme jí volný průběh…

  return EXCEPTION_CONTINUE_SEARCH;

}

__try blok:

__try 
{
__asm
{
INT 3 //první chyba, kterou program způsobí
NOP //NOP je zde velice důležitý!! cx_Eip(NT) ukazuje na INT 3, ale cx_Eip(WIN95) ukazuje na NOP!!


NOP //1. breakpoint
NOP

NOP //2. breakpoint
NOP

NOP //3. breakpoint
NOP

NOP //4. breakpoint
NOP 
}
mybreak++; 
}

Záměrně jsem vyvolal chybu instrukcí INT3, protože jsme ji již použili při detekci debuggeru a chybu jsem následně ošetřili voláním API funkce SetUnhanldedExceptionFilter. Tím chci pouze ukázat, že volání této API funkce není jediným možným řešením.Takto vzniklou chybu opravíme posunem ve zpracování instrukcí o jeden bajt. Pokud zvolíte ke způsobení chyby instrukci, která zabírá větší počet bajtů, musíte náležitě upravit počet bajtů, o které posouváte zpracování dopředu. 

A na závěr už jen zkontrolujeme, jestli opravdu došlo ke všem, tedy čtyřem (Dr0 - Dr3), nastaveným breakpointům:

if (check == 4)
{ // vše je v pořádku
MessageBox("No BPM's",NULL,MB_OK);
}
else
{ // POZOR!! Zlý cracker si nastavil hardwarový breakpoint
MessageBox("BPM found",NULL,MB_OK);
}

Doufám, že již všichni aspoň trochu pochopili jak náš ukázkový příklad pracuje a v příštím díle si ukážeme nějaké další možnosti využití SEHu ke "zmatení soupeře".

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: