🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

GDB

GDBはGNUソフトウェアシステムのための標準的なデバッガーです。

Q&A

解決済

1回答

686閲覧

環境変数のアドレス確認方法について GDB

kazuyakazuya

総合スコア193

C

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

GDB

GDBはGNUソフトウェアシステムのための標準的なデバッガーです。

0グッド

1クリップ

投稿2019/11/12 18:24

シェルコードを環境変数に登録しました。
(動くかはわからない)

イメージ説明
今気づいたけど0があるからシェルコードとしては使えない・・・
ただ、今回は話が違うので・・・

シェルコードが置かれている環境変数のアドレスを確認します。

cmd

1$gdb ./test 2 3$break main 4 5$run 6 7$x/24s $rsp + 900

すると

イメージ説明

なんで、16進数表記のアドレスが6バイトで表示されているのでしょうか?
ふつう、4バイトですよね?

c

1int main(void){ 2printf("%p\n",getenv("SHELLCODE")); 3return 0; 4}

それで、実行するとこちらも6バイトで表示されます。

なぜでしょうか?

分からないのでお願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

64bitのOSとコンパイラなのでは?
上の2byte分は0なので、表示してないだけのように思えます。

投稿2019/11/12 22:10

PingHermit

総合スコア478

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

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

退会済みユーザー

退会済みユーザー

2019/11/12 22:33

補足です。アーキテクチャの記載がないので推測ですが、amd64だと仮定します。 https://ja.wikipedia.org/wiki/X64#AMD64 にあるとおり、 「AMD64アーキテクチャでは、現状の実装で48ビットのアドレス空間を持ち、256テラバイトまでのメモリを扱うことが出来る」から です。 正確には物理アドレスとは違うマッピングがプロセスごとにされているので、違うけど、大まかにはそういうことになります。 回答者さんのおっしゃるとおり、48bitより上の部分はたとえレジスタが64bitでも意味を持ちません。
kazuyakazuya

2019/11/13 00:16

回答ありがとうございます。 64ビット windows 上で仮想環境を築き 64ビット CentOS を使っています。 つまり、x24/s $rsp + 900 というコマンド自体が 32ビットOSを前提にしたものあから アドレスの表示がおかしいことになっているということですか?
maisumakun

2019/11/13 00:31

> 32ビットOSを前提にしたものあからアドレスの表示がおかしいことになっているということですか? いえ、違います。32ビットならメモリ空間は4GBしかないので、32ビットしか出ません。
kazuyakazuya

2019/11/13 00:40

私が普段見てきた4バイト表示に することはできないのでしょうか? (今回表示されたアドレス 0x7FFFFFFFe7 ならば ひだりの7FFF 2バイトは無視したら4バイトになりますが・・・)
maisumakun

2019/11/13 00:42

> 私が普段見てきた4バイト表示にすることはできないのでしょうか? なんのためにでしょうか。アドレス空間は48ビットなので、勝手に削っては辻褄が合いません。
dodox86

2019/11/13 00:43 編集

> つまり、x24/s $rsp + 900 > というコマンド自体が > 32ビットOSを前提にしたものあから なぜそう言う解釈になるのかw 全然違います。 そもそも、$rspが64ビット用のスタックポインターです。この時点でもう意識は64ビットOS用です。次に、dameoさんのコメントをいたただいたように、 > AMD64アーキテクチャでは、現状の実装で48ビットのアドレス空間を持ち、 とあり、48ビットつまり6バイトです。64ビットOSとは言え、ハードウェアとして48ビット(=6バイト)しかアドレス空間を使わないので、gdbでも6バイトしか表示しない(上位2バイトは意味が無い)のです。
退会済みユーザー

退会済みユーザー

2019/11/13 00:48

はい、というわけで、細かい解説書きました。 ちゃんとお答えするとすると、64bit CentOSは32bit動作するものと64bit動作するプログラムの両方を動かせます。 64bit動作するプログラムを動かすと、アドレス表示は48bit=6バイトになり 32bit動作するプログラムを動かすと、アドレス表示は32bit=4バイトになります xコマンドはいわゆるメモリダンプコマンドです。 後ろで指定されたアドレスからダンプしてくれます。 x/24sはさらに、24個分メモリを文字列形式としてダンプしてくれって意味になります。 $rsp+900がアドレス指定です。 $rspはRSPレジスタの中身です。gdb的にはvoid*として扱われます。 つまりRSPから900先のアドレスを文字列形式で24個ダンプしてって言うコマンドです。 そのダンプしたときのアドレス表示が 64bitプログラムなら6バイト 32bitプログラムなら4バイト ってことです。
退会済みユーザー

退会済みユーザー

2019/11/13 00:50

※32bitプログラムのときは$rspではなくて、$spにしてください。
kazuyakazuya

2019/11/13 01:57 編集

ありがとうございます。 Visual stdio で、printf("%p") これでアドレスを表示させていたときは 4バイトで表示されたのは 32ビットで設定されていたから? では、バッファオーバーフローでリターンアドレスを書き換えるとき 先頭の2バイトは考慮せずに問題ないでしょうか?
退会済みユーザー

退会済みユーザー

2019/11/13 01:57

今の話はadm64のCentOS環境でgdbの出力がどうなるかという話なので、他のOSの他の処理系で、しかもデバッガの出力でもないものと比較は出来ません。 全く別の話です。 そしてバッファオーバーフローでリターンアドレスを書き換えるというのは、そもそもどちらとも関連がないです。
kazuyakazuya

2019/11/13 01:59

確かに関係ありませんでした。すみません。 もう一度調べなおします。
asm

2019/11/13 06:02

centos上の環境変数を書き換えたところで、windows上から読めないのと同様に 32bitのアドレスを入手したところで、攻撃対象の実行ファイルが64bitでは意味が(ほぼ)ないです。 (推測が不可能か?と言われると困るけど、普通に攻撃対象と同種の実行ファイルでアドレスを入手した方が簡単)
kazuyakazuya

2019/11/13 07:49 編集

おそらく、アドレスに対して間違った認識のままここまで 来たのだと思います・・・。 まず、Visual Stdioでは X86,X64を選べるそうですが CPUがX86のアーキテクチャで、VisualでX64を選択した場合 アドレスが48ビットではなく、32ビットになるもんなんですか? (仮想マシンではできるみたいですが・・・) もし、そうだとしたら CPU OS問わず、アドレスは4バイトだと固定だと勘違いしていました。
maisumakun

2019/11/13 07:50

> CPUがX86のアーキテクチャで、VisualでX64を選択した場合 動きません。
dodox86

2019/11/13 07:59

そういった一連のことの判断がつくようになることがkazuyakazuyaさんにとって最初に必要なのでは、と言う回答が、以下でいただいたものであったはずです。https://teratail.com/questions/219568 この質問も、(少なくとも私から見れば)PingHermitさんの回答と、その後の皆さんのコメントで充分過ぎるほどの回答になっていると思います。 (横からですみません)
dodox86

2019/11/13 08:24

> この質問も、(少なくとも私から見れば) あくまで質問主はkazuyakazuyaさんなので、少々出過ぎた意見で失礼しました。(回答に納得いくか否かは質問主が判断すべきこと、と言う意味で)
kazuyakazuya

2019/11/13 13:20

Visual Stdioで~という話は %pで表示させると、上のアドレスが省略されて表示されるみたいなので 本来6バイト長であるアドレスが4バイトに見えていただけのようです。 もしくは、32ビットとしてコンパイルしていたか?(らしいです。) ありがとうございました。
kazuyakazuya

2019/11/14 06:05

あ、分かったつもりでいましたが違がかったみたいです。 32ビットプロセスなら32ビット長アドレスになる。 (32,64ビットOS 32,64ビットCPUで実行可能 ) 64ビットプロセスなら48ビット長アドレスになる。 (64ビットCPU 64ビットOSでのみ実行可能) どうやってアドレス長が決まるかは CPU や OSではなく、プロセスで決まる 上のコメントの時点ではCPU OSで アドレス長が決まると思っていました。
asm

2019/11/14 06:12

ちなみに、アドレスバスの幅は48bitですが64bitプロセス(AMD64)の場合 機械語を含む多くの言語ではポインタ型の変数は64bitです。 printf("%d", sizeof(void*)); 等で確かめられるかと思います。
kazuyakazuya

2019/11/14 06:18

ありがとうございます。 それはデータバス幅がアドレスバスとは違い 64ビットとなっているからでしょうか?
kazuyakazuya

2019/11/14 06:39

あ、いやなんでもないです。 勘違いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問