What you’re doing will work.  Each time you increment contents, you also increment counter, so contents - counter gives you the original pointer that you can free.
Of course, a better way of doing this would be to use a temporary pointer to increment through the allocated memory so you can use the original to free.
int main() {
    char *contents = read_file("testNote.txt");
    char *tmp = contents;
    while (*tmp != '\0') {
        printf("%c", *tmp);
        ++tmp;
    }
    free(contents);
    return 0;
}
1
solved Is this an acceptable way to deallocate memory in c?