ďťż

W rejestrze EAX mamy liczbę, którą trzeba pomnożyć przez 2 i wynik dodać zmiennej first_thunk...

Nie chcesz mnie, Ben. Składam się z siedmiu warstw popieprzenia okraszonych odrobiną gównianego szaleństwa.
znaleziona_funkcja: shl mov add mov eax, 2 ebx, [ebp+offset first_thunk] eax, ebx eax, [eax] ; EAX= adres funkcji Mamy adres funkcji, teraz możemy już w łatwy sposób uzyskać adres KERNEL32.DLL kernel db "KERNEL32.DLL",0 mov edx, offset kernel add edx, ebp push edx ; zachowaj ;GetModuleHandle("KERNEL32.DLL"); ; jeżeli błąd, to funkcja zwraca NULL mov [ebp+offset adresGMH], eax cali eax cmp eax, O jne znaleziono_kernel W przypadku, gdy któryś z fragmentów kodu skoczy do etykiety "nie_znalezione", możemy się jeszcze ratować próbą wykorzystania stałego adresu załadowania KERNEL32.DLL, ale uwaga adres ten nie musi być we wszystkich wersjach Windows taki sam. Trzeba uważać ponieważ w przypadku, gdy nie jest to adres jądra, to możemy doprowadzić do zawieszenia się systemu. nie_znalezione: mov eax, OBFFTOOOOh Wcześniej jeżeli wszystko poszło po naszej myśli, to program skoczy do etykiety "znaleziono_kernel" a rejestr EAX będzie wskazywał na moduł jądra w pamięci. znaleziono_kernel: mov mov cmp jne mov add cmp jne [ebp+offset adres jądra], eax edi, eax wordptr [edi]. 'ZM' błąd edi, [edi+3Ch] edi, [ebp+offset adres jądra] word ptr [edi], 'EP' błąd zachowaj adres jądra standardowe sprawdzenia Wszystko w porządku, mamy zlokalizowane jądro w pamięci. Teraz powinniśmy odszukać funkcję GetProcAddress, która zwraca nam adres funkcji w pamięci. Dzięki temu w przyszłości nie będzie potrzeby stosowania naszego kodu do odnajdywania funkcji, co bardzo nam ułatwi prace, ponieważ kiedy zajdzie potrzeba wywołania dowolnego API, posłużymy się GetModuleHandle (zwróci nam uchwyt do modułu) oraz GetProcAddress (zwróci nam adres funkcji z tego modułu do którego mamy uchwyt). Sprawa wydaje się być prosta i oczywista. Posiadając adres jądra, możemy przystąpić do analizowania jego tabeli eksportów, w celu odnalezienia szukanej, eksportowanej przez ten moduł funkcji GetProcAddress . 32 pushad mov add mov add lodsd mov lodsd lodsd mov add lodsd add mov lodsd add mov lodsd add mov mov lodsd add esi, [edi+78h] esi, [ebp+offset adres jądra] [ebp+offset eksport], esi esi, lOh [ebp+offset baza_numer], eax [ebp+offset liczba_nazw], eax eax, [ebp+offset adres jądra] eax, [ebp+offset adres jądra] [ebp+offset adres_funkcji], eax eax, [ebp+offset adres jądra] [ebp+offset adres_nazw], eax eax, [ebp+offset adres jądra] [ebp+offset adres_numerow], eax esi, [ebp+offset adres_funkcji] eax, [ebp+offset adres jądra] ; przejdź do tabeli eksportu (element O w DataDirectory) ; dodaj aby otrzymać VA z RVA ; zachowaj ; ustaw się. na pole w IMAGE_EXPORT_DIRECTORY ; pobierz nBase ; pobierz NumberOfFunctions ; pobierz NumberOjNames ; pobierz AddressOfFunctions ; pobierz AddressOjNames ; pobierz AddressOjNameOrdinals Pobraliśmy wszystkie istotne pola z IMAGE_EXPORT_DIRECTORY. funkcji GetProcAddress w tabeli eksportów: Możemy przystąpić do szukania mov mov mov add xor mov add szuka j_dalej: mov skanuj: cmpsb jne cmp je esi, [ebp+offset adres_nazw] [ebp+offset indeks], esi edi, [esi] edi, [ebp+offset adres jądra] ecx, ecx ebx, offset strGPA ebx, ebp esi, ebx następny byte ptr [edi], O znaleziono_funkcj e skanuj ; wskaźnik na pierwszą nazwę ; zachowaj indeks do tabeli ;licznik ; ustaw EBX na nazwę funkcji, której szukamy ; ESI = nazwa szukanej funkcji ; porównaj jeden bajt (znak stringa) ; nie ta funkcja? ; koniec? następny: inc cmp jge add mov mov add ex ex, word ptr [ebp+offset liczba_nazw] błąd dword ptr [ebp+offset indeks], 4 esi, [ebp+offset indeks] edi, [esi] edi, [ebp+offset adres jądra] szukaj_dalej ; porównanie licznika z ilością ; importowanych funkcji z KERENL32.DLL ; 4 = DWORD, zwiększ i próbuj dalej 33 ,gdzie mamy tak zdefiniowane zmienne: strGPA db "GetProcAddress",0 adresGPA dd O Gdy znaleziono string w tabeli wskazywanej przez AddressOfNames, odpowiadający szukanej funkcji, to rejestr CX zawiera indeks do tabeli AddressOfNameOrdinals. Teraz jeżeli chcemy uzyskać RVA szukanej funkcji, to trzeba wykonać (zapis języka C): NumerFunkcji = *(CX * 2 + AddressOfNameOrdinals ); (mnożymy przez 2 bo elementami w tabeli AddressOfNameOrdinals są WORD'y) NumerFunkcji jest indeksem do tabeli adresów funkcji (AddressOfNames), której elementami sąDWORD'y. Zatem posiadając taki indeks, możemy otrzymać adres naszej API GetProcAddress: AdresFunkcji= *(NumerFunkcji*4 + AddressOfFunctions); Tak wygląda to w assemblerze: znaleziono_funkcje: mov ebx, esi inc ebx shl ecx, l ; ECX=ECX*2, bo 2A1=2 mov esi, [ebp+offset adres_numerow] ; AddressOfNameOrdinals add esi, ecx xor eax, eax mov ax, word ptr [esi] shl eax, 2 ; NumerFunkcji=NumerFunkcji*4, bo 2A2=4 mov esi, [ebp+offset adres_funkcji] ; AddressOfFunctions add esi, eax mov edi, dword ptr [esi] ; pobierz RVA add edi, [ebp+offset adres Jądra] ; i skonwertuj do VA (YirtalAddress) EDI wskazuje na funkcję GetProcAddress ! Zachowamy to. mov [ebp+offset adresGPA], edi popad ; zakończ całą operację, odzyskaj zachowane rejestry Teraz już możemy spokojnie wywoływać dowolne API, możemy przecież odnaleźć ich adresy: push offset mov eax, [ebp+offset adres jądra] push eax mov eax, [ebp+offset adresGPA] ; GetProcAddress(funkcja,moduł); cali eax cmp eax, O jz błąd Powyższy fragment kodu dotyczy przypadku, kiedy chcemy wywołać funkcję eksportowaną w KERNEL32.DLL. W innych przypadkach musimy uzyskać uchwyt do modułu, w którym znajduje się funkcja. Robimy to poprzez funkcję GetModuleHandle(), jej adres mamy zapamiętany w adresGMH. W rejestrze EAX mamy adres szukanej funkcji, teraz odkładając na stos kolejno jej argumenty (wg konwencji C) i wykonując cali eax wywołujemy odpowiednio naszą funkcję. 34 4
Wątki
Powered by wordpress | Theme: simpletex | © Nie chcesz mnie, Ben. Składam się z siedmiu warstw popieprzenia okraszonych odrobiną gĂłwnianego szaleństwa.