How to Remove Malware From Your WordPress Site Manually
You’ve probably landed here because Google Search Console just sent you a scary email, or your hosting company suspended your account, or a client called you in a panic saying their site is showing a pharma page when they search their own business name. I’ve been on the receiving end of those calls since 2011. The good news: WordPress malware removal done manually is absolutely possible — you don’t need to spend $300 on a one-click service to do what I’m going to walk you through here.
Let me be straight with you. This process takes 2–4 hours if you’re careful. Rushing it is how you end up re-infected within a week.
Before You Touch Anything — Get Your Bearings
First thing I do when a client sends me access to a compromised site: I don’t delete a single file until I know what I’m dealing with. Log into your hosting cPanel or SSH and take a full backup of the infected site. Yes, even the infected version. You’ll want it as a reference if something goes wrong during cleanup.
Then check your file modification dates. On most Linux servers you can run this via SSH to find recently changed PHP files:

find /public_html -name "*.php" -newer /public_html/wp-config.php -ls
What you’re looking for is anything modified in the last 30–60 days that you didn’t touch. I once found 47 files scattered across wp-content/uploads/2023/03/ — PHP files sitting right alongside legitimate JPEGs. That’s a classic move. The uploads folder is world-writable by default, so it’s the first place attackers hide shells.
Also pull your access logs. Look for POST requests to files that should never receive POST data — image files, cache files, anything in wp-includes that isn’t part of core WordPress. Repeated POSTs to a suspiciously named file in uploads? That’s your backdoor being used.
The Actual Cleanup — What to Replace, What to Scan
Here’s my standard sequence when I’m doing a full clean hacked WordPress site job manually. Follow all the steps from below:
Replace core files first
Download a fresh copy of WordPress from wordpress.org matching your exact version. Delete and replace wp-admin and wp-includes entirely — don’t merge, replace. Then compare your root-level PHP files (index.php, wp-login.php, wp-settings.php, etc.) against the clean copy. Even a single extra line of base64-encoded code at the top of wp-login.php is enough to maintain access.
Themes and plugins
Delete every inactive theme except one. Deactivate and delete every plugin you don’t recognise or haven’t used in six months. For active plugins, re-download them from the official repository and replace the plugin folders completely. Don’t try to diff them line by line — just replace. It’s faster and cleaner.
The wp-content/uploads problem
This one needs manual attention. You can’t just replace uploads — your client’s images are in there. Run a scan specifically for PHP and executable files hiding in that folder:
find /public_html/wp-content/uploads -name "*.php" -o -name "*.phtml" -o -name "*.exe" | xargs ls -la
Delete anything that comes back. There should be zero PHP files in your uploads directory. Zero. If you find them, check that whole date subfolder carefully — attackers often drop several shells nearby.
When you’re removing malware without a plugin like this, you’re working manually through the filesystem, which means you won’t miss things that automated tools skip because of permission errors or unusual encoding. I’ve seen Wordfence miss a base64 payload inside a crafted image comment header. That’s rare, but it happens.
Database — Don’t Ignore It
A lot of tutorials stop at the files. Big mistake. I’d say roughly 40% of the hacked sites I’ve worked on had something sitting in the database — spam links injected into post content, a rogue admin user, or malicious JavaScript stored in widget options or theme customiser data.
Log into phpMyAdmin and run a search across your wp_posts table for eval( and base64_decode. Also search wp_options for any unfamiliar script tags or external domain references. Check wp_users for admin accounts you didn’t create — I’ve found accounts with usernames like support77 or admin2 with administrator roles added silently.
If you find injected links in post content, a targeted SQL replace can clean thousands of rows in seconds rather than editing posts one by one. Just be careful and back up the database before running any UPDATE query.
My Honest Recommendation on WordPress Malware Scanners
People ask me all the time whether to use a WordPress malware scanner plugin or go fully manual. My opinion, formed after cleaning well over a hundred infected sites: use a scanner to confirm your work after the manual cleanup, not as a replacement for it.
Wordfence Free is good for a first scan to get a picture of what’s changed. MalCare does a decent job of detecting obfuscated code. But neither of them will catch everything in a sophisticated attack, and neither of them will fix your file permissions, update your salts, or make sure your database is actually clean. They flag things. You still have to make decisions.
After you’ve done the manual work, run a Wordfence scan. If it comes back clean, regenerate your WordPress secret keys in wp-config.php (use the WordPress.org salt generator), force-reset all user passwords, and update every plugin and theme to current versions. Then — and this is non-negotiable — figure out how they got in. Outdated plugin? Weak password? A nulled theme from a dodgy site? Fix the root cause or you’ll be doing this again in three weeks.
One last thing: block PHP execution in your uploads folder entirely. Add this to an .htaccess file placed inside wp-content/uploads/:
<Files *.php>
deny from all
</Files>
Simple. Effective. Stops a whole category of re-infection before it starts.
If you’ve gone through all of this and the site is still showing wordpress infected files in scans, or Google hasn’t cleared the warning after you submitted a review request, there’s usually something you’ve missed — a secondary backdoor, a cron job, or a compromised wp-config.php that’s pulling in remote code. That’s the point where it makes sense to bring in someone who does this regularly.
Related reading: Your WordPress Site Got Hacked. Do This First. and Japanese Keyword Hack: How to Clean It Up.
When to Call It: The Limits of DIY wordpress malware removal
I’ve talked a lot about doing this yourself, and honestly, most straightforward infections you can handle. But after cleaning sites since 2011, I’ve learned to recognize when a job’s outgrown the DIY approach. If you’re finding reinfection within 24 hours after a full clean, that’s usually a sign there’s a backdoor you missed — maybe something obfuscated with str_rot13 or split across multiple files in wp-includes. At that point, wordpress malware removal stops being a one-person job, especially if your host is on a shared server and the compromise is coming from a neighboring account. Know when to escalate.
I take on WordPress malware removal and site recovery work — if you’d rather hand this off than spend your weekend in phpMyAdmin, you can reach me through swsDreams and I’ll take a look.
