RSS Feed

Autodelete

August 11th, 2008

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…

August 11th, 2008

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”

January 19th, 2008

Problema de fata apare in versiunele 2005+ ale Visual Studio in modul de compilare "Release". Sa luam exemplul urmator:

C++:
  1. int functie(int)
  2. {
  3.    _asm
  4.          {
  5.            mov eax,[ebp+8]
  6.           }
  7. }
  8.  
  9.  
  10. int main()
  11. {
  12. int a=10,b;
  13. b=functie(a);
  14. printf("%d ",b);
  15. return 0;
  16. }

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:

C++:
  1. 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 :

C++:
  1. int main()
  2. {
  3. int a=10,b;
  4.    _asm
  5.          {
  6.            mov eax,[ebp+8]
  7.            mov b,eax
  8.           }
  9. printf("%d ",b);
  10. return 0;
  11. }

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

January 9th, 2008

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 :d

Naiv Sort - C++/ASM

January 1st, 2008

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 ...

C++:
  1. #include <stdio.h>
  2.  
  3. int v[5];
  4. /*
  5. void interschimba(int &a,int &b)
  6. {
  7.     int c;
  8.     c=a;
  9.     a=b;
  10.     b=c;
  11. }
  12. void Naiv_Sort(int v[],int n)
  13. {
  14.     int i,poz,min,j;
  15.     for(i=0;i<n;i++)
  16.     {
  17.         min=v[i];
  18.         poz=i;
  19.        
  20.         for(j=i+1;j<n;j++)
  21.             if(v[j]<min)
  22.             {
  23.                 min=v[j];
  24.                 poz=j;
  25.             }
  26.         interschimba(v[i],v[poz]);
  27.     }
  28. }*/
  29.  
  30. void Naiv_Sort(int*,int)
  31. {
  32.     _asm
  33.     {
  34.         mov ebx,0
  35. for_mare:
  36.         mov ecx,[ebp+12]
  37.         dec ecx
  38.         cmp ebx,ecx
  39.         je gata
  40.         mov esi,[ebp+8]
  41.         //ajungem pe pozitia curenta
  42.         mov eax,ebx
  43.         shl eax,2
  44.         add esi,eax
  45.         //in esi avem pozitia curenta
  46.         //in eax avem minimul, in edx avem pozitia minimului
  47.         mov eax,[esi]
  48.         mov edx,ebx
  49.         //ecx va fi contorul celui de-al doilea for
  50.         mov ecx,ebx
  51.         inc ecx
  52.         add esi,4
  53. for_mic:
  54.         cmp ecx,[ebp+12]
  55.         je stop
  56.         mov edi,[esi]
  57.         cmp edi,eax
  58.         jb schimba
  59.         jmp continua
  60. schimba:
  61.         mov eax,[esi]
  62.         mov edx,ecx
  63.         jmp continua
  64. continua:
  65.         add esi,4
  66.         inc ecx
  67.         jmp for_mic
  68. stop:
  69.         mov esi,[ebp+8]
  70.         mov eax,ebx
  71.         shl eax,2
  72.         add esi,eax
  73.         mov edi,[ebp+8]
  74.         mov eax,edx
  75.         shl eax,2
  76.         add edi,eax
  77.         //in esi si edi am cele 2 adrese ale elementelor ce trebuie schimbate
  78.        
  79.         push dword ptr [esi]
  80.         push dword ptr [edi]
  81.         pop dword ptr [esi]
  82.         pop dword ptr [edi]
  83.  
  84.         inc ebx
  85.         jmp for_mare
  86. gata:
  87.  
  88.     }
  89. }
  90.  
  91.  
  92. int main()
  93. {
  94.     int n,i;
  95.     n=5;
  96.     v[0]=10;v[1]=2;v[2]=1;v[3]=5;v[4]=6;
  97.     Naiv_Sort(v,n);
  98.     for(i=0;i<n;i++) printf("%d ",v[i]);
  99.     getchar();
  100.     return 0;
  101. }

Sa utilizam bubble sort …

December 29th, 2007

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...

C++:
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. void bubble_sort(int*)
  5. {
  6.     _asm
  7.     {
  8. bucla_mare:
  9.         mov ecx,0
  10.         mov eax,[ebp+8]
  11.         mov ebx,[eax]
  12.         add eax,4
  13. bucla_mica:
  14.         mov edx,eax
  15.         add edx,4
  16.         mov esi,[eax]
  17.         cmp esi,[edx]
  18.         ja interschimbare
  19.         jmp continua
  20. interschimbare:
  21.         push dword ptr [edx]
  22.         push dword ptr [eax]
  23.         pop dword ptr [edx]
  24.         pop dword ptr [eax]
  25.         mov ecx,1
  26.         jmp continua
  27. continua:
  28.         add eax,4
  29.         dec ebx
  30.         cmp ebx,1
  31.         jne bucla_mica
  32.         cmp ecx,1
  33.         je bucla_mare
  34.     }
  35. }
  36.  
  37. int maxim(int)
  38. {
  39.     int v[12];
  40.     _asm
  41.     {
  42.         mov eax,[ebp+8]
  43.         cmp eax,10
  44.         jb exceptie
  45.         jmp continua
  46. exceptie:
  47.         mov ecx,eax
  48.         jmp stop2
  49. continua:
  50.         mov ebx,10
  51.         mov ecx,0
  52.         lea esi,v
  53.         add esi,4
  54. bucla1:
  55.         mov edx,0
  56.         cmp eax,0
  57.         je stop1
  58.         div ebx
  59.         inc ecx
  60.         mov [esi],edx
  61.         add esi,4
  62.         jmp bucla1
  63. stop1:
  64.         lea eax,v
  65.         mov [eax],ecx
  66.         push eax
  67.         call bubble_sort
  68.         add esp,4
  69.  
  70.         mov ecx,0
  71.         mov eax,1
  72.         lea esi,v
  73.         mov ebx,[esi]
  74.         add esi,4
  75. bucla2:
  76.         cmp ebx,0
  77.         je stop2
  78.         push ecx
  79.         mov ecx,[esi]
  80.         mov edx,0
  81.         push eax
  82.         mov edi,eax
  83.         mov eax,1
  84.         mul edi
  85.         mul ecx
  86.         pop edx
  87.         pop ecx
  88.         push edx
  89.         add ecx,eax
  90.         pop eax
  91.         mov edi,10
  92.         mul edi
  93.         dec ebx
  94.         add esi,4
  95.         jmp bucla2
  96. stop2:
  97.         mov eax,ecx
  98.     }
  99. }
  100.  
  101. int main()
  102. {
  103.     int x;
  104.     cin>>x;
  105.     cout<<maxim(x)<<endl;
  106.     system("pause");
  107.     return 0;
  108. }

O mica problema in ASM … de Craciun

December 26th, 2007

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...

C++:
  1. #include <stdio.h>
  2. #include <iostream>
  3. using namespace std;
  4.  
  5.  
  6. int nr_biti(int)
  7. {
  8.     _asm
  9.     {
  10.         mov eax,[ebp+8]
  11.         cmp eax,0
  12.         je final
  13.         mov ebx,0
  14. bucla:
  15.         cmp eax,0
  16.         je stop
  17.         inc ebx
  18.         shr eax,1
  19.         jmp bucla
  20. stop:
  21.         mov eax,ebx
  22.         jmp stop2
  23. final:
  24.         mov ebx,1
  25.         jmp stop
  26. stop2:
  27.        
  28.     }
  29. }
  30.  
  31. void bubble_sort(int*,int)
  32. {
  33.     _asm
  34.     {
  35. bucla_mare:
  36.         mov ecx,0
  37.         mov eax,[ebp+8]
  38.         mov ebx,[ebp+12]
  39. bucla_mica:
  40.         mov edx,eax
  41.         add edx,4
  42.        
  43.         push dword ptr[eax]
  44.         push dword ptr[edx]
  45.  
  46.         push eax
  47.  
  48.         mov edi,eax
  49.  
  50.         push dword ptr[edx]
  51.         call nr_biti
  52.         mov  [edx],eax
  53.         add esp,4
  54.  
  55.         push dword ptr[edi]
  56.         call nr_biti
  57.         mov [edi],eax
  58.         add esp,4
  59.  
  60.         pop eax
  61.         push ecx
  62.         mov ecx,[edi]
  63.         mov [eax],ecx
  64.         pop ecx
  65.         mov esi,[eax]
  66.         cmp esi,[edx]
  67.         ja interschimbare
  68.         cmp esi,[edx]
  69.         jle nu_e
  70.        
  71. interschimbare:
  72.         pop dword ptr[edx]
  73.         pop dword ptr[eax]
  74.         push dword ptr [edx]
  75.         push dword ptr [eax]
  76.         pop dword ptr [edx]
  77.         pop dword ptr [eax]
  78.         mov ecx,1
  79.         jmp continua
  80. nu_e:   pop dword ptr[edx]
  81.         pop dword ptr[eax]
  82.         jmp continua
  83.  
  84. continua:
  85.  
  86.         add eax,4
  87.         dec ebx
  88.         cmp ebx,1
  89.         jne bucla_mica
  90.         cmp ecx,1
  91.         je bucla_mare
  92.     }
  93. }
  94.  
  95. int main()
  96. {
  97.     int v[100],n,i;
  98.     cin>>n;
  99.     for(i=0;i<n;i++) cin>>v[i];
  100.     bubble_sort(v,n);
  101.     for(i=0;i<n;i++) cout<<v[i]<<' ';
  102.     system("pause");
  103.     return 0;
  104. }

Use the stack , Luke !

December 23rd, 2007

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:

C++:
  1. void inversare(int*,int)
  2. {
  3.     _asm
  4.     {
  5.         mov ecx,0
  6.         mov ebx,[ebp+12]
  7.         shr ebx,1
  8.         dec ebx
  9. bucla:
  10.         mov eax,[ebp+8]
  11.        
  12.         push ecx
  13.         shl ecx,2
  14.         add eax,ecx
  15.         pop ecx
  16.        
  17.         mov edx,[ebp+12]
  18.         dec edx
  19.         sub edx,ecx
  20.         sub edx,ecx
  21.         shl edx,2
  22.  
  23.         push eax
  24.         add eax,edx
  25.         mov edx,eax
  26.         pop eax
  27.  
  28.         push dword ptr [eax]
  29.         push dword ptr [edx]
  30.         pop dword ptr [eax]
  31.         pop dword ptr [edx]
  32.    
  33.         cmp ecx,ebx
  34.         jne continua
  35.         cmp ecx,ebx
  36.         je stop
  37. continua:
  38.          inc ecx
  39.          jmp bucla
  40. stop:
  41.     }
  42. }

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 ...

C++:
  1. void inverseaza2(int*,int)
  2. {
  3.     _asm
  4.     {
  5.         mov eax,[ebp+8]
  6.         mov ecx,[ebp+12]
  7.         mov edx,0
  8. bucla:
  9.         cmp edx,ecx
  10.         je final
  11.         push dword ptr [eax]
  12.         add eax,4
  13.         inc edx
  14.         jmp bucla
  15. final:
  16.         mov eax,[ebp+8]
  17.         mov edx,0
  18. bucla2:
  19.         cmp edx,ecx
  20.         je final2
  21.         pop dword ptr [eax]
  22.         add eax,4
  23.         inc edx
  24.         jmp bucla2
  25. final2:
  26.     }
  27. }

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

December 20th, 2007

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 ...

C++:
  1. void bubble_sort(int*,int)
  2. {
  3.     _asm
  4.     {