The Crowdstrike Incident - Practical Part: Difference between revisions
No edit summary |
|||
| Line 69: | Line 69: | ||
return 0; | return 0; | ||
} | } | ||
=== Output on Terminal === | |||
C:\Users\test\CLionProject\out_of_bound\cmake-build-debug\ | |||
out_of_bound.exe | |||
Initialisiertes Objekt: 123456789 | |||
Out-of-Bounds Read: | |||
data[0] = 1 (Adresse: 00000004A99CF958) | |||
data[1] = 2 (Adresse: 00000004A99CF959) | |||
data[2] = 3 (Adresse: 00000004A99CF95A) | |||
data[3] = 4 (Adresse: 00000004A99CF95B) | |||
data[4] = 5 (Adresse: 00000004A99CF95C) | |||
data[5] = 6 (Adresse: 00000004A99CF95D) | |||
data[6] = 7 (Adresse: 00000004A99CF95E) | |||
data[7] = 8 (Adresse: 00000004A99CF95F) | |||
data[8] = 9 (Adresse: 00000004A99CF960) | |||
data[9] = (Adresse: 00000004A99CF961) | |||
data[10] = (Adresse: 00000004A99CF962) | |||
data[11] = (Adresse: 00000004A99CF963) | |||
data[12] = (Adresse: 00000004A99CF964) | |||
data[13] = (Adresse: 00000004A99CF965) | |||
data[14] = (Adresse: 00000004A99CF966) | |||
Out-of-Bounds Write: | |||
data[0] = A (Adresse: 00000004A99CF958) | |||
data[1] = B (Adresse: 00000004A99CF959) | |||
data[2] = C (Adresse: 00000004A99CF95A) | |||
data[3] = D (Adresse: 00000004A99CF95B) | |||
data[4] = E (Adresse: 00000004A99CF95C) | |||
data[5] = F (Adresse: 00000004A99CF95D) | |||
data[6] = G (Adresse: 00000004A99CF95E) | |||
data[7] = H (Adresse: 00000004A99CF95F) | |||
data[8] = I (Adresse: 00000004A99CF960) | |||
data[9] = J (Adresse: 00000004A99CF961) | |||
data[10] = K (Adresse: 00000004A99CF962) | |||
data[11] = L (Adresse: 00000004A99CF963) | |||
data[12] = M (Adresse: 00000004A99CF964) | |||
data[13] = N (Adresse: 00000004A99CF965) | |||
data[14] = O (Adresse: 00000004A99CF966) | |||
Process finished with exit code 3 | |||
=== Race Condition === | === Race Condition === | ||
Revision as of 00:10, 19 December 2024
Summary
In this article, we show an experimental approach of what mechanism leads to the Crowdstrike Incident of July 2024. For the theoretical part, please consult: https://wiki.elvis.science/index.php?title=The_Crowdstrike_Incident
Preamble
The Falcon software itself is only distributed to corporate customers, as it is purely an enterprise product. Therefore, experimenting with the Falcon Sensor for private or student purposes is not possible. However, we will practically demonstrate the mechanisms that led to the system failure. We will address the following points:
- Out-of-bounds memory access
- Race condition
- Channel-file internals
Requirements
For experimenting on a safe environment, we will setup a virtual machine.
- Operating system: MacOS Sequoia 15.1.1
- Virtualization: UTM; https://mac.getutm.app/
- Virtualized system: Windows 11, ARM-version (compatible for Apple Silicon)
- for coding in C: CLion as IDE
- for coding in Java: IntelliJ as IDE
Description
Demonstrating Out-Of-Bound Memory Access
For the practical demonstration, a virtual environment is set up using Windows 11 via UTM on macOS as the host operating system, ARM variant. This allows for experimentation independent of the host system. CLion, an IDE for C, is installed on the virtual machine. The reason for using C as the programming language lies in its memory management - here, faulty memory access can be simulated very easily. We write a program that is supposed to store data passed into an array. An object is defined using TYPEDEF and later instantiated in the running program, which receives more data to write than memory space allocated. This subsequently leads to a malfunction in memory management. In the case of the incident in question, an out-of-bounds write error occurred.
Code-Example
#include <string.h>
#include <stdio.h>
// Definition der Struktur mit typedef
typedef struct {
char data[10]; // Ein kleines Array, um Overflows zu demonstrieren
} Object;
void demonstrate_out_of_bounds_read(Object *obj) {
printf("Out-of-Bounds Read:\n");
for (int i = 0; i < 15; i++) { // Gezieltes Überschreiten der Grenze
printf("data[%d] = %c (Adresse: %p)\n", i, obj->data[i], &obj->data[i]);
}
}
void demonstrate_out_of_bounds_write(Object *obj) {
printf("Out-of-Bounds Write:\n");
for (int i = 0; i < 15; i++) { // Gezieltes Schreiben über die Grenze hinaus
obj->data[i] = 'A' + i; // Zufällige Daten schreiben
printf("data[%d] = %c (Adresse: %p)\n", i, obj->data[i], &obj->data[i]);
}
}
int main() {
Object obj;
// Daten initialisieren
strncpy(obj.data, "123456789", sizeof(obj.data) - 1);
obj.data[sizeof(obj.data) - 1] = '\0'; // Null-Terminierung
printf("Initialisiertes Objekt: %s\n\n", obj.data);
// Demonstration
demonstrate_out_of_bounds_read(&obj);
printf("\n");
demonstrate_out_of_bounds_write(&obj);
return 0;
}
Output on Terminal
C:\Users\test\CLionProject\out_of_bound\cmake-build-debug\ out_of_bound.exe Initialisiertes Objekt: 123456789 Out-of-Bounds Read: data[0] = 1 (Adresse: 00000004A99CF958) data[1] = 2 (Adresse: 00000004A99CF959) data[2] = 3 (Adresse: 00000004A99CF95A) data[3] = 4 (Adresse: 00000004A99CF95B) data[4] = 5 (Adresse: 00000004A99CF95C) data[5] = 6 (Adresse: 00000004A99CF95D) data[6] = 7 (Adresse: 00000004A99CF95E) data[7] = 8 (Adresse: 00000004A99CF95F) data[8] = 9 (Adresse: 00000004A99CF960) data[9] = (Adresse: 00000004A99CF961) data[10] = (Adresse: 00000004A99CF962) data[11] = (Adresse: 00000004A99CF963) data[12] = (Adresse: 00000004A99CF964) data[13] = (Adresse: 00000004A99CF965) data[14] = (Adresse: 00000004A99CF966) Out-of-Bounds Write: data[0] = A (Adresse: 00000004A99CF958) data[1] = B (Adresse: 00000004A99CF959) data[2] = C (Adresse: 00000004A99CF95A) data[3] = D (Adresse: 00000004A99CF95B) data[4] = E (Adresse: 00000004A99CF95C) data[5] = F (Adresse: 00000004A99CF95D) data[6] = G (Adresse: 00000004A99CF95E) data[7] = H (Adresse: 00000004A99CF95F) data[8] = I (Adresse: 00000004A99CF960) data[9] = J (Adresse: 00000004A99CF961) data[10] = K (Adresse: 00000004A99CF962) data[11] = L (Adresse: 00000004A99CF963) data[12] = M (Adresse: 00000004A99CF964) data[13] = N (Adresse: 00000004A99CF965) data[14] = O (Adresse: 00000004A99CF966) Process finished with exit code 3