Вопрос Syscalls x32

  • Автор темы Автор темы mxrz
  • Дата начала Дата начала
Searching for myself
Пользователь
Пользователь
Статус
Оффлайн
Регистрация
29 Сен 2021
Сообщения
214
Реакции
69
Все началось с данного сурса
Пожалуйста, авторизуйтесь для просмотра ссылки.
, увидел что функции winapi вызываются через некие
Пожалуйста, авторизуйтесь для просмотра ссылки.
? потом что функции вызываются через
Пожалуйста, авторизуйтесь для просмотра ссылки.
, OpenAi обьяснил это так
The system call number is passed in the ecx register, and the arguments to the system call are passed on the stack. The function first moves the system call number from the ecx register to the eax register, then it pushes the value of the m_param variable onto the stack as an argument to the system call.
It then calls the int 0x2E interrupt, which invokes the system call with the given number and arguments. The function then adds 4 to the stack pointer to clean up the argument, and returns.
Я не доконца понимаю, как передается сам индекс функции и аргументы, предположение что из-за
Пожалуйста, авторизуйтесь для просмотра ссылки.
первый параметр, тоесть индекс передается в ECX, второй же в EDX регистры, но тогда я доконца не понимаю что за значение m_param, и почему оно тоже передается,
Пожалуйста, авторизуйтесь для просмотра ссылки.


Далеё я хотел попробовать вызвать CloseHandle через сискалы, посмотрел что функция вызывает ZwClose который аналогичен NtClose и оба ноходятся в ntdll, сама же функция просто вызывает Wow64SystemServiceCall без передачи чего либо
Пожалуйста, авторизуйтесь для просмотра ссылки.


И теперь сам вопрос, как получить адрес самого syscall функции, по моим предположениям, это он 0x3000?
Пожалуйста, авторизуйтесь для просмотра ссылки.

И как его вызвать, поискав по юц я нашел пару разных вариантов и все они под х64, как
Пожалуйста, авторизуйтесь для просмотра ссылки.
, тогда почему они передают сразу столько аргументов , и используют typename... args только в конце

При вызове я получаю краш
C++:
Expand Collapse Copy
template < typename ... TArguments >
long __fastcall Wow64SystemServiceCall( std::uint32_t uiIndex, TArguments ... tArgumentsList ) {
__asm {
    mov eax, ecx; Передаем индекс
    call dword ptr fs : [0xC0]; Тут я понял мы получем сам Heaven Gate (TIB + 0xC0)
    add esp, 0x4; Очищаем аргумент
    retn;
    }
}

long NtClose( void *pHandle ) {
    return Wow64SystemServiceCall( 0x3000, pHandle );
}
Только не бейте, я пытался вникнуть гуглив, у меня уже голова болит
 
Последнее редактирование:
И теперь сам вопрос, как получить адрес самого syscall функции, по моим предположениям, это он 0x3000?
Не совсем. Это номер системного вызова. Номера системных вызовов всегда передаются в eax. Есть прекрасная
Пожалуйста, авторизуйтесь для просмотра ссылки.
со всеми сисколлами (до 20H2, по крайней мере), там смотришь нужные тебе сисколлы и используешь их. Учти, что это микромягкие и номера могут меняться. Но, как правило "фундаментальные" сисколлы не меняют номера от билда к билду. Далее, под оберткой сисколлов они форвардятся во что-либо дальше (например, NtWriteVirtualMemory форвардится в MiReadWriteVirtualMemory).


тогда почему они передают сразу столько аргументов , и используют typename... args только в конце
Потому что первые 4 аргумента передаются в регистры: rcx, rdx, r8, r9, остальные аргументы идут в стек.
Если хочешь почитать поподробнее о Heaven's Gate, то рекомендую проштудировать
Пожалуйста, авторизуйтесь для просмотра ссылки.
от Ионеску. Дополнительно можешь глянуть сами реализации HG (мне еще
Пожалуйста, авторизуйтесь для просмотра ссылки.
заходит)
 
  • Мне нравится
Реакции: mxrz
Последнее редактирование:
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
  • Вау!
Реакции: mxrz
А если мне нжуно под 11 винду? Разве они же не меняются?
Вшивать индексы сисколлов довольно опрометчиво со стороны разработчика, чтобы получать системные номера для 7, 8, 10 и 11 можно написать функцию, которая будет проходиться по экспортам ntdll, проверять начальные байты (паттерн для х32: B8 ?? ?? ?? ?? BA ?? ?? ?? ?? FF D2, и гетать значение по смещению, что тебе надо как раз в первом муве с неизвестными байтами). Ну и будь внимательнее, NtClose у тебя на скриншоте имеет номер 0x3000F, а ты вписал 0x3000

По поводу кода, поизучай семплы и попробуй сделать что-то из этого кода своё, и не забудь установить masm для поддержки асм файлов

.asm
Код:
Expand Collapse Copy
.MODEL FLAT, C

.code
NtCloseExample PROC
    mov eax, 3000Fh
    assume fs:nothing
    mov edx, dword ptr fs:[0C0h]
    assume fs:error
    call edx
    ret
NtCloseExample ENDP

NtSuspendThreadExample PROC
    mov eax, 701BCh
    assume fs:nothing
    mov edx, dword ptr fs:[0C0h]
    assume fs:error
    call edx
    ret
NtSuspendThreadExample ENDP

END

.cpp
C++:
Expand Collapse Copy
EXTERN_C NTSTATUS NtCloseExample( HANDLE hHandle );
EXTERN_C NTSTATUS NtSuspendThreadExample( HANDLE hThread );

void Boo()
{
    printf( "!\n" );
}

int main()
{
    printf( "0x%x\n", NtCloseExample( CreateThread( 0, 0, ( LPTHREAD_START_ROUTINE )Boo, 0, 0, 0 ) ) );
    NtSuspendThreadExample( GetCurrentThread() );
}
 
/del
 
Последнее редактирование:
А если мне нужно под 11 винду? Разве они же не меняются?
1)Я рекомендую переходить в x64 code т.к я не совсем вижу смысл вызывать таким способом NtApi
Посмотрите heavens gate:
Пожалуйста, авторизуйтесь для просмотра ссылки.
,
Пожалуйста, авторизуйтесь для просмотра ссылки.

Полезно самому потренироваться и что-либо сделать, но я не вижу просто смысл делать маленькую эмуляцию функции Wow64SystemServiceCall(если только shell-code)
2)Вы можете просто загрузить ntdll с диска и взять номера syscall'ов от туда.
Если вы хотите уклоняться от загрузки с диска и быть более скрытными,то прочитайте ntdll у другого легитного процесса, а затем получите syscall.
Пример получение syscall из мапнутой ntdll с использования distorm(можете ругать и кекать из-за lazy import т.к я лентяй)
C++:
Expand Collapse Copy
class syscall_help_map
{
private:

    INT process_platrorm = NULL;
    PVOID nt_open_secthion = NULL;
    PVOID nt_map_view_of_secthion = NULL;
    PVOID nt_close = NULL;
    PVOID nt_unmap_view_of_secthion = NULL;

    INLINE auto init_struct() -> bool
    {
        if (process_platrorm && nt_open_secthion && nt_map_view_of_secthion && nt_close && nt_unmap_view_of_secthion)
            return TRUE;
        process_platrorm = get_proc_info::get_process_platform();
        nt_open_secthion = LI_FN(NtOpenSection).nt_cached();
        nt_map_view_of_secthion = LI_FN(NtMapViewOfSection).nt_cached();
        nt_close = LI_FN(NtClose).nt_cached();
        nt_unmap_view_of_secthion = LI_FN(NtUnmapViewOfSection).nt_cached();

        return nt_open_secthion && nt_map_view_of_secthion && nt_close && nt_unmap_view_of_secthion;
    }

public:

    INLINE auto map_get_syscall(CONST WCHAR* name_module, uint64_t hahs_str) -> INT
    {
        INT syscall_number = NULL;
        SIZE_T viewSize = NULL;
        HANDLE secthion_handle = NULL;
        PVOID functhion_address = NULL;
        PVOID mapped_module = NULL;
        UNICODE_STRING secthion_name = { NULL };
        OBJECT_ATTRIBUTES obj_attribut = { NULL };
        NTSTATUS nt_status = STATUS_UNSUCCESSFUL;
        WCHAR buffer[MAX_PATH];

        //Disassembly
        UINT count_decode = NULL;
        _CodeInfo ci = { 0 };
        _DInst decode_instr[100] = { 0 };

        if (!init_struct())
            return NULL;

    crt_wrapper:memset(buffer, NULL, MAX_PATH);
#ifdef _WIN64
        crt_wrapper::str_cat_w(buffer, L"\\KnownDlls\\");
#else
        if (process_platrorm == PROCESS_WOW64)
            crt_wrapper::str_cat_w(buffer, L"\\KnownDlls32\\");
        else
            crt_wrapper::str_cat_w(buffer, L"\\KnownDlls\\");
#endif 
        crt_wrapper::str_cat_w(buffer, name_module);

        secthion_name = crt_wrapper::init_unicode_str(buffer);

        InitializeObjectAttributes(&obj_attribut, &secthion_name, OBJ_CASE_INSENSITIVE, NULL, NULL);
        nt_status = reinterpret_cast<decltype(&NtOpenSection)>(nt_open_secthion)(&secthion_handle, SECTION_MAP_READ, &obj_attribut);

        if (!NT_SUCCESS(nt_status))
            return NULL;

        nt_status = reinterpret_cast<decltype(&NtMapViewOfSection)>(nt_map_view_of_secthion)(secthion_handle, NtCurrentProcess, &mapped_module, NULL, NULL, nullptr,
            &viewSize, (SECTION_INHERIT)1, NULL, PAGE_READONLY);

        if (!NT_SUCCESS(nt_status))
        {
            if (secthion_handle)
                reinterpret_cast<decltype(&NtClose)>(nt_close)(secthion_handle);
            return NULL;
        }

        if (secthion_handle && mapped_module)
        {
            functhion_address = crt_wrapper::get_proc_address(mapped_module, hahs_str);
#ifdef _WIN64
            if (process_platrorm == PROCESS_64)
            {
                ci.features = NULL;
                ci.code = reinterpret_cast<uint8_t*>(functhion_address);
                ci.codeLen = 0x20;//Safe min lenght need
                ci.dt = Decode64Bits;

                if (distorm_decompose(&ci, decode_instr, 100, &count_decode) != DECRES_INPUTERR)
                {
                    for (uint32_t i = NULL; i < count_decode ; i++)
                    {
                        if (
                            decode_instr[i].flags != FLAG_NOT_DECODABLE &&
                            decode_instr[i].opcode == I_MOV &&
                            decode_instr[i].ops[0].index == R_R10 &&
                            decode_instr[i].ops[1].index == R_RCX &&

                            decode_instr[i + 1].flags != FLAG_NOT_DECODABLE &&
                            decode_instr[i + 1].opcode == I_MOV &&
                            decode_instr[i + 1].ops[0].index == R_EAX &&

                            decode_instr[i + 4].flags != FLAG_NOT_DECODABLE &&
                            decode_instr[i + 4].opcode == I_SYSCALL
                            )
                        {
                            syscall_number = decode_instr[i + 1].imm.dword;
                            break;
                        }
                    }
                }
            }
#else
            ci.features = NULL;
            ci.code = reinterpret_cast<uint8_t*>(functhion_address);
            ci.codeLen = MAXIMUM_INSTRUCTION_SIZE;
            ci.dt = Decode32Bits;

            /*
            * WoW64:
            * Windows 10
             | B8 9F010000                        | mov eax,19F
             | BA 408B5D77                        | mov edx,ntdll.775D8B40
             | FFD2                               | call edx
             | C2 1000
             | ret 10

             X32 windows 10
             B8 9B 00 00 00                       | mov     eax, 9Bh                                                     ; RtlGetNativeSystemInformation
             E8 03 00 00 00                       | call    sub_6A290E8D  via call $+8
             C2 10 00                             | retn    10h
             8B D4                                | mov     edx, esp
             0F 34                                | sysenter
             C3                                   | retn
            */
            if (process_platrorm == PROCESS_WOW64 && functhion_address)
            {

                if (distorm_decompose(&ci, decode_instr, 100, &count_decode) != DECRES_INPUTERR)
                {
                    for (uint32_t i = NULL; i < count_decode; i++)
                    {
                        if (
                            decode_instr[i].flags != FLAG_NOT_DECODABLE &&
                            decode_instr[i].opcode == I_MOV &&
                            decode_instr[i].ops[0].index == R_EAX &&
                            decode_instr[i].size == 0x5
                            )
                        {
                            //Not dword for get correct number(thank's microsoft)
                            syscall_number = decode_instr[i].imm.sword;
                            break;
                        }
                    }
                }
            }
            else if (process_platrorm == PROCESS_32 && functhion_address)
            {
                if (distorm_decompose(&ci, decode_instr, 100, &count_decode) != DECRES_INPUTERR)
                {
                    for (uint32_t i = NULL; i < count_decode; i++)
                    {

                        if (
                            decode_instr[i].flags != FLAG_NOT_DECODABLE &&
                            decode_instr[i].opcode == I_MOV &&
                            decode_instr[i].ops[0].index == R_EAX &&
                            decode_instr[i].size == 0x5
                            )
                        {
                            syscall_number = decode_instr[i].imm.dword;
                            break;
                        }
                    }
                }
            }


#endif // _WIN64

            if (secthion_handle)
                reinterpret_cast<decltype(&NtClose)>(nt_close)(secthion_handle);
            
            if (mapped_module && NT_SUCCESS(nt_status))
                reinterpret_cast<decltype(&NtUnmapViewOfSection)>(nt_unmap_view_of_secthion)(NtCurrentProcess, mapped_module);
        }
        return syscall_number;
    }
};

auto main() -> INT
{
    INT  process_platrorm = dump_syscall_util::get_proc_info::get_process_platform();
    if (process_platrorm == PROCESS_32)
        std::cout << "Process is x32(x32 system)\n";
    else if(process_platrorm == PROCESS_64)
        std::cout << "Process is x64(x64 system)\n";
    else if(process_platrorm == PROCESS_WOW64)
        std::cout << "Process is WoW64(x64 system)\n";
    else
        std::cout << "Unknown process(not supported)\n";
    
    dump_syscall_util::syscall_help_map syscall_set_info_thread;

    std::cout << std::dec << "windows build number ->\t" << NtCurrentPeb()->OSBuildNumber << '\n';
    std::cout << "syscall number NtQueryInformationProcess ->\t0x" << std::hex << syscall_set_info_thread.map_get_syscall(L"ntdll.dll", FNV("NtQueryInformationProcess") )<< '\n';
    std::cout << "syscall number NtSetInformationProcess ->\t0x" << std::hex << syscall_set_info_thread.map_get_syscall(L"ntdll.dll", FNV("NtSetInformationProcess") )<< '\n';
    std::cout << "syscall number NtDebugActiveProcess ->\t0x" << std::hex << syscall_set_info_thread.map_get_syscall(L"ntdll.dll", FNV("NtDebugActiveProcess")) << '\n';
    std::cout << "syscall number NtRemoveProcessDebug ->\t0x" << std::hex << syscall_set_info_thread.map_get_syscall(L"ntdll.dll", FNV("NtRemoveProcessDebug")) << '\n';

    std::cin.get();

    return NULL;
}
get_syscall.png
 
  • Мне нравится
Реакции: mxrz
Назад
Сверху Снизу