ReverseCraft
Info
Seria ReverseCraft niestety nie będzie już kontynuowana (wyjaśnienie), ale nagrywam/publikuje teraz inne serie videotutoriali (również o sprawach niskopoziomowych, w tym np. kurs assembly) w trochę innej formie. Są dostępne na moim kanale na Youtube. Zachęcam do rzucenia okiem :)

Wszystkie epsy ReverseCraft są również dostępne via Youtube: http://www.youtube.com/user/GynvaelColdwind (playlisty ReverseCraft (PL) oraz ReverseCraft Asm (PL).
Video Details
screen z reversecraft 3 ReverseCraft #3 - Pamięć, proces i PE

Czas trwania:
32 minut (opublikowano 2009-07-08)

Opis:
Trzeci odcinek kursu, w którym omawiam wirtualną przestrzeń procesu, mechanizmy nią kierujące, oraz co się w niej znajduje. Dodatkowo wspominam o mechaniźmie wczytywania pliku PE (czy to modułu (biblioteki) DLL czy modułu EXE) do pamięci procesu.

Linki do video:

Materiały:

Informacje uzupełniające:
Przypominam ze programiści C/C++ znajdą struktury opisujące pliki PE w winnt.h. Natomiast inne struktury, takie jak PEB, TEB, czy SharedUserData, nie są podeklarowane w plikach nagłówkowych - w sekcji Inne linki poniżej umieściłem zestaw linków do rozsianych po necie opisów różnych wspominanych przeze mnie struktur.
Wspominając o SharedUserData w tutorialu wyraziłem się trochę nieściśle mówiąc że jest to 'kawałek pamięci kernela' - jest to prawda, ponieważ ten fragment należy do kernela (kernel go zaalokował, i z tego co mi wiadomo nie ma możliwości odmapowania tego skrawka pamięci), natomiast mimo tego, ten fragment jest zamapowany do przestrzeni adresowej użytkownika, czyli poniżej adresu 0x80000000, więc jest dostępny (do odczytu) również z trybu użytkownika (aka ring 3; w trybie kernela aka ring 0 mamy dostęp również do przestrzeni wirtualnej kernela).
Niewiele czasu poświęciłem również segmentacji; z waznych rzeczy nalezy wiedzieć że każdy rejestr segmentowy (w assemblerze każda instrukcja operująca na pamięci korzysta domyślnie z jakiegoś segmentu, np. PUSH korzysta zawsze z segmentu SS; każdej instrukcji można narzucić inny segment) zawiera w sobie numer pola w tablicy GDT/LDT (patrz manuale Intela) - w tym polu zapisane są dwie informacje - gdzie zaczyna się segment w przestrzeni wirtualnej, oraz jaką ma wielkość. Pod systemami z rodziny Windows większość segmentów (DS, SS, CS i ES) ustawione są tak aby obejmować cały zakres przestrzeni wirtualnej, natomiast FS jest ustawiony różnie w różnych wątkach, i zawsze rozpoczyna się tam gdzie znajduje się TEB danego wątku, i ma wielkość jednej strony. Mając adres wyrażony za pomocą segmentu, np. FS:[18h], należy do adresu początkowego segmentu dodać przesunięcie (w tym wypadku 18h) aby otrzymać adres VA. Segment GS jest segmentem pustym (tj. ma wielkość równą 0).
Poniższy przykładowy program pobiera z systemu oraz wyświetla położenia wszystkich segmentów (kod dla MinGW GCC):
/* ignore the 'control reaches end of non-void function' warnings */
/* code by gynvael.coldwind//vx (gynvael@vexillium.org)           */
#include<windows.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>

/* push SEG; pop eax */
WORD GetCS(void) { __asm__(".ascii \"\\x0E\\x58\""); }
WORD GetDS(void) { __asm__(".ascii \"\\x1E\\x58\""); }
WORD GetES(void) { __asm__(".ascii \"\\x06\\x58\""); }
WORD GetFS(void) { __asm__(".ascii \"\\x0F\\xA0\\x58\""); }
WORD GetGS(void) { __asm__(".ascii \"\\x0F\\xA8\\x58\""); }
WORD GetSS(void) { __asm__(".ascii \"\\x16\\x58\""); }

int
main(void)
{
  LDT_ENTRY ldt;
  HANDLE thdl = GetCurrentThread();

#define PRINT_SEG(a) { GetThreadSelectorEntry(thdl, Get ## a (), &ldt);\
                       printf(#a ": %.8x (%.8x)%s\n",\
         ldt.BaseLow | (ldt.HighWord.Bytes.BaseMid << 16) | (ldt.HighWord.Bytes.BaseHi << 24),\
         (int)(short)ldt.LimitLow, ldt.LimitLow > 0 ? "" : " [unused]"); }
  
  PRINT_SEG(CS);
  PRINT_SEG(DS);
  PRINT_SEG(ES);
  PRINT_SEG(FS);
  PRINT_SEG(GS);
  PRINT_SEG(SS);

  return 0;
}
W tutorialu wspominam o różnych funkcjach, za równo z WinAPI, jak i z bibliotek C; są to następujące funkcje:
  • VirtualAlloc - funkcja do rezerwowania oraz alokowania (wraz z mapowaniem) całych stron pamięci (parametr dwSize zawsze jest zaokrąglany w górę do wielkości strony, czyli np. mimo iż podajemy 1 bajt, to i tak zaalokowana zostanie cała strona); patrz również VirtualFree; przydatna również przy używaniu AWE (patrz niżej)
  • HeapAlloc - funkcja do alokowania pamięci ze sterty (z heap'u); jest to funkcja WinAPI, więc w przeciwieństwie do malloc (który jest C-specyfic) można z niej korzystać w dowolnym języku który ma bindingi do WinAPI; patrz również HeapFree, GetProcessHeap oraz HeapCreate
  • LocalAlloc - kolejna funkcja alokująca pamięć ze starty; obecnie jest ona równoznaczna z GlobalAlloc
  • GlobalAlloc - kolejna funkcja alokująca pamięć ze starty; obecnie jest ona równoznaczna z LocalAlloc
  • malloc - funkcja w C do alokacji pamięci ze starty; patrz również free
  • CreateFileMapping - jednym z zastosowań tej funkcji jest alokacja dodatkowej pamięci, którą następnie można zamapować w dowolne miejsce (jest to jeden ze sposobów na alokację powyżej 2GB pamięci w procesie; nalezy jednak pamiętać że przestrzeń adresowa procesu pozostaje ograniczona do 2GB, więc mimo iż zaalokujemy więcej pamięci, to i tak dostęp "na raz" będziemy mieli tylko do około 2GB - ale to nie powinien być żaden problem, ponieważ pamięć można przemapowywać, tak aby raz mieć dostęp do jednej części stron, a potem do innej - patrz również Inne linki)
  • MapViewOfFile - funkcja do mapowania w przestrzeń adresową procesu pamięci zaalokowanej przez CreateFileMapping (warto rzucić okiem również na spis innych funkcji z tej rodziny, choćby takich jak UnmapViewOfFile)
  • AllocateUserPhysicalPages - funkcja z rozszerzenia AWE (Address Windowing Extension) do alokowania fizycznych stron pamięci (uwaga: proces musi mieć dostęp do tokenu SeLockMemoryPrivilege - w tym celu trzeba ustawić userowi dostęp do 'Lock Pages In Memory' w lokalnych politykach); jest to drugi zestaw funkcji pozwalający zaalokować więcej niż 2GB pamięci, a na systemach serwerowych nawet więcej niż 4GB pamięci
  • MapUserPhysicalPages - funkcja AWE do pamowania fizycznych stron pamięci w przestrzeń procesu

Użyte narzędzia:

Inne linki:
Video Tutorials RSS
ReverseCraft:
Legal stuff
ReverseCraft project (c) 2009 gynvael.coldwind//vx
Video tutoriale dostępne są na licencji Creative Commons BY-NC-ND

cat