質問: ついさっきの質問の続き 前回は8bitレジスタにアドレスを格納しようとしましたが・・・ 指摘されている通り、48bitあるアドレスを8bitレジスタに格納できるわけがありませんでした。 それで、私の知識の範囲内で考えたのですが いい方法が思いつかないのでアドバイスお願いします。 ``` .globl main main: jmp run3 run2: xor %eax,%eax mov $4,%AL xor %ebx,%ebx mov $1,%bl pop %rcx xor %edx,%edx mov $6,%dl int $0x80 mov $1,%AL mov $0,%bl int $0x80 run3: call run2 .asciz "hello" ``` シェルコードを作成しています。NULLバイトがあると非常に邪魔なので NULLを除去するため、レジスタを8bit長にしました。(上記) ただ、rcx(64bit長)を使用しているため NULLバイトを除去できずにいます。 まず、このプログラムを64bitプロセスとして実行させているので アドレスは48ビット長です。 なので・・・ 8bit,16bit,32bitレジスタには格納しきれません。(てか、16bit以外に関してはそもそも使えなかった。) なので、64bitモードだとrcxレジスタを使うしか選択肢がないのですが・・・ 提案1 --- プロセスを32bitモードにする。そうすればアドレス帳は32bitになるはず。 ここで使えるレジスタは、rcx(32bit) と ecx(64bit) の2つ。 rcx --- 同じ方法でNULLバイトが検出されたので使えない。(わかっていたけど) ecx --- pop ecx のような感じで使いたかったが、pop命令で32bitレジスタは使えない。 最終的にecxレジスタにアドレスが格納されればいいのだから ``` pop %rbp movl %rbp,%ecx ``` 中身は32bitなのだからできないことはないんじゃないか? と思いましたが・・・ よくよく考えたら、このプロセス自体を64bitで実行させているので 64bitレジスタは使えませんよね? ダメもとで、 ``` gcc -m32 sample.s ``` -m32オプションをつけてアセンブルを試みましたが、"rcxレジスタなんてない" みたいな感じで、怒られます。 もう、NULLバイトさえつかなければどんな手段でも構わないので rcxレジスタかecxレジスタにリターンアドレスを格納する方法はないでしょうか? 参考書では 32bitモード NASMコンパイラを使っていますが pop命令も使えているし、 pop %ecx ・・・ pop命令って64bit限定ではないんでしょうか? (64bitプロセスではないと使えないんでは?ということ) 64bitプロセスでも指定できなかったecxレジスタを使っている・・・ NASMコンパイラなら、使える・・・いや、違いますよね? (参考書がおかしい・・・?) なにかしらのヒントを貰えると嬉しいです。 分からないのでお願いします。
回答: `as`で生成したa.outもしくは.oを`objdump -d`で表示してください。 私の環境では以下が生成されました。 ``` 0000000000000000 : 0: eb 15 jmp 17 0000000000000002 : 2: 31 c0 xor %eax,%eax 4: b0 04 mov $0x4,%al 6: 31 db xor %ebx,%ebx 8: b3 01 mov $0x1,%bl a: 59 pop %rcx b: 31 d2 xor %edx,%edx d: b2 06 mov $0x6,%dl f: cd 80 int $0x80 11: b0 01 mov $0x1,%al 13: b3 00 mov $0x0,%bl 15: cd 80 int $0x80 0000000000000017 : 17: e8 e6 ff ff ff callq 2 1c: 68 65 6c 6c 6f pushq $0x6f6c6c65 21: 00 90 90 90 90 90 add %dl,-0x6f6f6f70(%rax) 27: 90 nop 28: 90 nop 29: 90 nop 2a: 90 nop 2b: 90 nop 2c: 90 nop 2d: 90 nop 2e: 90 nop 2f: 90 nop ``` 問題が `mov $0,%bl`である事がわかると思います。 `xor %bl, %bl`しとけばいいです。