Can you change an AES encrypted message if you control the IV? Let's say that an attacker has the plaintext, the ciphertext and the IV of a specific message. If the attacker can control the ciphertext and the IV, could he forge valid plaintext? Let's say that the message is shorter than the block size, just a few bytes. Could the attacker change the value of the plaintext by changing the IV?
Consider the case where you encrypt the plaintext message attack at noon!! using AES-CBC-256, with the key 7ac01f50605b8fcebd1c82ea6a6aacd6b112e8c9675b84cd77054b2f49668301 and the iv f822ee7b8c0a8ba40daa773b01d9485a:
echo -n 'attack at noon!!' | openssl aes-256-cbc -e -nopad -K 7ac01f50605b8fcebd1c82ea6a6aacd6b112e8c9675b84cd77054b2f49668301 -iv f822ee7b8c0a8ba40daa773b01d9485a | xxd -p

The plaintext message is one block in length (16 bytes), and no padding is used, so this produces one block of cipher text:
8b2f9ede941cb6f3958d809510f579a5

Naturally, if you decrypt the ciphertext above using the same key and iv, you get the original plaintext:
echo -n '8b2f9ede941cb6f3958d809510f579a5' | xxd -p -r |  openssl aes-256-cbc -d -nopad -K 7ac01f50605b8fcebd1c82ea6a6aacd6b112e8c9675b84cd77054b2f49668301 -iv f822ee7b8c0a8ba40daa773b01d9485a

produces:
attack at noon!!

Now, an attacker who knows the original plaintext (attack at noon!!), the ciphertext, and the iv wishes to modify the iv, so that upon decryption, the plaintext produced is attack at dawn!!.
To see how this is done, refer to the diagram below (copied from https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation):

Consider point labeled E.  E is the AES decryption of the first block (in the case, the only block) of ciphertext, using the key.  We don't know the key, so we can't compute E...
Or, can we?  Looking further, the first block of ciphertext is E XOR IV.  The XOR function is unique in that: if A XOR B = C, then you can re-arrange A, B, and C in any order, and the expression still holds true - i.e. A XOR C = B, and B XOR C = A.  So:
Plaintext = E XOR IV
E = Plaintext XOR IV
IV = E XOR Plaintext

So, knowing the original plaintext (attack at noon!!) and the IV (f822ee7b8c0a8ba40daa773b01d9485a), we can compute E.  To do this, we use E = Plaintext XOR IV (above).  First, use the following command to get the hex representation of the underlying ascii-decoded bytes of the plaintext:
echo -n 'attack at noon!!' | xxd -p

This produces:
61747461636b206174206e6f6f6e2121

Now, XOR the plaintext and the IV to get E like so:
python3 -c &quot;print (hex(0x61747461636b206174206e6f6f6e2121 ^ 0xf822ee7b8c0a8ba40daa773b01d9485a))&quot;

This produces:
0x99569a1aef61abc5798a19546eb7697b

So, E is 99569a1aef61abc5798a19546eb7697b.
Now, we can compute what the IV should be, so that when the ciphertext is decrypted by AES-CBC with our specially crafted IV, and E gets XOR'd with this IV, the plaintext produced will be our wanted plaintext 'attack at dawn!!'.  To do this, we use IV = E XOR Plaintext (above).  First, get the hex representation of the underlying ascii-decoded bytes of the wanted plaintext, like we did before:
echo -n 'attack at dawn!!' | xxd -p

this produces:
61747461636b206174206461776e2121

Now, XOR the the wanted plaintext with E to get the IV that we need, like so:
python3 -c &quot;print (hex(0x61747461636b206174206461776e2121 ^ 0x99569a1aef61abc5798a19546eb7697b))&quot;

This produces:
0xf822ee7b8c0a8ba40daa7d3519d9485a

Let's see if it worked.  Let's use the decryption command above to decypt the ciphertext, using iv f822ee7b8c0a8ba40daa7d3519d9485a in place of f822ee7b8c0a8ba40daa773b01d9485a:
echo -n '8b2f9ede941cb6f3958d809510f579a5' | xxd -p -r |  openssl aes-256-cbc -d -nopad -K 7ac01f50605b8fcebd1c82ea6a6aacd6b112e8c9675b84cd77054b2f49668301 -iv f822ee7b8c0a8ba40daa7d3519d9485a

Sure enough, the plaintext produced is:
attack at dawn!!

***Special thanks to Ángel for helping me work through this in the comments under the question.