Site in American English
Password
User name
 
 
« Drive thy business or it will drive thee »
Benjamin Franklin
NetSky.D Musical Payload: Sounds From Outer Space

This mass mailer has a funny musical payload. You want to hear it? As you surely don't intend to run the worm, just read these few lines.

Date Trigger

After unpacking the executable file (byte liposuction is made using PEtite compressor), it takes a few seconds to find the date trigger:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
0040296A
0040296D
0040296E
00402974
00402979
0040297B
00402980
00402982
00402988
0040298A
0040298F
00402991
00402996
00402998
0040299D
lea eax,dword ptr [ebp-10h]
push eax
call dword ptr kernel32.GetLocalTime()
cmp word ptr [ebp-0Ah],0002h
jne 004029BF
cmp word ptr [ebp-0Eh],0003h
jne 004029BF
cmp word ptr [ebp-10h],07D4h
jne 004029BF
cmp word ptr [ebp-08h],0006h
je 0040299F
cmp word ptr [ebp-08h],0007h
je 0040299F
cmp word ptr [ebp-08h],0008h
jne 004029BF
 

Figure 1. NetSky.D date trigger.

GetLocalTime() requires only one single parameter, a pointer to a SYSTEMTIME structure (refer to the MSDN for further details). The first byte address of the structure used here is located at [ebp-10h]. Once GetLocalTime() has returned, our SYSTEMTIME structure fields map is:

[ebp-10h]
[ebp-0Eh]
[ebp-0Ch]
[ebp-0Ah]
[ebp-08h]
[ebp-06h]
[ebp-04h]
[ebp-02h]
wYear
wMonth
wDayOfWeek
wDay
wHour
wMinute
wSecond
wMilliseconds
 

Figure 2. SYSTEMTIME structure fields locations map.

Lines 4-15 of figure 1 are now obvious: we check if the target local date is 03/02/2004 (march 2nd, 2004) and if the local time is between 06:00 and 08:59. In case it is true, we enter a musical loop.

Musical Loop

This loop is devoted to tones generated through the speaker. It's the "audible" and funny part of the worm payload (Internet providers won't find the SMTP part that hilarious). Notice that, between 06:00 and 08:59, NetSky.D is not really discreet... Here is the code:

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
0040299F
004029A4
004029A6
004029A7
004029A8
004029AA
004029AB
004029B0
004029B1
004029B6
004029B8
004029B9
004029BF
004029C1
004029C7
call 00401910h
push 00000032h
cdq
pop ecx
idiv ecx
push edx
call 00401910h
cdq
mov ecx,00000BB8h
idiv ecx
push edx
call dword ptr kernel32.Beep()
push 00000032h
call dword ptr kernel32.Sleep()
jmp 0040296Ah
 

Figure. 3. NetSky.D musical loop.

To generate a tone, Beep() needs two sound parameters: a frequency and a duration. They are supplied using a "random" number generator, located at address 00401910h:

1
2
3
4
5
6
7
00401910
00401915
0040191B
00401920
00401925
00401928
0040192D
mov eax,dword ptr [00414BF0h]
imul eax,000343FDh
add eax,00269EC3h
mov dword ptr [00414BF0h],eax
shr eax,10h
and eax,00007FFFh
ret
 

Figure 4. NetSky.D random number generator.

If you are not familiar with random number generators, just look at lines 5-6 to understand that the code above delivers 16-bits values from the [0h-7FFFh] interval into eax (actually, only the ax part is significant).

Using C language, we can rewrite lines 16-29 of figure 3 in a more readable and concise form:

dwDuration = call_00401910() % 50;

dwFreq = call_00401910() % 3000;

Beep(dwFreq,dwDuration);

Sleep(50);

Figure 5. C version of the musical loop code.

In english, we play sounds which frequencies are in the range [0-3000] Hz, during [0-50] ms. Then, we wait for 50 ms. Here is a C version playing this genuine alien melody until you press a key:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
#include <windows.h>
#include <conio.h>

DWORD call_00401910(void)
{
  static DWORD _00414BF0 = GetTickCount();

  _00414BF0 = _00414BF0 * 214013 + 2531011;

  return ( _00414BF0 >> 16 ) & 32767;
}

void main(void)
{
  while ( !_kbhit() )
  {
    Beep(call_00401910()%3000,call_00401910()%50);

    Sleep(50);
  }
}
 

Figure 6. C version of NetSky.D musical payload.

The GetTickCount() call is used to initialize the random generator seed.

Weird

We can notice two weird things. Strictly speaking, the code should check if the frequency value is in the range 25h through 7FFFh (only ones valid for the Beep() function). You can see that the lower boundary is not tested, hence values from 0 through 24h can be generated. In this case, the speaker will stay dumb.

Finally, what's the point in using push/pop style coding at lines 17 and 19 of figure 3, kind of obfuscation? Well, a weak one...

Virus writers aren't tidy enough.

Credits

Death - Perennial quest (musical inspiration).

Enjoy, cya!

(Written 03/04/2004, revised 10/10/2009)

Click here to go to the Malwares page.
Link to this page
Page #7200001, generated in 24.26 ms
 
Copyright © 2003-2017 Arnold McDonald. All rights reserved.
W3C HTML conformity
W3C CSS conformity