jeśli zadzwonisz systemu CreateProcess
wewnętrznie zadzwonić ZwCreateThread[Ex]
stworzyć pierwszy wątek w procesie
podczas tworzenia wątku - ty (jeśli bezpośrednie połączenie ZwCreateThread
) lub system zainicjować rekord nowego wątku CONTEXT
- TUTAJ Eip(i386)
lub Rip(amd64)
na punkt wejścia wątku. jeśli to zrobisz - możesz podać dowolny adres. ale kiedy zadzwonisz, powiedz Create[Remote]Thread[Ex]
- jak mówię - wypełnij system CONTEXT
i ustaw samoczynną rutynę jako punkt wejścia wątku. Twój oryginalny punkt wejścia zostanie zapisany w rejestrze Eax(i386)
lub Rcx(amd64)
.
Nazwa tej procedury zależała od wersji systemu Windows.
wcześniej to było BaseThreadStartThunk
lub BaseProcessStartThunk
(w przypadku od CreateProcess
nazywany) od kernel32.dll
.
, ale teraz system określa RtlUserThreadStart
z ntdll.dll
. RtlUserThreadStart
zwykle wywołuje BaseThreadInitThunk
od kernel32.dll
(z wyjątkiem rodzimych (uruchamianie rozruchu) aplikacji, takich jak smss.exe
i chkdsk.exe
, które nie mają w ogóle przestrzeni adresowej w ogóle). BaseThreadInitThunk
już wywołuje swój pierwotny punkt wejścia wątku i po (jeśli) go zwróci - RtlExitUserThread
wywołana.
głównym celem tego wspólnego wątku startowego owijki - zestaw najwyższym poziomie SEH
filtr. tylko dlatego, że możemy nazwać funkcję SetUnhandledExceptionFilter
. jeśli wątek rozpoczyna się bezpośrednio od punktu wejścia, bez opakowania - funkcja Top level Exception Filter staje się niedostępna.
ale niezależnie od punktu wejścia wątku - wątku w przestrzeni użytkownika - NIGDY zacznij wykonywać od tego punktu!
wcześnie, kiedy użytkownik rozpoczyna wątek Tryb wykonać - System APC
wstawić do wątku z LdrInitializeThunk
jako APC-rutyna - odbywa się to poprzez kopiowanie (zapisz) wątek CONTEXT
do stosu użytkownika, a następnie zadzwonić KiUserApcDispatcher
który nazywamy LdrInitializeThunk
.gdy zakończy się LdrInitializeThunk
- wracamy do KiUserApcDispatcher
, który wywołał NtContinue
z zapisanym wątkiem CONTEXT
- dopiero po tym, jak już zaczyna się wykonywanie punktu wejścia wątku.
, ale teraz system wykonuje pewne optymalizacje w tym procesie - kopiuje (zapisuje) wątek CONTEXT
do stosu użytkownika i wywołuje bezpośrednio LdrInitializeThunk
. na końcu tej funkcji wywołana - i wykonywany jest punkt wejścia wątku.
tak KAŻDY wątek rozpocząć wykonywać w trybie użytkownika z LdrInitializeThunk
. (tej funkcji z dokładnie nazwie istnieje i nazywa się we wszystkich wersjach Windows z NT4 do win10)
Co to jest funkcja zrobić? bo co to jest? możesz być słuchać powiadomienia o DLL_THREAD_ATTACH
? kiedy rozpoczyna się nowy wątek w procesie (z wyjątkiem specjalnych obrobionych przez system wątków, takich jak LdrpWorkCallback
) - przechodzi on przez załadowaną listę DLL i wywołuje punkty wejściowe bibliotek DLL z powiadomieniem DLL_THREAD_ATTACH
(oczywiście, jeśli DLL ma punkt wejścia i DisableThreadLibraryCalls
nie jest wywoływany dla tej biblioteki DLL). ale w jaki sposób jest to realizowane? Dzięki LdrInitializeThunk
, które wymagają LdrpInitialize
->LdrpInitializeThread
->LdrpCallInitRoutine
(DLL dla PE)
gdy pierwsza nić na początku procesu - jest to przypadek szczególny. potrzeba wielu dodatkowych zadań do inicjalizacji procesu. w tej chwili tylko dwa moduły załadowane w procesie - EXE
i ntdll.dll
. LdrInitializeThunk
zadzwoń pod numer LdrpInitializeProcess
dla tego zadania. jeśli bardzo krótko:
- różne struktury proces jest inicjowany
- ładowanie wszystkich DLL (i ich rodzin), do którego EXE statycznie powiązane - ale nie nazywają EPS!
- nazywa
LdrpDoDebuggerBreak
- funkcja wygląd - są debugger dołączone do procesu, a jeśli tak - int 3
nazywa - tak debugger otrzymać wiadomość Wyjątek - STATUS_BREAKPOINT
- większość debugery mogą rozpocząć debugowanie rozpocząć UI tylko z tego punktu. jednak istnieje debugger (S), które pozwoli jak proces debugowania z LdrInitializeThunk
- wszystkie moje screeny z tego rodzaju debuggera
- ważny punkt - aż w procesie wykonywany kod tylko z
ntdll.dll
(i może wynosić od kernel32.dll
) - kod z innego Pliki DLL, jakikolwiek kod firm zewnętrznych, który nie został jeszcze wykonany w procesie.
- Opcjonalny załadowany shim dll do przetworzenia - Zainicjowano silnik Shim. ale jest to opcjonalne
- spacer przez załadowanej listy DLL i wywołać jego EPki z
DLL_PROCESS_DETACH
TLS inicjacji i wywołania zwrotne TLS zwanych (jeśli istnieje)
ZwTestAlert
nazywa - to sprawdzenie połączenia są istnieć APC w wątek kolejki i wykonaj jego. ten punkt istnieje we wszystkich wersjach od NT4 do win 10.To pozwoli na przykład stworzyć proces w zawiesinie w a następnie wstawić połączenia APC (QueueUserAPC
), aby gwint (PROCESS_INFORMATION.hThread
) - w wyniku tego połączenia będzie wykonywane po zakończeniu procesu zostanie całkowicie inicjowane wszystkie DLL_PROCESS_DETACH
nazywa, ale przed EXE Punkt wejścia. w kontekście pierwszego wątku procesu.
- i NtContinue nazywa wreszcie - to przywrócenie zachowanego kontekstu wątek i wreszcie przejść do wątku EP
przeczytać również Flow of CreateProcess
ładowarka jest za to odpowiedzialny. Jest to składnik systemu operacyjnego, a sposób jego działania jest taki, że nie zobaczysz wielu dowodów na to w stosie wywołań. W innym przypadku wyjaśnienie w pojedynczej odpowiedzi z przepełnieniem stosu jest zbyt skomplikowane. Zastanów się nad zakupem książki na temat Windows Internals, jeśli chcesz dowiedzieć się o ... no cóż, o wewnętrznych cechach Windows. :-) –
Ponadto, Windows ładuje biblioteki DLL wymagane przez EXE i przeprowadza relokację. A niektóre kody z tych bibliotek DLL mogą być wykonywane przed main(). –
powiązane: proces uruchamiania w systemie Linux: http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html. Także [jak stworzyć malutki, ale wciąż działający plik wykonywalny Linuxa] (http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html). Linux robi większość rzeczy związanych z uruchamianiem procesu w jądrze niż Windows, ale dynamiczny plik binarny wciąż uruchamia dynamiczny linker, a następnie kod startowy CRT w kontekście nowo uruchomionego procesu przestrzeni użytkownika przed C 'main()' funkcjonować. –