• Mindscape ๐Ÿ”ฅ
    • Playlist ๐ŸŽง
  • Algorithm

    • 1018๋ฒˆ: ์ฒด์ŠคํŒ ๋‹ค์‹œ ์น ํ•˜๊ธฐ
    • 1966๋ฒˆ: ํ”„๋ฆฐํ„ฐ ํ
    • Python ์‹œ๊ฐ„ ์ดˆ๊ณผ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ ํŒ
    • C++ std::vector ์‚ฌ์šฉ๋ฒ• ์ •๋ฆฌ
    • Vim ์‚ฌ์šฉ ๋งค๋‰ด์–ผ
  • Ubuntu

    • ๋ฆฌ๋ˆ…์Šค ์šฐ๋ถ„ํˆฌ GRUB ํฐํŠธ ๋ณ€๊ฒฝ
    • ์šฐ๋ถ„ํˆฌ ์ด๋ฏธ์ง€ ๋น„๋””์˜ค ์ธ๋„ค์ผ(๋ฏธ๋ฆฌ๋ณด๊ธฐ) ์•ˆ ๋ณด์ž„ ๋ฌธ์ œ ํ•ด๊ฒฐ
    • Wine ํ™˜๊ฒฝ์—์„œ ์นด์นด์˜คํ†ก ์‹คํ–‰ ์‹œ explorer.exe ๋œจ์ง€ ์•Š๊ฒŒ ํ•˜๋Š” ๋ฒ•
    • ์šฐ๋ถ„ํˆฌ Wine ์นด์นด์˜คํ†ก ์‚ฌ์ง„ ์ด๋ฏธ์ง€ ์Šคํฌ๋ฆฐ์ƒท ๋ถ™์—ฌ๋„ฃ๊ธฐ
    • Wine ์นด์นด์˜คํ†ก ์ด๋ชจ์ง€ ๊นจ์ง ๋ฌธ์ œ ํ•ด๊ฒฐ
    • Ubuntu ์œˆ๋„์šฐ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋„๊ธฐ
  • Wellness

    • ์ฐจ์ „์žํ”ผ (Psyllium Husk)
    • ์—‘์ŠคํŠธ๋ผ ๋ฒ„์ง„ ์˜ฌ๋ฆฌ๋ธŒ์œ  (Extra Virgin Olive Oil)
    • ์ž๊ฐ€๋น„๊ฐ•์„ธ์ฒ™ (Nasal Irrigation)
    • QCY HT08 (MeloBuds Pro Plus)
    • ์ฝ˜์„œํƒ€ (Concerta)
    • ์ธ๋ฐ๋†€ (Inderal)
    • ์„คํŠธ๋ž„๋ฆฐ (Sertraline)
    • ๋ฉœ๋ผํ† ๋‹Œ (Melatonin)
    • ์น˜๊ฒฝ๋ถ€ ๋งˆ๋ชจ์ฆ
    • ๋ฐ”๋ฒจ ์Šค์ฟผํŠธ (Barbell Squat)
  • Humanities

    • Nordvik, Russia
    • North Sentinel Island
    • ๋กฑ๊ณ ๋กฑ๊ณ (Rongorongo)
    • ๋ฐ”๋กœํฌ ์Œ์•… (Baroque Music)
  • Design

    • ๊ตฌ๊ธ€์˜ ์•„์ด์ฝ˜ ๋Œ€๊ฐœํŽธ โ€” 6๋…„ ๋งŒ์˜ ์‹ค์ˆ˜ ์ธ์ •
    • ์ œ๋Ÿด๋“œ ์  ํƒ€ โ€” ๋Ÿญ์…”๋ฆฌ ์Šคํฌ์ธ  ์›Œ์น˜์˜ ์ฐฝ์‹œ์ž
    • ๋ฐ”์šฐํ•˜์šฐ์Šค โ€” ํ˜„๋Œ€ ๋””์ž์ธ์˜ ์›์ 
  • Brands

    • NOMOS Glashรผtte
    • Frรฉdรฉrique Constant
    • KZ (Knowledge Zenith)
    • ์—์ŠคํŠธ๋ผ (AESTURA)
    • JINHAO (้‡‘่ฑช)
    • Herman Miller
    • ๋ฐ์Šค์ปค (DESKER)
    • ๋ฌด์‹ ์‚ฌ ์Šคํƒ ๋‹ค๋“œ (Musinsa Standard)
  • Finance

    • ํ˜„๋Œ€์นด๋“œ ZERO โ€” Edition2 vs Edition3 ๋น„๊ต
    • ์‹ ํ•œ์นด๋“œ ์ฒ˜์Œ
    • S&P 500 ETF ํˆฌ์ž ๊ฐ€์ด๋“œ
    • ํŒŒํ‚นํ†ต์žฅ vs CMA ํ†ต์žฅ
    • ๋ฒ„ํฌ์…” ํ•ด์„œ์›จ์ด (Berkshire Hathaway)
    • ๋น„ํŠธ์ฝ”์ธ(Bitcoin)
  • Products

    • ์˜ค๋””์˜ค ์ธํ„ฐํŽ˜์ด์Šค (Audio Interface)
    • ์ฟ ๋ฃจํ† ๊ฐ€ (KURUTOGA)
    • CX31993 DAC ๋™๊ธ€
    • ํด๋ Œ์ง• ๋ฐ€ํฌ (Cleansing Milk)
    • ํ”ผ์ ฏ ํ† ์ด (Fidget Toy)
    • ThinkPad
  • Programming Languages

    • 8.0. Statement Level Control Structures
    • 8. Subprogram
    • 9. Implementing Subprogram
    • 10.1. Abstract Data Types and Encapsulation Constructs
    • 10.2. Support for Object Oriented Programming
    • 11. Concurrency
    • 12. FPL (1)
    • 13. FPL (2)
    • 14. Exception Handling and Event Handling
    • Final Exam

10. String Security

์ž‘์„ฑ 2026. 6. 12.ยท์ˆ˜์ • 2026. 6. 12.

Strings

Character Strings

  • ํ‘œ์ค€ C ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ง€์›
    • char ํƒ€์ž…์˜ strings
    • wchar_t ํƒ€์ž…์˜ wide strings

Figure 2.1. "hello"์˜ ๋ฌธ์ž์—ด ํ‘œํ˜„

An Example

  • size of an array
void clear(int array[]) {
  for (size_t i = 0; i < sizeof(array) / sizeof(array[0]); ++i) {
    array[i] = 0;
  }
}

void dowork(void) {
  int dis[12];

  clear(dis);
  /* ... */
}

multibyte character set

  • Basic execution character set
    • 26๊ฐœ์˜ ๋Œ€๋ฌธ์ž, 26๊ฐœ์˜ ์†Œ๋ฌธ์ž ๋“ฑ
  • UTF-8
    • A multibyte character set
    • Backward compatible
    • 1 ~ 4 bytes
  • String literals
    • L"xyz"
    • Type wchar_t

Strings

  • const char s[3] = "abc";
    • Array์˜ ํฌ๊ธฐ๋Š” 3
    • Trailing null byte๋Š” ์ƒ๋žต
    • const char s[ ] = "abc";

Strings in C++

  • std::basic_string
    • Characters์˜ ์‹œํ€€์Šค
    • string์€ template specialization basic_string<char>์— ๋Œ€ํ•œ typedef
    • wstring์€ template specialization basic_string<wchar_t>์— ๋Œ€ํ•œ typedef
  • C++ string class
    • ๋ชจ๋“  ์ผ๋ฐ˜์ ์ธ implementation์€ null-terminated
    • Win32 LSA_UNICODE_STRING๊ณผ ๊ฐ™์€ ์ผ๋ถ€ ๋‹ค๋ฅธ string type์€ null-terminated์ผ ํ•„์š”๋Š” ์—†์Œ.

Character Types

  • three types
    • char, signed char, unsigned char
  • Philosophy
    • Signed char and unsigned char
      • ์ž‘์€ ์ •์ˆ˜๊ฐ’์— ์ ํ•ฉ
    • Plain char
      • ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์˜ ๊ฐ๊ฐ ์š”์†Œ๋“ค์˜ ํƒ€์ž…
      • ์ •์ˆ˜ ๋ฐ์ดํ„ฐ ๋Œ€์‹  ๋ฌธ์ž(character) ๋ฐ์ดํ„ฐ๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ (๋ถ€ํ˜ธ์˜ ์˜๋ฏธ๊ฐ€ ์ ์€)
  • Example
size_t len;
char cstr[] = "char string";
signed char scstr[] = "signed char string";
unsigned char ucstr[] = "unsigned char string";

len = strlen(cstr);
len = strlen(scstr); /* warns when char is unsigned */
len = strlen(ucstr); /* warns when char is signed */

int

  • EOF (์Œ์ˆ˜ ๊ฐ’)
  • ๋˜๋Š” unsigned char๋กœ ํ•ด์„๋œ char data
  • int๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
    • fgetc(), getc(), getchar(), fgetwc(), getwc(), getwchar()
  • <ctype.h>์— ์„ ์–ธ๋œ char classification functions
    • int๋ฅผ ์ธ์ˆ˜๋กœ ํ—ˆ์šฉ
    • ์˜ˆ: isalpha()

Example

  • Code Example ๋ถ„์„
    int main() {
        char c = 'a';
        char b[] = โ€œaโ€;
        wchar_t wc;
        printf(" size of 'a': %d \n", sizeof('a'));
        printf(" size of c: %d \n", sizeof(c));
        printf(" size of wc: %d \n", sizeof(wc));
    }
    
  • C์—์„œ sizeof('a') โ†’ ???, sizeof(c) โ†’ ???
  • C++์—์„œ sizeof('a') โ†’ ???

unsigned char

  • ๊ฐ์ฒด๊ฐ€ ์–ด๋–ค type์ด๋“  ๋  ์ˆ˜ ์žˆ์„ ๋•Œ ์œ ์šฉ
  • fwrite()
  • Pure binary notation์„ ์‚ฌ์šฉํ•˜์—ฌ ํ‘œํ˜„๋จ์ด ๋ณด์žฅ
  • Example
int main() {
    unsigned char buf1[6] = { 0xff, 0x56, 0x78, 0xfa, 0xf1, 0};
    unsigned char buf2[6];
    FILE *stream;
    stream = fopen(โ€œout.datโ€, โ€œwbโ€);
    fwrite(buf1, sizeof(char), 6, stream);
    fclose(stream);
    stream = fopen(โ€œout.datโ€, โ€œrbโ€);
    fread(buf2, sizeof(char), 6, stream); fclose(stream);
    for (int i=0; i<6 && buf2[i] != NULL; i++)
        printf(โ€œ%x โ€œ, buf2[i]);
    printf(โ€œ\nโ€);
    return 0;
}

Sizing Strings

  • Buffer overflows๋ฅผ ์˜ˆ๋ฐฉํ•˜๊ธฐ ์œ„ํ•ด ํ•„์ˆ˜
  • The CERT C Secure Coding Standard
    • STR31-C. strings์šฉ ์ €์žฅ ๊ณต๊ฐ„์ด character data์™€ null terminator๋ฅผ ์œ„ํ•œ ์ถฉ๋ถ„ํ•œ ๊ณต๊ฐ„์„ ๊ฐ–๋„๋ก ๋ณด์žฅ
  • ์šฉ์–ด
    • Size: array์— ํ• ๋‹น๋œ byte ์ˆ˜ (sizeof(array)์™€ ๋™์ผ)
    • Count: array์˜ element ์ˆ˜ (Visual Studio 2010์˜ _countof(array)์™€ ๋™์ผ)
    • Length: null terminator ์•ž์˜ character ์ˆ˜ (strlen() ๊ฒฐ๊ณผ)
  • Example
wchar_t wide_str1[] = Lโ€0123456789โ€;
wchar_t *wide_str2 = (wchar_t *) malloc (strlen(wide_str1) +1);
if (wide_str2 == NULL) {
  /* handle error */
}
strcpy(wide_str2, wide_str1);
/* โ€ฆ */
free(wide_str2);
wide_str2 = NULL;

Common String Manipulation Errors

  • 4๊ฐ€์ง€ ์ผ๋ฐ˜์ ์ธ ์˜ค๋ฅ˜
    • unbounded string copies (๋ฌดํ•œ string ๋ณต์‚ฌ)
    • off-by-one errors
    • null-termination errors
    • String truncation
    • String truncation

Improperly Bounded String Copies

  • ๋ฐ์ดํ„ฐ๊ฐ€ ๊ณ ์ •๋œ ๊ธธ์ด์˜ ๋ฌธ์ž์—ด๋กœ๋ถ€ํ„ฐ ๋ณต์‚ฌ๋  ๋•Œ
    • ์˜ˆ: ๊ณ ์ •๋œ ๊ธธ์ด ๋ฒ„ํผ์— ํ‘œ์ค€ ์ž…๋ ฅ์œผ๋กœ ์ฝ์–ด์˜ค๋Š” ๊ฒฝ์šฐ
  • gets() C99์— ์ถ”๊ฐ€๋˜์—ˆ์œผ๋‚˜ C11์—์„œ ์ œ๊ฑฐ
  • "STR35-C. unbounded source์—์„œ๋ถ€ํ„ฐ ๊ณ ์ • ๊ธธ์ด ๋ฐฐ์—ด์— ๋ณต์‚ฌํ•˜์ง€ ๋งˆ์‹œ์˜ค."
#include <stdio.h>
#include <stdlib.h>

void get_y_or_n(void) {
  char response[8];
  puts("Continue? [y] n: ");
  gets(response);
  if (response[0] == 'n')
    exit(0);
  return;
}

Example 2.1. Reading from stdin()

Copying and concatenating strings

Improperly Bounded String Copies

  • Standard lib functions
    • strcpy(), strcat(), sprintf()
  • int main(int argc, char *argv[ ]) ...
    • argv[0] ~ argv[argc-1] : Null-terminated string์„ ๊ฐ€๋ฆฌํ‚ค๋Š” pointer
    • argv array์˜ ์–ด๋–ค ์š”์†Œ๋„(argv[0] ํฌํ•จ) null์ด ์•„๋‹ˆ๋ผ๊ณ  ๊ฐ€์ •ํ•˜์ง€ ๋ง ๊ฒƒ
int main(int argc, char *argv[]) {
    /* Do not assume that argv[0] can-
    not be null */
    const char * const name =
    argv[0] ? argv[0] : "";
    char *prog_name = (char *)mal-
    loc(strlen(name) + 1);
    if (prog_name != NULL) {
        strcpy(prog_name, name);
    }
    else {
        /* Failed to allocate memory -
    recover */
    }
    /* ... */
}

sprintf() function

  • array์— output์„ ์ž‘์„ฑ
  • ์ž‘์„ฑ๋œ character์˜ ๋์— null character๊ฐ€ ์ž‘์„ฑ
  • target array์— ํ•„์š”ํ•œ ์ตœ๋Œ€ ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•˜๊ธฐ ์–ด๋ ค์›€
    • ์˜ˆ: INT_MAX โ†’ ์ตœ์†Œ 11 characters
    • ์Œ์˜ ์ •์ˆ˜, floating-point values๋Š” ์˜ˆ์ธก์ด ๋” ์–ด๋ ค์›€
  • snprintf() ํ•จ์ˆ˜
    • ์ถ”๊ฐ€ parameter: size_t n
    • null char๊ฐ€ ์ถ”๊ฐ€๋˜๋ฏ€๋กœ nโˆ’1n-1nโˆ’1 characters๊ฐ€ ์ž‘์„ฑ
    • ์„ฑ๊ณต ์‹œ ์ž‘์„ฑ๋œ character ์ˆ˜ (excluding null char) ๋ฐ˜ํ™˜
    • ๋น„๊ต์  ์•ˆ์ „ํ•˜์ง€๋งŒ, format string vulnerabilities์— ์ทจ์•ฝ

C++์˜ std::cin

  • ์ด ๋˜ํ•œ ๋ฌธ์ œ์  ์žˆ์Œ.
#include <iostream>

int main(void) {
  char buf[12];

  std::cin >> buf;
  std::cout << "echo: " << buf << '\n';
}
  • field width๋ฅผ ios_base::width ๋˜๋Š” setw()๋กœ ์„ค์ • ๊ฐ€๋Šฅ
  • nโˆ’1n-1nโˆ’1 characters๊ฐ€ ์ถ”์ถœ๋œ ํ›„ null character๊ฐ€ ์ž๋™์œผ๋กœ ์ถ”๊ฐ€๋จ
#include <iostream>

int main(void) {
  char buf[12];

  std::cin.width(12);
  std::cin >> buf;
  std::cout << "echo: " << buf << '\n';
}

Off-by-One Errors

  • ๋˜ ๋‹ค๋ฅธ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ
  • unbounded string copies์™€ ์œ ์‚ฌ
  • Example
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
  char s1[] = "012345678";
  char s2[] = "0123456789";
  char *dest;
  int i;

  strcpy_s(s1, sizeof(s2), s2);
  dest = (char *) malloc (strlen(s1));
  for (i = 1; i <= 11; i++) {
    dest[i] = s1[i];
  }
  dest[i] = '\0';
  printf("dest = %s", dest);
  /* ... */;
}

Null-Termination Errors

  • Example
int main(void) {
  char a[16];
  char b[16];
  char c[16];
  strncpy(a, "0123456789abcdef", sizeof(a));
  strncpy(b, "0123456789abcdef", sizeof(b));
  strncpy(c, a);
  /* ... */
}
  • strncpy()๋Š” ์ฒ˜์Œ nnn characters๋ฅผ ๋ณต์‚ฌ
    • Null-termination์„ ๋ณด์žฅํ•˜์ง€ ์•Š์Œ.

String Vulnerabilities and Exploits

  • C ๋˜๋Š” C++์—์„œ String manipulation
    • ์™ธ๋ถ€ source์˜ untrusted data์—์„œ ์ž‘๋™ํ•  ๋•Œ ์œ„ํ—˜ํ•ด์ง
    • ๋ชจ๋“  ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ untrusted๋กœ ๋ณด๋Š” ๊ฒƒ์ด ์•ˆ์ „
  • Example
bool IsPasswordOK(void) {
  char Password[12];

  gets(Password);
  return 0 == strcmp(Password, "goodpass");
}

int main(void) {
  bool PwStatus;

  puts("Enter password: ");
  PwStatus = IsPasswordOK();
  if (PwStatus == false) {
    puts("Access denied");
    exit(-1);
  }
}

Buffer Overflows

  • Example
  • C ๋ฐ C++๊ฐ€ buffer overflows์— ์ทจ์•ฝํ•œ ์ด์œ 
    • Strings๋ฅผ null-terminated arrays of characters๋กœ ์ •์˜
    • ์•”๋ฌต์ ์ธ bounds checking์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Œ.
    • Bounds checking์„ ๊ฐ•์ œํ•˜์ง€ ์•Š๋Š” strings์— ๋Œ€ํ•œ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜ธ์ถœ ์ œ๊ณต

Process Memory Organization

Programs and Processes

Figure 10.4 Program Loading into Process Memory

Stack Buffer Overflows

  • Buffer๊ฐ€ stack์— ์œ„์น˜ํ•  ๋•Œ ๋ฐœ์ƒ
    • Stack smashing์ด๋ผ๊ณ ๋„ ํ•จ
  • Morris Worm์— ์˜ํ•ด ์‚ฌ์šฉ
    • exploits๋Š” unchecked buffer overflow๋ฅผ ํฌํ•จ
  • ์—ฌ์ „ํžˆ ๋„๋ฆฌ ์•…์šฉ๋˜๊ณ  ์žˆ์Œ.
  • Stack frame
    • ํ•œ ํ•จ์ˆ˜๊ฐ€ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ return address๋ฅผ ์ €์žฅํ•  ๊ณต๊ฐ„ ํ•„์š”
    • ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜์— ์ „๋‹ฌ๋  parameters์™€ register values๋ฅผ ์ €์žฅํ•  ์œ„์น˜๋„ ํ•„์š”

Stack Frame with Functions P and Q

  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                   
P:โ”‚    Return Addr    โ”‚                   
  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                   
  โ”‚ Old Frame Pointer โ”‚โ—„โ”€โ”€โ”               
  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค   โ”‚               
  โ”‚      param 2      โ”‚   โ”‚               
  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค   โ”‚               
  โ”‚      param 1      โ”‚   โ”‚               
  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค   โ”‚               
Q:โ”‚ Return Addr in P  โ”‚   โ”‚               
  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค   โ”‚               
  โ”‚ Old Frame Pointer โ”‚โ—„โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€ Frame  
  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค            Pointer
  โ”‚      local 1      โ”‚                   
  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                   
  โ”‚      local 2      โ”‚โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Stack  
  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค            Pointer
  โ”‚         โ”‚         โ”‚                   
  โ”‚         โ–ผ         โ”‚                   

Figure 10.3 Examples Stack Frame with Functions P and Q

Stack Management

  • Stack์€ automatic process-state data๋ฅผ ์œ ์ง€ํ•˜์—ฌ program execution์„ ์ง€์›

    Figure 2.6. Stack management

  • Stack frame์˜ ์ •๋ณด
    • return address
    • local variables
    • frame pointer
  • (Disassembly using Intel Notation)

  • foo() ํ•จ์ˆ˜ prologue
void foo(int i, char *name) {
    char LocalChar[24];
    int LocalInt;
    push ebp        # Save the frame pointer.
    mov ebp, esp    # Frame pointer for subroutine is set to the
                    # current stack pointer.
    sub esp, 28     # Allocates space for local variables.
    /* ... */
  • foo() ํ•จ์ˆ˜ Epilogue
/* ... */
return;
    mov  esp, ebp   # Restores the stack pointer.
    pop  ebp        # Restores the frame pointer.
    ret             # Pops the return address off the stack
                    # and transfers control to that location.
}
  • foo() ํ˜ธ์ถœ ํ›„ Stack frame
AddressValueDescription (์„ค๋ช…)Length
0x0012FF4C?๋งˆ์ง€๋ง‰ local variableโ€”integer: LocalInt4
0x0012FF50?์ฒซ ๋ฒˆ์งธ local variableโ€”string: LocalChar24
0x0012FF680x12FF80ํ˜ธ์ถœ ํ•จ์ˆ˜ main()์˜ calling frame4
0x0012FF6C0x401040ํ˜ธ์ถœ ํ•จ์ˆ˜ main()์˜ return address4
0x0012FF701์ฒซ ๋ฒˆ์งธ argument: MyInt (int)4
0x0012FF740x40703C๋‘ ๋ฒˆ์งธ argument: pointer toMyString (char *)4

Stack Smashing

  • Stack smashing
    • Buffer overflow๊ฐ€ execution stack์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฎ์–ด์“ธ ๋•Œ ๋ฐœ์ƒ
    • Stack segment์˜ buffer overflow๋Š” ๊ณต๊ฒฉ์ž๊ฐ€ arbitrary code๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ์œ ๋„ ๊ฐ€๋Šฅ
  • Example

Corrupted program stack

alt textalt text

  • Carefully crafted input string
    • j = 0x6A, = 0x10, * = 0x2A, ! = 0x21

Code Injection

  • Return address๊ฐ€ ๋ฎ์–ด์“ฐ์—ฌ์งˆ ๋•Œ
    • ์ œ์–ด ํ๋ฆ„์„ ์ƒˆ ์ฃผ์†Œ๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์€ ์ผ๋ฐ˜์ ์œผ๋กœ trap์„ ์œ ๋ฐœํ•˜๊ณ  corrupted stack์„ ์ดˆ๋ž˜
    • ๊ณต๊ฒฉ์ž๊ฐ€ ์•…์„ฑ code์— ๋Œ€ํ•œ pointer๋ฅผ ํฌํ•จํ•˜๋Š” specially crafted string์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅ
    • ์•…์„ฑ code๋Š” ์ทจ์•ฝํ•œ program์ด ๊ฐ€์ง„ ๊ถŒํ•œ์œผ๋กœ ์‹คํ–‰
  • Malicious arguments
    • ์ทจ์•ฝํ•œ program์— ์˜ํ•ด legitimate input์œผ๋กœ ์ˆ˜์šฉ๋˜์–ด์•ผ ํ•จ
    • ๋‹ค๋ฅธ ์ œ์–ด ๊ฐ€๋Šฅํ•œ ์ž…๋ ฅ๊ณผ ํ•จ๊ป˜ ์ธ์ˆ˜๊ฐ€ ์ทจ์•ฝํ•œ code path์˜ ์‹คํ–‰์„ ์ดˆ๋ž˜ํ•ด์•ผ ํ•จ
    • Shellcode๋กœ ์ œ์–ด๊ฐ€ ์ „๋‹ฌ๋˜๊ธฐ ์ „์— ์ธ์ˆ˜๊ฐ€ program์„ ๋น„์ •์ƒ์ ์œผ๋กœ ์ข…๋ฃŒ์‹œํ‚ค์ง€ ์•Š์•„์•ผ ํ•จ
  • Example
    • ./BufferOverflow < exploit.binalt text
    1. ์ฒซ ๋ฒˆ์งธ mov instruction์€ %eax register์— 0xB ํ• ๋‹น
    2. execve() ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ์œ„ํ•œ ์„ธ ์ธ์ˆ˜๋Š” ํ›„์† ์„ธ instructions์—์„œ ์„ค์ •
    3. int $0x50 instruction์€ execve()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Linux calendar program์„ ์‹คํ–‰

Modified Example

alt text

  • gets() ๋Œ€์‹  fgets() ์‚ฌ์šฉ
  • Buffer overflow๊ฐ€ ์—ฌ์ „ํžˆ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ.
  • Modified Example
    • Exploit Code alt text
    • Corrupted Stack
RowAddressContentDescription
10xbffff9c0
-0xbffff9cf
"123456789012456"Password(16 bytes) ๋ฐ padding์„ ์œ„ํ•œ ์ €์žฅ ๊ณต๊ฐ„
20xbffff9d0
-0xbffff9db
"789012345678"์ถ”๊ฐ€ padding
30xbffff9dc(0xbffff9e0)์ƒˆ๋กœ์šด return address
40xbffff9e0xor %eax,%eaxeax๋ฅผ 0์œผ๋กœ ์„ค์ •
50xbffff9e2mov %eax,0xbffff9ffNull pointer๋กœ pointer array ์ข…๋ฃŒ
60xbffff9e7mov $0xb,%alexecve() function call์„ ์œ„ํ•œ code ์„ค์ •
70xbffff9e9mov $0xbffffa03,%ebxexecve()์˜ ์ฒซ ๋ฒˆ์งธ argument๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ebx ์„ค์ •
80xbffff9eemov $0xbffff9fb,%ecxexecve()์˜ ๋‘ ๋ฒˆ์งธ argument๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ecx ์„ค์ •
90xbffff9f3mov 0xbffff9ff,%edxexecve()์˜ ์„ธ ๋ฒˆ์งธ argument๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก edx ์„ค์ •
100xbffff9f9int $80execve() system call ํ˜ธ์ถœ
110xbffff9fb0xbffff9ff์ƒˆ program์— ์ „๋‹ฌ๋˜๋Š” argument string๋“ค์˜ array
120xbffff9ff"1111"Pointer array๋ฅผ ์ข…๋ฃŒํ•˜๊ธฐ ์œ„ํ•ด 0x00000000์œผ๋กœ ๋ณ€๊ฒฝ ๋ฐ ์„ธ ๋ฒˆ์งธ argument๋กœ ์‚ฌ์šฉ
130xbffffa03
-0xbffffa0f
"/usr/bin/cal\0"์‹คํ–‰ํ•  command

Arc Injection

  • Arc injection technique
    • ์ด๋ฏธ process memory์— ์กด์žฌํ•˜๋Š” code๋กœ ์ œ์–ด๋ฅผ ์ „๋‹ฌ
    • ์ƒˆ๋กœ์šด arc (control-flow transfer) ์‚ฝ์ž…
    • system() ๋˜๋Š” exec()์„ ์‚ฌ์šฉํ•˜์—ฌ commands ์‹คํ–‰ ๊ฐ€๋Šฅ
    • ์—ฌ๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ํ˜ธ์ถœ ๊ฐ€๋Šฅ
  • ๊ณต๊ฒฉ์ž๊ฐ€ code injection๋ณด๋‹ค arc injection์„ ์„ ํ˜ธํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ 
    • ๋Œ€์ƒ ์‹œ์Šคํ…œ์˜ ๋ฉ”๋ชจ๋ฆฌ์— ์ด๋ฏธ code๊ฐ€ ์กด์žฌ
    • Footprint๋ฅผ ํ˜„์ €ํžˆ ์ž‘๊ฒŒ ์œ ์ง€ ๊ฐ€๋Šฅ
    • Memory-based protection schemes๋กœ ๋ณดํ˜ธํ•  ์ˆ˜ ์—†์Œ.
  • Example
#inclue <string.h>

int get_buff(char *user_input, size_t size) {
    char buff[40];
    memcpy(buff, user_input, size);
    return 0;
}

int main(void) {
    /* ... */
    get_buff(tainted_char_array, tainted_size);
    /* ... */
}

Mitigation Strategies

  • ์—ฌ๋Ÿฌ ์ „๋žต์„ ๊ฒฐํ•ฉํ•˜๋Š” defense-in-depth tactic ์ฑ„ํƒ
    • String handling์— ๋Œ€ํ•œ secure technique
      • ํ•˜๋‚˜ ์ด์ƒ์˜ runtime detection
  • String handling
    • Character strings ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ๋‹จ์ผ ์ ‘๊ทผ ๋ฐฉ์‹ ์„ ํƒ ๊ถŒ์žฅ
    • Character strings ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ๋‹จ์ผ ์ ‘๊ทผ ๋ฐฉ์‹ ์„ ํƒ ๊ถŒ์žฅ
    • String-handling functions๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๋ฐฉ์‹์— ๋”ฐ๋ผ ๋ถ„๋ฅ˜
      • Caller allocates, caller frees (C99, OpenBSD, C11 Annex K)
      • Callee allocates, caller frees (ISO/IEC TR 24731-2)
      • Callee allocates, callee frees (C++ std::basic_string)

C11 Annex K Bounds-Checking

  • ์ฒซ ๋ฒˆ์งธ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ model (caller allocatesํ•˜๊ณ  caller freeํ•˜๋Š” ๋ฐฉ๋ฒ•)
  • C11 Annex K
    • ๋Œ€์•ˆ์ ์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•จ์ˆ˜ ์ œ๊ณต
    • output buffers๊ฐ€ ์˜๋„ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋‹ด์„ ๋งŒํผ ์ถฉ๋ถ„ํžˆ ํฐ์ง€ ํ™•์ธ
    • ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์œผ๋ฉด failure indicator ๋ฐ˜ํ™˜
    • ๋ชจ๋“  string results๋Š” null-terminated
  • ์˜ˆ: strcpy_s(), strcat_s(), strncpy_s(), strncat_s(), ... ์ •์˜
  • ISO/IEC TR 24731-1๋กœ ๊ฒŒ์‹œ โ†’ ๋‚˜์ค‘์— C11์— optional extensions ์„ธํŠธ๋กœ ํ†ตํ•ฉ
  • __STDC_LIB_EXT1__ macro ์ •์˜ ํ•„์š”
  • C11 Annex K๋Š” normative์ด์ง€๋งŒ optimal annex
  • gcc์—์„œ๋Š” implemented๋˜์ง€ ์•Š์Œ.
  • ์œ ํšจํ•˜์ง€ ์•Š์€ ํฌ๊ธฐ๊ฐ€ ํ•จ์ˆ˜์— ์ „๋‹ฌ๋˜๋ฉด buffer overflow problems๋ฅผ ๊ฒช์„ ์ˆ˜ ์žˆ์Œ.

C11 Annex K

  • Example: gets_s()
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>

void get_y_or_n(void) {
    char response[8];
    size_t len = sizeof(response);
    puts("Continue? [y] n: ");
    gets_s(response, len);
    if (response[0] == n)
        exit(0);
}

Runtime-constraint-handler function

  • ์˜ค๋ฅ˜ ๊ฐ์ง€ ์‹œ ํŠน์ˆ˜ runtime-constraint-handler function ํ˜ธ์ถœ
    • ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ ๋ฐ/๋˜๋Š” program ์ค‘๋‹จ ๊ฐ€๋Šฅ
  • set_constraint_handler_s() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํ˜ธ์ถœ๋˜๋Š” handler function ์ œ์–ด ๊ฐ€๋Šฅ
  • "ERR03-C. Use runtime-constraint handlers when calling functions defined by TR24731-1"
    • Implementation-defined behavior๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด runtime-constraint handler ์„ค์น˜ ๊ถŒ์žฅ

C11 Annex K

  • Example 2.6. gets_s() (Improved)
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>

void get_y_or_n(void) {
    char response[8];
    size_t len = sizeof(response);

    puts("Continue? [y] n: ");
    if ((gets_s(response, len) == NULL) || (response[0] == 'n')) {
        exit(0);
    }
}

int main(void) {
    constraint_handler_t oconstraint = set_constraint_handler_s(ignore_handler_s);
    get_y_or_n();
}

Runtime-constraint-handler function

  • ignore_handler_s() ํ•จ์ˆ˜๋กœ ์„ค์ •๋œ ๊ฒฝ์šฐ
    • ๋ชจ๋“  ์œ„๋ฐ˜์€ caller์—๊ฒŒ ๋ฐ˜ํ™˜
  • ๋Œ€๋ถ€๋ถ„์˜ bounds-checking functions๋Š” nonzero errno_t ๋ฐ˜ํ™˜
    • gets_s() ํ•จ์ˆ˜๋Š” null pointer ๋ฐ˜ํ™˜ (compatibility๋ฅผ ์œ„ํ•ด)
  • "ERR00-C. ์ผ๊ด€๋˜๊ณ  ํฌ๊ด„์ ์ธ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ์ •์ฑ…์„ ์ฑ„ํƒํ•˜๊ณ  ์‹œํ–‰"
  • Original constraint handler
    • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•จ์ˆ˜๊ฐ€ constraint handler๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒฝ์šฐ, ํ•จ์ˆ˜๋Š” ๋ฐ˜ํ™˜ ๋˜๋Š” ์ข…๋ฃŒ ์ „์— original constraint handler๋ฅผ ๋ณต์›ํ•ด์ค˜์•ผ ํ•จ

Dynamic Allocation Functions

  • ๋‘ ๋ฒˆ์งธ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ model (callee allocates, caller frees)
    • ISO/IEC TR 24731-2
    • ISO/IEC TR 24731-2
  • ์ด๋Ÿฌํ•œ ํ•จ์ˆ˜ ์‚ฌ์šฉ์€ ๋‚˜์ค‘์— buffers๋ฅผ freeํ•˜๊ธฐ ์œ„ํ•œ ์ถ”๊ฐ€ ํ˜ธ์ถœ์ด ํ•„์š”
  • ISO/IEC TR 24731-2์— ์„ค๋ช…๋œ ํ•จ์ˆ˜๋Š” ๋ฒ„ํผ๊ฐ€ ํ•ญ์ƒ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๋„๋ก ์ž๋™ ํฌ๊ธฐ ์กฐ์ • โ†’ ๋” ํฐ ๋ณด์žฅ ์ œ๊ณต
    • Denial-of-service attacks๋ฅผ ๊ฒช์„ ์ˆ˜ ์žˆ์Œ.
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>

void get_y_or_n(void) {
    char response[8];
    size_t len = sizeof(response);

    puts("Continue? [y] n: ");
    if ((getline(&response, &len, stdin) < 0) || (len && response[0] == 'n')) {
        free(response);
        exit(0);
    }
    free(response);
}
  • Example: getline()
    • Buffer๋ฅผ dynamically allocate
    • Buffer๋ฅผ freeํ•ด์•ผ ํ•จ

String stream

  • fmemopen(), open_memstream()
  • ํ•จ์ˆ˜ prototypes
FILE *fmemopen(
    void * restrict buf, size_t size, const char * restrict mode
);
FILE *open_memstream(
    char ** restrict bufp, size_t * restrict sizep
);
)
  • open_memstream()์— ์˜ํ•ด ์—ด๋ฆฐ stream์˜ ๊ฒฝ์šฐ
    • write operations๋ฅผ ์ˆ˜์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์ด dynamically ์ฆ๊ฐ€
    • Caller๋Š” ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ freeํ•ด์•ผ ํ•จ (line 16)
  • Dynamic allocation์€ safety-critical systems์—์„œ ์ข…์ข… ํ—ˆ์šฉ๋˜์ง€ ์•Š์Œ.
  • Example
#include <stdio.h>

int main(void) {
    char *buf;
    size_t size;
    FILE *stream;

    stream = open_memstream(&buf, &size);
    if (stream == NULL) { /* handle error */ };
    fprintf(stream, "hello");
    fflusth(stream);

    printf("buf = '%s', size = %zu\n", buf, size);
    fprintf(stream, ", world");
    fclose(stream);
    printf("buf = '%s', size = %zu\n", buf, size);
    free(buf);
    return 0;
}

C++ std::basic_string

  • C++ extraction operator operator>>
    • Field width๋ฅผ ์„ค์ •ํ•˜์—ฌ buffer overflow vulnerability ์ œ๊ฑฐ
    • Truncation ๋ฌธ์ œ
    • ์˜ˆ์ƒ์น˜ ๋ชปํ•œ program behavior๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ.
  • ISO/IEC 14882์— ์ •์˜๋œ ํ‘œ์ค€ std::string class
    • type char์— ๋Œ€ํ•œ std::basic_string template์˜ specialization
  • basic_string class
    • Strings์— ๋Œ€ํ•œ dynamic approach ์‚ฌ์šฉ
    • "callee allocates, callee frees" ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ์ „๋žต โ†’ ๊ฐ€์žฅ ์•ˆ์ „ํ•œ ์ ‘๊ทผ ๋ฐฉ์‹
  • Example
string str1 = โ€œhello, โ€œ;
string str2 = โ€œworldโ€;
string str3 = str1 + str2;

Example: std::cin

#include <iostream>
#include <string>
using namepsace std;

int main(void) {
    string str;

    cin >> str;
    cout << "str 1: " << str << '\n';
}

std::out_of_range

  • Subscript member std::string::operator[]
    • Exception์„ ๋˜์ง€์ง€ ์•Š์Œ.
    • Example
      string bs(โ€œ01234567โ€);
      size_t i = 10;
      bs[i] = โ€˜\0โ€™;
      
  • at() method
    • operator[]์™€ ์œ ์‚ฌํ•˜์ง€๋งŒ, pos >= size()์ด๋ฉด out_of_range exception ๋ฐœ์ƒ
  • Example
string bs("01234567");
try {
    size_t i = f();
    bs.at(i) = '\0';
}
catch (out_of_range& oor) {
    cerr << "Out of Range error: " << oor.what() << '\n';
}

c_str()

  • string์„ null-terminated byte string์œผ๋กœ ๋ณ€ํ™˜
    • c_str() method
    • Example
      string str(โ€œabcdโ€);
      cout << strlen(str.c_str());
      

String-Handling Functions

  • gets()
    • ์ ˆ๋Œ€ gets() ํ•จ์ˆ˜ ํ˜ธ์ถœ ๊ธˆ์ง€
    • ์ข…๋ฃŒ newline ๋˜๋Š” EOF๊ฐ€ ๋ฐœ๊ฒฌ๋  ๋•Œ๊นŒ์ง€ ํ‘œ์ค€ ์ž…๋ ฅ์—์„œ buffer๋กœ ํ•œ ์ค„์„ ์ฝ์Œ.
    • C11์—์„œ ์ œ๊ฑฐ
    • C11์—์„œ ์ œ๊ฑฐ
  • ๋Œ€์ฒด ํ•จ์ˆ˜
    • C99
      • fgets()
      • getchar()

fgets()

char buf[LINE_MAX];
int ch;
char *p;

if (fgets(buf, sizeof(buf), stdin)) {
    /* fgets succeeds, scan for newline character */
    p = strchr(buf, '\n');
    if (p) {
        *p = '\0';
    }
    else {
        /* newline not found, flush stdin to end of line */
        while (((ch = getchar()) != '\n')
            && !feof(stdin)
            && !ferror(stdin)
        );
    }
}
else {
    /* fgets failed, handle error */
}

fgets() and getchar()

  • fgets()
    • Newline character๋ฅผ ์œ ์ง€
    • Truncation: ์‚ฌ์šฉ์ž ์ž…๋ ฅ์ด ์ž˜๋ฆด ์ˆ˜ ์žˆ์Œ.
    • ์ž…๋ ฅํ•  character ์ˆ˜๊ฐ€ destination buffer์˜ ๊ธธ์ด๋ณด๋‹ค ํฌ๋ฉด buffer overflow ๋ฐœ์ƒ ๊ฐ€๋Šฅ
  • getchar()
    • stdin์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ์ž…๋ ฅ stream์—์„œ ๋‹ค์Œ character ๋ฐ˜ํ™˜
    • Stream์ด EOF์— ์žˆ๊ฑฐ๋‚˜ read error ๋ฐœ์ƒ ์‹œ EOF ๋ฐ˜ํ™˜

getchar()

  • Example 2.10. getchar()
char buf[BUFSIZ];
int ch;
int index = 0;
int chars_read = 0;

while (((ch = getchar()) != '\n')
    && !feof(stdin)
    && !ferror(stdin)) 
{
    if (index < BUFSIZ - 1) {
        buf[index++] = (unsigned char)ch;
    }
    chars_read++;
} /* end while */

buf[index] = '\0'; /* null-terminate */

if (feof(stdin)) {
    /* handle EOF */
}
if (ferror(stdin)) {
    /* handle error */
}
if (chars_read > index) {
    /* handle truncation */
}

C11 Annext K gets_s()

  • C11 gets_s() ํ•จ์ˆ˜
    • gets()์™€ ํ˜ธํ™˜
    • ๋” ์•ˆ์ „ํ•œ version
    • stdin์—์„œ ์ฝ์Œ.
    • Newline character๋ฅผ ์œ ์ง€ํ•˜์ง€ ์•Š์Œ.
  • ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ
    • ์ž…๋ ฅ ์ˆ˜ํ–‰ ์•ˆ ํ•จ
    • Char array ์ˆ˜์ • ์•ˆ ํ•จ
  • ๊ทธ ์™ธ์˜ ๊ฒฝ์šฐ
    • ์ง€์ •๋œ char ์ˆ˜๋ณด๋‹ค ์ตœ๋Œ€ ํ•˜๋‚˜ ์ ๊ฒŒ ์ฝ์Œ.
    • ๋งˆ์ง€๋ง‰ char ๋‹ค์Œ์— null char ์ž‘์„ฑ
  • gets_s() ํ•จ์ˆ˜
    • ์™„์ „ํ•œ ํ•œ ์ค„์„ ์ฝ์„ ๋•Œ๋งŒ ์„ฑ๊ณต
    • ์™„์ „ํ•œ ์ค„์„ ์ฝ์„ ์ˆ˜ ์—†์œผ๋ฉด NULL ๋ฐ˜ํ™˜, buffer๋ฅผ null string์œผ๋กœ ์„ค์ •, ์ž…๋ ฅ stream์„ ๋‹ค์Œ newline char๊นŒ์ง€ ์ •๋ฆฌ

Dynamic Allocation Functions

  • getline() ํ•จ์ˆ˜
    • ISO/IEC TR 24731-2์— ์„ค๋ช…
    • ISO/IEC TR 24731-2์— ์„ค๋ช…
    • fgets()์™€ ์œ ์‚ฌํ•˜์ง€๋งŒ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ ํฌํ•จ
      • Destination buffer๋ฅผ dynamically resize
      • ์ฝ์€ character ์ˆ˜ ๋ฐ˜ํ™˜
    • Destination buffer๊ฐ€ malloc()์œผ๋กœ ํ• ๋‹น๋œ ๊ฒฝ์šฐ์—๋งŒ ์ž‘๋™
    • ์‚ฌ์šฉ์ž๋Š” ๋‚˜์ค‘์— buffer๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ free()ํ•ด์•ผ ํ•จ

getline()

int ch;
char *p;
size_t buffer_size = 10;
char *buffer = malloc(buffer_size);
ssize_t size;

if ((size = getline(&buffer, &buffer_size, stdin)) == -1) {
    /* handle error */
} else {
    p = strchr(buffer, '\n');
    if (p) {
        *p = '\0';
    } else {
        /* newline not found, flush stdin to end of line */
        while (((ch = getchar()) != '\n')
            && !feof(stdin)
            && !ferror(stdin)
        );
    }
}

/* ... work with buffer ... */

free(buffer);

Alternative functions for gets()

Table 2.4. Alternative Functions for gets()

Standard/TRRetains Newline CharacterDynamically Allocates Memory
fgets()C99YesNo
getline()TR 24731-2YesYes
gets_s()C11NoNo

strcpy() and strcat()

  • C99
    • C ํ‘œ์ค€ strncpy() ํ•จ์ˆ˜๊ฐ€ ์ข…์ข… ๋Œ€์•ˆ์œผ๋กœ ๊ถŒ์žฅ
      • strncpy()๋Š” null-termination errors ๋ฐ ๊ธฐํƒ€ ๋ฌธ์ œ์— ์ทจ์•ฝ
  • OpenBSD
    • strlcpy() ๋ฐ strlcat()
    • Size parameter๋กœ destination string์˜ ์ „์ฒด ํฌ๊ธฐ ์‚ฌ์šฉ
    • Destination string์ด null-terminated์ž„์„ ๋ณด์žฅ
    • ์ƒ์„ฑํ•˜๋ ค๊ณ  ์‹œ๋„ํ•œ string์˜ ์ด ๊ธธ์ด ๋ฐ˜ํ™˜

C11 Annex K Bounds-Checking interfaces

  • strcpy_s() ๋ฐ strcat_s()
    • ์„ฑ๊ณต ์‹œ 0 ๋ฐ˜ํ™˜
    • ๊ทธ ์™ธ์˜ ๊ฒฝ์šฐ nonzero value ๋ฐ˜ํ™˜
    • ๋‹ค์–‘ํ•œ runtime constraints ๊ฐ•์ œ
      • s1 ๋˜๋Š” s2๊ฐ€ null pointer์ธ ๊ฒฝ์šฐ
      • Destination buffer์˜ ํฌ๊ธฐ๊ฐ€ 0, RSIZE_MAX๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜, source string์˜ ๊ธธ์ด๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์€ ๊ฒฝ์šฐ

String copy functions

Table 2.5. String Copy Functions

Standard/TRBuffer Overflow ProtectionGuarantees Null TerminationMay Truncate StringAllocates Dynamic Memory
strcpy()C99NoNoNoNo
strncpy()C99YesNoYesNo
strlcpy()OpenBSDYesYesYesNo
strdup()TR 24731-2YesYesNoYes
strcpy_s()C11YesYesNoNo

Table 2.6. String Concatenation Functions

Standard/TRBuffer Overflow ProtectionGuarantees Null TerminationMay Truncate StringAllocates Dynamic Memory
strcat()C99NoNoNoNo
strncat()C99YesNoYesNo
strlcat()OpenBSDYesYesYesNo
strcat_s()C11YesYesNoNo

strncpy() and strncat()

  • size_t parameter n ์ถ”๊ฐ€
  • strncpy()
    • Destination string์˜ null-terminate๋ฅผ ๋ณด์žฅํ•˜์ง€ ์•Š์Œ.
    • String termination errors์— ์ทจ์•ฝ
  • strncat(s1, s2, n)
    • S1 buffer์˜ ์ตœ์†Œ ํฌ๊ธฐ๋Š” strlen(s1) + n + 1์ด์–ด์•ผ ํ•จ
    • S1 buffer์˜ ์ตœ์†Œ ํฌ๊ธฐ๋Š” strlen(s1) + n + 1์ด์–ด์•ผ ํ•จ
    • strncat()์˜ ๋งˆ์ง€๋ง‰ ์ธ์ˆ˜๋Š” ์ด buffer length๊ฐ€ ์•„๋‹ˆ์–ด์•ผ ํ•จ
    • strncat(dest, source, dest_size โ€“ strlen(dest) โ€“ 1)
  • ๊ฒฐ๊ณผ string์ด ์ž˜๋ฆด ๋•Œ status code ์—†์Œ.

strncpy_s()

errno_t strncpy_s (
    char * restrict s1,
    rsize_t s1max,
    const char * restrict s2,
    rsize_t n
);
  • Runtime-constraint violation ๋ฐœ์ƒ ์‹œ destination array๋Š” empty string์œผ๋กœ ์„ค์ •
  • Null terminator ์ถ”๊ฐ€๋จ
  • ์„ฑ๊ณต์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด 0 ๋ฐ˜ํ™˜
  • ์ž…๋ ฅ ์ธ์ˆ˜๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š์œผ๋ฉด nonzero value ๋ฐ˜ํ™˜
  • No truncation!
  • Example
char src1[100] = "hello";
char src2[7] = { 'g', 'o', 'o', 'd', 'b', 'y', 'e' };
char dst1[6], dst2[5], dst3[5];
errno t r1, r2, r3;
  • r1 = strncpy_s(dst1, sizeof(dst1), src1, sizeof(src1));
    • r1 = 0, dst1 = โ€œhello\0โ€
  • r2 = strncpy_s(dst2, sizeof(dst2), src2, 4);
    • r2 = 0, dst2 = โ€œgood\0โ€
  • r3 = strncpy_s(dst3, sizeof(dst3), src1, sizeof(src1));
    • r3 = nonzero value, dst3[0] = โ€˜\0โ€™

Summary of strcpy() and strcat()

Table 2.7. Truncating Copy Functions

Standard/TRBuffer Overflow ProtectionGuarantees Null TerminationMay Truncate StringAllocates Dynamic MemoryChecks Runtime Constraints
strncpy()C99YesNoYesNoNo
strlcpy()OpenBSDYesYesYesNoNo
strndup()TR 24731-2YesYesYesYesNo
strncpy_s()C11YesYesNoNoYes
Standard/TRBuffer Overflow ProtectionGuarantees Null TerminationMay Truncate StringAllocates Dynamic MemoryChecks Runtime Constraints
strncat()C99YesNoYesNoNo
strlcat()OpenBSDYesYesYesNoNo
strncat_s()C11YesYesNoNoYes

Runtime Protection Strategies

  • Programmer๊ฐ€ ๋ถˆ์™„์ „ํ•œ detection and recovery strategy๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋‹ค๊ณ  ์ž˜๋ชป๋œ ํ™•์‹ ์„ ๊ฐ€์งˆ ์œ„ํ—˜
  • Buffer overflow mitigation strategies
    • Mitigation mechanism์„ ์ œ๊ณตํ•˜๋Š” ์‹œ์Šคํ…œ์˜ component์— ๋”ฐ๋ผ ๋ถ„๋ฅ˜ ๊ฐ€๋Šฅ
      • ๊ฐœ๋ฐœ์ž (์ž…๋ ฅ validation์„ ํ†ตํ•ด)
      • Compiler ๋ฐ ๊ด€๋ จ runtime system
      • Operating system

Input validation

  • Buffer overflows๋ฅผ ์™„ํ™”ํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•
void f(const char *arg) {
    char buff[100];
    if (strlen(arg) >= sizeof(buff)) {
        abort();
    }
    strncpy(buff, arg);
    /* ... */
}
  • Trust boundary๋ฅผ ๋„˜์–ด program interface์— ๋„๋‹ฌํ•˜๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋Š” validation ํ•„์š”
    • ์˜ˆ: argv ๋ฐ argc, environment variables, sockets/files/devices์—์„œ ์ฝ์€ ๋ฐ์ดํ„ฐ

Object Size Checking

  • GCC
    • Pointer๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด์˜ ํฌ๊ธฐ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ์ œํ•œ๋œ ๊ธฐ๋Šฅ ์ œ๊ณต
    • GCC 4.1: size_t __builtin_object_size(void *ptr, int type)
      • ptr: ๊ฐ์ฒด์˜ ์‹œ์ž‘ ๋ถ€๋ถ„์„ ๊ฐ€๋ฆฌ์ผœ์•ผ ํ•จ
      • type: 0โˆผ30 \sim 30โˆผ3
        • 000 ๋˜๋Š” 222: ์ฐธ์กฐ๋œ ๊ฐ์ฒด๋Š” ๊ฐ€๋ฆฌํ‚ค๋Š” byte๋ฅผ ํฌํ•จํ•˜๋Š” ๊ฐ€์žฅ ํฐ ๊ฐ์ฒด
        • ๊ทธ ์™ธ: ๊ฐ์ฒด๋Š” ๊ฐ€์žฅ ์ž‘์€ ๊ฐ์ฒด
      • Byte ์ˆ˜ ๋ฐ˜ํ™˜
  • Example
struct V { char buf1[10]; int b; char buf2[10]; } var;
void *ptr = &var.b;
  • __builtin_object_size(ptr, 0)
  • __builtin_object_size(ptr, 1)
  • __builtin_object_size() ํ•จ์ˆ˜
    • _FORTIFY_SOURCE๊ฐ€ ์ •์˜๋  ๋•Œ ์‚ฌ์šฉ alt text
Value of type ArgumentOperates onIf Unknown, Returns
0Maximum object(size_t) -1
1Minimum object(size_t) -1
2Maximum object(size_t) 0
3Minimum object(size_t) 0
  • ํฌ๊ธฐ ๊ฒฐ์ • ๋ถˆ๊ฐ€
  • src_end = โ€˜\0โ€™๋ฅผ ํฌํ•จํ•œ byte ์ˆ˜
  • Example
char dest[BUFFER_SIZE];
char *src = /* valid pointer */;
size_t src_end = __builtin_object_size(src, 0);
if (src_end == (size_t) -1 && /* don't know if src is too big */
    strlen(src) < BUFFER_SIZE) {
    strcpy(dest, src);
} else if (src_end <= BUFFER_SIZE) {
    strcpy(dest, src);
} else {
    /* src would overflow dest */
}

Visual Studio Compiler-Generated Runtime Checks

  • Visual C++ 2010
    • /RTCs compiler flag
      • Arrays์™€ ๊ฐ™์€ local variables์˜ overflows
      • ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ variables ์‚ฌ์šฉ
      • Stack pointer corruption
      • ๋“ฑ์˜ runtime checks ํ™œ์„ฑํ™”
    • /GS
    • Pragma๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ flags ์กฐ์ • ๊ฐ€๋Šฅ

Stack-Smashing Protector (ProPolice)

  • GCC 4.1

    • Stack-Smashing Protector (SSP) ๊ธฐ๋Šฅ ๋„์ž…
    • Buffers ๋’ค์— pointers๋ฅผ ๋ฐฐ์น˜ํ•˜๋„๋ก local variables ์žฌ์ •๋ ฌ
    • ํ•จ์ˆ˜ ์ธ์ˆ˜์˜ pointers๋ฅผ local variable buffers ์•ž ์˜์—ญ์œผ๋กœ ๋ณต์‚ฌ
  • SSP

    • Canary๋ฅผ ๋„์ž…ํ•˜์—ฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ ๊ฐ์ง€
  • SSP stack structure

     Stack     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ–ฒ         
    pointerโ”€โ”€โ–บ โ”‚          ...           โ”‚ โ”‚         
               โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค           
               โ”‚  local variables (C)   โ”‚           
               โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค           
               โ”‚       arrays (B)       โ”‚ โ”‚         
               โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚         
     Frame     โ”‚         guard         โ”€โ”ผโ”€โ”ผโ”€โ”€โ”€ stack
    pointerโ”€โ”€โ–บ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚    guard
               โ”‚ previous frame pointer โ”‚ โ”‚         
               โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚         
               โ”‚     return address     โ”‚ โ”‚         
               โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค           
               โ”‚     arguments (A)      โ”‚           
               โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค           
               โ”‚          ...           โ”‚           
               โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜           
    
    • ์œ„์น˜ (A): array ๋˜๋Š” pointer variables ์—†์Œ.
    • ์œ„์น˜ (B): arrays๋ฅผ ํฌํ•จํ•˜๋Š” arrays ๋˜๋Š” structures
    • ์œ„์น˜ (B) ๋’ค์— guard ๋ฐฐ์น˜
    • ์œ„์น˜ (C): arrays ์—†์Œ.
    • Stack guard

Operating System Strategies

  • Address space layout randomization (ASLR)
    • Arbitrary code execution ๋ฐฉ์ง€
    • Linux, Windows Vista ์ดํ›„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
    • ๊ฐœ๋ฐœ์ž๋Š” /DYNAMICBASE linker option์„ ์‚ฌ์šฉํ•˜์—ฌ ASLR ์ง€์›์— opt in ํ•ด์•ผ ํ•จ
  • Nonexecutable stacks
    • ๊ณต๊ฒฉ์ž๊ฐ€ stack์—์„œ executable code๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Œ.
  • W ^ X (W xor X)
    • Process address space์˜ ์–ด๋–ค ๋ถ€๋ถ„๋„ writable์ด๋ฉด์„œ executable์ด์ง€ ์•Š์Œ.
    • ์—ฌ๋Ÿฌ CPU์—์„œ No eXecute (NX) bit ์‚ฌ์šฉ์œผ๋กœ ์ง€์›
  • Data Execution Prevention (DEP)
    • Microsoft Visual Studio์šฉ W ^ X ์ •์ฑ…์˜ implementation
    • NX technology๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ data segments์— ์ €์žฅ๋œ instructions์˜ ์‹คํ–‰ ๋ฐฉ์ง€
    • /NXCOMPACT๋กœ code๋ฅผ linkํ•˜๊ฑฐ๋‚˜ SetProcessDEPPolicy() ํ˜ธ์ถœ๋กœ DEP ํ™œ์„ฑํ™”
  • PaX
    • Linux kernel security patch
    • Nonexecutable stack, ASLR ๋“ฑ
    • Denial of Service (DoS) ์œ ๋ฐœ ๊ฐ€๋Šฅ
    • ํ˜„์žฌ grsecurity project์˜ ์ผ๋ถ€
  • StackGap
    • Stack memory ํ• ๋‹น ์‹œ randomly sized gap ๋„์ž…

Future Direction

Figure 2.19. A possible Safe-Secure C/C++(SSCC) implementation alt text

  • ๊ฐ€๋Šฅํ•œ Safe-Secure C/C++ (SSCC) implementation

Notable Vulnerabilities

  • Remote Login (rlogin)
    • Buffer overflow: TERM environment variable์„ local stack variable๋กœ ์„ ์–ธ๋œ 1,024 characters array๋กœ ๋ณต์‚ฌ
  • Kerberos
    • Network authentication protocol
    • http://web.mit.edu/Kerberos/
    • krb_rd_req() ํ•จ์ˆ˜์—์„œ buffer overflow
      • ๊ณต๊ฒฉ์ž๊ฐ€ ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด root access ์–ป์„ ์ˆ˜ ์žˆ์Œ.

Summary

  • C ๋ฐ C++์—์„œ buffer overflows๊ฐ€ ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ์ด์œ 
    1. Strings๋ฅผ null-terminated arrays of characters๋กœ ์ •์˜
    2. ์•”๋ฌต์ ์ธ bounds checking์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Œ.
    3. Bounds checking์„ ๊ฐ•์ œํ•˜์ง€ ์•Š๋Š” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜ธ์ถœ ์ œ๊ณต
  • ์ผ๋ฐ˜์ ์ธ ์™„ํ™” ์ „๋žต์€ ์ƒˆ๋กœ์šด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฑ„ํƒ
  • ์‹ค์šฉ์ ์ธ ์™„ํ™” ์ „๋žต์€ static analysis ๋ฐ dynamic analysis ํฌํ•จ
  • Runtime solutions
    • Bounds checkers, canaries, safe libraries
  • Defense-in-depth strategy

์‹œํ—˜ ์ •๋ณด

์žฅ์†Œ: 501ํ˜ธ

์ตœ๊ทผ ์ˆ˜์ •: 26. 6. 12. ์˜คํ›„ 3:28
Contributors: kmbzn, Claude Sonnet 4.6

BUILT WITH

CloudflareNode.jsGitHubGitVue.jsJavaScriptVSCodenpm

All trademarks and logos are property of their respective owners.
ยฉ 2026 kmbzn ยท MIT License