I don't have NT4 vm
Also your link points to several samples
Providing exact MD5/SHA/some verifiable checksum
of the sample can eliminate ambiguities while answering
here is a small walk through using basic hex editor and a basic disassembler of why it might be possible for that exception to be generated.
using winxp sp3 vm hxd hexeditor and ollydbg 1.10 in a basic dis-aaseembler mode
downloaded the first sample in openmalware
MD5: f40547d521818f7c34754710f8603d5a
SHA1: f9e3c0e824dda984046b4eedeef06f938805983b
SHA256: a9beda469c835abbf416ea8da5462170eafdef215b96ac68523045600883855b
OCID: 245478739
Original Filename: Virus.Win32.Bolzano.5572
drag dropped to vpc 2007 xp sp3 vm
unzipped using given password infected
drag dropped into hxd hexeditor and verified checksums
MD-5: F40547D521818F7C34754710F8603D5A
SHA-1: F9E3C0E824DDA984046B4EEDEEF06F938805983B
SHA-256: A9BEDA469C835ABBF416EA8DA5462170EAFDEF215B96AC68523045600883855B
all three checksums match ok
WORD MajorSubsystemVersion
WORD MinorSubsystemVersion
Contains the minimum subsystem version required to run the executable.
A typical value for this field is 3.10 (meaning Windows NT 3.1).
http://msdn.microsoft.com/en-us/library/ms809762.aspx
using ollydbg as a disassembler
view -> file -> malware.exe -> right click -> speacial -> pe header
ctrl+g 100
pe header shows
00000148 0300 DW 0003 ; MajorSubsystemVersion = 3
0000014A 0A00 DW 000A ; MinorSubsystemVersion = A (10.)
00000200 00100000 DD 00001000 ; VirtualSize = 1000 (4096.)
00000204 00100000 DD 00001000 ; VirtualAddress = 1000 <-----
00000208 00020000 DD 00000200 ; SizeOfRawData = 200 (512.)
0000020C 00060000 DD 00000600 ; PointerToRawData = 600
00000228 00200000 DD 00002000 ; VirtualSize = 2000 (8192.)
0000022C 00200000 DD 00002000 ; VirtualAddress = 2000
00000230 00200000 DD 00002000 ; SizeOfRawData = 2000 (8192.)
00000234 00080000 DD 00000800 ; PointerToRawData = 800 <------
00000128 00100000 DD 00001000 ; AddressOfEntryPoint = 1000
so we can start disassembling at 0x600
ctrl+g 600 right click -> disassemble
disassembly
1. 00000600 60 PUSHAD
2. 00000601 E9 FA0F0000 JMP 00001600
virtual size of section is 1000 as we saw earlier
so it jumps to next section
next section starts at 0x800 as we saw earlier
ctrl+g 800 disassemble
disassembly
00000800 E8 D50E0000 CALL 000016DA (402eda) 400000 +2000 + (16da-800)
following
000016DA E8 00000000 CALL 000016DF $+5 (402edf) 400000+ 2000+ (16df-800)
000016DF 5D POP EBP ebp will be 402edf
000016E0 81ED DF0E0000 SUB EBP, 0EDF ebp will be 402000
000016E6 C3 RETN will return to 805 or 402005
ctrl+g 805 disassemble
00000805 BF 000C0100 MOV EDI, 10C00
0000080A B9 00010000 MOV ECX, 100
0000080F 33C0 XOR EAX, EAX
00000811 F3:AE REPE SCAS BYTE PTR ES:[EDI]
scan all bytes from 10c00 to 10d00 for 0
00000813 75 0C JNZ SHORT 00000821
if all not zero go to win95/98
00000815 BE 2D110000 MOV ESI, 112D win nt
0000081A BF 0000F077 MOV EDI, 77F00000 k32 base
0000081F EB 0A JMP SHORT 0000082B
00000821 BE 25110000 MOV ESI, 1125 win 95 / 98
00000826 BF 0000F7BF MOV EDI, BFF70000 k32 base
sets the base of kernel32.dll to edi
for byte scanning puproses
looks if all 100 bytes starting at 10c00 are zero
if they are zero sets kernel base to 77f00000
(win nt k32 base no aslr fixed)
else to bff70000
(win 95 / 98 kernel32 base no aslr fixed)
esi to some offset
( esi = 1125 or 112d) ( ebp = 402000) 40312d/25 1925 or 192d (800+1125 or 112d)
0000082B 03F5 ADD ESI, EBP
(so esi will be either 403125 or 40312d)
0000082D 89BD C8170000 MOV DWORD PTR SS:[EBP+17C8], EDI
saves the pointer kernel base guess why ??
00000833 BA 00000400 MOV EDX, 40000
00000838 FC CLD
00000839 B9 08000000 MOV ECX, 8
0000083E 56 PUSH ESI
0000083F 57 PUSH EDI
00000840 F3:A6 REPE CMPS BYTE PTR ES:[EDI], BYTE PTR>
00000842 5F POP EDI
00000843 5E POP ESI
compares byte pattern
in k32 dll
for 95/98
this pattern
00001925 C2 0400 RETN 4
00001928 57 PUSH EDI
00001929 6A 22 PUSH 22
0000192B 2BD2 SUB EDX, EDX
for win nt
this pattern
0000192D C2 0400 RETN 4
00001930 55 PUSH EBP
00001931 8B4C24 0C MOV ECX, DWORD PTR SS:[ESP+C]
jumps to ok or not ok
00000844 74 0A JE SHORT 00000850 `right user with right os jump`
00000846 47 INC EDI
00000847 4A DEC EDX
00000848 0F84 CD000000 JE 0000091B `wrong user with wrong os jump`
0000084E ^ EB E9 JMP SHORT 00000839
if it finds the pattern will go to 850
else 91b
at 91b there is
0000091B E8 BA0D0000 CALL 000016DA
so this will return to 920 (see above retn to 402005)
00000920 8B5424 20 MOV EDX, DWORD PTR SS:[ESP+20]
00000924 B9 40000000 MOV ECX, 40
00000929 83EA 05 SUB EDX, 5
0000092C BE 4F180000 MOV ESI, 184F
this will retn to kernel or exit thread address (pushad == 0x20)
all else are junk
exe contains nothing at 204f to 224f will simply exit via retn
(184f+800 ecx = 40 two lodsd = 80 dwords = 200 bytes = 224f)
if the region compared ok to retn value - 5 (see sub edx,5)
the app will crash and ollydbg can issue that warning
00000931 03F5 ADD ESI, EBP
00000933 AD LODS DWORD PTR DS:[ESI]
00000934 3BC2 CMP EAX, EDX
00000936 AD LODS DWORD PTR DS:[ESI]
00000937 74 04 JE SHORT 0000093D
00000939 ^ E2 F8 LOOPD SHORT 00000933
0000093B 61 POPAD
0000093C C3 RETN
0000093D 8985 47010000 MOV DWORD PTR SS:[EBP+147], EAX
00000943 61 POPAD
00000944 EB 00 JMP SHORT 00000946
00000946 68 00000000 PUSH 0 <---- apllication will crash
0000094B C3 RETN eip not valid or 0
ollydbg will show dont know how to step because memory at address 0
is not readable try changing Eip or pass exception to program if it reaches here
disassembling at 850 or 402050
00000850 83C7 03 ADD EDI, 3 add 3 to bytepattern address
00000853 BE E70E0000 MOV ESI, 0EE7
00000858 03F5 ADD ESI, EBP 402ee7 = 16e7 (ee7 -800 + 1000)
0000085A 8BC6 MOV EAX, ESI
0000085C 83C0 07 ADD EAX, 7 16e7+7 = 16ee
byte pattern at 16ee
000016EE 43 72 65 61 74 65 46 69 6C 65 4D 61 70 70 69 6E CreateFileMappin
000016FE 67 41 gA
disassembling further
0000085F 50 PUSH EAX **pushes string CreateFileMapping**
00000860 8B85 C8170000 MOV EAX, DWORD PTR SS:[EBP+17C**8]
00000866 50 PUSH EAX** pushes kernel base
00000867 FFD7 CALL NEAR EDI (can you guess ?? what api ??)
try walking ahead a bit :)