Cela ressemble à du code auto-modifiable.
Il boucle 7 fois et lorsque ecx atteint zéro, il remplace l'instruction jmp L par une autre instruction JMP qui saute à l'instruction après le second JMP.
Foos:
mov ecx,7
mov edx,5
L:
inc edx
sub ecx,1
setZ al ; set al to 1 if zero flag, otherwise al=0
shl al,1 ; multiply by 2, so al=2 when ecx reaches zero
mov byte[L1+1],al
L1:
jmp L
jmp L
mov eax,edx
ret
La magie est dans l'octet mov [L1 + 1]. Quand al = 0, il remplace le premier JMP par un JMP à l'instruction suivante, qui est à nouveau JMP L, donc il boucle. Lorsque al = 2, il remplace le premier JMP pour ignorer 2 octets, donc il ignore le second saut, donc la boucle se termine. À la fin edx est 12 (5 + 7)
Pourquoi est-ce?
Les instructions JMP utilisées ici sont sauts courts. Ils sont codés sur 2 octets: EB suivi d'un seul octet représentant le nombre relatif d'octets à sauter. L'instruction mov remplace le deuxième octet par (passer à l'instruction suivante) ou (sauter 2 octets en avant).
oui mais comment remplacer le saut et où ??? – nisnis84
merci beaucoup !!!!! – nisnis84
Je pense que la plupart des x86 modernes ne verront pas la mise à jour de l'instruction. Au moment où le "octet de déplacement [L1 + 1]" est exécuté, le code de L1 a été préalablement extrait par la CPU dans son cache d'instructions, et la mise à jour n'est pas vue par ce cache. Cela arrive parce que cela ne vaut pas la peine pour les concepteurs de CPU de faire fonctionner les interactions entre le code auto-modifiable et la mise en cache des instructions. Il existe des instructions pour forcer une reprise du flux d'instructions après une telle mise à jour, mais ce code ne les utilise pas. Donc ce code boucle à jamais ==> edx n'a jamais de valeur à l'instruction ret. –