After the fact:
Restore database from backup (to a temporary database name Natch!), before the event, and compare the two
if you have transaction log backups then restore to POINT IN TIME (using the STOP AT) command to just before the event . That might need server attempts to figure out "When" the event was (unless you already know that)
That will enable you to figure out what data was changed, and exactly when, but not Who.
Before the fact:
We have Create / Update Date and User on everything single row of every single table in our database. (yeah, a couple of exceptions, but literally only one or tw0)
We also have an "Archive / Audit" table for every table, with a trigger that copies PREVIOUS record into Audit Table whenever it is changes (and adds a Timestamp and whether the record was Updated or Deleted)
At the time of the DML change the system has information about who is connected. Depends a bit how your APP works, it might connect with a single login for all users (and have its own method of logging in actual users), in which case the APP will have the User Details and can use that for the Audit data (in addition to, or instead of, the system data)
We also have a DDL trigger that stores any DDL change to the database
All that enables us to sort out "accidental delete / update of 10,000 customer records" without too much difficulty, and also detect / report on "Fraudulent / Malicious behaviour"