A compromised site is not fixed by deleting the obvious bad file. Whoever got in almost always left a second way back, and cleaning the visible damage while leaving that in place means the site is reinfected within days: often within hours.
The order below is what separates a recovery from a cycle.
First: take it offline and take a copy
Put the site into maintenance mode or return a holding page. A compromised site is usually serving something to visitors, spam pages, redirects, or malware, and every hour it stays up damages your reputation with search engines and with people.
Then take a full copy of the site as it is now, infected. That sounds wrong and it is important: it is evidence of how they got in, and if a cleanup deletes something legitimate you need a way back.
Label it clearly as infected and keep it away from anything automatic.
Change credentials, in the right order
Change the cPanel password first. It is the one that controls everything else.
Then database passwords (updating wp-config.php to match), FTP accounts, and every WordPress administrator. Delete FTP accounts you do not recognise rather than changing their password.
Then force all WordPress users to log out by changing the security keys in wp-config.php. New values invalidate every existing session, including the attacker's: without this, someone with an active session keeps their access through every password change you make. For those keys, see understanding wp-config.php.
Find how they got in
Skipping this is what produces reinfection.
Four causes account for nearly all of it. An outdated plugin or theme with a known vulnerability, by far the most common. A weak or reused administrator password. Nulled software, where the backdoor is the point rather than an accident. Another site on the same account, since one compromised site can reach its neighbours.
The access log gives you the time. Look at what was requested around when the first modified file changed. The entry point is usually visible as a POST to a plugin path shortly before. There is more on reading it in viewing website statistics.
Replace rather than clean
Do not try to remove malicious code from files by hand. You will miss something.
Delete WordPress core entirely except wp-content and wp-config.php, and install a fresh copy of the same version. Core files should be byte-for-byte identical to the official release, so replacing them is free.
Do the same for plugins and themes: delete and reinstall from the official source. A plugin you cannot reinstall, because it was abandoned, or you never had a licence, must be removed, not repaired.
That leaves uploads, your own customisations, and the database.
Where backdoors hide
The uploads directory should contain media and nothing else. Any .php file there is malicious. There is no legitimate reason for one, and it is the most common hiding place.
Block execution there entirely, which stops the next one from working:
<Files *.php> Require all denied </Files>
Also check: files whose names mimic core files in the wrong directory, anything modified around the compromise date, and .htaccess files in unexpected places, which are frequently used for redirects.
Sort the file list by modification date. The cluster of files changed within the same few minutes is the attack.
The database is part of it
People clean the files and stop, and the site reinfects from the database.
Check the users table for administrator accounts you did not create. That is the most common persistence mechanism, and the account often has an innocuous name.
Check wp_options for injected content in fields that should hold simple values, and look at any scheduled task, since attackers use them to re-create deleted files. How WP-Cron works walks through where those live.
Search post content for injected scripts and links, which are usually hidden with styling rather than removed from view.
Then scan, rather than starting with a scan
Run a security plugin's scan after the manual work, not instead of it.
Scanners find known patterns. They miss code written for your site specifically, and a clean report on a site that was compromised is not proof of anything.
What they are good at is comparing your files to the official versions and listing what differs, which is a useful cross-check on the replacement work above.
Getting the warning removed
If browsers are showing a warning, the site was flagged. Once it is genuinely clean, request a review through the search console for the site, and only once, because a failed review takes longer to get a second look.
Also check whether the server's IP ended up on a mail blocklist, which happens when a compromised site was used to send spam. That affects your legitimate mail until it is resolved.
Then close it properly
Update everything. Remove plugins and themes you are not using rather than deactivating them: deactivated files are still on disk and still reachable.
Add two-factor authentication for administrators, which stops the password-guessing route entirely, and limit login attempts.
Then get backups onto a schedule that stores copies off the server, and keep enough history to reach back past an infection you did not notice for a fortnight, managing WordPress backups goes into the retention that makes recovery possible, and securing WordPress deals with the rest.
When to start over instead
If the compromise is old, if you cannot identify the entry point, or if the site was running nulled software, a clean rebuild is faster and more trustworthy than a cleanup.
Fresh WordPress, plugins from official sources, content imported deliberately, uploads copied after inspection. It feels like more work and it ends, which a cycle of reinfection does not.
For the plugin layer specifically: what it does and what it cannot do. How to Improve WordPress Security with Plugins deals with choosing one.
If browsers are already showing a warning, clearing it has its own order. What to Do If Your Site Is Flagged or Blocked walks through requesting the review properly.