No to zaczynamy ^^
Dzisiaj spróbujemy poszukać pewnej zmiennej w pamięci i zmienić jej wartość, aby program wykonał się tak jak my tego chcemy, oczywiście bez żadnej ingerencji w kod źródłowy programu. Do dyspozycji mamy skompilowany program.
Zaczynajmy.
Na początku skompilujemy program (ja to zrobiłem za pomocą mojego ulubionego IDE tj. Dev-Cpp).
#include <iostream>
void f_forfun(void)
{
puts("for fun");
}
int main(int argc, char *argv[])
{
int x = 29;
if(x > 30)
{
f_forfun();
}
else
{
puts(“there’s no fun”);
}
return 0;
}
Po uruchomieniu, program wyświetli nam na ekranie tylko napis “there’s no fun”, ale my chcemy coś innego.
Krótka analiza kodu.
Funkcja f_forfun wyświetla napis „for fun”, jednak nie wykona się, ponieważ warunek x > 30 nie jest prawdziwy, bo zmienna x ma wartość 29. Czyli, żeby nasza funkcja się wykonała, zmienna x musi być większa od 30.
Najpierw zdisassemblujemy execa poleceniem:
dumppe test.exe -disasm > test.dasm
Mamy przygotowany listing asemblera. Teraz może trochę info o stosie.
Stos, przede wszystkim jest to obszar w pamięci; struktura danych rosnąca w dół, mamy coś takiego jak wskaźnik stosu, który jest na początku ustawiany na sam ‘szczyt’ obszaru pamięci, gdy wrzucamy (push) na stos jakąś daną jest ona kopiowana do aktualnego obszaru wskazywanego przez wskaźnik, po czym wskaźnik jest zmniejszany w dół (najczęściej o 4) – stos rośnie w dół. Natomiast instrukcja pop pobiera daną ze stosu i zwiększa wskaźnik.
W 32-bitowej architekturze x86 wskaźnik „szczytu” stosu nazywa się ESP, natomiast „dno” stosu wskazuje rejestr EBP.
Zmienne lokalne alokowane są na stosie, do których mamy dostęp poprzez rejestr ESP. Zmienna x ma wartość 29, w systemie szesnastkowym to 1D. Więc musimy szukać operacji wykonywanych na tej wartości.
Po chwili napotykamy takie linijki:
004012CE C745FC1D000000 mov dword ptr [ebp-4],1Dh
004012D5 837DFC1E cmp dword ptr [ebp-4],1Eh
Pierwsza kolumna to adres w pamięci, druga to skompilowany rozkaz asma, następnie jest mnemonik.
W pierwszej linijce widać, że jest operacja na stosie i nasza wartość (1Dh), czyli mamy już adres naszej zmiennej.
Druga linijka to porównanie (cmp) wartości 29 z 30.
1D (hex) = 29 (Dec)
1E (hex) = 30 (Dec)
Adres zmiennej w pamięci mamy w pierwszej kolumnie, pierwszej linijki. Jednak musimy teraz obliczyć adres tej zmiennej w pliku za pomocą poniższego wzoru:
adres w pliku = adres w listingu - (Image Base + Virtual Address sekcji ) + Raw Offset sekcji
Potrzebujemy jeszcze adresy początku pamięci procesu (image base), Raw Data Offset i Virtual Address.
Image Base 00400000
Virtual Address 00001000
Raw Data Offset 00000400
Podstawiamy..
4012CE - (400000 + 1000) + 400 = 6CE
.. i mamy adres zmiennej x w pliku.
Edytujemy za pomocą Hexplorera naszą binarkę, i przechodzimy do wcześniej wyliczonego adresu – 6CE. Widzimy tam wartość 1D, po prostu zwiększamy ją, np. na 1F. Zapisujemy.
Teraz po uruchomieniu naszego programu, warunek będzie prawdziwy, więc wykona się funkcja for_fun i otrzymamy napis „for fun”.
W następnej części postaram sie napisać przykład wymagający więcej myślenia ;p
Tyle ^^

