Another trick that's commonly used by malware authors is code transportation. This technique doesn't insert junk code; instead, it rearranges the code inside each subroutine with lots of unconditional jumps, including call and pop or conditional jumps that are always true.
It makes the function graph look very complicated to analyze and wastes the reverse engineer's time. An example of such code can be seen in the following screenshot:
There is a more complicated form of this where malware rearranges the code of each subroutine in the middle of the other subroutines. This form makes it harder for the disassembler to connect each subroutine as it makes it miss the ret instruction at the end of the function and then not consider it as a function.
Some other malware families don't put a ret instruction at the end of the subroutine and substitute it with pop and jmp to hide this subroutine from...