If the input strings are always as you show them, i.e. the first "." to replace comes after an underscore followed by a number you can use a property function and use C#'s static Regex.Replace method:
<Target Name="Repl">
<PropertyGroup>
<Prop>ABCD_1.2.3.112211</Prop>
</PropertyGroup>
<Message Text="$([System.Text.RegularExpressions.Regex]::Replace( $(Prop), '_(\d*)\.', '_$1_' ) )" />
</Target>
If the use case is more complicated there are other options:
- use another regular expression in the code above
- MSBuild Community tasks has a Regex task which supports the Count parameter of Regex.Replace, so you can use a simple regex to replace "." with "_" and set count to one to only do the first instance
- use an inline task in which you write your preferred implementation to replace the first instance from the answers here