diff --git a/Check/Hacked/Hacked.php b/Check/Hacked/Hacked.php
new file mode 100644
index 0000000..8908582
--- /dev/null
+++ b/Check/Hacked/Hacked.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * @file
+ * Contains \SiteAudit\Check\Codebase\SizeAll.
+ */
+
+class SiteAuditCheckHackedHacked extends SiteAuditCheckAbstract {
+  /**
+   * Implements \SiteAudit\Check\Abstract\getLabel().
+   */
+  public function getLabel() {
+    return dt('Hacked');
+  }
+
+  /**
+   * Implements \SiteAudit\Check\Abstract\getDescription().
+   */
+  public function getDescription() {
+    return dt('Determine whether core or contrib modules have been hacked.');
+  }
+
+  /**
+   * Implements \SiteAudit\Check\Abstract\getResultFail().
+   */
+  public function getResultFail() {
+    return dt('Unable to determine whether core or contrib modules have been hacked!');
+  }
+
+  /**
+   * Implements \SiteAudit\Check\Abstract\getResultInfo().
+   */
+  public function getResultInfo() {}
+
+  /**
+   * Implements \SiteAudit\Check\Abstract\getResultPass().
+   */
+  public function getResultPass() {
+    return dt('No hacks were found.');
+  }
+
+  /**
+   * Implements \SiteAudit\Check\Abstract\getResultWarn().
+   */
+  public function getResultWarn() {
+    $ret_val = dt('The following modules(s) were found to be hacked:');
+
+    if (drush_get_option('html')) {
+      $ret_val = '<p>' . $ret_val . '</p>';
+      $ret_val .= '<table class="table table-condensed">';
+      $ret_val .= '<thead><tr><th>Name</th><th>Title</th><th>Version</th><th>Changed</th></thead>';
+      $ret_val .= '<tbody>';
+      foreach ($this->registry['hacked'] as $row) {
+        $ret_val .= '<tr><td>' . implode('</td><td>', $row) . '</td></tr>';
+      }
+      $ret_val .= '</tbody>';
+      $ret_val .= '</table>';
+    }
+    else {
+      foreach ($this->registry['hacked'] as $row) {
+        $ret_val .= PHP_EOL . str_repeat(' ', 6) . '- ' . implode(' -- ', $row);
+      }
+    }
+    return $ret_val;
+  }
+
+  /**
+   * Implements \SiteAudit\Check\Abstract\getAction().
+   */
+  public function getAction() {}
+
+  /**
+   * Implements \SiteAudit\Check\Abstract\calculateScore().
+   */
+  public function calculateScore() {
+    //$drupal_root = drush_get_context('DRUSH_SELECTED_DRUPAL_ROOT');
+
+    // Download and enable Hacked.
+    if (!drush_invoke_process('@self', 'pm-download', array('-y', 'hacked'), array('--strict=0'), FALSE)) drush_set_error('HACKED_DOWNLOAD', dt('Failed to download Hacked.'));
+    if (!drush_invoke_process('@self', 'pm-enable', array('-y', 'hacked'), array('--strict=0'), FALSE)) drush_set_error('HACKED_ENABLE', dt('Failed to enable Hacked.'));
+
+    // Clear drush commands to reveal new functions.
+    drush_cache_clear_drush();
+    $result = drush_invoke_process('@self', 'hacked-list-projects', array(), array('--include-unchanged=0'), FALSE);
+
+    $rows = array();
+    foreach ($result['object'] as $info) {
+      if ($info['counts']['different'] != 0) {
+        $rows[] = array(
+          $info['project_name'],
+          $info['title'],
+          $info['existing_version'],
+          $info['counts']['different'],
+        );
+      }
+    }
+
+    // Disable and uninstall Hacked.
+    drush_invoke_process('@self', 'pm-disable', array('-y', 'hacked'), array('--strict=0'), FALSE);
+    drush_invoke_process('@self', 'pm-uninstall', array('-y', 'hacked'), array('--strict=0'), FALSE);
+
+    $this->registry['hacked'] = $result;
+    if (!$this->registry['hacked']) {
+      $this->abort = TRUE;
+      return SiteAuditCheckAbstract::AUDIT_CHECK_SCORE_FAIL;
+    }
+    else if (!empty($rows)) {
+      $this->registry['hacked'] = $rows;
+      return SiteAuditCheckAbstract::AUDIT_CHECK_SCORE_WARN;
+    }
+    else {
+      return SiteAuditCheckAbstract::AUDIT_CHECK_SCORE_PASS;
+    }
+  }
+}
diff --git a/Report/Hacked.php b/Report/Hacked.php
new file mode 100644
index 0000000..7c6fb48
--- /dev/null
+++ b/Report/Hacked.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * @file
+ * Contains \SiteAudit\Report\Codebase.
+ */
+
+class SiteAuditReportHacked extends SiteAuditReportAbstract {
+  /**
+   * Implements \SiteAudit\Report\Abstract\getLabel().
+   */
+  public function getLabel() {
+    return dt('Hacked');
+  }
+
+  /**
+   * Implements \SiteAudit\Report\Abstract\getCheckNames().
+   */
+  public function getCheckNames() {
+    return array(
+      'Hacked',
+    );
+  }
+}
diff --git a/site_audit-hacked.patch b/site_audit-hacked.patch
new file mode 100644
index 0000000..e69de29
diff --git a/site_audit.drush.inc b/site_audit.drush.inc
index 8721920..4e63bfa 100644
--- a/site_audit.drush.inc
+++ b/site_audit.drush.inc
@@ -106,6 +106,13 @@ function site_audit_drush_command() {
     'options' => $options,
   );
 
+  $items['audit_hacked'] = array(
+    'description' => dt('Audit the codebase to ensure no hacks.'),
+    'aliases' => array('ah'),
+    'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL,
+    'options' => $options,
+  );
+
   $arguments_gi = array(
     'url' => dt('The URL that you wish to test.'),
     'key' => dt('Google Code API Key - see https://developers.google.com/speed/docs/insights/v1/getting_started#auth'),
@@ -189,6 +196,9 @@ function site_audit_drush_help($section) {
     case 'drush:audit_views':
       return dt('Audit Views displays');
 
+    case 'drush:audit_hacked':
+      return dt('Audit the codebase to ensure no hacks');
+
     case 'meta:site_audit:title':
       return dt('Tools for auditing a Drupal site');
 
@@ -410,6 +420,14 @@ function drush_site_audit_audit_views() {
 }
 
 /**
+ * Audit the codebase to ensure no hacks.
+ */
+function drush_site_audit_audit_hacked() {
+  $report = new SiteAuditReportHacked();
+  $report->render();
+}
+
+/**
  * Validate parameters.
  *
  * @param string $url
