Neinicijalizovane promenljive
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Osnovne informacije
Suština je ovde da se razume šta se dešava sa neinicijalizovanim promenljivama, jer one imaju vrednost koja je već bila na dodeljenoj memorijskoj lokaciji. Primer:
- Funkcija 1:
initializeVariable: Deklarišemo promenljivuxi dodelimo joj vrednost, recimo0x1234. Ova akcija je kao rezervisanje mesta u memoriji i upisivanje određene vrednosti. - Funkcija 2:
useUninitializedVariable: Ovde deklarišemo drugu promenljivuy, ali joj ne dodeljujemo vrednost. U C-u, neinicijalizovane promenljive se automatski ne postavljaju na nulu. Umesto toga, zadržavaju vrednost koja je poslednja bila smeštena na toj memorijskoj lokaciji.
Kada pokrenemo ove dve funkcije sekvencijalno:
- U
initializeVariable,xdobija vrednost (0x1234), koja zauzima određenu memorijsku adresu. - U
useUninitializedVariable,yje deklarisana ali joj nije dodeljena vrednost, tako da zauzima memorijsko mesto odmah poslex. Zbog neinicijalizovanjay, ona na kraju “nasleđuje” vrednost iz iste memorijske lokacije koju je koristiox, jer je to poslednja vrednost koja je tamo bila.
Ovo ponašanje ilustruje ključni koncept u niskonivnom programiranju: upravljanje memorijom je ključno, i neinicijalizovane promenljive mogu dovesti do nepredvidivog ponašanja ili sigurnosnih ranjivosti, jer mogu nenamerno sadržati osetljive podatke preostale u memoriji.
Neinicijalizovane stack promenljive mogu predstavljati nekoliko sigurnosnih rizika, kao što su:
- Data Leakage: Osetljive informacije kao što su lozinke, ključevi za enkripciju ili lični podaci mogu biti izloženi ako su smešteni u neinicijalizovanim promenljivama, što napadačima može omogućiti da potencijalno pročitaju te podatke.
- Otkrivanje informacija: Sadržaj neinicijalizovanih promenljivih može otkriti detalje o rasporedu memorije programa ili internim operacijama, pomažući napadačima u razvoju ciljnih exploits.
- Padovi i nestabilnost: Operacije koje uključuju neinicijalizovane promenljive mogu rezultirati nedefinisanim ponašanjem, što dovodi do pada programa ili nepredvidivih rezultata.
- Arbitrary Code Execution: U određenim scenarijima, napadači bi mogli iskoristiti ove ranjivosti da promene tok izvršavanja programa, omogućavajući im da izvrše arbitrary code, što može uključivati remote code execution pretnje.
Primer
#include <stdio.h>
// Function to initialize and print a variable
void initializeAndPrint() {
int initializedVar = 100; // Initialize the variable
printf("Initialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
}
// Function to demonstrate the behavior of an uninitialized variable
void demonstrateUninitializedVar() {
int uninitializedVar; // Declare but do not initialize
printf("Uninitialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
}
int main() {
printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
// First, call the function that initializes its variable
initializeAndPrint();
// Then, call the function that has an uninitialized variable
demonstrateUninitializedVar();
return 0;
}
Kako ovo funkcioniše:
initializeAndPrintFunction: Ova funkcija deklariše celo-brojnu promenljivuinitializedVar, dodeljuje joj vrednost100i zatim ispisuje i memorijsku adresu i vrednost promenljive. Ovaj korak je jednostavan i pokazuje kako se ponaša inicijalizovana promenljiva.demonstrateUninitializedVarFunction: U ovoj funkciji deklarišemo celo-brojnu promenljivuuninitializedVarbez inicijalizacije. Kada pokušamo da ispišemo njenu vrednost, izlaz može prikazati nasumičan broj. Taj broj predstavlja podatke koji su prethodno bili na toj lokaciji u memoriji. U zavisnosti od okruženja i kompajlera, stvarni izlaz može varirati, i ponekad, iz bezbednosnih razloga, neki kompajleri mogu automatski inicijalizovati promenljive na nulu, mada se na to ne treba oslanjati.mainFunction: Funkcijamainpoziva obe prethodne funkcije redom, demonstrirajući kontrast između inicijalizovane promenljive i neinicijalizovane.
Praktični obrasci eksploatacije (2024–2025)
The classic “read-before-write” bug remains relevant because modern mitigations (ASLR, canaries) often rely on secrecy. Typical attack surfaces:
- Partially initialized structs copied to userland: Kernel or drivers frequently
memsetonly a length field and thencopy_to_user(&u, &local_struct, sizeof(local_struct)). Padding and unused fields leak stack canary halves, saved frame pointers or kernel pointers. If the struct contains a function pointer, leaving it uninitialized may also allow controlled overwrite when later reused. - Uninitialized stack buffers reused as indexes/lengths: An uninitialized
size_t len;used to boundread(fd, buf, len)may give attackers out-of-bounds reads/writes or allow bypassing size checks when the stack slot still contains a large value from a prior call. - Compiler-added padding: Čak i kada su pojedinačni članovi inicijalizovani, implicitni padding bajtovi između njih nisu. Kopiranje celog struct-a u userland može leak padding koji često sadrži prethodni sadržaj stacka (canaries, pointers).
- ROP/Canary disclosure: Ako funkcija kopira lokalni struct na stdout radi debugovanja, uninitialized padding može otkriti stack canary, omogućavajući naknadnu stack overflow eksploataciju bez brute-force.
Minimal PoC pattern to detect such issues during review:
struct msg {
char data[0x20];
uint32_t len;
};
ssize_t handler(int fd) {
struct msg m; // never fully initialized
m.len = read(fd, m.data, sizeof(m.data));
// later debug helper
write(1, &m, sizeof(m)); // leaks padding + stale stack
return m.len;
}
Mitigacije & opcije kompajlera (imajte na umu prilikom zaobilaženja)
- Clang/GCC auto-init: Recent toolchains expose
-ftrivial-auto-var-init=zeroor-ftrivial-auto-var-init=pattern, filling every automatic (stack) variable at function entry with zeros or a poison pattern (0xAA / 0xFE). Ovo zatvara većinu uninitialized-stack info leaks i otežava eksploataciju pretvarajući tajne u poznate vrednosti. - Linux kernel hardening: Kerneli kompajlirani sa
CONFIG_INIT_STACK_ALLili novijimCONFIG_INIT_STACK_ALL_PATTERNnuliraju/pattern-inicijalizuju svaki stack slot na ulazu funkcije, brišući canaries/pointers koji bi inače leak-ovali. Potražite distro-e koji isporučuju Clang-built kernel-e sa ovim opcijama uključenim (uobičajeno u 6.8+ hardening konfiguracijama). - Opt-out attributes: Clang now allows
__attribute__((uninitialized))on specific locals/structs to keep performance-critical areas uninitialized even when global auto-init is enabled. Pažljivo pregledajte takve anotacije—često označavaju namerno attack surface za side channels.
Sa stanovišta napadača, poznavanje da li je binarni fajl izgrađen sa ovim flag-ovima određuje da li su stack-leak primitives izvodljive ili morate pivot-ovati na heap/data-section disclosures.
Finding uninitialized-stack bugs quickly
- Compiler diagnostics: Kompajlirajte sa
-Wall -Wextra -Wuninitialized(GCC/Clang). Za C++ kod,clang-tidy -checks=cppcoreguidelines-init-variablesće auto-fix-ovati mnoge slučajeve u zero-init i korisno je za pronalaženje propuštenih lokalnih promenljivih tokom audita. - Dynamic tools:
-fsanitize=memory(MSan) in Clang or Valgrind’s--track-origins=yespouzdano flag-uju čitanja neinicijalizovanih stack bajtova tokom fuzz-ovanja. Instrumentujte test harness-e ovim alatima da izvučete suptilne padding leaks. - Grepping patterns: U review-ima tražite
copy_to_user/writepozive koji šalju cele strukture, ilimemcpy/sendstack podataka gde je samo deo strukture postavljen. Obratite posebnu pažnju na error path-ove gde je inicijalizacija preskočena.
ARM64 Example
Ovo se uopšte ne menja na ARM64 jer se lokalne promenljive takođe smeštaju na stack; možete check this example gde je ovo prikazano.
References
- CONFIG_INIT_STACK_ALL_PATTERN documentation
- GHSL-2024-197: GStreamer uninitialized stack variable leading to function pointer overwrite
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.


