Code-reuse attacks continue to evolve and remain a severe threat to modern software. Recent research has proposed a variety of defenses with differing security, effciency, and practicality characteristics. Whereas the majority of these solutions focus on specific code-reuse attack variants such as return-oriented programming (ROP), other attack variants that reuse whole functions, such as the classic return-into-libc, have received much less attention. Mitigating function-level code reuse is highly challenging because one needs to distinguish a legitimate call to a function from an illegitimate one. In fact, the recent counterfeit object-oriented programming (COOP) attack demonstrated that the majority of code-reuse defenses can be bypassed by reusing dynamically bound functions, i.e., functions that are accessed through global offset tables and virtual function tables, respectively. In this paper, we first significantly improve and simplify the COOP attack. Based on a strong adversarial model, we then present the design and implementation of a comprehensive code-reuse defense which is resilient against reuse of dynamically-bound functions. In particular, we introduce two novel defense techniques: (i) a practical technique to randomize the layout of tables containing code pointers resilient to memory disclosure and (ii) booby trap insertion to mitigate the threat of brute-force attacks iterating over the randomized tables. Booby traps serve the dual purpose of preventing fault-analysis side channels and ensuring that each table has suffciently many possible permutations. Our detailed evaluation demonstrates that our approach is secure, effective, and practical. We prevent realistic, COOP-style attacks against the Chromium web browser and report an average overhead of 1.1% on the SPEC CPU2006 benchmarks.