問題タブ [dynamic-code]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - 関数をFuncに保存する方法はJintにありますか?
Jint を使用して、C# コードの関数を動的に実行しています。機能を実行するのに完全に機能します。ただし、実行時間は実行ごとに線形です
潜在的に 100 万回以上の関数を実行する予定です。現在、このコードの実行には 126197 ミリ秒 (2 分 6 秒) かかります。エンジンによって読み取られた後、関数を C# に格納する方法はありますか? または、この実行回数をより速い時間枠で処理する別のライブラリはありますか?
編集
私はこのようなことを考えています:
ありがとう、
c - 動的 C コード実行: メモリ参照
tl;dr : 別のスニペットからいくつかのコードを動的に実行しようとしています。しかし、メモリ参照の処理に行き詰まっています (例: コードからのオフセットとして) 正しく解決されるmov 40200b, %rdi
ように、自分のコードまたは実行中のコードのスニペットにパッチを適用できますか?0x40200b
200b
動的に実行されるコードを生成するには、(カーネル) オブジェクトから開始し、ld を使用して参照を解決します。
次に、mmaped ファイルを介して実行するコードを送信します
このコードでコードを動的に実行します
このアプローチは、次のようなメモリにアクセスしないコードに対して機能しますが"\x55\x48\x89\xe5\xc7\x45\xf8\x02\x00\x00\x00\xc7\x45\xfc\x03\x00\x00\x00\x8b\x55\xf8\x8b\x45\xfc\x01\xd0\x5d\xc3"
、メモリが関係している場合に問題があります。
以下の例を参照してください。
関数 vm_close を動的に実行したくないと仮定しましょう。Objdump -d -S
戻り値:
実行時に、関数ポインターは正しいコードを指します。
しかし、このコードは次の理由で失敗します:
1) 私のコンテキストでは、 $0x40200bはコードの先頭からでは$0x40200b
なく、物理アドレスを指してoffset 200b
います。
2) 理由はわかりませんが、そこに表示されるアドレスは実際には正しいアドレス (0xffffc8ff818ec3de != ffffffff810e73de) とは異なるため、シンボルを指せず、クラッシュします。
私の2つの問題を解決する方法はありますか?
また、私の問題 (低レベルのメモリ解決) に関連する適切なドキュメントを見つけるのに苦労しました。
編集: カーネルでコードを実行するため、 gcc で許可されていない、-fPIC
または-fpie
gcc で許可されていないコードを単純にコンパイルすることはできません ( cc1: error: code model kernel does not support PIC mode
)
編集 24/09:
@Peter Cordes のコメントによるとmcmodel=small -fpie -mno-red-zone -mnosse
、Makefile ( /lib/modules/$(uname -r)fixed/build/Makefile
) に追加して再コンパイルしました。これは、リンク前に生成されたコードが次のようになっているため、元のバージョンよりも優れています。
これで、スクリプトの他の変数にアクセスできるようになりました…</p>
したがって、リンク後、バッファ内に埋め込まれた変数に正常にアクセスできます。
それでも、1 つの問題が残っています。
アクセスしたいシンボル ( printk
) と実行可能バッファは、たとえば次のように異なるアドレス空間にあります。
しかし、私のcallq
toでは、カーネルにセクションがないためprintk
、オフセットとして呼び出すアドレスを書き込むのに 32 ビットしかありません。これは、printkを内に配置する必要があることを意味します。しかし、そうではありません。$rip
.got
[$rip-2GO, $rip+2GO]
printk アドレスはバッファから 2GO 以上離れていますが (使用しようとしmcmodel=medium
ましたが、生成されたコードに違いは見られませんでした)、たとえば gcc オプションを変更して、バイナリが実際に.got
セクションがありますか?
または、実行可能ファイルと潜在的に大きすぎる kmallocバッファーを強制的に割り当てる信頼できる方法はありますか[0xffffffff00000000 ; 0xffffffffffffffff] range?
(私は現在使用しています__vmalloc(BUFFER_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
)
編集 27/09:エクスポートされていない関数を (汚い) ハックとして[0xffffffff00000000 ; 0xffffffffffffffff]
使用して、範囲内
にバッファを割り当てることに成功しました。 __vmalloc_node_range
次に、実行可能バッファのアドレスとカーネル シンボルのアドレスがわかったら ( を解析して)、のオプションwhere/proc/kallsyms
を使用してバイナリにパッチを適用できます。ld
--defsym symbol=relative_address
relative_address = symbol_address - buffer_offset
非常に汚れていますが、このアプローチは実際に機能します。
ただし、バッファが別のアドレスに割り当てられる可能性があるため (そして割り当てられる予定)、実行するたびにバイナリを再リンクする必要があります。この問題を解決するには、実行可能ファイルを実際の位置に依存しない実行可能ファイルとしてビルドして、グローバル オフセット テーブルにパッチを適用し、モジュールを完全に再リンクしないようにするのが最善の方法だと思います。
しかし、そこで提供されたオプションを使用すると、リップ相対アドレスを取得できましたが、get/plt は取得できませんでした。したがって、モジュールを適切な PIE としてビルドする方法を見つけたいと思います。
この投稿は巨大で乱雑になり、元の質問から逸脱しています。したがって、そこに新しい簡略化された投稿を開きました。興味深い回答が得られたら、この投稿を編集して説明します。
注: 簡単にするために、安全性テストは表示されません。
注 2: 私の PoC が非常に珍しいものであり、悪い習慣になる可能性があることは十分承知していますが、とにかくやりたいと思っています。