- Nu voi salva EBP pentru functiile mici sau cele care nu lucreaza extensiv cu stiva si voi lucra direct cu ESP.
- Exemple:
FUNC_SetPixel
,FUNC_ComputeNewKey
,FUNC_CharToMorse
- Toate functiile scrise de mine respecta urmatoarele conventii:
- dupa un apel, caller-ul curata stiva (cdecl)
- registrii
EAX
,ECX
,EDX
pot fi folositi de functia apelata fara a-i salva - ceilalti registri trebuie salvati de callee (Intel ABI)
-
Logica de gasire a cheii XOR si a mesajului a fost delegata procedurii
bruteforce_singlebyte_xor
care primeste ca parametru imaginea si returneaza indexul randului si cheia astfel:- octetul cel mai nesemnificativ: cheia XOR
- cei 3 octeti ramasi: indexul randului
-
In C, s-ar scrie:
ret = (row_index << 8) | xor_key
. -
Daca ar fi permisa modificarea antetului functiei, as returna acesti parametri separat, ca parametri trimisi pe stiva prin referinta.
-
Logica functiei:
- Se face un loop de la 0->255 care stabileste cheia XOR ce va fi incercata.
- Pentru fiecare cheie XOR, se XOR-eaza intreaga imagine (
FUNC_XorBuffer
) - Se cauta mesajul (needle) in imaginea XOR-ata (
FUNC_memmem
- implementare naiva in ASM a functieimemmem
din glibc):- daca se gaseste mesajul, se calculeaza indexul randului si se returneaza datele cerute in formatul specificat mai sus
- daca nu se gaseste, se XOR-eaza din nou imaginea (revenind la starea initiala si se incrementeaza cheia XOR, revenind la pasul 2.
-
Printarea mesajului se face manual, iterand prin fiecare caracter, deoarece
printf
nu poate lucra cu string-uri in care caracterele sunt stocate pe DWORD in loc de BYTE.
-
Logica acestui task a fost delegata procedurii
insert_message
care executa urmatorii pasi:- Se apeleaza functia
bruteforce_singlebyte_xor
pentru decodarea imaginii si pentru gasirea locatiei mesajului si a cheii XOR folosite. - Se insereaza noul mesaj pe randul urmator.
- Se calculeaza noua cheie XOR (
FUNC_ComputeNewKey
) - Se aplica noua cheie pe intreaga imagine (
FUNC_XorBuffer
)
- Se apeleaza functia
- Pentru acest task am definit codul fiecarui caracter in sectiunea .rodata si am creat un lookup table unde am stocat adresa la care se gaseste reprezentarea in cod Morse a fiecarui caracter.
- Task-ul este rezolvat efectiv de procedura
morse_encrypt
:- Pentru fiecare caracter al mesajului se produce reprezentarea in cod Morse
pe caractere de 1-byte (
FUNC_CharToMorse
) - Se calculeaza lungimea reprezentarii Morse (
FUNC_strlen
) - Se transforma reprezentarea cu caractere 1-byte in reprezentare cu caractere 4-byte si se salveaza rezultatul in imagine.
- Se creste indexul destinatie cu numarul de caractere al reprezentarii Morse
- Dupa fiecare cod Morse se adauga separatorul spatiu.
- Se reiau pasii pana se termina de procesat mesajul.
- Pentru fiecare caracter al mesajului se produce reprezentarea in cod Morse
pe caractere de 1-byte (
- Logica functiei
lsb_encode
:- Pentru fiecare byte din mesaj se face un loop pe fiecare bit, de la MSB spre LSB
- Se verifica bitul curent daca este setat:
- daca este setat, se seteaza LSB in DWORD-ul destinatie
- daca nu este setat, se reseteaza LSB in DWORD-ul destinatie
- Se trece la urmatorul bit mesaj si se trece la urmatorul DWORD din destinatie
- Daca tocmai s-a terminat de procesat 1 byte din mesaj, se verifica daca acest
byte a fost 0 (terminator de sir):
- true -> s-a terminat encodarea
- false -> se trece la urmatorul byte din mesaj si se reia de la pasul 1.
- Logica functiei
lsb_decode
:- Se aloca pe stiva 32 bytes pentru mesajul decodat.
- Se calculeaza adresa de la care se va incepe decodarea (
&img[byte_id-1]
) - Pentru fiecare 8 DWORD-uri consecutive, se ia LSB si se pune intr-un byte, de la MSB spre LSB.
- Dupa procesarea a 8 DWORD-uri consecutive, se verifica daca byte-ul rezultat
este 0 (terminator de sir):
- true -> s-a terminat decodarea
- false -> se reia de la pasul 3.
- Logica functiei
blur
:- Se calculeaza marimea in bytes a imaginii de input
- Se aloca pe stiva spatiul necesar pentru o copie a imaginii
- Se itereaza prin fiecare pixel al imaginii
- Se calculeaza noul pixel (
FUNC_ComputeBlurForPixel
) - Se seteaza pixelul in noua imagine (
FUNC_SetPixel
) - Afiseaza imaginea (
print_image
)