質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.51%

  • C

    4279questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

(*(void(*)()) hoge)();というコードがどう作用するのか噛み砕いて教えてください

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 451

jaguarundi

score 6

前提・実現したいこと

C言語からシェルを実行するためのコードを勉強中です。(セキュリティ関連なので、シェルコードです。)

C言語の知識は一通り学んだのですが、唐突に出てきた(*(void(*)()) hoge)();というコードの部分が理解できず困っております。(関数ポインタでしょうか?)

このコードを実行すると、確かに希望通りの動作をするのですが、(*(void(*)()) hoge)();の部分がなぜ動くのか、自分の力では理解できなかったので、teratailの人々に質問した次第です。

該当のソースコード

char *hoge="\x48\x31....."; //シェルコード

int main(){
 (*(void(*)()) hoge)();
 return 0;

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+5

式 (*(void(*)()) hoge)(); は、構文上次のように分解できます。

  • 式全体: 関数呼び出し {#1}();
  • {#1}: 参照はがし (* {#2})
  • {#2}: 型キャスト ({#3}) hoge

{#3}部は関数ポインタ型void(*)()、つまり「“引数をとらずvoid型を返す関数”へのポインタ型」です。※注1

少しだけわかりやすく書き直すと、次コードのようになります。

typedef void (*FuncType)();
(* (FuncType) hoge)();

関数ポインタ型に対する参照はがし(*)は明示不要ですから、下記のようにも書けます。※注2

typedef void (*FuncType)();
((FuncType) hoge)();

※注1: C言語仕様に厳格に従うと、void(*)(void)表記がより望ましいです。void(*)()は任意個の実引数を取りうる関数ポインタ型です。この回答では本質ではないため、簡単に「引数なし」と説明しています。

※注2: C言語仕様に厳格に従うと、関数呼び出しは 常に 関数ポインタ型を経由します。つまり、普通の関数呼び出しにおいて「関数名から関数ポインタ型への変換」が暗黙に行われています。プログラマがこの型変換を意識することはないでしょう。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/13 18:58

    噛み砕いた説明、大変助かりました。
    他の回答者の方々にも感謝します!

    キャンセル

+1

シェルコードhogeを関数ポインタに変換できればよいので

char *hoge="\x48\x31....."; //シェルコード
void (*fptr)() = (キャスト)hoge; // 関数ポインタ

キャストは、変数宣言から識別子を抜いた形になるので

void (*fptr)() = (void(*)()) hoge;

となります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

構造的には、(キャストする型名 hoge)()で、ポインタhogeを関数型にキャストしてそれを()で呼び出すと言う事です。

キャスト先の型名が、*(void(*)())ですが、これは、(void(*)())もしくは(void*(*)())の間違いじゃないのかなぁ。

前者だとすると、
値(この場合はchar *であるhoge)の指す先(内側の*が示す意味)を関数として呼び出して(()が示す意味)、その関数が返す値がvoid型である。ということです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

hogeを関数としてキャストして、そこに飛びます。
それだけです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • C

    4279questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。