(This was originally a diary but a few people thought I ought to post this as a story. It's my first, so any editorial feedback would be appreciated)
I once thought about the following: Code Red's still around after God knows how many years now (as well as all its Me-Too knockoffs) and you're always hearing of some other worm that's making the rounds. The thing that all of them (except Sircam, I think) have in common is that they're all targeted at one exploit. Now, let's say someone does a bit of research this time 'round. One could look for some fairly fresh Win2K exploits (there's plenty enough of those around) as well as exploits for various UNIX services; Sendmail's got a lot, Apache's had the odd few, although it doesn't run as root, wu-ftpd ... needs no introduction, and so on. We're already talking about a worm that could command staggering numbers of hosts, probably somewhere in the order of a million. Do your research right and target exploits with loads of vulnerable machines and that could well happen.
Of course if you take the approach that the SQL worm takes you'd probably make yourself seriously noticed within a few hours and no static piece of code can withstand concentrated effort to destroy it for very long  Now we come onto the second facet of its design:
This part is fairly simple: networking. Most worms are on their own in the wild, however some have taken the approach of forming an IRC botnet. Of course such worms will really not last very long because they've got their central point of failure hardcoded into them. Handy for getting back at that l4m0r ircop who k-lined you for flooding #daves-mp3s but otherwise not really a serious proposition. Instead why not use the existing network that the worms themselves are forming? Think about it, each worm knows who put it there and who it's managed to infect. You now have a complete distributed routing table for effectively sending broadcast commands to your entire worm base. Only that's a bit of a problem because then all it takes is for someone to send a "shut down" broadcast command and there's your wormnet bollocksed.
So you need to assure the wormnet of your identity. Luckily enough that's a long solved problem: public key cryptography. Make a large private key for yourself, and encode the public key into your worm. Now you can send command messages via UDP (so you can spoof the source address and make yourself harder to find) and control your worm net manually if the occasion calls for it: if your identity checks out, each node will feed it forwards and keep its message id in a cache (if it's already recieved that message, it will ignore it). And throw a TTL field in there too for good measure, though we don't care about retransmissions too much so we can set a value of 40000 or something initially. Heck you could even be very sophisticated about it, making each node that has root enter a promiscuous scanning mode and look for the data passing by it; you could even steno it into a JPEG file and unzip it on some webserver somewhere, then wait for some poor schmuck to access it and the first worm to catch sight of the raw data stream. Or something. Holding an RSA key that the entire wormnet understands basically paints a big "I AM THE BUILDER OF THIS WORM" sign on your behind in neon letters, so you clearly need to use a ton of indirection and camoflague when talking to your net. This is left as an exercise to the reader.
Looking pretty evil isn't it? But remember something I said a bit back: "no static piece of code can survive concentrated efforts to destroy it for very long". Now we enter bold new territory: the dynamic worm. I've thought about this a bit and come up with a multipart design for such a worm:
This is all pretty huge and some of it could probably be cut (eg the VM idea's probably a little excessive, and having to deal with routers effectively would be quite tricky to pull off). But it gives you an idea at least.
- VM Yep, that's right, this bastard's got its own VM. Most people run x86 servers, sure, but there are also other arches such as Sun. Then consider all those Cisco boxes running IIS. Wouldn't having a worm that could command servers and routers alike be nice? Perhaps but then there's always overheads, although Sun has shown that you can get a functional VM into a few tens of kilobytes.
- Kernel This is the bit that communicates with the OS -- it can use the OS TCP/IP stack when it can't get root, or it can use its own TCP/IP stack for the various extended features. It can use local root exploits to try to escalate its priviledges. It also attempts to embed itself directly into the kernel where possible and hide its traces. It also tries to attach itself into various system control files and keep itself on that host as long as possible, as well as remaining hidden.
- TCP/IP When the kernel can get packet socket priviledges, this can be used for TCP/IP spoofing, flooding, and port scanning. Consider the Paketto Keiretsu stateless port scanner for instance; we could build something like this into the TCP/IP stack and scan nearby networks really really fast. This saves us some time scanning every single host that might support a comprimiseable service.
- Algorithm This controls the scanning system. Using a shotgun approach to the problem won't get you very far, instead this could implement a lot of the ideas discussed in the Warhol Worm paper; explicit hit lists for instance, or time bombs a la Code Red. One could infect a load of clearly badly set up machines, then simply lie dormant. Then on the appointed hour, all of them could awaken at once and start attacking the internet proper so it'd look like the attack was coming from everywhere at once. Also a topology cache could be kept so that a fast infect plan could be built and the worm could infect as many hosts as possible in the shortest space of time. Natch, any comprimised routers could be quite helpful here. Or you can even use heuristics; for instance you assign per-subnet weights to each exploit and try the ones that usually work first: this could rip though a heterogeneous cluster in an extremely short space of time.
- Command Algorithm's all well and good but sometimes you want to override it. This can be used to intercept and interpret and forward those RSA'ed command packets we were talking about earlier.
- Exploits Ah yes, the core of any worm. Each instance of the worm would have a sackload of exploits in it, natch. Throw some zero day unpublished stuff into here for a real nightmare.
The idea behind the segmented model is that each of these components are interchangeable: the kernel is specific to each OS and the VM is specific to each hardware architecture, for instance. Also you could have several different implementations of the Algorithm component. These are all different Roles: a Win2K Kernel and a Linux Kernel are different roles for the abstract Kernel component to play, as Near Attack, Far Attack and Hitlist Attack all roles for the abstract Algorithm component. Now, for the coup de grace let us add an upload facility to the Command module which lets us insert new Roles into the wormnet on the fly, as well as introducing Versioning so that each Role can be continually updated.
If we have Major versions which always override previous Major versions, and Minor versions which are randomly selected from a pool, we've got a worm which is always being improved, ever learning new attack strategies and having its bugs and idiosyncracies fixed, but also one with loads of similar components with minor variations: eg some instances of MOV R0,0 type instructions could be replaced with XOR R0,R0, small loops could be unrolled and re-rolled and so on. Because every component is replaceable you've got a worm that's becoming very hard to even detect much less stop; a constantly shifting code base makes for quite the moving target.
Of course this worm is looking fairly huge; in the megabyte range, quite probably. While the odd megabyte is chump change for a server sitting on a DS3 connection, you still want to keep your traffic to a minimum. So if you really want to push the boat out and set fire to it you could adopt a generative approach: once an Exploit module conquers a target machine, it simply loads one of each module into the target, which would be significantly smaller, then make a note of that host. As time goes on these nodes can then differentiate: Scout hosts could alert their peers of new networks. Attacker hosts could comprimise new nodes. Repository nodes could keep a bunch of signed modules of different role and minor version and feed them forwards to hosts that are being comprimised. And so on. You'd have to have a time and topology limited trust relationship between these hosts for all of that to work, and while these metrics could be built into the host cache system this is all beginning to get incredibly complicated so it probably isn't worth the hassle.
But it's a thought. Chances are what I've described is far too overweight and complex to be at all rapid or reliable, but if you think along these lines you've got to admit that the worm concept is a whole pandora's box of possible demons whose surface we've really only scratched. Or maybe I'm talking out of my ass, who knows ;) Regardless it's something to think about.
Sidenote: why's nobody written an antiworm that infects vulnerable SQL servers and then just sits there stopping the nasty flooding one from infecting? who cares if it's legal or not, it'd certainly stop the torrent.