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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

2回答

3313閲覧

関数へのポインタでの関数呼び出しについて

Divided_by_Zero

総合スコア42

C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

1グッド

1クリップ

投稿2016/01/29 05:49

プログラミング初心者なので暖かい目で見ていただけると幸いです。

execve("/bin/sh", ["/bin/sh", NULL], NULL)を16進数に変換し、C言語で呼び出すことで、シェルを立ち上げるというやり方について、少し疑問があったので質問させていただきます。

#include <stdio.h> typedef void (*func)(); char shellcode[] = "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"; int main(void) { ((func)&shellcode)(); // ((func)shellcode)(); // こっちでも呼び出せる?? return 0; }

16進数をリトルエンディアンで文字列としてグローバル変数shellcodeに定義しておき、main関数内で呼び出しを行っています。

簡単のため、事前にtypedefにより、
引数を取らず、void型を返す関数へのポインタ型をfunc型
と定義しています。

私は、アスタリスク演算子はメモリ上のその変数がある番地の値を取得、アンパサンド演算子はメモリ上のその変数がある番地を取得(この部分について、少し自信がないので今回質問させていただきました)していると考えているのですが、
番地でも、その番地に格納された値でもfunc型にキャストして関数呼び出しができてしまうのは何故なのでしょうか?

ポインタの初歩的なところでつまづいてしまっていますが、どなたかご教授いただけないでしょうか?

Magkinh👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

shellcodeのように、配列の名前を式の中に書くと、自動で「配列の先頭アドレス」として処理されます。一方、明示的に&shellcodeとアドレスを取ると、それは「配列全体のアドレス」となります(参考)。型は違いますが位置は同じです。

つまり、shellcode&shellcodeも、キャストしてしまえば何も変わりません

投稿2016/01/29 06:12

編集2016/01/29 06:13
maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2016/01/29 06:54

&shellcodeなんて自分で書いたことなかったので「配列全体」を指すとは知りませんでした。 printf("%d\n", sizeof *shellcode); printf("%d\n", sizeof *&shellcode[0]); printf("%d\n", sizeof *&shellcode); で、違いが分かりますね。
Divided_by_Zero

2016/02/07 16:05

連絡がおくれてしまって大変申し訳ないです。 回答ありがとうございます。 頂いた参考記事、とても勉強になりました。 Cを触った時に、ポインタについても少し触れていたものの、理解が浅く、手間取ってしまう場面が多かったのですが、アプローチ(考え方?)が間違っていたようです。 ありがとうございます。
guest

0

(これは質問への直接回答ではありませんが)

execve("/bin/sh", ["/bin/sh", NULL], NULL)を16進数に変換し、C言語で呼び出すことで、シェルを立ち上げると
(略)
16進数をリトルエンディアンで文字列としてグローバル変数shellcodeに定義しておき、main関数内で呼び出し

目的と実装がマッチしていないのですが、大丈夫でしょうか?あなたのコードが実際に行っていることは、shellcodeに格納されているバイト列をマシン語命令とみなして、それを実行時に呼び出すという(かなり危険な)処理になっています。実際に動作させるとクラッシュするのでは?


一応、該当のマシン語命令を逆アセンブルしてみましたが全く意味のない命令列になっています。(Intel x86と仮定)

$ printf "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80" > shellcode.bin $ objdump -D -b binary -m i386 shellcode.bin 0: 31 d2 xor %edx,%edx 2: 52 push %edx 3: 68 2f 2f 73 68 push $0x68732f2f 8: 68 2f 62 69 6e push $0x6e69622f d: 89 e3 mov %esp,%ebx f: 52 push %edx 10: 53 push %ebx 11: 89 e1 mov %esp,%ecx 13: 8d 42 0b lea 0xb(%edx),%eax 16: cd 80 int $0x80

投稿2016/01/29 15:26

編集2016/01/29 15:29
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Divided_by_Zero

2016/02/07 16:14

申し訳ありません。 私の日本語力がないばかりに、質問文が分かりづらい表現となってしまっていました。 このやり方は、ご指摘頂いたとおり、危険なやり方になると思われます。 shellcodeの箇所をアセンブラに戻すと、割り込みシステムコール呼び出しにより、execve("/bin/sh", ["/bin/sh", NULL], NULL);を呼び出すようになっています。 もちろん、本来ならばこのようなやり方はおかしいはずで、ただインラインアセンブラを書きたいだけなのであれば__asm__()を呼び出すことで実現できると思います(あまり詳しくないので、これは適切じゃないかもしれません・・・)。 ですが今回は、スタック上に置かれた配列に対し、ユーザからの入力によってバッファーオーバーフローが起きた際に、うまいことshellcodeの先頭部分にEIPが飛び、shellcodeが実行されてしまう場合について考えています。 その勉強をしていたところ、質問文にあるような関数呼び出しが行われていたため、なぜ異なった呼び方なのに結果的には同じようにshellcodeが呼び出せてしまうのだろう・・・?と思い、質問させていただきました。
Divided_by_Zero

2016/02/07 16:15

知見が浅いため、表現が不適切な箇所が散見されるかもしれません。 申し訳ありません。
yohhoy

2016/02/08 02:54

「shellcodeの箇所をアセンブラに戻すと、割り込みシステムコール呼び出し」 なるほど言われてみれば、ちゃんと読むとそのようなアセンブラコードになっていますね。失礼しました。
Divided_by_Zero

2016/02/08 05:59

貴重なご指摘をいただけて大変嬉しいです。 明確に「こういう部分がいけないきがする」とご指摘いただけたので、より知見を深めることができました。 よろしければ、今後ともご指摘いただけると幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問