Table of contents11
The site looked perfectly fine. The homepage loaded, the blog posts were all there, the owner had just visited it that morning and noticed nothing. But their search traffic had collapsed, and when I searched their domain with a “site:” query, page after page of pharmaceutical spam showed up — hundreds of fake pharmacy pages that only appeared to search engines, never to human visitors. The malware had been living on that site for weeks, invisible to everyone except Google. That case is exactly why I teach site owners to scan WordPress for malware manually.
I’m Mei Chen, and I clean up hacked WordPress sites for a living. That pharmacy-spam case is one of dozens I have worked, and it taught me the lesson behind this entire guide: automated scanners are useful, but the most reliable malware detector is a human who knows where to look. Learning how to scan WordPress malware manually — with your own eyes and a few simple commands — is a skill that will serve you long after any particular scanner becomes outdated.
Here is the fear I want to name honestly: malware on WordPress rarely announces itself. It hides in files with innocent names, injects spam only search engines can see, and reinfects sites within hours when cleanup misses a single backdoor. If you cannot inspect your own site by hand, you are trusting a black box to catch an enemy that specializes in hiding from black boxes.
In this guide I will teach you the manual malware inspection workflow I use on every cleanup job: the ground rules that prevent you from breaking things, how to find recently modified files, how to compare your core files against the official WordPress originals, where to hunt for hidden PHP files, the suspicious code patterns that reveal obfuscated malware, how to check wp-config.php and .htaccess for tampering, how to search your database for injected content, and how to spot rogue admin accounts. This is for site owners comfortable opening a file manager or terminal who want real detective skills. Ready? Let’s get started.
One honest note before we begin: manual inspection finds things scanners miss, but it also requires judgment. I will show you exactly which findings are serious, which are usually harmless, and the one rule that prevents the most common self-inflicted disaster in malware cleanup.

What You Will Learn in This Guide
- The two ground rules of manual inspection: back up first, quarantine instead of deleting
- How to find recently modified files that betray when malware was planted
- How to verify your WordPress core files against the official originals
- Where malware hides: the uploads folder, must-use plugins, and innocent-looking filenames
- The suspicious code patterns — eval, base64_decode, gzinflate — and how to read them in context
- How to check wp-config.php and .htaccess for tampering
- How to search your database for injected scripts and spam
- How to spot rogue admin accounts and malicious scheduled tasks
Ready? Let’s get started.
Ground Rules: Back Up First, Quarantine Instead of Delete
Before you inspect a single file, I need you to internalize two rules, because violating either one causes more damage than most malware. Rule one: take a complete backup of the site in its current state — infected and all — before you change anything. I know that sounds strange. Why back up a hacked site? Because cleanup is surgery, and surgeons do not operate without the ability to undo. If you delete the wrong file and the site white-screens, that backup is your way back.
Rule two is the one I repeat like a mantra on every job: quarantine, do not delete. When you find a suspicious file, move it into a quarantine folder outside your web root — or download it to your computer and then remove it from the server. Do not just hit delete. I have rescued more sites broken by panicked cleanup than by the original hack. Deleting a real plugin file white-screens your site. Deleting visible malware while missing one hidden backdoor means the attacker reinfects you within hours and you have learned nothing. Quarantine keeps every action reversible and preserves evidence of how the attacker got in. These two rules are the foundation of every safe plan to scan WordPress for malware manually.
With those rules in place, you are ready to scan WordPress for malware manually. Access your site’s files through SFTP or your hosting file manager. If you have SSH access, the command-line techniques below will make you dramatically faster. If not, everything here can be done through a file manager — it just takes longer. Let’s start hunting.
Check 1: Find Recently Modified Files
Malware has to be written to disk, and writing to disk changes a file’s modification time. That simple fact makes recently-modified files your first and fastest lead. On every cleanup I start here, because it immediately narrows thousands of files down to a handful of suspects.
Over SSH, run this from your WordPress root to list PHP files changed in the last 14 days:
find . -type f -mtime -14 -name "*.php" | grep -v "wp-content/cache"
Adjust the 14 to cover the window before you first noticed something wrong. The grep -v part excludes cache folders, which change constantly for innocent reasons. What you are looking for: files modified at odd hours, files in locations you do not recognize, and files whose modification dates do not match your own update activity. If you updated a plugin last Tuesday, its files changing last Tuesday is innocent. A file in wp-includes changing at 3 AM on a Sunday when you were asleep is not.
Two honest caveats. First, legitimate updates also change files, so compare against your site’s update history before concluding anything. Second, sophisticated attackers can fake modification timestamps — so treat this as one signal among several, not proof by itself. It is a metal detector, not a conviction. The real confirmation comes from the checks below.
Check 2: Compare Core Files Against the Official Originals
Here is a fact that makes manual WordPress inspection uniquely powerful: WordPress core files should be byte-identical to the official copies on WordPress.org. Not similar — identical. Any difference in wp-admin, wp-includes, or the root files (outside wp-config.php and .htaccess, which are yours) means something changed them, and WordPress updates are the only legitimate reason.
If you have WP-CLI — and if your host offers SSH, you probably do — one command does the entire comparison:
wp core verify-checksums
This compares every core file against the official checksums for your installed version and lists anything altered, missing, or unexpected. A clean result is genuinely reassuring. Any flagged file deserves immediate inspection. Do the same for your plugins:
wp plugin verify-checksums --all
One limitation to know: the plugin check only works for plugins hosted on WordPress.org. Premium plugins will report that no checksums are available — for those, download a fresh copy from the vendor and compare manually. Modified core files are the most serious finding in this entire guide. Core files should never differ from the official version, so a modified core file is malware until proven otherwise.
Bonus Tip: if you do not have WP-CLI, you can do the same comparison by downloading a fresh WordPress zip of your exact version from WordPress.org and comparing folders with a diff tool. It is slower but just as conclusive. Precision matters more than speed here.

Check 3: Hunt for PHP Files Where They Do Not Belong
Now we go looking in the places malware likes to hide. The single most productive hunt in WordPress cleanup is also the simplest: look for PHP files inside wp-content/uploads. The uploads folder should contain images, videos, and documents — never executable PHP. WordPress never places PHP there. A .php file in uploads is a backdoor until proven otherwise.
Over SSH, this one command exposes them:
find wp-content/uploads -name "*.php" -type f
Watch for files disguised as images too — names like logo.jpg.php or image.png.php exploit servers that execute based on the final extension. Beyond uploads, check these hiding spots I see in real cleanups: wp-content/mu-plugins (must-use plugins load automatically on every request and are easy to forget during cleanup — a perfect backdoor home), theme folders for files you do not recognize, and the site root for innocuously named files like wp-login-check.php or class-wp-cache.php that are not part of WordPress.
Attackers pick names designed to blend in: wp-feed.php, wp-tmp.php, radio.php, or random-looking strings tucked into odd directories. When you find a file you cannot account for, do not delete it — quarantine it per the ground rules, then open it and read it. Which brings us to recognizing what malicious code actually looks like.
Check 4: Recognize Suspicious Code Patterns
Most WordPress malware is obfuscated PHP — real malicious code hidden inside layers of encoding so it looks like gibberish at first glance. Once you know the handful of patterns attackers reuse, obfuscated code stops looking mysterious and starts looking obvious. These are the signatures I search for on every job:
grep -rl "eval(base64_decode" --include="*.php" .
grep -rl "eval(gzinflate" --include="*.php" .
grep -rl "str_rot13" --include="*.php" .
grep -rl "shell_exec" --include="*.php" .
Here is what each pattern means in plain language. eval() tells PHP to execute a string as code — legitimate code almost never needs this. base64_decode and gzinflate decode hidden text, so eval combined with either one usually means “decode this hidden payload and run it.” str_rot13 is a simple letter-shuffling cipher attackers use to hide readable strings. Long strings of gibberish characters, hex-encoded blobs like \x62\x61\x73\x65, and code that builds function names by concatenating string fragments are all the same trick: hiding what the code really does until the moment it runs.
Now the crucial judgment call: context matters. Legitimate plugins occasionally use base64 encoding for innocent purposes like storing settings or handling image data. Finding the pattern in a known plugin file from a reputable developer is usually a false positive. Finding the same pattern in an unknown file in your uploads folder is a smoking gun. Never judge the pattern alone — judge the pattern plus the location plus whether the file belongs there at all. When in doubt, compare the file against a fresh download of the plugin or theme it claims to belong to.
Also inspect JavaScript with the same skepticism: look for document.write calls with long encoded strings or suspicious atob() decoding in theme files. Redirect malware in particular often lives in JavaScript that sends only search-engine visitors to spam pages — which is exactly the pharmacy-spam trick from my opening story.

Check 5: Inspect wp-config.php and .htaccess for Tampering
Two files deserve special individual attention because malware loves to abuse them. Open wp-config.php — you know this file from our file permissions guide — and read it top to bottom. You are looking for anything that does not belong: unknown include or require lines pulling in files from strange locations, remote URLs being fetched, modified database credentials, or code appended before the opening or after the closing of the normal configuration. A clean wp-config.php contains only defines, the table prefix, and the “stop editing” line. Anything else is suspicious.
Then open .htaccess in your site root. Malware frequently injects rewrite rules here that redirect only search-engine visitors to spam sites — the classic conditional redirect that made my pharmacy-spam case invisible to the site owner. Look for rewrite conditions checking user agents or referrers, redirect rules pointing to domains you do not recognize, and blocks of encoded text. Compare it against a known-clean WordPress .htaccess: the default WordPress block between the BEGIN and END markers is short and recognizable. Anything beyond it needs an explanation.
Check 6: Search the Database for Injected Content
Not all malware lives in files. Injected redirects, hidden spam links, and malicious scripts often live in the database instead — inside post content, widget settings, or options tables. File scans miss these completely, which is why the database check is non-negotiable.
In phpMyAdmin or a similar tool, run this query to find script tags hiding in your posts:
SELECT ID, post_title FROM wp_posts
WHERE post_content LIKE '%<script%'
OR post_content LIKE '%eval(%';
Replace wp_ with your actual table prefix if it differs. Also check the wp_options table for suspicious entries — malware sometimes stores payloads in options with innocent-looking names — and review recently modified posts with a query ordered by post_modified date, focusing on anything changed around the time problems started. Spam links injected into old posts are a classic sign: the attacker edits existing high-ranking content rather than creating new posts, because existing posts already have search-engine trust.
While you are in the database, check wp_users and wp_usermeta for accounts you did not create. Attackers routinely add themselves as administrators with innocuous usernames. Any admin account you do not recognize — especially one created recently — should be treated as hostile until proven otherwise. Demote or remove it, but note the details first: the username, email, and creation date are evidence of when the breach happened.

Check 7: Review Server Logs and Scheduled Tasks
The final layer of the investigation is asking how the attacker got in and whether anything is still calling home. Download your recent access logs from your hosting panel and look for the patterns: unusual POST requests to plugin or theme files, requests from unfamiliar countries at odd hours, file uploads to wp-content/uploads that you did not perform, and repeated hits on xmlrpc.php or wp-login.php. Note down the timestamps — they tell you when the breach happened, which tells you which backup is still clean.
Then check for persistence mechanisms — the tricks malware uses to survive cleanup. In WordPress, look at scheduled cron events for tasks you do not recognize; attackers register cron jobs that reinstall the malware if you delete the files. Check mu-plugins once more, since anything there loads on every single request. And review any recently added admin users again from the WordPress dashboard under Users, because a second hidden admin is the most common reinfection vector I encounter. Finding how the malware persists matters more than finding the malware itself — delete the files but miss the cron job, and you will be cleaning the same site again next week.
If this inspection confirms your site is compromised, do not panic — work through our WordPress hacked recovery guide for the full cleanup sequence, and review our brute-force protection guide to close the door the attacker walked through.
Scan WordPress for Malware Manually: Frequently Asked Questions
Can I scan for malware manually without SSH access? Yes. Everything in this guide can be done through your hosting file manager and phpMyAdmin — it just takes longer. The file manager shows modification dates, lets you open and read files, and supports searching within folders on most hosts. SSH and WP-CLI make you faster, not more capable.
I found eval(base64_decode in a plugin file. Is my site hacked? Not necessarily. Some legitimate plugins use these functions for innocent purposes. Check whether the file belongs to a known plugin from a reputable source, and compare it against a fresh download of that plugin. The pattern is only damning in combination with a suspicious location — an unknown file, the uploads folder, or code that does not match the official version.
Should I delete malware files as soon as I find them? No — quarantine first, always. Move suspicious files to a folder outside the web root or download them to your computer before removing them from the server. Deleting blindly is how sites get white-screened, and quarantined files preserve the evidence you need to find the entry point and the persistence mechanism.
How do I know the cleanup actually worked? Re-run every check in this guide after cleanup: verify checksums again, confirm no PHP remains in uploads, re-scan the database, and confirm no rogue admins or cron jobs survive. Then monitor for two weeks — reinfection usually happens within days if a backdoor was missed. A site that stays clean for two weeks with all checks passing is genuinely clean.
Is manual scanning better than a security scanner plugin? They answer different questions. Scanners are fast and catch known malware signatures; manual inspection catches novel or heavily obfuscated malware and teaches you how your site actually works. I use both: automated scans for routine monitoring, manual inspection whenever something feels wrong or after any confirmed incident. Neither replaces the other.
Final Thoughts: Scan WordPress for Malware Manually
That pharmacy-spam site from my opening story? We found the infection with exactly the workflow you just learned: recently modified files led us to a backdoor in the uploads folder, the code patterns confirmed it was obfuscated malware, the database held the injected spam pages, and a hidden admin account explained how it kept coming back. Four checks, one afternoon, complete picture. The owner now runs this inspection quarterly, and it takes them under an hour.
You now have the same detective toolkit: the ground rules that keep you safe, the file hunts that find planted malware, the checksum verification that proves what changed, the code patterns that reveal obfuscation, the database queries that catch injected content, and the log review that reveals the entry point. That is a genuine skill, not a checklist to forget.
The honest line: manual inspection takes longer than clicking “scan,” and it demands judgment that only practice builds. Your first inspection will feel slow and uncertain. Your fifth will feel like reading a familiar map. Start with a healthy site — run these checks now, while nothing is wrong, so you know what “normal” looks like before you ever need to spot “abnormal.” And keep our safe update checklist handy, because prevention will always beat cleanup.
Have you ever found something suspicious hiding on your site? Tell me what it was and where you found it in the comments — I read every one, and your story might teach someone else where to look.
Published: October 18, 2026 · Updated: October 18, 2026 · By Mei Chen










