2009-10-09 19 views
3

J'essaie de coder un packer/protecteur exe comme un moyen d'en apprendre plus sur l'assembleur, C++, et comment fonctionnent les fichiers PE. Je l'ai actuellement fonctionné ainsi la section contenant l'EP est XORed avec une clé et une nouvelle section est créée qui contient mon code de déchiffrement. Tout fonctionne très bien sauf quand j'essaie et JMP à l'EP original après le décryptage.JMP à l'adresse absolue (codes op)

En fait, je fais ceci:

DWORD originalEntryPoint = optionalHeader->AddressOfEntryPoint; 
// -- snip -- // 
    crypted.put(0xE9); 
crypted.write((char*)&orginalEntryPoint, sizeof(DWORD)); 

Mais au lieu de sauter au point d'entrée, ollydbg montre que ce code désassemble à:

00404030 .-E9 00100000 JMP 00405035 ; should be 00401000 =[ 

et lorsque je tente de le changer manuellement olly le nouvel opcode apparaît comme

00404030 -E9 CBCFFFFF JMP crypted.00401000 

D'où provient 0xCBCFFFFF? Comment pourrais-je générer cela du côté C++?

Répondre

5

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

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

+0

Des idées sur ce qui remplacerait E9? –

+0

@Chris: cela peut vous aider dans votre recherche: http://ref.x86asm.net/ – fvu

+0

Les sauts sont généralement relatifs. Il y a un opcode 'EA' pour un saut à une adresse extrême absolue, et des opcodes pour des sauts vers une adresse indirecte (où l'opérande spécifie l'emplacement de mémoire qui contient l'adresse à laquelle on doit sauter). – ChrisW

14

vous pouvez utiliser:

push DESTINATION_VA 
ret 

ou

mov eax,DESTINATION_VA 
jmp eax 

encodage JMP relatif E9 est utilisé comme ceci:

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

bouton + RET est la meilleure solution si vous avez VA adresse et l'image n'est pas déplacée

+1

merci de m'avoir sauvé! – Gizmo

6

L'opcode pour saut indirect absolu est FF + adresse 4 octets. Ceci est le plus souvent utilisé pour les jumptables d'adresses stockées dans des données.

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

Le manuel d'optimisation Intel indique que le CPU s'attend à ce que call et ret soient utilisés par paires, donc le ret sans appel suggéré dans la réponse 2 provoquerait 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 supposé, le ret planterait probablement le programme. Il serait plus sûr de calculer une adresse relative.

+3

peut-être que vous voulez dire FF 25 4byte ..FF 4 octets n'a aucun sens du tout. – Laie

+0

@Laie cela a encore du sens puisque 'FF' est l'opcode et nous savons que le mnémonique est' jmp'. Il pourrait être «FF/4» ou «FF/5», car ils sont tous les deux des sauts indirects - l'un étant proche et l'autre un saut lointain. Mais oui, 'FF 25 aa bb cc dd' est comment vous observer' FF/4' (le plus commun des deux) dans le code machine. –