質問

私は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はおそらくプログラムをクラッシュしていました。相対アドレスを計算する方が安全だろう。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top