2016-11-08 3 views
0

64-bit Linux stack smashing tutorial: Part 1Get 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 프로그램 이름을 조정하는 데 사용됩니다?

제 생각 엔 프로그램 이름이 스택 위에 두 번 저장됩니다. ./stackdump이 프로그램을 실행하는데 사용되며,이 도면에서

------------------------------------------------------------- 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   |  | |  | | | 

:

enter image description here

https://lwn.net/Articles/631631/로부터 다음 도표 자세히 준다. 그래서 프로그램 이름 ./stackdump이 환경 문자열 위에 한 번 저장된다는 것을 알 수 있습니다. ./stackdump 배쉬 쉘에서 실행되는 경우에, Bashell 키 _와 환경 문자열에 저장됩니다

를 _

(밑줄). 쉘 시작에서, 쉘을 호출하는 데 사용되는 절대 경로로 설정 또는 쉘 스크립트는 환경 또는 인수 목록에 전달 된대로 실행됩니다. 그런 다음 확장 후 이전 명령에 대한 마지막 인수로 확장합니다. 또한 실행 된 각 명령을 호출하는 데 사용 된 전체 경로 이름으로 설정되어 해당 명령으로 내 보낸 환경에 배치됩니다. 메일을 확인할 때,이 매개 변수는 메일 파일의 이름을 보유합니다.

환경 문자열이 스택 위에 있습니다. 그래서 프로그램 이름은 스택 위에 또 한번 저장됩니다.

+1

정확히 무엇을 요구하고 있습니까? 코드는 getenv가 환경 변수의 주소를 가져오고 프로그램 호출이 스택의 공간을 차지하기 때문에 코드가 작동하므로 그에 따라 포인터를 조정합니다. 그것은 코드 주석에 있습니다. –

+0

필자가 아는 한, 스택에 할당 된 프로그램 이름에는 대개 문자 당 약 2 바이트가 있습니다. 이 코드 조각을 처음 본 것은 * Hacking : Jon Erickson의 착취 기술 *이었습니다. 더 많은 것을 읽거나 스택이 메모리에서 어떻게 보이는지 리눅스 커널을 연구하는 것이 좋습니다. –

+0

@JacobH 예, 코드는 Jon Erickson의 * 해킹 : The Exploitation, 2nd Edition *의 147 페이지와 148 페이지에서 발췌 한 것입니다. 그러나이 책은 왜 그것이 작동하는지 설명하지 않습니다. –

답변

0

누가 아직도 궁금해하는 경우. 이는 프로그램 이름이 모든 환경 변수보다 먼저 스택에 푸시 된 환경 변수 이름 "_"에도 저장되어 있기 때문입니다.

gdb를 프로세스에 연결하고 마지막 환경 변수 아래의 스택 내용을 검사하여이를 확인할 수 있습니다. 가정하자 0x7fffffffabcd 마지막 환경 변수의 주소입니다 :

$ gdb -p <pid> 

(gdb) x/20s 0x7fffffffabcd 

이 스택의 마지막 환경 변수의 상단에 배치되기 때문에 환경 변수의 주소에는 영향을 미치지 않습니다 argv[0]에 저장된 프로그램 이름.

0

저장 stackdump.c으로 다음 코드를 코드를 컴파일 할 gcc -o stackdump 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); 
} 

. 둘째, 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 부 프로그램의 주소 공간에 있습니다.그 중 두 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입니다.