絶対アドレスへのJMP(OPコード)
-
20-09-2019 - |
質問
私はC ++、アセンブラについての詳細を学ぶ方法としてexeファイルパッカー/プロテクターをコーディングしようとすると、どのようにPEファイルが動作しています。私は現在、それはとてもEPを含むセクションは、キーと私の復号化コードが含まれて作成された新しいセクションとXORされた作業を持っています。すべては私が解読した後、元のEPに試してみて、JMPとき以外は素晴らしい作品ます。
基本的に私はこれを行う:
DWORD originalEntryPoint = optionalHeader->AddressOfEntryPoint;
// -- snip -- //
crypted.put(0xE9);
crypted.write((char*)&orginalEntryPoint, sizeof(DWORD));
しかし、その代わりに、それはエントリポイントにジャンプするのは、ollydbgは、このコードは、に分解していることを示して
00404030 .-E9 00100000 JMP 00405035 ; should be 00401000 =[
と私はオリーに手動で変更しようとすると、新しいオペコードは、
として表示されます00404030 -E9 CBCFFFFF JMP crypted.00401000
0xCBCFFFFFはどこから来たのか?どのように私はC ++側から発生するのでしょうか?
解決
私はE9
が相対ジャンプのオペコードであることを考える:そのオペランドは跳ね上がっする相対距離を指定し、プラスまたは次の命令の開始からマイナス
、あなたは別のオペコードが必要になります。
他のヒント
あなたが使用することができます:
mov eax,DESTINATION_VA
jmp eax ; pick any register the destination doesn't care about
または
push DESTINATION_VA
ret ; not recommended for performance
このバック予測ミスます。この深さよりも高いコールツリー上がって次のアップに-16 ret
命令、彼らはより深いコール深さによって、リターンアドレス予測スタックをオフにプッシュされた場合を除きます。 (現在のCPUは、典型的には16エントリ予測スタックを有する)。
相対E9
jmp
の符号化は次のように使用されている
CURRENT_RVA: jmp (DESTINATION_RVA - CURRENT_RVA - 5 [sizeof(E9 xx xx xx xx)])
あなたはVAアドレスを持っているし、イメージが再配置されていない場合は、プッシュ+ RETとは、最小のソリューションですが、それが直接jmp rel32
より大きいですので、それはまだ6バイトです。
あなたは、通常の直接jmp
を使用できない場合はレジスタ間接は、おそらく最も効率的である。
オペコードはFF + 4バイトのアドレスです。これは、ほとんどの場合、データに格納されたアドレスのjumptablesのために使用されます。
絶対アドレスが期待されるアドレスにロードされていない時に再配置を必要としないので、相対アドレスが一般的に好ましいです。相対ジャンプのためのコードは、2バイト小さい。
インテルの最適化マニュアルは、彼らは、「パフォーマンスの低下」と呼んでしまい、CPUが呼び出しとRETペアで使用されることを想定して、そのコールなしRETは答え2で提案されていると述べています。
コードは、コンパイラが想定し、同じアドレスにロードされなかった場合は、また、RETはおそらくプログラムをクラッシュしていました。相対アドレスを計算する方が安全だろう。