2016-11-08 6 views
0

64-bit Linux stack smashing tutorial: Part 1は、Get environment variable address gistを使用して環境変数のアドレスを取得します。前提条件は、まずecho 0 > proc/sys/kernel/randomize_va_spaceでASLRを無効にすることです。なぜこのコードは環境変数のアドレスを取得できますか?

要旨の内容は次のとおりです。

/* 
* I'm not the author of this code, and I'm not sure who is. 
* There are several variants floating around on the Internet, 
* but this is the one I use. 
*/ 

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(int argc, char *argv[]) { 
    char *ptr; 

    if(argc < 3) { 
     printf("Usage: %s <environment variable> <target program name>\n", argv[0]); 
     exit(0); 
    } 
    ptr = getenv(argv[1]); /* get env var location */ 
    ptr += (strlen(argv[0]) - strlen(argv[2]))*2; /* adjust for program name */ 
    printf("%s will be at %p\n", argv[1], ptr); 
} 

*2は、プログラム名を調整するために使用されているのはなぜ?

私の推測では、プログラム名はスタックの上に2回保存されます。

enter image description here

https://lwn.net/Articles/631631/から次の図は、詳細を与える:この図で

------------------------------------------------------------- 0x7fff6c845000 
0x7fff6c844ff8: 0x0000000000000000 
     _ 4fec: './stackdump\0'      <------+ 
    env/ 4fe2: 'ENVVAR2=2\0'        | <----+ 
     \_ 4fd8: 'ENVVAR1=1\0'        | <---+ | 
    / 4fd4: 'two\0'          |  | |  <----+ 
args | 4fd0: 'one\0'          |  | | <---+ | 
     \_ 4fcb: 'zero\0'         |  | | <--+ | | 
      3020: random gap padded to 16B boundary   |  | |  | | | 

./stackdumpは、プログラムを実行するために使用されます。だから私は、プログラム名./stackdumpが環境文字列の上に一度保存されていることがわかります。そして./stackdumpがBashellキー_と環境文字列に保存されます、bashのシェルから起動された場合:

_

(アンダースコア)。シェルの起動時に、シェルを呼び出すために使用される絶対パス名に設定またはシェルスクリプトは、 環境または引数リストで渡されたとおりに実行されます。その後、展開後に前のコマンドの最後の 引数に展開されます。そのコマンドにエクスポートされた 環境に配置され実行された各コマンドを呼び出すために使用されるフルパス名 にも設定します。メールをチェックするとき、この パラメータはメールファイルの名前を保持します。

環境ストリングはスタックの上にあります。したがって、プログラム名はスタックの上に別の時間に保存されます。

+1

正確に何を求めていますか?コードはgetenvが環境変数のアドレスを取得し、プログラムへの呼び出しもスタック上の領域を占めるため、ポインタが適切に調整されるため、コードは機能します。それはコードのコメントです。 –

+0

私の知る限り、スタックに割り当てられたプログラム名には、通常、1文字あたり約2バイトあります。このコードを最初に見たのは、Jon Ericksonの「Hacking:The Exploitation *」です。私はそこでもっと読んだり、スタックがどのようにメモリ内にあるかを理解するためにLinuxカーネルを研究したりすることをお勧めします。 –

+0

@JacobHはい、コードはJon Ericksonによる* Hacking:The Exploitation、2nd Edition *の147ページと148ページに由来しています。しかし、この本はそれがなぜ機能するのか説明していない。 –

答えて

0

誰もがなぜ不思議に思っているのでしょうか。これは、プログラム名がすべての環境変数の前にスタックにプッシュされるのに加えて、環境変数名 "_"にも格納されているためです。

gdbをプロセスにアタッチし、最後の環境変数の下にあるスタックの内容を調べることで確認できます。仮定0x7fffffffabcdは、最後の環境変数のアドレスです:

$ gdb -p <pid> 

(gdb) x/20s 0x7fffffffabcd 

それは、スタック上の最後の環境変数の上に配置されているため、環境変数のアドレスには影響を与えませんargv[0]に保存されているプログラム名。

0

保存stackdump.cとして、次のコード:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/auxv.h> 

int main(int argc, char *argv[]) { 
    char *ptr; 
    int i; 

    for (i = 0; i < argc; i++) { 
    printf(" argv[%d]: %p, %p, %s\n", i, argv + i, argv[i], argv[i]); 
    } 

    char * program = (char *)getauxval(AT_EXECFN); 
    printf("AT_EXECFN:    , %p, %s\n", program, program); 
    char* path = getenv("PATH"); 
    printf("  PATH:    , %p, %s\n", path, path); 
    char* underscore = getenv("_"); 
    printf("  _:    , %p, %s\n", underscore, underscore); 
} 

まず、コードをコンパイルするためにgcc -o stackdump stackdump.cを実行しています。次に、echo 0 > proc/sys/kernel/randomize_va_spaceを実行します。第三に、与えること./stackdump zero one twoを実行している:上記のよう./stackdump

argv[0]: 0x7fffffffe4a8, 0x7fffffffe6e5, ./stackdump 
    argv[1]: 0x7fffffffe4b0, 0x7fffffffe6f1, zero 
    argv[2]: 0x7fffffffe4b8, 0x7fffffffe6f6, one 
    argv[3]: 0x7fffffffe4c0, 0x7fffffffe6fa, two 
AT_EXECFN:    , 0x7fffffffefec, ./stackdump 
    PATH:    , 0x7fffffffee89, /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/cloud-user/.local/bin:/home/cloud-user/bin 
     _:    , 0x7fffffffefe0, ./stackdump 

3つのコピーがプログラムのアドレス空間です。それらのうちの2つは、PATHのより上位のアドレスは以下のように示されている:

AT_EXECFN: 0x7fffffffefec, ./stackdump 
     _: 0x7fffffffefe0, ./stackdump 
    PATH: 0x7fffffffee89, /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/cloud-user/.local/bin:/home/cloud-user/bin 

ので*2理由は_環境変数とAT_EXECFNauxiliary vector valueです。

関連する問題