Integrity versus Authenticity
Integrity means the message did not change in transmission. It makes a guarantee that the message sent is the message received but it makes no guarantee about the authenticity of the message. Another mechanism needs to be used to authenticate participants.
So, how do I guarantee integrity of a message?
As for your specific example, an attacker can and will change the hash of the message (by virtue of changing the message). Hash functions are deterministic meaning the same message will always result in the same hash. If the location where we publish a hash is secure and when we run the message through the hash function we get the same value, we can prove that the message did not change during transmission.
All this assumes that the hash algorithm that we use does not have a predictable way to create collisions where two different messages result in the same hash value.
Hash functions are supposed to be open and public and this property is what makes them useful. Some examples would be SHA1 or MD5, etc.
Let's imagine I have a binary file on my web server and I store and publish the MD5 hash of the binary file on another server. If you download the binary and use the same public hash function on it, in this case MD5, you should end up with the same sum that I have published.
If you end up with a different sum then something changed the binary, either on the server or during transmission. This catches both man-in-the-middle attacks as well as normal data corruption (integrity) issues.
So, how do I guarantee authenticity of a message?
You need to take additional measures to guarantee the authenticity of the message. That is to say, the message was sent by the person we think it was.
Going back to our binary example, the most common way to provide authenticity of the binary is to create a signature (or fingerprint) using a well known public key cryptography algorithm.
Basically, I take something that only I have (a private key) and create a signature of the binary's MD5 hash. I could then publish the public side of my key to allow you to verify the signature of the binary produced by my private key. If you trust my private key to be me, then you can trust the binary to be from me, if when you decrypt the signature with my public key you end up with the original and known MD5 hash.
Leave the first remark and get the conversation going!