関数名を書かずにC言語で関数を呼び出す方法

Calling a function in C without naming it

学校の自動採点システムは、許可された関数以外の使用をAST解析で検出する。execveを直接呼べないため、ASanで置き換えられたprintfとmmapのオフセットを漏洩させ、unionで関数ポインタを偽装。mmapで書き込み可能かつ実行可能なページを確保し、syscall命令を配置してexecveを呼び出すことに成功した。

C言語では、安全性の欠如は機能です。だからunionをそのまま使うことができます。
  1. ashdnazg

    うちの大学はずっとずさんで、提出物は他のすべてと同じネットワーク上で、ほぼ権限のないユーザーで実行していただけだった。

    自動テストが僕の提出物をクラッシュさせたとき、`system`を使ってテスト入力をホームディレクトリにダンプしただけだった。でもパーミッションの設定を忘れてしまい、実際にはアクセスできなかった!何度か再提出してchmodを追加し、毎回別のものを台無しにしながら、なんとかバグを再現し、修正し、再提出して、証拠をすべて(あるいはほとんど)消し去ることに成功した。

  2. Kevin_Flynn

    私たちのコードはASanでコンパイルされていると分かっていたので、常に許可されている関数であるprintfと、任意のアセンブリコード実行を可能にするmmapとの間のオフセットをリークさせることを選んだ。これにより学校のチェックを回避して任意のシステムコールを呼び出せる。私たちの場合はexecveでシェルアクセスを得た。

    それ以上は調査せず、この可能性のある問題を学校に報告しただけだ。

    これを修正する簡単な方法は見当たらない。

    欠陥は提出システムにあるようだ。

    提出システムは、あなたのコードをトランポリンライブラリにビルド/再リンクし、禁止される各関数の本体をエラー報告とabortに置き換えることができる。あなたの例では、次のものをトラップするだろう:

    char *code =

    notmmap.fn(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC,

    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

    そして提出検証の実行フェーズ中にPROT_EXECフラグの使用を防ぐ。

    AIによると、Linuxでは:「...各プロセスがプログラムを実行し始める前に適用されるseccomp-BPFフィルタ。これはmmapのprot引数を検査し、PROT_EXECが設定されている場合にEPERMを返すことができる。」

    さらにLinuxでは:「systemdはサービスに対してMemoryDenyWriteExecute=yesを提供している。これはすべての実行可能マッピングを禁止するよりも制限が緩い:書き込み可能かつ実行可能なマッピングと、メモリを実行可能にする関連する方法を対象としている。」

    (記事を正しく読んでいれば)

    ps. 提案された解決策を学科長や他の権威に提出して、何らかの恩恵をもらえるかもしれない […]

  3. PeterWhittaker

    学校はseccompのdenylistで物事をラップする必要があるようだ。簡単ではないかもしれないが、面白いかもしれない。

この日のほかの記事

2026-10-08