일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- ability task
- sampling theory
- ret2libc
- DSP
- 유니티
- 운영체제
- 유스케이스
- gas
- 게임 개발
- 언리얼엔진
- dtft
- Rr
- MAC
- pdlc
- 메카님
- stride
- CTF
- frequency-domain spectrum analysis
- Unreal Engine
- dirty cow
- Security
- 게임개발
- linear difference equation
- DP
- MLFQ
- Race condition
- 언리얼 엔진
- Double free
- AINCAA
- TSet
- Today
- Total
다양한 기록
Dirty COW #2 mmap(), madvise() 본문
Kernel Local Privilege Escalation "Dirty COW", CVE-2016-5195
레이스 컨디션의 한 케이스
int main()
{
struct stat st;
char content[20];
char *new_content = "New Content";
void *map;
int f = open("./zzz", O_RDWR)
fstat(f, &st);
map = mmap(NULL, st.size, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);
// read 10 bytes
memcpy( (void*)content, map, 10 );
printf("read: %s\n", content);
// write
memcpy(map+5, new_content, strlen(new_content));
munmap(map, st.st_size);
close(f);
return 0;
}
mmap -> 파일을 메모리에 매핑해서 메모리처럼 읽고 쓸 수 있음
mmap(1, 2, 3, 4, 5, 6)
1: 매핑 시작 주소, NULL이면 OS가 알아서 함
2: 매핑할 사이즈
3: 읽기 쓰기 .. open해서 열었던 거랑 맞춰야 함 (O_RDWR로 열었으니 PROT_READ | PROT_WRITE로 맞춤)
4: 다른 프로세스가 쓰려고 할 때 공유할지(MAP_SHARED) 혼자 쓸지(MAP_PRIVATE)
5: 매핑하려는 파일의 fd
6. 매핑 시 파일의 시작 오프셋
memcpy(void dest[restrict .n], const void src[restrict .n], size_t n);
n만큼 read, write가 가능
첫번째 인자의 map+5대로면 앞에 5개는 냅두고 write하겠다는 의미가 됨
munmap((void *)map, size_t n)
매핑 해제
MAP_SHARED & MAP_PRIVATE
MAP_SHARED
- 매핑된 메모리는 두 프로세스 간의 공유 메모리처럼 동작
- 여러 프로세스가 동일한 파일을 메모리에 매핑할 때 파일을 서로 다른 가상 메모리 주소에 매핑할 수 있지만 파일 콘텐츠가 저장되는 물리적 주소는 동일함
MAP_PRIVATE
- 파일이 호출 프로세스 전용 메모리에 매핑
- 오리지널 메모리의 내용이 프라이빗 메모리에 카피될 필요 있음
- 쓰기 시도 시 피지컬 메모리에 새 블록을 할당하고 컨텐츠 카피해둠
- 이후 매핑된 버추얼 메모리는 새 피지컬 메모리를 가리킴
madvise(void *addr, size_t length, int advice)
- addr ~ addr + length까지 메모리에 대해 커널에 어드바이스 하는 용도
advice가 MADV_DONTNEED => 안쓴다고 생각하고 버림
카피본에 이걸 쓰면 날려버리고 기존 페이지 테이블은 원본을 가리킴
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <stdio.h>
int main()
{
char *content = "**content**";
char buffer[30];
struct stat st;
void* map;
int f = open("./zzz", O_RDONLY);
fstat(f, &st);
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, f, 0);
int fm = open("/proc/self/mem", O_RDWR);
lseek(fm, (off_t)map + 5, SEEK_SET);
write(fm, content, strlen(content));
memcpy(buffer, map, 29);
printf("Content after write: %s\n", buffer);
madvise(map, st.st_size, MADV_DONTNEED);
memcpy(buffer, map, 29);
printf("Content after write: %s\n", buffer);
}
1. ./zzz가 리드 온리로 열리고 리드온리 및 private로 메모리 매핑됨
2. /proc/self/mem 파일 열어서 메모리 접근 .. 리드/라이트로 열음(자기 거니까 됨)
3. 위치를 lseek로 옮겨서 매핑된 곳 + 5 자리로 옮김
4. 쓰기
5. 출력 => 덮어써진게 보임
6. madvise
7. 출력 => 원본이 보임
'운영체제보안' 카테고리의 다른 글
Dirty COW #4 완화법 (0) | 2024.12.06 |
---|---|
Dirty COW #3 Exploit (0) | 2024.12.06 |
Dirty COW #1 Copy-on-Write (0) | 2024.12.06 |
ToCTToU (Time of Check-to-Time of Use) Vulnerability (0) | 2024.12.06 |
Race Condition Problem (0) | 2024.12.06 |