How I Recovered Three Hacked WordPress Sites Using LocalWP and Claude Code CLI

A real-world story of WordPress disaster recovery, malware forensics, and modern AI-assisted development tools


When you get hacked, it feels like everything is lost. Your work, your content, your portfolio — gone or compromised. That’s exactly where I found myself recently, staring at three old WordPress sites that had been sitting dormant after a hack, wondering if I’d ever get them back.

What followed was one of the most educational experiences I’ve had as a web professional — and I want to share it, because the tools available today make this kind of recovery dramatically easier than it used to be.


The Setup: Three Sites, Three Problems

I had three WordPress sites I needed to recover and bring back to life locally:

  • DCF — running WordPress 4.9.12, built on the Enfold theme
  • HHC — running WordPress 4.6.29
  • Dekalb — running WordPress 5.3.20

All three had been hacked at some point. None were running live. All I had were old site folders and database exports. My goal was to get each one running locally in LocalWP, clean up any malware, and eventually get them onto my live GoDaddy hosting as part of my portfolio.


The Tools I Used

Before diving into the process, here’s the stack that made this possible:

LocalWP — A free local WordPress development environment for Mac and Windows. It handles Apache, PHP, and MySQL automatically, letting you spin up WordPress sites on your own machine without any server configuration.

Claude Code CLI — Anthropic’s command-line AI tool that runs directly in your terminal. Unlike a standard chatbot, Claude Code can read your files, run commands, edit code, and work through multi-step tasks autonomously. It was genuinely transformative for this kind of forensic work.


Step 1: Choosing the Right Environment

The first decision was getting the LocalWP environment settings right. For WordPress 4.x and 5.x sites, compatibility matters enormously.

For each site I used:

  • Web Server: Apache 2.4.43 — WordPress was built around Apache, and its .htaccess permalink handling works automatically here
  • PHP: 7.4.x — Compatible with older WordPress versions without the breaking changes introduced in PHP 8
  • Database: MySQL 5.7.28 — Critical choice. MySQL 8 changed its default authentication plugin to caching_sha2_password, which breaks older WordPress and PHP combinations. MySQL 5.7 is the native, compatible choice for these older sites

Getting these settings right before touching anything else saved me from a lot of avoidable headaches.


Step 2: Malware Forensics — Scanning Before Touching Anything

This is the step most people skip, and it’s the most important one. Never copy old files from a hacked site into a clean environment without scanning them first.

Using Claude Code CLI, I ran a series of targeted scans across each site’s file system:

What We Scanned For

PHP files hiding in the uploads folder:

bash

find /path/to/site/wp-content/uploads -name "*.php"

PHP files have no business being in a media uploads folder. Any found there are almost certainly malware.

Common obfuscated malware signatures:

bash

grep -rl "eval(base64_decode" /path/to/site/wp-content
grep -rl "gzinflate\|str_rot13\|eval(\$" /path/to/site/wp-content

These are the fingerprints of the most common WordPress injection attacks — code that decodes and executes hidden malicious instructions.

Suspicious files in the site root: Hackers frequently place files in the WordPress root that mimic legitimate WordPress filenames to avoid detection. On the DCF site, we found five empty shell files in the root directory:

  • admin-ajax.php — legitimately lives in /wp-admin/ only
  • admin.php — legitimately lives in /wp-admin/ only
  • themes.php — legitimately lives in /wp-admin/ only
  • profile.php — legitimately lives in /wp-admin/ only
  • radio.php — doesn’t exist anywhere in WordPress core

All were empty (0 bytes) — meaning the attacker placed backdoor shells that were either never filled with code or were partially cleaned at some point. All were deleted.

The mu-plugins folder: The wp-content/mu-plugins directory is a common place for hackers to hide persistent backdoors, because must-use plugins load automatically and survive standard plugin deactivation.

A wp-snapshots folder: An empty index.php sitting inside a wp-snapshots folder that wasn’t intentionally installed — same pattern as the other remnants, deleted.

Database Audit

The malware scan didn’t stop at files. Using Claude Code, I also audited the database after import, checking:

  • wp_users — for unauthorized admin accounts (found and deleted two suspicious users on DCF)
  • wp_usermeta — for unexpected administrator capabilities
  • wp_options — for injected scripts, malware URLs, or fake cron jobs
  • wp_posts and wp_postmeta — for JavaScript or iframe injections in content

The database came back clean beyond the suspicious user accounts. Catching those accounts is critical — they’re how attackers maintain persistent access even after files are cleaned.


Step 3: The Recovery Process

With each site scanned and cleaned, the recovery followed a consistent, repeatable workflow:

1. Create a Fresh LocalWP Site

Spin up a clean WordPress install with the correct Apache, PHP, and MySQL versions. This gives you a clean core — never copy old WordPress core files from a hacked site.

2. Import the Database

Using LocalWP’s built-in Adminer database tool, or via Claude Code’s direct MySQL access, drop the default empty tables and import the old .sql database export. Claude Code handled this elegantly by calling LocalWP’s own MySQL binary directly.

3. Update the Site URL

The old database still contains the old live domain. Before the site will load locally, the URL needs updating:

sql

UPDATE wp_options SET option_value = 'http://yoursite.local' 
WHERE option_name = 'siteurl' OR option_name = 'home';

4. Copy the Cleaned wp-content

The cleaned wp-content folder — themes, plugins, and uploads — gets copied into the LocalWP site’s app/public/ directory, replacing the default empty one. This is the only part of the old site that comes over. WordPress core files are always fresh.

5. Verify wp-config.php Credentials

LocalWP uses standard local credentials. The wp-config.php needs to point to LocalWP’s database:

php

define('DB_NAME',     'local');
define('DB_USER',     'root');
define('DB_PASSWORD', 'root');
define('DB_HOST',     'localhost');

6. Handle Compatibility Warnings

Older plugins written for PHP 5.x or early 6.x sometimes throw warnings under PHP 7.4. On the HHC site, Revolution Slider’s operations.class.php contained a continue statement inside a switch block — valid in older PHP, flagged in 7.4. Claude Code patched it in place with a single sed command.

7. Run the WordPress Database Upgrade

When an old database schema meets newer WordPress files, WordPress prompts you to run a database upgrade. This is completely safe — it updates table structure only, never touching content, media, or settings.


Results

All three sites are now running cleanly in LocalWP:

SiteWordPress VersionStatus
DCF4.9.12✅ Running locally
HHC4.6.29✅ Running locally
Dekalb5.3.20✅ Running locally

Content intact. Themes intact. Media intact. Malware gone.


What Made Claude Code a Game Changer

I want to be direct about this: Claude Code CLI fundamentally changed how this work felt. Instead of manually hunting through thousands of files for malware strings, running grep commands one at a time and interpreting raw output, Claude Code:

  • Ran comprehensive scans and explained every finding in plain language
  • Distinguished between legitimate theme files and actual threats
  • Identified that files like themes.php in the root were mimicking legitimate WordPress filenames
  • Handled database operations including dropping tables, importing SQL, and updating URLs
  • Patched a PHP compatibility warning in a plugin file
  • Audited the database for injected malware and unauthorized users

It’s the difference between doing forensic work with a magnifying glass versus a full lab toolkit.


Key Lessons for WordPress Professionals

1. Never copy WordPress core files from a hacked site. Core files are the first target. Always start with a fresh download of the exact version you need.

2. wp-content is also a target. Scan it thoroughly before bringing it into a clean environment. Pay special attention to the uploads folder, mu-plugins, and any plugin folders with unusual names.

3. The database needs auditing too. File scanning alone isn’t enough. Unauthorized admin accounts and injected options in wp_options are common and easy to miss.

4. MySQL version matters more than you think. Using MySQL 8 with older WordPress sites will cause authentication errors. MySQL 5.7.28 is the right choice for WP 4.x and early 5.x sites.

5. Local development environments are essential. LocalWP makes it possible to recover, test, and verify a site completely before it ever touches a live server. There’s no reason to debug a hacked site in production.


What’s Next

With all three sites running locally, the next steps are:

  • Update WordPress core, plugins, and themes on each site
  • Build and integrate these into my portfolio
  • Upload to GoDaddy Web Hosting (Deluxe plan with cPanel)
  • Set up a proper Git workflow — LocalWP to GitHub to live server — for ongoing version control

I’ll be writing about each of those steps as they happen. If you’re a WordPress professional, agency developer, or anyone managing client sites, I hope this walkthrough gives you a practical, repeatable framework for the next time you’re handed a compromised site.


Have questions about the process or want to share your own recovery experience? Leave a comment below.

//Let’sBuildSomemething

//INFO [LEONARD_MALCOM]
UX Engineer & Frontend Developer _ 10+
Response within 24h
//TECH_STACK
  • JavaScript
  • Responsive Design
  • WCAG Accessibility
  • Semantic HTML
  • Design Systems
  • Reusable Components
  • Front-End Performance
  • Scalable Front-End Systems
  • WordPress
  • Drupal
  • Twig
  • Enterprise CMS Platforms
  • Figma
  • Wireframing
  • Prototyping
  • Git
  • Agile Workflows
  • Cross-Functional Collaboration
//CONNECT RESUME.pdf
Portv2.2026
//PRIMING
Portv2 - Inspired by Eric Jordan