6

execve を実行するシェルコードを作成しようとしています。同等の c プログラムは次のようになります。

int main ()
{

  char *argv[3] = {"/bin/sh","-i", "/dev/tty", NULL};
  execve("/bin/sh", argv, NULL);

  return 0;
}

c プログラムは正常に実行されます。次に、次のようにテスト プログラムを作成しようとします (null をプッシュするように修正)。

#include<stdio.h>
int main(){
    __asm__(
            "xor    %rdx,%rdx\n\t"   //rdx is the third argument for execve, null in this case.
            "push   %rdx\n\t"
            "mov    -8(%rbp),%rdx\n\t"
            "mov    $0x692d,%rdi\n\t" //$0x6924 is 'i-'
            "push   %rdi\n\t"         //push '-i' to the stack
            "lea    -16(%rbp),%rax\n\t"    //now rax points to '-i'
            "mov    $0x31b7f54a83,%rdi\n\t" //the address of /bin/sh
            "push   %rdi\n\t"                //push it to the stack              
            "push   %rdx\n\t"                //end the array with null
            "mov    $0x31b7e43bb3,%rdi\n\t"  //the address of "/bin/sh"
            "push   %rdi\n\t"              //push the address of "/dev/tty to the stack
            "push   %rax\n\t"              //push the address of '-i' to the stack
            "mov    $0x31b7f54a83,%rdi\n\t"
            "push   %rdi\n\t"              //push the address of /bin/sh again to the stack
            "mov    %rsp,%rsi\n\t"         //rsi now points to the beginning of the array
            "mov    -24(%rbp),%rdi\n\t"   //rdi now points to the addresss of "/bin/sh"
            "mov    $0x3b,%rax\n\t"               // syscall number = 59
            "syscall\n\t"
    );
    }

ここにメモリ内の文字列のアドレスがあり、変更されないと想定できます。しかし、文字列 '-i' のアドレスがありません。ここで行っているのは、次のように引数をスタックにプッシュすることです。


Low                  ------------------------------------------------------------------             High

|addressof"/bin/sh"(rsi points to here)|addressof"-i"|addressof"/dev/ssh"|addressof"/bin/sh"(rdi points to here)|-i|

うまくいきませんでした。プログラムは正常にコンパイルされましたが、プログラムを実行しても何も起こりませんでした。

私はアセンブリに詳しくなく、引数が渡される方法についていくつか懸念があります。

編集

Niklas B による以下の提案のおかげで、trace を使用して execve が実際に実行されるかどうかを確認しました。これはexecve(0x31b7f54a83, [0x31b7f54a83, "-i", 0x31b7e43bb3, 0x31b7f54a83, 0x692d], [/* 0 vars */]) = -1 EFAULT (Bad address)、2 番目の引数が間違って渡されたことを意味します。スタックにプッシュしたものはすべて、argv 引数の一部と見なされます!

null をスタックにプッシュした後、strace はexecve(0x31b7f54a83, [0x31b7f54a83, "-i", 0x31b7e43bb3], [/* 0 vars */]) = -1 EFAULT (Bad address). アドレスが文字列の場合のみ、これは正しい答えに非常に近いです...

ブライアンのおかげで、問題がどこにあるのかがわかりました。ハードコーディングされたアドレスは、別のプログラムの共有ライブラリにあります。したがって、このプログラムは、実際にそのプログラムに入力されるまで実行されるべきではありません。みんなありがとう、できるだけ早くこれを更新します。問題が解決したら、解決済みとしてマークします。

4

1 に答える 1

3

Kerrek SB と user9000 がコメントで指摘しているように、argv配列は null で終わる文字列の配列である必要がありました。

それが修正されると、このプログラムをスタンドアロンで実行しても機能しません。文字列"/bin/sh""/dev/tty"おそらくコンパイルしたばかりのプログラムのその場所には存在せず、シェルコードがあるプログラムのその場所に存在するからです。対象にするように設計されています。それらの文字列がそれらのアドレスにある場所で実行されるように、実際にそのプログラムに挿入する必要があります。

于 2013-10-21T23:40:00.853 に答える