haker.info  — Etyczny hacking_

 Wykrywanie okna określonego narzędzia

   Dawid Farbaniec    730 słów

1. Słowem wstępu

en wpis zawiera opis prostej i znanej metody przeciwko inżynierii odwrotnej kodu (RCE). Jej zasada działania polega na wykrywaniu czy okno określonego narzędzia (np. debuggera, disassemblera, piaskownicy, hex edytora itp.) jest uruchomione. W przypadku wykrycia danego narzędzia analizowana aplikacja może zmienić swój przepływ wykonania, czyli działać inaczej niż zwykle. Można zaprogramować nieoczekiwane zamknięcie aplikacji (z komunikatem ostrzegawczym lub bez) czy po prostu powodować jej błędne działanie w celu utrudnienia analizy wstecznej jej kodu. Metoda ta nie jest żadną nowością, jednak chciałbym przedstawić ją na gotowych przykładach w trzech językach programowania (Asembler, C++ i C#.NET), aby początkujący programiści, którzy jej potrzebują mieli mocny punkt zaczepienia.

2. Schemat działania

  • Utworzenie funkcji zwrotnej EnumWindowsProc, która porównuje pobrany tytuł (GetWindowText) bieżącego okna z szukanym napisem.
  • Wywołanie funkcji EnumDesktopWindows interującej po oknach bieżącego pulpitu (podając jej adres funkcji zwrotnej typu callback).
  • W przypadku wykrycia okna pulpitu o określonym tytule wyświetlany jest komunikat.
  • Zachowanie po wykryciu okna narzędzia należy zaprogramować wedle uznania.

3. Przykład w Asemblerze x64 (MASM64 / ML64.EXE)

;------------------------------------------------------------+ ; Coded in Assembler x64 (MASM64 / ML64.EXE) by haker.info | ; | ; PL: Program sprawdza czy okno określonego | ; narzędzia jest uruchomione (Unicode!) | ; | ; EN: Application iterates through all | ; desktop windows to check specified window title | ;------------------------------------------------------------+ extrn EnumDesktopWindows : proc extrn GetWindowTextW : proc extrn GetWindowTextLengthW : proc extrn MessageBoxW : proc extrn lstrcmpW : proc extrn ExitProcess : proc .data ;unicode string "Kalkulator" szTargetTitle dw "K","a","l","k","u","l","a","t","o","r", 0 ;bufor na aktualnie pobrany tytuł szCurrentWindow dw 4096 dup(0) ;unicode string "Znaleziono!" szMessageText dw "Z","n","a","l","e","z","i","o","n","o","!",0 szCopyright db "haker.info", 0 .code ;funkcja zwrotna (callback) pobierająca uchwyty okien pulpitu EnumWindowsProc proc hWnd : qword, lparam : qword ;pobierz tytuł bieżącego okna sub rsp, 30h xor r9,r9 mov r8, 255 mov rdx, offset szCurrentWindow call GetWindowTextW add rsp, 30h ;jeśli napis jest pusty zwróć TRUE (szukaj dalej) test rax, rax jz _true ;porównaj bieżący tytuł okna z szukanym napisem sub rsp, 30h xor r9,r9 xor r8, r8 mov rdx, offset szTargetTitle mov rcx, offset szCurrentWindow call lstrcmpW add rsp, 30h ;jeśli to nie ten tytuł to zwróć TRUE (szukaj dalej) test rax, rax jnz _true ;w przeciwnym wypadku wyświetl komunikat, że znaleziono :) sub rsp, 30h xor r9,r9 mov r8, offset szMessageText mov rdx, offset szMessageText xor rcx, rcx call MessageBoxW add rsp, 30h jmp _false _true: mov rax, 01h ret _false: mov rax, 0h ret EnumWindowsProc endp ;funkcja główna Main proc ;wywołanie funkcji wyliczającej okna bieżącego pulpitu sub rsp, 28h xor r9, r9 mov r8, offset szTargetTitle mov rdx, EnumWindowsProc xor rcx, rcx call EnumDesktopWindows add rsp, 28h ;zakończ program sub rsp, 8h xor rcx, rcx call ExitProcess Main endp end


Budowanie powyższego kodu w Asemblerze MASM64 (BUILD.BAT):

@echo off ml64.exe prog1.asm /link /entry:Main /subsystem:windows /defaultlib:"kernel32.Lib" /defaultlib:"user32.Lib" /LARGEADDRESSAWARE:NO pause

4. Przykład w Visual C++

/* Coded in Visual C++ by haker.info PL: Program sprawdza czy okno określonego narzędzia jest uruchomione EN: Application iterates through all desktop windows to check specified window title */ #include <Windows.h> #include <string> BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { WCHAR titleText[255] = { '\0' }; std::wstring title; if (GetWindowTextLength(hwnd) == 0) return TRUE; GetWindowText(hwnd, titleText, 255+1); title = titleText; if (title.find((LPCWSTR)lParam) == 0) { MessageBox(0, (std::wstring(L"Znaleziono okno o nazwie: ") + title).c_str(), L"Informacja", MB_ICONINFORMATION); return FALSE; } return TRUE; } int wmain() { std::wstring targetTitle = L"Kalkulator"; EnumDesktopWindows(0, &EnumWindowsProc, (LPARAM)targetTitle.c_str()); return EXIT_SUCCESS; }

5. Przykład w Visual C# (.NET)

/* Coded in C#.NET by haker.info PL: Program sprawdza czy okno określonego narzędzia jest uruchomione EN: Application iterates through all desktop windows to check specified window title */ using System; using System.Text; using System.Runtime.InteropServices; namespace ConsoleApp1 { class Program { [DllImport("user32.dll")] static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDesktopWindowsDelegate lpfn, IntPtr lParam); [DllImport("user32.dll", EntryPoint = "GetWindowText", ExactSpelling = false, CharSet = CharSet.Auto)] static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount); [DllImport("user32.dll", CharSet = CharSet.Unicode)] static extern int MessageBox(int hWnd, string text, string caption, uint type); const int MB_ICONINFORMATION = 0x00000040; delegate bool EnumDesktopWindowsDelegate(IntPtr hWnd, int lParam); static void Main(string[] args) { string targetTitle = "Kalkulator"; EnumDesktopWindowsDelegate EnumWindowsProc = (IntPtr hWnd, int lParam) => { var title = new StringBuilder(255); GetWindowText(hWnd, title, title.Capacity + 1); if (string.IsNullOrEmpty(title.ToString())) return true; if (title.ToString().Contains(targetTitle)) { MessageBox(0, "Znaleziono okno o nazwie: " + title, "Informacja", MB_ICONINFORMATION); return false; } return true; }; EnumDesktopWindows(IntPtr.Zero, EnumWindowsProc, IntPtr.Zero); } } }

Zakończenie

Dziękuję za czas poświęcony na przeczytanie tego wpisu.

Dawid Farbaniec


Tagi:  reverse-engineering  masm64  visual-cpp  c-sharp 

Komentarze czytających



Wszystkie treści umieszczone na tej witrynie są chronione prawem autorskim. Surowo zabronione jest kopiowanie i rozpowszechnianie zawartości tej witryny bez zgody autora. Wszelkie opublikowane tutaj treści (w tym kody źródłowe i inne) służą wyłącznie celom informacyjnym oraz edukacyjnym. Właściciele tej witryny nie ponoszą odpowiedzialności za ewentualne niezgodne z prawem wykorzystanie zasobów dostępnych w witrynie. Użytkownik tej witryny oświadcza, że z zamieszczonych tutaj danych korzysta na własną odpowiedzialność. Wszelkie znaki towarowe i nazwy zastrzeżone zostały użyte jedynie w celach informacyjnych i należą wyłącznie do ich prawnych właścicieli. Korzystając z zasobów witryny haker.info oświadczasz, że akceptujesz powyższe warunki.