// Main

// Prologo

0x5555523d <+0>: push rbp
0x5555523e <+1>: mov rbp,rsp
0x55555241 <+4>: sub rsp,0x30 // crea spazio nello stack per le variabili locali
0x55555245 <+8>: mov DWORD PTR [rbp-0x24],edi
0x55555248 <+11>: mov QWORD PTR [rbp-0x30],rsi

// malloc per la stringa

0x5555524c <+15>: mov edi,0xf
0x55555251 <+20>: call0x555555555070 <malloc@plt>
0x55555256 <+25>: mov QWORD PTR [rbp-0x8],rax // potrebbe essere quello che ritorna il malloc, un indirizzo, che poi viene assegnato strres

// printf

0x5555525a <+29>: lea rdi,[rip+0xda7] // stringa da passare alla printf
0x55555261 <+36>: mov eax,0x0
0x55555266 <+41>: call0x555555555050 <printf@plt>

// fgets

0x5555526b <+46>: mov rdx,QWORD PTR [rip+0x2dee] // indirizzo stdin <stdin@@GLIBC_2.2.5>
0x55555272 <+53>: lea rax,[rbp-0x17] // variabile str
0x55555276 <+57>: mov esi,0xf // parametro 15
0x5555527b <+62>: mov rdi,rax
0x5555527e <+65>: call0x555555555060 <fgets@plt> // fscanf

// printf

0x55555283 <+70>: lea rdi,[rip+0xd96] # 0x555555556020
0x5555528a <+77>: mov eax,0x0
0x5555528f <+82>: call0x555555555050 <printf@plt>

// scanf

0x55555294 <+87>: lea rax,[rbp-0x18] // variabile ch
0x55555298 <+91>: mov rsi,rax
0x5555529b <+94>: lea rdi,[rip+0xda5] //format string
0x555552a2 <+101>: mov eax,0x0
0x555552a7 <+106>: call0x555555555080 <__isoc99_scanf@plt>

// call removechar

0x555552ac <+111>: movzx eax,BYTE PTR [rbp-0x18] // da 8 bit a 32 bit inserendo 0
0x555552b0 <+115>: movsx edx,al // da 8 bit a 32 bit estendendo il segno
0x555552b3 <+118>: lea rax,[rbp-0x17] // variabile str
0x555552b7 <+122>: mov esi,edx
0x555552b9 <+124>: mov rdi,rax
0x555552bc <+127>: call0x555555555185 <removechar> // chiamata alla funzione removechar

// printf

0x555552c1 <+132>: mov QWORD PTR [rbp-0x8],rax //c'è il valore di ritorno delle funzione?
0x555552c5 <+136>: mov rax,QWORD PTR [rbp-0x8] // perchè rimetterlo in rax?
0x555552c9 <+140>: mov rsi,rax // strres
0x555552cc <+143>: lea rdi,[rip+0xd77] // format string # 0x55555555604a
0x555552d3 <+150>: mov eax,0x0
0x555552d8 <+155>: call0x555555555050 <printf@plt>

// ret

0x555552dd <+160>: mov eax,0x0
0x555552e2 <+165>: leave
0x555552e3 <+166>: ret

// removechar

// Dump of assembler code for function removechar:

// prologo

0x55555185 <+0>: push rbp
0x55555186 <+1>: mov rbp,rsp
0x55555189 <+4>: sub rsp,0x30
0x5555518d <+8>: mov QWORD PTR [rbp-0x28],rdi // rbp-0x28 indirizzo di str


0x55555191 <+12>: mov eax,esi
0x55555193 <+14>: mov BYTE PTR [rbp-0x2c],al // rbp-0x2c c'è il carattere
0x55555196 <+17>: mov DWORD PTR [rbp-0x8],0x0

// strlen

0x5555519d <+24>: mov rax,QWORD PTR [rbp-0x28] // rbp-0x28, str
0x555551a1 <+28>: mov rdi,rax
0x555551a4 <+31>: call0x555555555040 <strlen@plt>
0x555551a9 <+36>: mov DWORD PTR [rbp-0xc],eax // rbp-0xc, n

// malloc

0x555551ac <+39>: mov edi,0xf
0x555551b1 <+44>: call0x555555555070 <malloc@plt>
0x555551b6 <+49>: mov QWORD PTR [rbp-0x18],rax // rbp-0x18, strres


0x555551ba <+53>: mov DWORD PTR [rbp-0x4],0x0 // j=0
0x555551c1 <+60>: jmp 0x555555555213 <removechar+142> // salta a j<n


0x555551c3 <+62>: mov eax,DWORD PTR [rbp-0x4] // valore di i
0x555551c6 <+65>: movsxd rdx,eax // estende da 32 a 64 bit con il segno
0x555551c9 <+68>: mov rax,QWORD PTR [rbp-0x28] // indirizzo di str
0x555551cd <+72>: add rax,rdx // a cui aggiungiamo i, visto che si tratta di char
0x555551d0 <+75>: movzx eax,BYTE PTR [rax] // mette in eax il carattere iesimo
0x555551d3 <+78>: cmp BYTE PTR [rbp-0x2c],al // e lo compara a il ch passato alla funzione
0x555551d6 <+81>: je 0x55555555520f <removechar+138>

// il blocco seguente mette in OR la prima condzione negata con la seconda :
// if (str[i]!=ch && str[i]!='\0') { -> if (str[i]==ch || str[i]=='\0') {
// leggi di De Morgan , una AND di due espressioni negate diventa una OR di due espressioni non negate

0x555551d8 <+83>: mov eax,DWORD PTR [rbp-0x4]
0x555551db <+86>: movsxd rdx,eax
0x555551de <+89>: mov rax,QWORD PTR [rbp-0x28]
0x555551e2 <+93>: add rax,rdx // str + i
0x555551e5 <+96>: movzx eax,BYTE PTR [rax] // contenuto di str[i]
0x555551e8 <+99>: test al,al // confronto con il byte null
0x555551ea <+101>: je 0x55555555520f <removechar+138> // salta all'incremento di i

// blocco di costruzione della nuova stringa senza il carattere da rimuovere, copiando i caratteri dalla
// vecchia stringa

0x555551ec <+103>: mov eax,DWORD PTR [rbp-0x4] // i
0x555551ef <+106>: movsxd rdx,eax // esteso a 64 bit con segno
0x555551f2 <+109>: mov rax,QWORD PTR [rbp-0x28] // str
0x555551f6 <+113>: add rax,rdx // str + i
0x555551f9 <+116>: mov edx,DWORD PTR [rbp-0x8] // j
0x555551fc <+119>: movsxd rcx,edx // esteso a 64 bit con segno in rcx
0x555551ff <+122>: mov rdx,QWORD PTR [rbp-0x18] // strres
0x55555203 <+126>: add rdx,rcx // strres + j
0x55555206 <+129>: movzx eax,BYTE PTR [rax] // valore di str[i]
0x55555209 <+132>: mov BYTE PTR [rdx],al // in strres + j ci metto il carattere str[i]
0x5555520b <+134>: add DWORD PTR [rbp-0x8],0x1 // incremento j

// incremento di i e confronto con n

0x5555520f <+138>: add DWORD PTR [rbp-0x4],0x1 // incrementa i
0x55555213 <+142>: mov eax,DWORD PTR [rbp-0x4] // i
0x55555216 <+145>: cmp eax,DWORD PTR [rbp-0xc] // i<n
0x55555219 <+148>: jl 0x5555555551c3 <removechar+62> // se è minore torno indietro

// blocco che setta l'ultimo carattere della strres a \0

0x5555521b <+150>: mov eax,DWORD PTR [rbp-0x8]
0x5555521e <+153>: movsxd rdx,eax
0x55555221 <+156>: mov rax,QWORD PTR [rbp-0x18]
0x55555225 <+160>: add rax,rdx
0x55555228 <+163>: mov BYTE PTR [rax],0x0

// printf della strres

0x5555522b <+166>: mov rax,QWORD PTR [rbp-0x18]
0x5555522f <+170>: mov rdi,rax
0x55555232 <+173>: call0x555555555030 <puts@plt>

// ret

0x55555237 <+178>: mov rax,QWORD PTR [rbp-0x18] // in reax ci metto l'indirizzo della stringa risultato

0x5555523b <+182>: leave
0x5555523c <+183>: ret

// C Code

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char* removechar(char* str, char ch)
{

char* strres;
int n,i,j;
j=0;

n=strlen(str);

strres=malloc(15*sizeof(char));

for (i=0; i<n; i++) {
if (str[i]!=ch && str[i]!='\0') {
strres[j]=str[i];
j++;
}

}
strres[j]='\0';
printf("%s\n",strres);
return strres;


}


int main(int argc, char** argv) {

char str[15];
char* strres;
strres=malloc(15*sizeof(char));

printf("Inserisci la stringa : ");
fgets(str, 15, stdin);
char ch;

printf("Inserisci il carattere da rimuovere : ");
scanf("%c",&ch);

strres=removechar(str,ch);
printf("la stringa finale è %s",strres);


return 0;

}

// primi 4 byte indirizzo 0x00005555;

// prologo :

55555145 <+0>: push rbp
55555146 <+1>: mov rbp,rsp
55555149 <+4>: sub rsp,0x50 // qui crea lo spazio anche per l'array di interi

// non ho ben copreso ma potrebbe essere che mette in queste due locazioni, argc e *argv[], in effetti l'int è un DWORD, mentre l'indirizzo è un QWORD;

5555514d <+8>: mov DWORD PTR [rbp-0x44],edi
55555150 <+11>: mov QWORD PTR [rbp-0x50],rsi

// variabili intere;

55555154 <+15>: mov DWORD PTR [rbp-0xc],0xa
5555515b <+22>: mov DWORD PTR [rbp-0x8],0x0
55555162 <+29>: mov DWORD PTR [rbp-0x4],0x0
55555169 <+36>: jmp 0x5555555551ae <main+105> // qui salta al for;

// dovrebbe essere il blocco per puntare a arr[i] per poi passarlo alla scanf;

5555516b <+38>: lea rax,[rbp-0x40]
5555516f <+42>: mov edx,DWORD PTR [rbp-0x4] // mette in edx l'indice i;
55555172 <+45>: movsxd rdx,edx // da DWORD a QWORD;
55555175 <+48>: shl rdx,0x2 // questo doppio shift a sinistra trova il numero da;
55555179 <+52>: add rax,rdx // aggiungere a rax (che punta all'inizio dell'array) per puntare all'iesimo elemento di arr in memoria visto che ogni int sono 4 byte;

// la scanf che i due parametri, nell'rsi l'indirizzo di arr[i] e nel rdi il format string;

5555517c <+55>: mov rsi,rax
5555517f <+58>: lea rdi,[rip+0xe7e] # 0x555555556004
55555186 <+65>: mov eax,0x0
5555518b <+70>: call 0x555555555040 <__isoc99_scanf@plt>

// l'if per vedere se è il nuovo max e aggiornare la variabile max;

55555190 <+75>: mov eax,DWORD PTR [rbp-0x4] // questo è il valore di i;
55555193 <+78>: cdqe // qui viene convertito da eax a rax;
55555195 <+80>: mov eax,DWORD PTR [rbp+rax*4-0x40] // qui viene ricavato il valore di arr[i];
55555199 <+84>: cmp DWORD PTR [rbp-0x8],eax // se max è piu grande salta a 101 e incrementa i;
5555519c <+87>: jg 0x5555555551aa <main+101>

// se abbiamo il nuovo max;

5555519e <+89>: mov eax,DWORD PTR [rbp-0x4]
555551a1 <+92>: cdqe
555551a3 <+94>: mov eax,DWORD PTR [rbp+rax*4-0x40]
555551a7 <+98>: mov DWORD PTR [rbp-0x8],eax // viene assegnato a max il valore di arr[i]

// incremento della variabile i;

555551aa <+101>: add DWORD PTR [rbp-0x4],0x1

// for (i=0; i<n; i++), la pare della comparazione, tra rbp-0x04 che è la i, e rbp-0xc che è a quindi 10;

555551ae <+105>: mov eax,DWORD PTR [rbp-0x4]
555551b1 <+108>: cmp eax,DWORD PTR [rbp-0xc]
555551b4 <+111>: jl 0x55555555516b <main+38>

// la funzione printf che stampa il max valore dell'array;

555551b6 <+113>: mov eax,DWORD PTR [rbp-0x8]
555551b9 <+116>: mov esi,eax
555551bb <+118>: lea rdi,[rip+0xe45] // stringa printf # 0x555555556007
555551c2 <+125>: mov eax,0x0
555551c7 <+130>: call 0x555555555030 <printf@plt>

// ret;

555551cc <+135>: mov eax,0x0
555551d1 <+140>: leave
555551d2 <+141>: ret


#include <stdio.h>

int main(int argc, char** argv)
{

int arr[10];int n=10;
int i;
int max=0;

for (i=0; i<n; i++) {
scanf("%d",&arr[i]);
if (arr[i]>=max) max=arr[i];
}

printf("il massimo è %d\n:", max);
return 0;

 } 


r2 ./license_1

aaa, analisi automatica del binario

[0x004005c5]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for objc references
[x] Check for vtables
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.

afl, list functions

[0x004005c5]> afl
0x004004d0    1 41           entry0
0x004004a0    1 6            sym.imp.__libc_start_main
0x00400500    4 41           sym.deregister_tm_clones
0x00400530    4 57           sym.register_tm_clones
0x00400570    3 28           entry.fini0
0x00400590    4 45   -> 42   entry.init0
0x004006b0    1 2            sym.__libc_csu_fini
0x004006b4    1 9            sym._fini
0x00400640    4 101          sym.__libc_csu_init
0x004005bd    6 119          main
0x00400450    3 26           sym._init
0x004004c0    1 6            loc.imp.__gmon_start
0x00400480    1 6            sym.imp.puts
0x00400490    1 6            sym.imp.printf
0x004004b0    1 6            sym.imp.strcmp

s sym.main

V , ti permette di visualizzare il binario in diversi modi, codice assembler, ascii, debug, byte colorati

[0x004005c5]> V

ti muovi tra le varie visualizzazione con p per adnare avanti e P per tornare indietro, mentre con le frecce ti sposti nel codice, selezionando l'indirizzo dell'istuzione nella prima linea in alto;

axt [addr] find data/code references to this address
axf [addr] find data/code references from this address


next [count]

// Continue to the next source line in the current (innermost) stack frame. This is similar to step, but function calls that appear within the line of code are executed without stopping. Execution stops when control reaches a different line of code at the original stack level that was executing when you gave the next command. This command is abbreviated n.

// An argument count is a repeat count, as for step.

004005ef <+50>:    mov    rax,QWORD PTR [rbp-0x10]
004005f3 <+54>:    add    rax,0x8
004005f7 <+58>:    mov    rax,QWORD PTR [rax]
004005fa <+61>:    mov    esi,0x4006da
004005ff <+66>:    mov    rdi,rax
00400602 <+69>:    call   0x4004b0 <strcmp@plt>

(gdb) b main

(gdb) run BBBB

(gdb) b *0x0000000000400602

(gdb) n

(gdb) x/10s $rsi
0x4006da:    "AAAA-Z10N-42-OK"
0x4006ea:    "Access Granted!"

la strcmp viene fatta tra i due registri rsi e rdi, e ritorna zero se contengono stringhe uguali;

ltrace ./license_1 AAAA
__libc_start_main(0x4005bd, 2, 0x7ffccebfc2d8, 0x400640 <unfinished ...>
printf("Checking License: %s\n", "AAAA"Checking License: AAAA
)                                                  = 23
strcmp("AAAA", "AAAA-Z10N-42-OK")                                                         = -45
puts("WRONG!"WRONG!
)                                                                            = 7
+++ exited (status 0) +++ 

C Code

#include <string.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
        if(argc==2) {
        printf("Checking License: %s\n", argv[1]);
        if(strcmp(argv[1], "AAAA-Z10N-42-OK")==0) {
            printf("Access Granted!\n");
        } else {
            printf("WRONG!\n");
        }
    } else {
        printf("Usage: <key>\n");
    }
    return 0;
}
 


substring.c
===========

#include <stdio.h> // librerie standard input/output

// il main ti fa inserire una stringa, poi una posizione from, primo carattere? nesimo carattere? e un numero n, cioè quanti caratteri andare a considerare per la sottostringa partendo dal from;

int substring(char *source, int from, int n, char *target) {

int length, i;

// qui si calcola la lunghezza della stringa immessa come input, scorre la stringa, carattere dopo carattere fino al byte null;

for (length=0; source[length]!='\0'; length++);

// se il from immesso è maggiore della lunghezza della stringa appena calcolata, esce fuori con un codice di errore 1;

if (from>length) {
printf("Starting index is invalid.\n");
return 1;
}

// se (from + n) è un numero maggiore della lunghezza calcolata, imposta n, al massimo n possibile, in modo da raggiungere la fine della stringa;

if ((from+n)>length) {
n = (length - from);
}

// partendo da from, per tutti gli n caratteri, copia il carattere sorgente nella stringa target;

for (i=0; i target[i]=source[from+i];
}

// finalizza la stringa target con il byte null;


target[i]='\0';

return 0;

}


int main(int argc,char *argv[]) {

char str[100], targetString[100];
int from, n;

printf("Enter any string:");

// la funzione gets è una funzione non sicura, andrebbe usata la funziona fscanf;

gets(str);

printf("Enter from index (count from 0): ");
scanf("%d",&from);

printf("Enter number of characters: ");
scanf("%d",&n);

// se la funzione substring ritorna un valore 0, stampa la sottostringa estratta dalla stringa immessa;

if (substring(str, from, n, targetString) == 0) {
printf("Substring is: %s\n",targetString);
}

return 0;

}