double(...)
の関数をx64シェルコードとしてコンパイルしたいと思います。私はすでにa + b/a
のような単純な数学演算のためのエンコードされたアセンブリを生成する作業プログラムを持っています。ここではa
とb
はdouble
です。シェルコード内で関数を呼び出す
生成されたコードは実行可能なmmap
バッファにロードされ、後で呼び出すことができます。
私は次のような問題があります。私は生成されたシェルコードの中に、exp
などのようにmath.h
の機能を呼びたいと思います。すべてのcall
オペコードは32ビットのアドレスまたは相対ジャンプを使用するため、これらの命令を簡単に使用することはできません。したがって、私は自分のcall
-instructionをこのように実装してみました:
lea rax, [rip+0x0] ;load instruction pointer into rax
add rax, <offset-to-return-to>
push rax
moveabs rax, <adress-of-function> ;load the function pointer to rax
jmp rax
これは、これらの命令を生成するために私のコードです:残念ながら
//lea rax, [rip+0x0]
insertAll(code,std::list<uint8_t>{ 0x48, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x00 });
//add rax, <offset-to-return-to>
insertAll(code,std::list<uint8_t>{ 0x48, 0x83, 0xC0, <offset-to-return-to>});
//push rax
code.push_back(0x50);
//moveabs rax, address-of-function
uint8_t reg = 0; //rax
uint8_t rexWPrefix = 0x48 + (reg > 8);
uint8_t opCode = 0xB8 + (reg % 8);
insertAll(code,std::list<uint8_t>{ rexWPrefix, opCode });
code.insert(code.end(),reinterpret_cast<uint8_t*>(&fabs),reinterpret_cast<uint8_t*>(&fabs) + 8);
//jmp rax
insertAll(code,std::list<uint8_t>{ 0xFF, 0xE0 });
、この方法が機能しない関数を呼び出すと、プログラムはでクラッシュa SIGSEGV
エラー。私のアセンブリコードや命令のエンコーディングに何か問題がありますか?機能が正しい位置に戻るようにするには、どの値を<offset-to-return-to>
にする必要がありますか?
免責事項:私は、これがコードの動的生成を処理する最良の方法ではないことを知っています...ダイナミックライブラリをコンパイルし、dlsym
でロードできます。これは、アセンブリ/シェルコードについて学ぶためのちょうど楽しい方法です。あまり深刻ではありません。
一見理にかなって見るためにデバッガを使用どこで、なぜそれが失敗するのか。 PS:あなたはもちろん、 'lex 'に' add rax'をマージすることができます。正しいオフセットを使用してください。 – Jester
「x64シェルコード」とは何ですか? CとC++は異なる言語です。タグをスパムしないでください。 – Olaf
@Olaf:私はコードにx86-64命令を使用していると言いたいと思います。これは、アドレスのサイズが64ビットであるため、jmp命令では重要です。 – tly