Correct with respect to what
The phrase "prove a program correct" hides its most important word. Correct with respect to a specification, and the specification is a separate artefact that someone has to write.
That is not a technicality. It relocates the problem rather than removing it. A verified program is one shown to satisfy its specification, and if the specification says the wrong thing, the proof is a proof of the wrong property. Verification eliminates implementation bugs and cannot eliminate specification bugs.
What it buys in exchange is a change of quantifier. Testing establishes behaviour on the inputs tried, which is a statement about some inputs. A proof establishes behaviour for all inputs satisfying the precondition, including the ones nobody thought of.
That is the entire value proposition, and the lesson What Undecidability Costs Real Tools explains why it cannot be had automatically: Rice's theorem closes every non-trivial semantic question, so a proof needs either a restricted language or human guidance. This cursus is about the machinery that guidance operates.

