A buffer overflow is used to overwrite another data field which happens to be located in RAM nearby the overflown buffer. Classically, buffer overflows are exploited to overwrite a "return address" slot on the stack, or a function pointer (e.g. in a vtable in object-oriented languages), so make the CPU jump to an attacker chosen location.
When such a jump occurs, it can be to any address that contains executable code, and DLL contents are, by definition, eligible. A DLL is a piece of code which, when used, is made apparent into the address space of the application, as code which can be executed.
This can still be challenging for the attacker:
Many modern operating systems enforce Address Space Layout Randomization, meaning that DLL will be loaded at an address that the attacker cannot necessarily guess in advance. This contrasts with the main executable, which in some OS will still appear at a predictable address (although there are OS which enable ASLR-like processing for the main executable too). Details vary a lot. If the attacker can try his attack thousands of times, then he may hope to "get lucky", especially on 32-bit systems where the ASLR has relatively little room for address randomization.
Depending on the kind of buffer that overflows, the attacker may have trouble overwriting his target address field with arbitrary contents. In particular, when the buffer holds text, in a C-based system, the overflow may stop at the first byte of value 0x00, so the attacker might find it infeasible to overwrite an address field with a value containing such a null byte at an inconvenient place.
Making a target process load a specific, attacker-chosen DLL, already requires a lot of control over the said process. Normally, the attacker has to make do with the "normal" DLL that the application loads as part of its regular processing. This includes "core" DLL from the system (e.g.
kernel32.dll on Windows systems). In classical buffer overflows, the buffer contents themselves were used as code; however, many modern machines and OS distinguish data from executable code, so any attempt to "jump into the stack" will trigger an exception from the kernel (and normally process termination). This is why attackers try to jump into existing DLL code.