μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ λ³€μˆ˜

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°

κΈ°λ³Έ 정보

핡심 μ•„μ΄λ””μ–΄λŠ” μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ λ³€μˆ˜λŠ” ν•΄λ‹Ή λ©”λͺ¨λ¦¬ μ£Όμ†Œμ— 이미 있던 값을 κ°–κ²Œ λœλ‹€λŠ” 사싀을 μ΄ν•΄ν•˜λŠ” 것이닀. 예:

  • Function 1: initializeVariable: λ³€μˆ˜ xλ₯Ό μ„ μ–Έν•˜κ³  κ°’(예: 0x1234)을 ν• λ‹Ήν•œλ‹€. 이 λ™μž‘μ€ λ©”λͺ¨λ¦¬μ˜ ν•œ 자리λ₯Ό μ˜ˆμ•½ν•˜κ³  νŠΉμ • 값을 λ„£λŠ” 것과 κ°™λ‹€.
  • Function 2: useUninitializedVariable: μ—¬κΈ°μ„œλŠ” 또 λ‹€λ₯Έ λ³€μˆ˜ yλ₯Ό μ„ μ–Έν•˜μ§€λ§Œ 값을 ν• λ‹Ήν•˜μ§€ μ•ŠλŠ”λ‹€. Cμ—μ„œλŠ” μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ λ³€μˆ˜κ°€ μžλ™μœΌλ‘œ 0으둜 μ„€μ •λ˜μ§€ μ•ŠλŠ”λ‹€. λŒ€μ‹  ν•΄λ‹Ή λ©”λͺ¨λ¦¬ μœ„μΉ˜μ— λ§ˆμ§€λ§‰μœΌλ‘œ μ €μž₯λ˜μ–΄ 있던 값을 κ·ΈλŒ€λ‘œ μœ μ§€ν•œλ‹€.

이 두 ν•¨μˆ˜λ₯Ό 순차적으둜 μ‹€ν–‰ν•˜λ©΄:

  1. initializeVariableμ—μ„œ x에 κ°’(0x1234)이 ν• λ‹Ήλ˜λ©°, μ΄λŠ” νŠΉμ • λ©”λͺ¨λ¦¬ μ£Όμ†Œλ₯Ό μ°¨μ§€ν•œλ‹€.
  2. useUninitializedVariableμ—μ„œλŠ” yκ°€ μ„ μ–Έλ˜μ§€λ§Œ 값이 ν• λ‹Ήλ˜μ§€ μ•Šμ•„ x λ°”λ‘œ λ‹€μŒ λ©”λͺ¨λ¦¬ μœ„μΉ˜λ₯Ό μ°¨μ§€ν•œλ‹€. yλ₯Ό μ΄ˆκΈ°ν™”ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— κ·Έ λ©”λͺ¨λ¦¬ μœ„μΉ˜μ— λ§ˆμ§€λ§‰μœΌλ‘œ 남아 있던 κ°’(즉 xκ°€ μ‚¬μš©ν•œ κ°’)을 β€™μƒμ†β€™λ°›κ²Œ λœλ‹€.

이 λ™μž‘μ€ μ €μˆ˜μ€€ ν”„λ‘œκ·Έλž˜λ°μ˜ 핡심 κ°œλ…μ„ 보여쀀닀: λ©”λͺ¨λ¦¬ 관리가 μ€‘μš”ν•˜λ‹€λŠ” 것. μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ λ³€μˆ˜λŠ” λ©”λͺ¨λ¦¬μ— 남아 있던 λ―Όκ°ν•œ 데이터λ₯Ό μ˜λ„μΉ˜ μ•Šκ²Œ λ³΄μœ ν•  수 μžˆμ–΄ 예츑 λΆˆκ°€λŠ₯ν•œ λ™μž‘μ΄λ‚˜ λ³΄μ•ˆ μ·¨μ•½μ μœΌλ‘œ μ΄μ–΄μ§ˆ 수 μžˆλ‹€.

μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ μŠ€νƒ λ³€μˆ˜λŠ” λ‹€μŒκ³Ό 같은 μ—¬λŸ¬ λ³΄μ•ˆ μœ„ν—˜μ„ μ΄ˆλž˜ν•  수 μžˆλ‹€:

  • Data Leakage: λΉ„λ°€λ²ˆν˜Έ, μ•”ν˜Έν™” ν‚€ λ˜λŠ” 개인 정보 같은 λ―Όκ°ν•œ 정보가 μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ λ³€μˆ˜μ— 남아 있으면 λ…ΈμΆœλ  수 있으며, κ³΅κ²©μžκ°€ ν•΄λ‹Ή 데이터λ₯Ό 읽을 수 μžˆλ‹€.
  • Information Disclosure: μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ λ³€μˆ˜μ˜ λ‚΄μš©μ€ ν”„λ‘œκ·Έλž¨μ˜ λ©”λͺ¨λ¦¬ λ ˆμ΄μ•„μ›ƒμ΄λ‚˜ λ‚΄λΆ€ λ™μž‘μ— λŒ€ν•œ 정보λ₯Ό λ“œλŸ¬λ‚΄μ–΄ κ³΅κ²©μžκ°€ ν‘œμ ν™”λœ μ΅μŠ€ν”Œλ‘œμž‡μ„ κ°œλ°œν•˜λŠ” 데 도움을 쀄 수 μžˆλ‹€.
  • Crashes and Instability: μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜λŠ” 연산은 μ •μ˜λ˜μ§€ μ•Šμ€ λ™μž‘μ„ 일으켜 ν”„λ‘œκ·Έλž¨ μΆ©λŒμ΄λ‚˜ 예츑 λΆˆκ°€λŠ₯ν•œ κ²°κ³Όλ₯Ό μ΄ˆλž˜ν•  수 μžˆλ‹€.
  • Arbitrary Code Execution: νŠΉμ • μ‹œλ‚˜λ¦¬μ˜€μ—μ„œλŠ” κ³΅κ²©μžκ°€ μ΄λŸ¬ν•œ 취약점을 μ΄μš©ν•΄ ν”„λ‘œκ·Έλž¨μ˜ μ‹€ν–‰ 흐름을 λ³€κ²½ν•˜μ—¬ μž„μ˜μ˜ μ½”λ“œλ₯Ό μ‹€ν–‰ν•  수 있으며, μ΄λŠ” 원격 μ½”λ“œ μ‹€ν–‰ μœ„ν˜‘μ„ 포함할 수 μžˆλ‹€.

예제

#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;
}

How This Works:

  • initializeAndPrint Function: 이 ν•¨μˆ˜λŠ” μ •μˆ˜ λ³€μˆ˜ initializedVarλ₯Ό μ„ μ–Έν•˜κ³  κ°’ 100을 λŒ€μž…ν•œ λ’€, λ³€μˆ˜μ˜ λ©”λͺ¨λ¦¬ μ£Όμ†Œμ™€ 값을 좜λ ₯ν•©λ‹ˆλ‹€. 이 λ‹¨κ³„λŠ” λ‹¨μˆœν•˜λ©° μ΄ˆκΈ°ν™”λœ λ³€μˆ˜κ°€ μ–΄λ–»κ²Œ λ™μž‘ν•˜λŠ”μ§€ λ³΄μ—¬μ€λ‹ˆλ‹€.
  • demonstrateUninitializedVar Function: 이 ν•¨μˆ˜μ—μ„œλŠ” μ •μˆ˜ λ³€μˆ˜ uninitializedVarλ₯Ό μ΄ˆκΈ°ν™”ν•˜μ§€ μ•Šκ³  μ„ μ–Έν•©λ‹ˆλ‹€. 값을 좜λ ₯ν•˜λ € ν•˜λ©΄ 좜λ ₯이 λ¬΄μž‘μœ„ 숫자λ₯Ό 보일 수 μžˆμŠ΅λ‹ˆλ‹€. 이 μˆ«μžλŠ” ν•΄λ‹Ή λ©”λͺ¨λ¦¬ μœ„μΉ˜μ— 이전에 있던 데이터λ₯Ό λ‚˜νƒ€λƒ…λ‹ˆλ‹€. ν™˜κ²½κ³Ό μ»΄νŒŒμΌλŸ¬μ— 따라 μ‹€μ œ 좜λ ₯은 λ‹¬λΌμ§ˆ 수 있고, 일뢀 μ»΄νŒŒμΌλŸ¬λŠ” μ•ˆμ „μ„ μœ„ν•΄ λ³€μˆ˜λ₯Ό μžλ™μœΌλ‘œ 0으둜 μ΄ˆκΈ°ν™”ν•  μˆ˜λ„ μžˆμ§€λ§Œ, 이λ₯Ό μ‹ λ’°ν•΄μ„œλŠ” μ•ˆ λ©λ‹ˆλ‹€.
  • main Function: main ν•¨μˆ˜λŠ” μœ„ 두 ν•¨μˆ˜λ₯Ό μˆœμ„œλŒ€λ‘œ ν˜ΈμΆœν•˜μ—¬ μ΄ˆκΈ°ν™”λœ λ³€μˆ˜μ™€ μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ λ³€μˆ˜μ˜ 차이λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.

Practical exploitation patterns (2024–2025)

고전적인 β€œread-before-write” λ²„κ·ΈλŠ” μ—¬μ „νžˆ μœ νš¨ν•©λ‹ˆλ‹€. ν˜„λŒ€μ˜ μ™„ν™”μ±…(ASLR, canaries)이 μ’…μ’… λΉ„λ°€ μœ μ§€μ— μ˜μ‘΄ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. 일반적인 곡격 ν‘œλ©΄:

  • Partially initialized structs copied to userland: μ»€λ„μ΄λ‚˜ λ“œλΌμ΄λ²„λŠ” μ’…μ’… 길이 ν•„λ“œλ§Œ memset ν•˜κ³  copy_to_user(&u, &local_struct, sizeof(local_struct))λ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€. νŒ¨λ”©κ³Ό μ‚¬μš©λ˜μ§€ μ•Šμ€ ν•„λ“œλŠ” stack canary halves, saved frame pointers λ˜λŠ” kernel pointersλ₯Ό leak ν•©λ‹ˆλ‹€. ꡬ쑰체에 function pointerκ°€ ν¬ν•¨λ˜μ–΄ μžˆλ‹€λ©΄, 이λ₯Ό μ΄ˆκΈ°ν™”ν•˜μ§€ μ•ŠμœΌλ©΄ λ‚˜μ€‘μ— μž¬μ‚¬μš©λ  λ•Œ controlled overwriteλ₯Ό ν—ˆμš©ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.
  • Uninitialized stack buffers reused as indexes/lengths: μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ size_t len;κ°€ read(fd, buf, len)의 경계λ₯Ό μ •ν•˜λŠ” 데 μ‚¬μš©λ˜λ©΄, ν•΄λ‹Ή μŠ€νƒ 슬둯이 이전 호좜의 큰 값을 μœ μ§€ν•˜κ³  μžˆμ„ λ•Œ κ³΅κ²©μžκ°€ λ²”μœ„λ₯Ό λ²—μ–΄λ‚œ 읽기/μ“°κΈ°(out-of-bounds reads/writes)λ₯Ό ν•˜κ±°λ‚˜ 크기 검사λ₯Ό μš°νšŒν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • Compiler-added padding: κ°œλ³„ 멀버가 μ΄ˆκΈ°ν™”λ˜μ–΄ μžˆμ–΄λ„ κ·Έ μ‚¬μ΄μ˜ 암묡적 νŒ¨λ”© λ°”μ΄νŠΈλŠ” μ΄ˆκΈ°ν™”λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. ꡬ쑰체 전체λ₯Ό userland둜 λ³΅μ‚¬ν•˜λ©΄ 이전 μŠ€νƒ λ‚΄μš©(canaries, pointers)을 ν¬ν•¨ν•˜λŠ” νŒ¨λ”©μ΄ leak λ©λ‹ˆλ‹€.
  • ROP/Canary disclosure: ν•¨μˆ˜κ°€ 디버깅을 μœ„ν•΄ 둜컬 ꡬ쑰체λ₯Ό stdout으둜 λ³΅μ‚¬ν•˜λ©΄, μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ νŒ¨λ”©μ΄ stack canaryλ₯Ό λ“œλŸ¬λ‚΄μ–΄ μ΄ν›„μ˜ stack overflow 곡격을 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;
}

μ™„ν™”μ±… 및 컴파일러 μ˜΅μ…˜ (우회 μ‹œ 염두에 λ‘˜ 것)

  • Clang/GCC auto-init: Recent toolchains expose -ftrivial-auto-var-init=zero or -ftrivial-auto-var-init=pattern, filling every automatic (stack) variable at function entry with zeros or a poison pattern (0xAA / 0xFE). μ΄λŠ” ν•¨μˆ˜ μ§„μž… μ‹œ λͺ¨λ“  μžλ™(stack) λ³€μˆ˜λ₯Ό 0 λ˜λŠ” νŒ¨ν„΄μœΌλ‘œ μ±„μ›Œ λŒ€λΆ€λΆ„μ˜ uninitialized-stack info leaksλ₯Ό μ°¨λ‹¨ν•˜κ³ , 비밀값을 μ•Œλ €μ§„ κ°’μœΌλ‘œ λ°”κΏ” exploitation을 더 μ–΄λ ΅κ²Œ λ§Œλ“­λ‹ˆλ‹€.
  • Linux kernel hardening: Kernels built with CONFIG_INIT_STACK_ALL or the newer CONFIG_INIT_STACK_ALL_PATTERN zero/pattern-initialize every stack slot at function entry, wiping canaries/pointers that would otherwise leak. μ΄λŸ¬ν•œ μ˜΅μ…˜μœΌλ‘œ λΉŒλ“œλœ(특히 Clang으둜 λΉŒλ“œλœ) 컀널을 λ°°ν¬ν•˜λŠ” λ°°ν¬νŒμ„ μ°Ύμ•„λ³΄μ„Έμš”(6.8+ ν•˜λ“œλ‹ κ΅¬μ„±μ—μ„œ 흔함).
  • 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. μ΄λŸ¬ν•œ μ–΄λ…Έν…Œμ΄μ…˜μ€ μ„±λŠ₯ 상 μ€‘μš”ν•œ μ˜μ—­μ„ μ˜λ„μ μœΌλ‘œ μ΄ˆκΈ°ν™”ν•˜μ§€ μ•ŠκΈ° μœ„ν•΄ μ‚¬μš©λ˜λ―€λ‘œ 주의 깊게 κ²€ν† ν•˜μ„Έμš”β€”μ’…μ’… side channels을 λ…Έλ¦° 곡격 ν‘œλ©΄μ„ ν‘œμ‹œν•©λ‹ˆλ‹€.

곡격자 κ΄€μ μ—μ„œλŠ” λ°”μ΄λ„ˆλ¦¬κ°€ μ΄λŸ¬ν•œ ν”Œλž˜κ·Έλ‘œ λΉŒλ“œλ˜μ—ˆλŠ”μ§€ μ—¬λΆ€κ°€ stack-leak primitivesκ°€ μ‹€μš©μ μΈμ§€, μ•„λ‹ˆλ©΄ heap/data-section disclosures둜 μ „ν™˜ν•΄μ•Ό ν•˜λŠ”μ§€λ₯Ό κ²°μ •ν•©λ‹ˆλ‹€.

Finding uninitialized-stack bugs quickly

  • 컴파일러 진단(Compiler diagnostics): Build with -Wall -Wextra -Wuninitialized (GCC/Clang). For C++ code, clang-tidy -checks=cppcoreguidelines-init-variables will auto-fix many cases to zero-init and is handy to spot missed locals during audit.
  • 동적 도ꡬ(Dynamic tools): -fsanitize=memory (MSan) in Clang or Valgrind’s --track-origins=yes reliably flag reads of uninitialized stack bytes during fuzzing. ν…ŒμŠ€νŠΈ ν•˜λ‹ˆμŠ€μ— 이 도ꡬ듀을 μ μš©ν•˜λ©΄ λ―Έμ„Έν•œ padding leaksλ₯Ό λ“œλŸ¬λ‚Ό 수 μžˆμŠ΅λ‹ˆλ‹€.
  • Grepping νŒ¨ν„΄(Grepping patterns): μ½”λ“œ 리뷰 μ‹œ 전체 ꡬ쑰체λ₯Ό λŒ€μƒμœΌλ‘œ ν•˜λŠ” copy_to_user / write ν˜ΈμΆœμ΄λ‚˜, ꡬ쑰체의 μΌλΆ€λ§Œ μ„€μ •λœ μƒνƒœμ—μ„œμ˜ memcpy/send 같은 stack 데이터 전솑을 κ²€μƒ‰ν•˜μ„Έμš”. μ΄ˆκΈ°ν™”κ°€ κ±΄λ„ˆλ›°μ–΄μ§€λŠ” μ—λŸ¬ κ²½λ‘œμ— 특히 μ£Όμ˜ν•˜μ„Έμš”.

ARM64 μ˜ˆμ‹œ

ARM64μ—μ„œλŠ” 둜컬 λ³€μˆ˜κ°€ μ—­μ‹œ stackμ—μ„œ κ΄€λ¦¬λ˜λ―€λ‘œ μ „ν˜€ 달라지지 μ•ŠμŠ΅λ‹ˆλ‹€. μ΄λŠ” check this exampleμ—μ„œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

References

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°