본 포스팅은 DreamHack 사이트의 Linux Exploitation & Mitigation Part 1 강의 내용을 요약한 것입니다.
이 글은 저의 취향에 맞춘 정리글이므로 Dreamhack 사이트의 내용을 보시기 바랍니다.
https://dreamhack.io/
2. Return Address Overwrite
이 장에서는 스택 버퍼 오버플로우 취약점을 공격하는 방법에 대해 배워보겠습니다.
이 공격방법은 주로 스택의 리턴 주소를 다른 값으로 바꿔 실행 흐름을 조작할 수 있습니다.
*리턴 주소: 함수가 끝나고 돌아갈 이전 함수의 주소
// gcc -o example1 example1.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2 -m32
#include <stdio.h>
int vuln(char *src) {
char buf[32] = {};
strcpy(buf, src);
return 0;
}
int main(int argc, char *argv[], char *environ[]) {
if (argc < 2){
exit(-1);
}
vuln(argv[1]);
return 0;
}
//example1.c
아래와 같은 방식으로 컴파일이 가능합니다.
gcc -o example1 example1.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2 -m32
* -fno-stack-protector: ssp(Stack Smashing Protector, 메모리 보호기법)를 끕니다.
*-z exestack: 스택 실행권한 설정
*-mpreferred-stack-boundary=: 스택의 경계값 설정
*-m32: 32비트 컴파일
위의 코드에서는 프로그램의 argv[1]를 vuln 함수의 인자로 전달합니다.
vuln함수에서는 src 버퍼를 buf 버퍼에 strcpy 함수를 이용해 복사합니다.
strcpy 함수는 피복사 버퍼(buf)에 대한 길이검증이 없어서 프로그램의 첫번째 인자에 buf 배열의 크기보다 긴 문자열을 넣으면 스택 오버플로우가 발생합니다.
이때의 vuln함수의 메모리 구조는 아래와 같습니다.
x86 아키텍처 호출 규약에 의해 vuln함수가 호출되면 vuln의 인자인 src 포인터가 먼저 쌓이고 이후 리턴주소가 쌓이게 됩니다. 또 이후에 함수의 프롤로그에서 ebp레지스터를 저장한 다음 지역 변수의 공간을 할당합니다.
(대충 위의 사진에서 데이터가 밑에서부터 쌓였다는 이야기입니다)
이제 gdb를 통해 vuln에 브레이크포인트를 설정한 후 첫 번째 인자와 함께 example1 바이너리를 실행해보겠습니다.
스택 메모리를 보면 첫 4바이트는 vuln 함수의 리턴 주소(main +30, 함수가 호출이 끝난 다음주소)이고, 다음 4바이트는 vuln 함수의 인자인 argv[1]의 주소임을 알 수 있습니다.
자 이제 브레이크포인트를 strcpy 실행 직전으로 설정해주고 이동해봤습니다.
스택에 buf주소와 argv[1]의 주소가 저장되어 있습니다. 아직 strcpy를 실행하지는 않았어요.
다음으로 strcpy를 실행해보겠습니다!
여기 스택에서의 차이점이 보이시나요..?
문자열을 복사해주긴 했지만 더 긴 문자열을 주었기 때문에 vuln의 리턴 주소가 저장된 부분을 넘어서까지 argv[1]이 복사된 것을 확인할 수 있습니다. 이런 방식으로 stack BOF가 발생한다고 합니다.
아래에 문제가 있네요.
문제는 간단히 풀 수 있습니다. ret 부분에 저 16진수를 넣어주면 되는데 그 값은 j를 나타내므로 ret부분을 j로 물들여주시면 됩니다.
참고로 ret명령어는 esp레지스터가 가리키고 있는 주소에 저장된 값으로 점프하는 명령어입니다.
Linux Exploitation은 로컬 환경의 타겟을 대상으로 하기 때문에 익스플로잇 최종 목표는 프로그램의 실행 흐름을 조작하여 /bin/sh 혹은 셸 바이너리를 실행하는 것입니다.
셸은 커맨드 라인의 명령어, 혹은 스크립트를 받아 서버에서 그에 맞는 기능을 실행시켜주는 프로그램입니다. 이렇듯 프로그램의 흐름을 조작해 셸을 실행하는 이유는, 권한 상승이나 본래의 프로그램이 의도치 않은 행위를 하기 위해서입니다. 취약점이 존재하는 바이너리를 익스플로잇하여 셸 프로그램을 실행하면 해당 바이너리의 권한의 셸을 획득하여 서버에 임의의 명령어를 실행할 수 있게 됩니다.
셸코드에 대한 자세한 설명은 이 강의를 통해서 확인하시기 바랍니다!
여기까지! 두번째 return address overwrite(ret값 물들이기)를 했습니다.
'Hacking-기초 > Pwnable' 카테고리의 다른 글
보호기법 정리 (0) | 2020.08.01 |
---|---|
Linux Exploitation & Mitigation Part 1 (3) (0) | 2020.04.15 |
Linux Exploitation & Mitigation Part 1 (1) (1) | 2020.04.13 |
Memory Corruption - C (2) FSB 문제해설 (1) | 2020.04.11 |
Buffer Overflow Attack 기초(1) (0) | 2020.04.11 |