Ty masz ten kod przeanalizować rozpisując to co się dzieje na kartce? Bo bezpośrednia zmiana wartości rejestru ESP
jest błędem i skończyłoby się to w normalnym programie jakimś SIGSEGV. Jeśli to ma być tylko analiza "przyjmijmy, że" to mogłoby wyglądać to mniej więcej tak:
EAX 00000000
EBX 00410000
ECX 23450090
EDX FEDC0000
EBP 00900000
ESP 00100000
ESI 00300000
EDI 00000000
Kod:
MOV [ESP-4], EAX ; na szczyt stosu program wrzuca null-byte'y
CALL EBX ; w miejsce null-byte'ów na stosie wrzuca adres powrotu z funkcji, której aktualny adres posiada rejestr EBX (adresem powrotu jest adres kolejnej instrukcji, czyli NOP) i wywołuje funkcje
:00400000
NOP
------
:00410000, ; patrząc po wartościach rejestrów - to jest funkcja, której nastąpi wywołanie
ADD CX, 0BBBBh ; do dolnych 16-bitów rejestru ECX dodaje wartość hex 0xBBBB
SHR CX, 1 ; SHR to instrukcja przesuwająca bity w prawo odnosząc się do wartości unsigned, czyli to jest po prostu podzielenie dolnych 16-bitów rejestru ECX przez 2^1
OR EAX, [ESP] ; tu następuje operacja logiczna OR wartości w rejestrze EAX z wartością na szczycie stosu, czyli adresem powrotu z tej funkcji
JZ 00410000 ; jeśli poprzednia operacja OR dała wynik 0 to skocz ponownie na początek funkcji, czyli mamy do czynienia z pętlą
JMP EAX ; w przeciwnym wypadku skocz w miejsce, w które wskazuje wartość w rejestrze EAX
:004F0000
NOP
I teraz stos będzie wyglądał tak (przed wykonaniem instrukcji CALL EBX
):
######################################################################
WARTOŚĆ EAX (0)
######################################################################
ADRES POWROTU main (przyjmując, że ta pierwsza funkcja to funkcja main) <---- ESP
######################################################################
Po wykonaniu instrukcji CALL EBX
:
######################################################################
ADRES POWROTU FUNKCJI (ADRES INSTRUKCJI NOP) <---- ESP
######################################################################
ADRES POWROTU main (przyjmując, że ta pierwsza funkcja to funkcja main)
######################################################################
Więc skoro szczytem stosu jest adres powrotu funkcji, czyli adres kolejnej instrukcji będącej za CALL EBX
to ta instrukcja OR EAX, [ESP]
da wynik większy od 0, ponieważ EAX
przechowuje wartość 0 --> http://www.ee.surrey.ac.uk/Projects/CAL/digital-logic/gatesfunc/#orgate
W EAX
po wykonaniu tej operacji będzie adres instrukcji spod labela :00400000, czyli NOP
. Ta instrukcja jest bezpośrednio przed pętlą zatem procesor wykona instrukcję, która tak naprawdę nie robi nic (NOP == No OPeration) zatem znów jesteśmy w pętli. Pętla nie zmienia wartości, na którą wskazuje rejestr ESP
i z tego powodu zawsze wykonywana jest taka operacja --> ADRES POWROTU Z FUNKCJI, KTÓREJ ADRES PRZECHOWYWANY JEST W EBX
or ADRES POWROTU Z FUNKCJI, KTÓREJ ADRES PRZECHOWYWANY JEST W EBX
, a z tego z kolei wynika, że znów wartość tej operacji nie jest zerowa i znów następuje skok do tego adresu powrotu, znów wykonana jest instrukcja NOP i znów jesteśmy w pętli ponownie - ta sytuacja będzie się powtarzać i dlatego występuje w tym kodzie infinite loop
.