It calls the sbrk system call:
sbrk -
man pages section 2: System Calls
In some cases it can use mmap(), at least on Linux, if you are asking for really big chunks of memory.
Growing existing allocations works as you suspect. If there is free memory after the allocation it might be able to merge the blocks to satisfy the request.
However, most likely is that new space will need to be allocated, and the existing contents copied to the new allocation, and the old one free()ed.
Have a look at the realloc() man page...