Autodelete
Scrisesem mai demult o mica aplicatie care odata ce facea ce facea ( chit ca facea ceva rau
) trebuia sa se stearga . Stiu ca m-am pus si in cap numai sa-mi dau seama cum se face chestia asta. Dar cunostintele mele de pe atunci nu cuprindeau Windows programming si pana la urma m-am lasat pagubas . Iata ca acum mi-am pus problema din nou insa intr-un nou context. L-am luat la intrebari pe Andrei , prietenul meu din Satu Mare ( Cluj in curand ) si mi-a spus ca se poate rezolva treaba printr-un alt thread care ar fi trebuit sa ruleze remote intr-un alt proces. Ceea ce insemna clar … Code Injecting. Asa ca m-am pus pe invatat code injecting . Si m-am tot chinuit 1 zi intreaga … pana la urma am apelat la ajutorul aceluiasi Andrei care mi-a suportat cele o mie si una de intrebari despre acest mecanisim . Si a inceput omu sa explice… si explica… si explica… si eu tot nu intelegeam
Rar mai gasesti oameni ca el .Probabil s-a cam sictirit de atata explicat … dar in cele din urma m-am prins cum merge treaba.
Dupa ce am invatat code injecting si l-am si stapanit in linii mari , am trecut la ofensiva . Sa scriu un program care se sterge singur dupa executie.
Problema suna bunal . La sfarsitul codului trantesc un DeleteFile(…) si gata. Problema nu e asa usoara. Daca procesul se afla inca in executie , stergerea esueaza. Asa ca am mers pe ideea lui Andrei, aceea a crearii unui thread remote intr-o alta aplicatie. Dar care ? Ca sa nu afectez niciun alt proces, am preferat sa-mi deschid eu personal un banal “calc.exe” . Apoi am injectat in el bucata de cod care sterge fisierul de pe hard-disk. Initial am abordat o varianta mai complicata .Thread remote verifica daca poate deschide procesul mai poate fi deschis intr-o bucla infinita . Am decis sa renunt la aceasta varianta dintr-un motiv foarte simplu : eu oricum imi doresc sa sterg procesul dupa ce isi termina executia . Prin urmare, dupa ce am creat thread-ul remote , imediat procesul meu se termina . Astfel pot apela lejer functia DeleteFile din thread-ul remote, fiind absolut sigur ca programul nu mai functioneaza. Dupa ce sterg executabilul, apelez ExitProcess din thread-ul remote si “calc.exe” se inchide … De fapt … toata acestea se petrec extrem de rapid. Utilizatorul nu apuca sa vada nicio fereastra pe ecran. Luasem masuri si impotriva acestui lucru … cand deschideam calc.exe , specificam functiei CreateProcess/ShellExecute sa ascunda fereastra insa se pare ca niciuna din cele 2 API-uri nu reuseste acest lucru asa ca am renuntat in cele din urma. Merge si asa…
Codul … nu il pun aici caci e destul de mare … am postat pe Softpedia o librarie in care am implementat functia care realizeaza acest lucru . Daca doriti, ma puteti contacta pe mess la adresa msmihai pentru acest lucru . Sau pe e-mail. Toate cele bune.
Revin…
Iata ca revin dupa o oarecare pauza … am terminat anul I … am ajuns acasa … m-am lasat de ASM
Da stiu , la cum arata pagina asta, e destul de greu de imaginat . Dar … asa e . Totusi sa nu se inteleaga gresit . Cunosc ASM-ul in mare parte, stiu cu se mananca , insa … nu-l mai folosesc . In schimb mi-am gasit timp sa ma plimb pe bicicleta … sa mai petrec timpul si altfel decat programand . Totusi … blestemul e blestem . Tot trebuia sa invat ceva vacanta asta … ceva ce n-am facut niciodata… si iata-ma ajuns la Win32 Programming, in toata splendoarea sa . Mi-am indeplinit un obiectiv pe care l-am avut de prima oara cand am pus mana pe Visual Studio si anume sa scriu o aplicatie GUI de la 0 . De altfel, acesta a si fost motivul pentru care am refuzat Visual Studio atata vreme in favoarea C++ Builder. Cu putin efort iata ca am reusit. Am mai invatat cateva chestii interesante legate de Win32P , precum hooking,injecting … dar nu intru in amanunte
Multi ma intreaba daca nu m-am plictisit in vacanta … mai toata lumea isi ia slujbe, se ocupa cu ceva util in vacanta … mie imi place sa fiu liber. Sa-mi pun rucsacul in spate si sa mai fac o plimbare la Iasi ( in curand, poate saptamana viitoare, mai fac una ) . Raspunsul e nu … nu m-am plictisit. Am reusit sa combin de minune programarea cu alte activitati . Si ma apucasem si de citit Biblia candva… am renuntat .
Probleme asm pe “release”
Problema de fata apare in versiunele 2005+ ale Visual Studio in modul de compilare "Release". Sa luam exemplul urmator:
-
int functie(int)
-
{
-
_asm
-
{
-
mov eax,[ebp+8]
-
}
-
}
-
-
-
int main()
-
{
-
int a=10,b;
-
b=functie(a);
-
printf("%d ",b);
-
return 0;
-
}
In mod normal, functia returneaza valoarea primita ca parametru . Prin urmare, b=functie(a) va lua valoarea lui a, adica 10. Pana acum toate bune si frumoase. Sa compilam acum pe "Release mode" . De data aceasta, b va lua valoarea ...0
. Ciudat ? Nicidecum. Daca vom modifica antetul functiei main in felul urmator:
-
int main(int)
b va lua valoarea ... 1
... acum sa rulam programul cu 5 parametri ... si da, intr-adevar , b va lua valoarea 5 ... hmmm...Situatia nu e atat de hazlie pe cat pare. Sa zicem ca avem o functie care primeste ca parametru adresa unei variabile ... daca in loc de adresa noi primim 0, 1 sau alte tampenii, cu siguranta ca programul nostru va functiona razna iar noi ne vom pune nervii la incercare pentru mult timp, cu debugger-ul etc., negasind eroarea.
Eroarea provine din cauza optimizarilor de cod pe care le efectueaza Visual Studio . Sa luam acelasi caz de mai sus. Ce inseamna optimizare ? Compilatorul "vede" ca functia de mai sus nu mai apeleaza alte functii si este apelata doar din main . Asa ca , literal, ia tot codul functiei si il pune in locul apelului din functia main . Ceea ce echivaleaza perfect cu :
-
int main()
-
{
-
int a=10,b;
-
_asm
-
{
-
mov eax,[ebp+8]
-
mov b,eax
-
}
-
printf("%d ",b);
-
return 0;
-
}
Astfel, nu se mai face saltul la codul functiei, codul e "performant", dar intelesul sau deja se schimba...
In mod logic, problema se rezolva in 2 moduri :
1. Spunem compilatorului sa nu mai optimizeze nimic ( foarte usor : Project Properties -> Configuration Properties -> C/C++ -> Optimization -> Optimization -> Disabled .
2. Spunem compilatorului sa nu optimizeze functia noastra ... va urma
Visual Studio 2008 … interesant
Hmm .. eram obisnuit sa setez release, si dau f5 , sa astept sa termina de incarcat aberatiile respective si sa am executabilul ... vremuri bune . Pe Visual Studio mai vechi poti face acest lucru pentru un program de tip console application. Se pare ca, mai nou, acest lucru nu mai este disponibil direct in Visual Studio 2008 . Daca dati simplu release si dati altcuiva programul, sunt sanse mari ca acesta sa nu-i mearga ( logica spune asa : daca eu sunt singurul tampit care foloseste Visual Studio 2008 cu .net 3.5, iar ceilalti folosesc altceva, e clar ca nu va merge ) . Problema se rezolva foarte simplu. Mergeti la Properties->Configurations Properties-> C/C++ ->Code Generation->Runtime Library-> Multi-threaded (/MT)... atata tot ... acum dati prietenilor programul vostru si virusati-i![]()
Naiv Sort - C++/ASM
Ah ... 2008 ... un nou an ... Dupa sampanie si cozonac ( meniu special de revelion ) , dupa artificii ( pe faleza Dunarii ) ...
Ma bucur cel putin ca acum folosesc un soft de anu asta ( Visual Studio 2008 ) , sunt trist ca in curand vin examenele, sunt bucuros ca in scurta vacanta de Craciun am reusit sa invat ASM ( un limbaj imposibil pentru mine la inceput - cu ocazia asta, tin sa-i multumesc lui AndreiASM .. de la el am invatat o buna parte a limbajului dar si profului ... printre cei mai de treaba de la FII ) ...
Si ca sa incep anul cu dreptul, m-am gandit in seara asta sa schimb algoritmul de anul trecut ( bubble sort ) , cu unul de "anul asta" ( naiv sort ) ... am implementat atat in C++ cat si in ASM ...
-
#include <stdio.h>
-
-
int v[5];
-
/*
-
void interschimba(int &a,int &b)
-
{
-
int c;
-
c=a;
-
a=b;
-
b=c;
-
}
-
void Naiv_Sort(int v[],int n)
-
{
-
int i,poz,min,j;
-
for(i=0;i<n;i++)
-
{
-
min=v[i];
-
poz=i;
-
-
for(j=i+1;j<n;j++)
-
if(v[j]<min)
-
{
-
min=v[j];
-
poz=j;
-
}
-
interschimba(v[i],v[poz]);
-
}
-
}*/
-
-
void Naiv_Sort(int*,int)
-
{
-
_asm
-
{
-
mov ebx,0
-
for_mare:
-
mov ecx,[ebp+12]
-
dec ecx
-
cmp ebx,ecx
-
je gata
-
mov esi,[ebp+8]
-
//ajungem pe pozitia curenta
-
mov eax,ebx
-
shl eax,2
-
add esi,eax
-
//in esi avem pozitia curenta
-
//in eax avem minimul, in edx avem pozitia minimului
-
mov eax,[esi]
-
mov edx,ebx
-
//ecx va fi contorul celui de-al doilea for
-
mov ecx,ebx
-
inc ecx
-
add esi,4
-
for_mic:
-
cmp ecx,[ebp+12]
-
je stop
-
mov edi,[esi]
-
cmp edi,eax
-
jb schimba
-
jmp continua
-
schimba:
-
mov eax,[esi]
-
mov edx,ecx
-
jmp continua
-
continua:
-
add esi,4
-
inc ecx
-
jmp for_mic
-
stop:
-
mov esi,[ebp+8]
-
mov eax,ebx
-
shl eax,2
-
add esi,eax
-
mov edi,[ebp+8]
-
mov eax,edx
-
shl eax,2
-
add edi,eax
-
//in esi si edi am cele 2 adrese ale elementelor ce trebuie schimbate
-
-
push dword ptr [esi]
-
push dword ptr [edi]
-
pop dword ptr [esi]
-
pop dword ptr [edi]
-
-
inc ebx
-
jmp for_mare
-
gata:
-
-
}
-
}
-
-
-
int main()
-
{
-
int n,i;
-
n=5;
-
v[0]=10;v[1]=2;v[2]=1;v[3]=5;v[4]=6;
-
Naiv_Sort(v,n);
-
for(i=0;i<n;i++) printf("%d ",v[i]);
-
getchar();
-
return 0;
-
}
Sa utilizam bubble sort …
M-am gandit sa ma mai joc putin cu bubble sort-ul, sa-l folosesc in cadrul unei anumite probleme. Problema care mi-a venit in minte este urmatoarea : Sa se scrie o functie care primeste ca parametru un numar natural si care returneaza cel mai mare numar care se poate forma cu cifrele sale . Algoritmul banal cu care se rezolva aceasta problema este urmatorul:
-retinem cifrele numarului intr-un vector
-le ordonam
-compunem noul numar
Am implementat totul in ASM desigur. Pentru a nu mai recurge la fel de fel de artificii, am organizat vectorul in felul urmator:
v[0] - numarul de cifre
v[1] ... v[v[0] - cifrele numarului
Bineinteles, am modificat usor bubble-sort-ul ( cel scris de mine avea nevoie de 2 variabile , un pointer catre primul element al vectorului, v[0] , si numarul de elemente ... cateva modificari minore si a fost gata. O alta problema care mi-a atras atentia la bubble sort a fost urmatoarea : ce se intampla daca exista un singur element in vector ? Am vrut sa merg la f**** masa si sa-l las asa, dar atunci cand compara v[i] cu v[i+1], sare la o adresa la care nu se gaseste nimic ... eroare
... am prevazut acest caz in functia maxim() . Este cel mai lung programel scris de mine in ASM ( vreo 90 linii de cod ) ... Sper sa nu mai am placerea sa scriu programe atat de lungi in ASM, e foarte dificil sa caut erori, chiar si cu ajutorul debugger-ului ... Iata codul...
-
#include <iostream>
-
using namespace std;
-
-
void bubble_sort(int*)
-
{
-
_asm
-
{
-
bucla_mare:
-
mov ecx,0
-
mov eax,[ebp+8]
-
mov ebx,[eax]
-
add eax,4
-
bucla_mica:
-
mov edx,eax
-
add edx,4
-
mov esi,[eax]
-
cmp esi,[edx]
-
ja interschimbare
-
jmp continua
-
interschimbare:
-
push dword ptr [edx]
-
push dword ptr [eax]
-
pop dword ptr [edx]
-
pop dword ptr [eax]
-
mov ecx,1
-
jmp continua
-
continua:
-
add eax,4
-
dec ebx
-
cmp ebx,1
-
jne bucla_mica
-
cmp ecx,1
-
je bucla_mare
-
}
-
}
-
-
int maxim(int)
-
{
-
int v[12];
-
_asm
-
{
-
mov eax,[ebp+8]
-
cmp eax,10
-
jb exceptie
-
jmp continua
-
exceptie:
-
mov ecx,eax
-
jmp stop2
-
continua:
-
mov ebx,10
-
mov ecx,0
-
lea esi,v
-
add esi,4
-
bucla1:
-
mov edx,0
-
cmp eax,0
-
je stop1
-
div ebx
-
inc ecx
-
mov [esi],edx
-
add esi,4
-
jmp bucla1
-
stop1:
-
lea eax,v
-
mov [eax],ecx
-
push eax
-
call bubble_sort
-
add esp,4
-
-
mov ecx,0
-
mov eax,1
-
lea esi,v
-
mov ebx,[esi]
-
add esi,4
-
bucla2:
-
cmp ebx,0
-
je stop2
-
push ecx
-
mov ecx,[esi]
-
mov edx,0
-
push eax
-
mov edi,eax
-
mov eax,1
-
mul edi
-
mul ecx
-
pop edx
-
pop ecx
-
push edx
-
add ecx,eax
-
pop eax
-
mov edi,10
-
mul edi
-
dec ebx
-
add esi,4
-
jmp bucla2
-
stop2:
-
mov eax,ecx
-
}
-
}
-
-
int main()
-
{
-
int x;
-
cin>>x;
-
cout<<maxim(x)<<endl;
-
system("pause");
-
return 0;
-
}
O mica problema in ASM … de Craciun
Pentru ca tot era Craciunul si nu aveam ce face, m-am apucat de o mica problema in ASM ... am apelat la un coleg de facultate,Alex D., care mi-a dat urmatoarea problema : Sa se ordoneze un vector de numere naturale dupa numarul de biti necesari pentru a le scrie in baza 2 ... aveam deja bubble sort-ul implementat in asm ... Am procedat in felul urmator: stiam ca bubble sort compara, la un moment dat cate 2 elemente si verifica daca unul e mai mare ca celalalt. In loc de aceasta condiitie, eu trebuia sa aflu daca numarul de biti al primului e mai mare ca numarul de biti al celui de-al doilea... ca sa evit o seara "plina", am scris o alta functie, tot in asm , care imi returneaza numarul de biti pentru un numar. De aici totul a fost simplu ... ba nu ! Am stat o ora intreaga, uitandu-ma dupa pop-uri, push-uri, unele adrese se pierdeau, o adevarata dezordine... noroc cu prietenul meu AndreiASM ( numele spune tot
), care m-a ajutat cu diverse chestii tehnice pe care nu aveam de unde sa le cunosc ( apelarea unei functii cu parametri, etc. ) . In cele din urma, a rezultat codul de mai jos, care "merge", dar nu am absolut niciun chef sa ma mai bag pe el in caz ca gasesc vreo eroare...
-
#include <stdio.h>
-
#include <iostream>
-
using namespace std;
-
-
-
int nr_biti(int)
-
{
-
_asm
-
{
-
mov eax,[ebp+8]
-
cmp eax,0
-
je final
-
mov ebx,0
-
bucla:
-
cmp eax,0
-
je stop
-
inc ebx
-
shr eax,1
-
jmp bucla
-
stop:
-
mov eax,ebx
-
jmp stop2
-
final:
-
mov ebx,1
-
jmp stop
-
stop2:
-
-
}
-
}
-
-
void bubble_sort(int*,int)
-
{
-
_asm
-
{
-
bucla_mare:
-
mov ecx,0
-
mov eax,[ebp+8]
-
mov ebx,[ebp+12]
-
bucla_mica:
-
mov edx,eax
-
add edx,4
-
-
push dword ptr[eax]
-
push dword ptr[edx]
-
-
push eax
-
-
mov edi,eax
-
-
push dword ptr[edx]
-
call nr_biti
-
mov [edx],eax
-
add esp,4
-
-
push dword ptr[edi]
-
call nr_biti
-
mov [edi],eax
-
add esp,4
-
-
pop eax
-
push ecx
-
mov ecx,[edi]
-
mov [eax],ecx
-
pop ecx
-
mov esi,[eax]
-
cmp esi,[edx]
-
ja interschimbare
-
cmp esi,[edx]
-
jle nu_e
-
-
interschimbare:
-
pop dword ptr[edx]
-
pop dword ptr[eax]
-
push dword ptr [edx]
-
push dword ptr [eax]
-
pop dword ptr [edx]
-
pop dword ptr [eax]
-
mov ecx,1
-
jmp continua
-
nu_e: pop dword ptr[edx]
-
pop dword ptr[eax]
-
jmp continua
-
-
continua:
-
-
add eax,4
-
dec ebx
-
cmp ebx,1
-
jne bucla_mica
-
cmp ecx,1
-
je bucla_mare
-
}
-
}
-
-
int main()
-
{
-
int v[100],n,i;
-
cin>>n;
-
for(i=0;i<n;i++) cin>>v[i];
-
bubble_sort(v,n);
-
for(i=0;i<n;i++) cout<<v[i]<<' ';
-
system("pause");
-
return 0;
-
}
Use the stack , Luke !
Lucrez de foarte putin timp timp in ASM si , cum imi sta mie mai bine, imi place sa ma complic al naibii de tare cand rezolv o problema... de exemplu, azi m-am gandit la urmatoarea problema in ASM : se da un vector de numere intregi. Sa se scrie o functie in ASM care inverseaza elementele vectorului .
Ok . Bag in registrul eax adresa elementului curent, calculez cati bytes trebuie sa sar ca sa ajung la ultimul element, fac o bucla, sar la elementul al doilea, calculez cati bytes am nevoie sa sar la penultimul ... etc., nervi, pana la urma adaug un sub edx,ecx ... minune, merge. De ce? Nu ma mai intereseaza... Merge si atat. Iata minunatul cod:
-
void inversare(int*,int)
-
{
-
_asm
-
{
-
mov ecx,0
-
mov ebx,[ebp+12]
-
shr ebx,1
-
dec ebx
-
bucla:
-
mov eax,[ebp+8]
-
-
push ecx
-
shl ecx,2
-
add eax,ecx
-
pop ecx
-
-
mov edx,[ebp+12]
-
dec edx
-
sub edx,ecx
-
sub edx,ecx
-
shl edx,2
-
-
push eax
-
add eax,edx
-
mov edx,eax
-
pop eax
-
-
push dword ptr [eax]
-
push dword ptr [edx]
-
pop dword ptr [eax]
-
pop dword ptr [edx]
-
-
cmp ecx,ebx
-
jne continua
-
cmp ecx,ebx
-
je stop
-
continua:
-
inc ecx
-
jmp bucla
-
stop:
-
}
-
}
Ok... , ma minunam si eu de cat de frumos e codul asta ... ma simteam mandru... USE THE STACK LUKE... mi-am adus aminte de Star Wars ... si de o mica chestie numite STIVA... care avea interesenta proprietate ca ultimul intrat era primul iesit . Sa vezi si sa nu crezi ... exact ce-mi trebuia mie .
Mi-am tras o palma peste cap, am pornit alt proiect, am scris repede codul, a rezultat cel de mai jos. Elegant, simplu, fara shiftari de biti sau alte magarii ...
-
void inverseaza2(int*,int)
-
{
-
_asm
-
{
-
mov eax,[ebp+8]
-
mov ecx,[ebp+12]
-
mov edx,0
-
bucla:
-
cmp edx,ecx
-
je final
-
push dword ptr [eax]
-
add eax,4
-
inc edx
-
jmp bucla
-
final:
-
mov eax,[ebp+8]
-
mov edx,0
-
bucla2:
-
cmp edx,ecx
-
je final2
-
pop dword ptr [eax]
-
add eax,4
-
inc edx
-
jmp bucla2
-
final2:
-
}
-
}
De acum incolo voi folosi stiva !
De acum incolo voi folosi stiva !
De acum incolo voi folosi stiva !
De acum incolo voi folosi stiva !
De acum incolo voi folosi stiva !
De acum incolo voi folosi stiva !
Bubble Sort - ASM
Astazi am reusit , cu ajutor ce-i drept ( din partea prof. meu de arhitectura ), sa implementez ultra-performantul, ultra-schimbistul si nemaipomenitul Bubble Sort . Il pun aici, in speranta ca mai exista cineva care este interesat de ASM ...
-
void bubble_sort(int*,int)
-
{
-
_asm
-
{