10
votes

JMP à l'adresse absolue (codes OP)

J'essaie de coder un EXE Packer / Protecteur comme moyen d'apprendre davantage sur l'assembleur, C ++ et comment fonctionnent les fichiers PE. Je l'ai actuellement travaillé pour que la section contenant le PE soit xored avec une clé et une nouvelle section est créée qui contient mon code de déchiffrement. Tout fonctionne bien, sauf lorsque j'essaie et JMP à l'EP d'origine après le décryptage.

En gros, je fais cela: p> xxx pré>

mais au lieu de passer au point d'entrée, OllyDBG montre que ce code démontait: p> xxx pré>

et lorsque j'essaie de le changer manuellement dans olly, le nouvel opcode apparaît comme P>

00404030    -E9 CBCFFFFF    JMP crypted.00401000


1 commentaires

À quiconque pourrait trébucher, il y avait une question similaire sur Re.se où j'ai fourni une explication très détaillée: ReverseGineering.stackexchange.com/Questions/19459/...


3 Réponses :


7
votes

Je pense que E9 est un opcode pour un saut relative: son opérande spécifie une distance relative à sauter, plus ou moins du début de l'instruction suivante.

Si vous souhaitez que l'opérande spécifie une adresse absolue, vous auriez besoin d'un opcode différent.


4 commentaires

Des idées quant à ce qui serait un remplaçant pour E9?


Les sauts sont généralement relatifs. Il y a un opcode ea pour un saut à une adresse lointaine lointaine et opcodes pour des sauts à une adresse indirecte (où l'opérande spécifie l'emplacement de mémoire qui contient l'adresse à sauter à).


Cela n'a pas répondu à la question, il suffit de confirmer que l'OP avait la mauvaise réponse.


@baordog La question était: "D'où vient 0xcbcfffff?" Quoi qu'il en soit, l'OP a compris la réponse et / ou était satisfait par ea dans le commentaire.



19
votes

Vous pouvez utiliser:

CURRENT_RVA: jmp (DESTINATION_RVA - CURRENT_RVA - 5 [sizeof(E9 xx xx xx xx)])


3 commentaires

Je cherche une méthode similaire pour l'espace d'adresses 64 bits, avec des codes OP.


@Thomastempelmann: appeler un pointeur absolu dans le code de machine X86 couvre X86-64.


Mon édition sur cette réponse a adressé des problèmes de performances graves avec Push / RET Mais malheureusement, l'affiche le retourna. Si vous vous souciez de la performance sur le X86 moderne, utilisez MOV EAX, DST / JMP EAX au lieu de déséquilibrer le prédicteur d'adresse de retour avec un RET que Ne correspond pas à un appel ( agner.org/optimize ). Et / ou voir appeler un pointeur absolu dans le code de machine X86 . MOV / JMP coûte 1 octet supplémentaire contre PUSH / reta et évite les futures branches malpréds si vous ret de la cible



5
votes

opcode pour un saut indirect absolu est FF + Adresse 4Byte. Ceci est le plus souvent utilisé pour les Jumpables d'adresses stockées dans des données.

Les adresses absolues nécessitent une relocalisation lorsqu'elles ne sont pas chargées à l'adresse attendue, les adresses relatives sont généralement préférées. Le code pour des sauts relatives est également 2 octets plus petit.

Manuel d'optimisation Intel stipule que la CPU attend d'appeler et RET à utiliser par paires, de sorte que le TR SANS sans appel suggéré dans la réponse 2 entraînerait ce qu'ils appellent une "pénalité de performance".

En outre, si le code n'a pas été chargé à la même adresse que le compilateur a supposé, le TRU annule probablement le programme. Il serait plus sûr de calculer une adresse relative.


4 commentaires

Peut-être que vous voulez dire FF 25 4Byte .. FF 4 octets n'a aucun sens du tout.


@LAIE Il a toujours du sens depuis ff est l'opcode et nous savons que le Mnemonic est JMP . Il pourrait être ff / 4 ou ff / 5 car ils sont tous deux absolus absolus indirects - l'un étant proche et l'autre un saut de loin. Mais oui, ff 25 aa bb cc dd est comment vous observerez ff / 4 (plus commun des deux) dans le code de la machine.


Le dernier paragraphe n'est pas correct: Push IMM32 / REV ne se bloque pas, la délocalisation du code ne changera pas l'adresse cible absolue que RET saute à. Le problème est la performance: le déséquilibre de la pile d'adresses de retour apportera quelques déclarations futures. A MOV REG, IMM32 + 2 octet Registre-Indirect Saut est probablement votre meilleur choix (plutôt que de charger un pointeur de la mémoire) si pour une raison quelconque, vous ne pouvez pas simplement encoder un JMP Rel32 de une adresse connue ,. Appeler un pointeur absolu dans le code de machine X86 .


Il serait agréable de mentionner un opcode JMP correspondant pour le mode 64 bits également.