[C++/ Wstawki assemblerowe] Hook na funkcje

0

Witam.

Chciałem zrobić hooka na funkcje używając assemblera i c++.

Nie chcę używac biblioteki detours, <ort>poza tym </ort>detours chyba tylko zakłada hooki na funkcje API ?

przykładowo tu jest funkcja z OllyDbg:


// naglowek funkcji (?)
push EBP
mov EBP, ESP

// przypisanie zmiennej
mov zmienna, 1

// wrzucenie parametru na stos
PUSH zmienna

// wywołanie jakiejs tam funkcji
CALL 0x12345

retn

i mysle, zeby dac <ort>po prostu </ort>pod nagłowkiem funkcji CALL do mojej funkcji i pobranie zwróconej wartosci i zwrocenie jej i przerwanie jezeli wartosc jest true, a kontynuowanie jezeli wartosc zwrocona przez moją funkcje przechwytującą jest false.

Tylko, że nie ma miejsca na CALL i sprawdzenie czy wartosc zwrocona przez moją funkcje przechwytującą jest true/false. I czy przesunięcie całej pamięci o kilka bajtow zeby zrobic miejsce byloby dobrym pomyslem ?

Czy może zadeklarować ileśtam bajtów funkcją VirtualAllocEx, i tam skopiować funkcje, którą chce przechwycić.

I w starym miejscu funkcji którą chce <ort>po prostu </ort>nadpisac kilka bajtów i dać CALL mojaFunkcja

czyli jezeli ktos wywola tą funkcje:

funkcjaKtórąChcęPrzechwycic();

to wywoła się wtedy moja funkcja:

int mojaFunkcja()
{
}

i wtedy moge np w niej dac wywołanie oryginału

int mojaFunkcja()
{
// sprawdzenie czegos tam

 // wywolanie i zwrocenie wartosci zwroconej przez funkcje oryginalną
 return funkcjaKtórąChcęPrzechwycic();

}

Co o tym myslicie?
Pozdrawiam</asm>

0

Kiedyś był taki jeden co by pewnie pomógł, ale poszedł, reszta nie ma jaj.

0

Można:

  • podmieniasz pierwsze 5 bajtów funkcji na call, później emulujesz usunięte instrukcje i przywracasz kontrolę funkcji - skomplikowane, trudne w realizacji (co jeśli funkcja skacze sobie do tych instrukcji) i wymaga disassemblera,
  • podmieniasz pierwsze 5 bajtów funkcji, przy powrocie zapisujesz stary kod, jednocześnie wrzucasz własny adres powrotu z funkcji, po tym jak funkcja wraca podmieniasz kod na call z powrotem,
  • debugujesz proces i normalnie ustawiasz breakpointy
    Drugie i trzecie rozwiązanie to w praktyce jedyne sensowne.
    Drugie może nie zadziałać jeśli kod jest dziwny (funkcja nie wraca, albo robi coś z adresem powrotu), trzecie jeśli są antydebugi, pierwsze wymaga analizy i dużo roboty...
0

Kiedyś był taki jeden co by pewnie pomógł, ale poszedł, reszta nie ma jaj.

A szukałeś zamiast czekać na objawienie.
http://4programmers.net/Forum/352226?h=
http://4programmers.net/Forum/viewtopic.php?id=104080&start=0
http://4programmers.net/Forum/376867?h=#id376867

Jeśli fun jest importowana statycznie z dll można użyć sposobu jak na fun systemowe.
Inna metoda - przerwania (jak debuger) int3 .

  • zdalne wątki i wciskanie .dll do procesu .
    Asembler nie jest tu bardzo potrzebny .
0
dzejo napisał(a)

Jeśli fun jest importowana statycznie z dll można użyć sposobu jak na fun systemowe.

Chyba wyraźnie napisał że chodzi mu o zwykłe?...

Inna metoda - przerwania (jak debuger) int3

Nie 'jak debugger' tylko debugując, metoda z ustawianiem globalnego handlera jest upośledzona, praktycznie każdy program ma zwykłą obsługę błędów, więc to nie zadziała,

  • zdalne wątki i wciskanie .dll do procesu .

A to, to po co? W samym hookowaniu nie ma niczego co wymagałoby wątków,

metoda z podmianą początku na call + podmianą adresu powrotu jest najlepsza, zadziała w większości przypadków.

0

Chyba wyraźnie napisał że chodzi mu o zwykłe?...
No to co ?

praktycznie każdy program ma zwykłą obsługę błędów

To jest i niezwykła ?
Może sobie mieć ,seh zadziała...
http://4programmers.net/Forum/viewtopic.php?id=104080&start=0

#include <windows.h>
#include <excpt.h>
#include <stdio.h>

EXCEPTION_DISPOSITION  _except_handler(EXCEPTION_RECORD *ExceptionRecord,
       void * EstablisherFrame,CONTEXT *ContextRecord,void * dispatcherContext) ;

char cWriteFile[10];
char bp[] = {'\xCC','\x90'} ;  // używam tylko pierwszego bajtu
FARPROC fnWriteFile;
const int byteIndex = 1 ;      // pierwszy (jeden bajt)
DWORD d ;

int main()
{

        fnWriteFile = GetProcAddress(GetModuleHandle("kernel32.dll"),"WriteFile"); // dodane
        if(fnWriteFile == NULL )
        {
          printf("Error->GetProcAddress->WriteFile\n");
          system("pause");
          return 1 ;
        }

//---------Instaluj Handler

         DWORD handler = (DWORD)_except_handler;

        // prawdziwa instalacja try
        __asm {
                push  handler // nowy handler
                push fs:0 // stary handler
                mov fs:0,esp // dodaj node do 'SEH'
        }

// zapamiętaj oryginalny bajt
        ReadProcessMemory(GetCurrentProcess(), fnWriteFile/*zmiana*/, cWriteFile, byteIndex,0);
// zapisz int3
        WriteProcessMemory(GetCurrentProcess(),fnWriteFile, bp, byteIndex, 0);
        // i czekaj na wyjątki
      try{
        WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\n**WriteFile**z main**\n", 22, &d, 0);


        getchar();
        WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\n**WriteFile**z main**\n", 22, &d, 0);
        }catch(...)
        {
          printf("dupa");
        }
        _asm {
                pop dword ptr fs:0  // usuwa node i przywraca stary handler
                add esp,4 // usuwa adres _except_handler
        }

        system("pause") ;
        return 0;
}


//------------------------------------------------------------------

EXCEPTION_DISPOSITION  _except_handler(EXCEPTION_RECORD *ExceptionRecord,
       void * EstablisherFrame,CONTEXT *ContextRecord,void * dispatcherContext)
{
        static bool singlestep = false;
        DWORD dwExceptionCode ;
        EXCEPTION_DISPOSITION status = ExceptionContinueSearch;
        // uwaga! printf używa WriteFile

        dwExceptionCode = ExceptionRecord->ExceptionCode ;

        switch (dwExceptionCode)
        {
          case EXCEPTION_BREAKPOINT:
          if (ExceptionRecord->ExceptionAddress == (LPVOID)fnWriteFile )
          {
            status = ExceptionContinueExecution;
            WriteProcessMemory(GetCurrentProcess(),fnWriteFile,cWriteFile, byteIndex, 0);

            ContextRecord->EFlags |= 0x100;
            ContextRecord->Eip = (DWORD)ExceptionRecord->ExceptionAddress;
            singlestep = true;
            printf("EXCEPTION_BREAKPOINT\n");
            printf("ktos uzyl WriteFile %X\n", (DWORD)fnWriteFile);
          }

          break;
          case EXCEPTION_SINGLE_STEP :
                if (singlestep)
                {
                  printf(" - ustawiam single step\n");
                        singlestep = false;
                  char bp = '\xCC';
                  WriteProcessMemory(GetCurrentProcess(), fnWriteFile, &bp, 1, 0);
                  status = ExceptionContinueExecution;
                }
          break ;
          default:
          status = ExceptionContinueSearch;

        }

        return status ;
}

A to, to po co? W samym hookowaniu nie ma niczego co wymagałoby wątków
Zabawne ,,, masz na myśli drętwe SetWindowsHookEx.
http://www.codeproject.com/KB/threads/winspy.aspx

0
dzejo napisał(a)

Chyba wyraźnie napisał że chodzi mu o zwykłe?...
No to co ?

praktycznie każdy program ma zwykłą obsługę błędów

To jest i niezwykła ?
Może sobie mieć ,seh zadziała...
http://4programmers.net/Forum/viewtopic.php?id=104080&start=0
<kod>

A to, to po co? W samym hookowaniu nie ma niczego co wymagałoby wątków
Zabawne ,,, masz na myśli drętwe SetWindowsHookEx.
http://www.codeproject.com/KB/threads/winspy.aspx

Czy ty jesteś upośledzony?
Tutaj chodzi o hookowanie zwykłej funkcji (znamy tylko jej adres) w innym procesie, nie (wiadomości) okien!
Ogólny, jeden dla całego procesu handler ustawia się używając funkcji SetUnhandledExceptionFilter.

SEH jest częścią TIB i każdy wątek ma osobny SEH. Żeby łapać wyjątki w oryginalnym wątku programu trzebaby ustawić SEH tego wątku. Można to zrobić z innego wątku korzystając z PEB, ale:

  • jest to trudniejsze
  • może wywalić program jeśli z jakiegoś powodu oczekuje on takiego, a nie innego układu SEH
  • przerwanie może zostać ukryte jeśli program zaopiekuje się nim sam wcześniej (zapewne się wyłączając)

I dlatego sposób drugi jest najlepszy. Ma on swoje problemy jeśli aplikacja jest wielowątkowa (da się rozwiazać), ale w większości przypadków wystarczy.

Ogólnie - pieprzysz bzdury nie na temat.

0

Czy ty jesteś upośledzony?
Tutaj chodzi o hookowanie zwykłej funkcji (znamy tylko jej adres) w innym procesie, nie (wiadomości) okien!

Chyba tak .
Ale chodziło mi nie o komunikaty tylko ładowanie .dll do procesu przy pomocy SetWindowsHookEx.
Mały Offtop.
Odnośnie upośledzenia , w takim razie cały temat :
http://4programmers.net/Forum/viewtopic.php?id=104080&start=0
można o d..e potłuc , miałeś rację z Seh .
Lokalnie to nawet chodzi (z SetUnhandledExceptionFilter) ale zdalnie nic z tego .

Mam jeszcze pytanie o ile w Win XP zapis za pomocą WriteProcessMemory(GetCurrentProcess(),f itd
danych do kodu programu idzie bez problemu to za cholerę ten sam kod
nie może zapisać nic , nawet po zmianie atr. ochrony przez VirtualProtect w Win 98 .
VirtualProtect zwraca Ok . jednak zapis nie .
Czy można zmienić Access dla istniejącego Procesu na PROCESS_VM_OPERATION , PROCESS_VM_WRITE w nim
samym ?

0

MSDN ukradli?

1 użytkowników online, w tym zalogowanych: 0, gości: 1