Buffer overflow attacks can exploit vulnerabilities in C library functions like strcpy() that do not perform bounds checking on buffers. By passing in a string longer than the buffer size, an attacker can overwrite adjacent memory, such as the return address on the stack, allowing them to execute arbitrary code. Defenses include using type-safe languages, marking the stack as non-executable, static source code analysis, and runtime checks.