2012-03-30 2 views
2

여러 가지 스타일의 버퍼 오버플로를 검토 중이며 문제가 발생하여 그 이유가 기억 나지 않습니다.Linux 버퍼 오버플로 환경 변수

#include <stdio.h> 

void func(char *buff){ 
    char buffer[5]; 
    strcpy(buffer, buff); 
    printf("%s\n", buffer); 
} 

int main(int argc, char *argv[]){ 
    func(argv[1]); 
    printf("I'm done!\n"); 
    return 0; 
} 

프로그램의 핵심 개념은 매우 간단합니다, 그냥 func()의 반환 주소를 덮어 버퍼 오버 플로우를 다음과 같이 코드는 내가에 버퍼 오버 플로우를 수행하려고 시도 오전 프로그램입니다. 그게 모든 프로그램의 <_fini> 일이 0x0804850c 같은 주소를 줄 때 위대한 작품. 해당 주소로 오버플로를 구현할 때 최종 결과는 프로그램이 종료되지 않고 "정상적으로"종료됩니다. I'm done!. 내가 지금 실행하고있는 문제는 반환 주소를 무언가로 리디렉션하려고 할 때 환경 변수가 0xbfffd89에 위치 할 때입니다.

해당 환경 변수에있는 셸 코드는 hello이라고 말한 후 프로그램을 종료해야합니다. 그러나 그것이 발생하지 않습니다, 프로그램은 단순히 결함을 seg하고 그게 전부입니다. 쉘 코드는 쉘 코드를 테스트하기 위해 작성한 이전 프로그램에서 작동하는 것으로 이미 확인되었습니다. 누구나 이것이 왜 작동하지 않는지 알 수 있습니다. Thx

+1

gdb에서 실행하여 segfault를 트리거하는 항목을 확인하십시오. 내 추측 : 환경 변수는 읽을 수는 있지만 실행 가능하지 않은 메모리 영역에 있습니다[email protected] EugeneMayevski'EldoSCorp : 여기에 "쉘 코드"란 쉘과 일부 외부 명령을 실행하는 기계어에 대한 전문 용어로, 일반적으로 악용하려는 작업입니다. 이 경우 실제 쉘이 실행되지 않는 것처럼 들리지만. – Celada

+0

@Celada GDB를 사용하여 환경 변수가 읽기 전용인지 확인하는 방법에 대한 제안. 또한 쉘 코드에 대해서도 정확합니다. – Blackninja543

+0

@ EugeneMayevski'EldoSCorp 일반적으로 정의 된 쉘 코드는 바이너리의 바이트 코드입니다. 이 경우 나는 x86 ASM에서 원하는 것을 작성하여 쉘 코드를 생성했다. 함수의 리턴 주소를 리다이렉트 할 때 새로운 명령어 세트가 들어있는 메모리 영역으로 전달한다. – Blackninja543

답변

2

환경 변수는 쓰기 권한이 있지만 실행 권한이 아닌 &의 메모리 영역에 있습니다. 다음과 같이 내가 쉽게 재현 :

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

int 
main(int argc, char **argv) 
{ 
void (*function)(void); 

     function = (void (*)(void))getenv("PATH"); 
     function(); 
     return 0; 
} 

gdb에서 실행, 나는이있어 : 다음 /proc/PID/maps 경우 주소 0x00007fffffffeb51을 보였다

Program received signal SIGSEGV, Segmentation fault. 
0x00007fffffffeb51 in ??() 
(gdb) 

과 같은 라인을 찾을 :

7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0       [stack] 

x (실행) 비트가 정상적으로 발견되는 -이 있습니다.

+0

OK 그래서 환경 변수의 권한을 변경할 수 없다는 가정하에 환경 변수 밖에서 쉘 코드를 실행할 수있는 다른 가능성이 있습니다. – Blackninja543

+1

취약한 프로그램에 대한 가능한 시나리오 : 환경 변수가 힙에 복사됩니다. 아마도 환경 변수는 디렉토리를 명명하고 파일 이름과 연결되어'malloc()'메모리에 전체 경로 이름을 형성합니다. 이제 버퍼 오버플로가 힙의이 주소로 이동할 수 있습니다. 실행 가능합니다. 하지만이 힙 주소가 무엇인지 짐작할 필요가 있습니다. 행운을 빈다. :-) – Celada

0

실행 사이에 변수의 주소를 확인할 수 있습니까? 시스템에서 ASLR과 같은 것을 사용하면 모든 실행마다 다를 수 있습니다. 그러나 argv [1]의 주소는 일부 레지스터를 통해 제공 될 수 있으므로이 레지스터를 통해 간접 호출하는 명령어의 주소를 반환 주소로 제공하면 (프로그램에서 objdump -d을 사용하는 것과 같은 명령어를 찾을 수 있음) 이 주소가 실행 가능한 페이지에 있다고 가정하면 어떤 주소에서든지 코드가 실행됩니다. 레지스터는 ABI에서 매개 변수를 전달하는 데 사용됩니다. 그러나 또 다른 문제가있을 수 있습니다 ...

자세한 내용을 제공하면 (아마도 프로그램의 해체 제외) 아마도 더 구체적으로 답변 할 수 있습니다.

+0

나는 기회가 생길 때 해체 된 코드를 추가 할 것이다. 주소 공간 무작위 화와 관련하여 필자는 테스트 환경에서이 기능을 해제했습니다. Celada가 보여 주었고 자신의 환경을 확인한 결과 내 환경 변수는 실행 불가능하지 않습니다. 코드 쉘 코드를 삽입하여 실행 파일로 만들 수있는 방법에 대한 의견이 있으십니까? 이 시점에서 내가 생각할 수있는 유일한 방법은 환경 변수를 사용하는 것입니다. – Blackninja543

2

현대 리눅스 배포판은 이러한 종류의 공격에 대비됩니다. NX 비트는 예를 들어 x86-64의 스택 페이지에 대해 설정됩니다. 또한 매핑 주소는 프로세스 외부에서 추측 할 수 없도록 임의로 지정됩니다. 다음을 참조하십시오 :

http://en.wikipedia.org/wiki/Executable_space_protection http://en.wikipedia.org/wiki/Address_space_layout_randomization

을 기본적으로, 당신은 당신이 좀 더 일을해야 할거야 현대적인 시스템 악용 작성합니다.

+1

수정. 이 특별한 경우에 대해 명확하지 않은 점은 실제로 환경 변수가 스택과 동일한 메모리 매핑 영역에 있다는 것입니다. 나는 지금까지 그것을 몰랐다! – Celada

+0

@Celada : 실제로'argc','argv','envp'와'auxv' 모두와 그것들에 대한 각각의 포인터는 스택의 각 프로세스에 전달됩니다. – ninjalj

+0

@ninjalj 나는'argv','envp','auxv'가 모두 "사용자 영역"으로 알려진 메모리 영역에 함께 있다는 것을 알았지 만, 스택과 같은 영역인지는 몰랐습니다. 하지만 저는 솔라리스에서 몇 년 전이 놀라운 것을 배웠을 때 상황이 바뀌었을 것입니다. 설명 주셔서 감사합니다! – Celada

관련 문제