C++ Исходник Superior Spoof Call [CallStack Spoofer]

Начинающий
Статус
Оффлайн
Регистрация
2 Фев 2022
Сообщения
69
Реакции[?]
14
Поинты[?]
19K
Всем ку, держите неплохой спуф калл с подменой калл стека, он намного лучше и безопаснее баянистого спуфа от
Пожалуйста, авторизуйтесь для просмотра ссылки.
, не использует баянистый jmp rbx/rcx/rdi/etc гаджет и содержит ROP цепочку из фейк вызовов находящихся в сигнед модулях, также на данный момент гаджет не проверяется в BE/EAC :seemsgood:

P.s. ASM код всратый, можно переписать/оптимизировать.

C++:
// 48 83 C4 C3

add rsp, 0xX
ret

C++:
EXTERNDEF proxy_call_returns:QWORD
EXTERNDEF proxy_call_fakestack:QWORD
EXTERNDEF proxy_call_fakestack_size:QWORD

.DATA
    proxy_call_returns QWORD 32 dup (?)
    proxy_call_fakestack dq ?
    proxy_call_fakestack_size dq ?

.CODE

    proxy_call_stub PROC PUBLIC
        ; push arguments
        push 0                              ; stack align
        push r9                             ; save 4th arg
        push r8                             ; save 3th arg
        push rdx                            ; save 2th arg
        push rcx                            ; save 1th arg

        mov rax, rdx                        ; mov function address to rax
        mov rcx, rsp                        ; mov stack value to rcx
        add rcx, 50h                        ; adjust stack
        mov rdx, rcx                        ; store stack to compare later

        ; check for arguments length

        cmp qword ptr[rsp], 21376969        ; check if it's last argument (our fake argument)

        jz end_args_calc                    ; we found our fake argument

        mov rax, r8;                        ; new possible function address
        cmp qword ptr[rsp + 8], 21376969h   ; check if it's last argument (our fake argument)

        jz end_args_calc                    ; we found our fake argument

        mov rax, r9;                        ; new possible function address
        cmp r8, 21376969h                   ; check if it's last argument (our fake argument)

        jz end_args_calc                    ; we found our fake argument

        mov rax, [rcx]                      ; new possible function address
        cmp r9, 21376969h                   ; check if it's last argument (our fake argument)

        jz end_args_calc                    ; we found our fake argument

    ; stackwalk to found our fake argument

    check_for_args_end:
        mov rax, [rcx + 8]                  ; new possible function address
        cmp qword ptr[rcx], 21376969h       ; check if it's last argument (our fake argument)

        jz end_args_calc                    ; we found our fake argument

        add rcx, 8                          ; add stack argument
        jmp check_for_args_end

        end_args_calc:

        sub rcx, rdx                        ; stack arguments size in bytes

        mov r8, cleanup_call
        push r8                             ; push our cleanup return address

        ; create fake callstack

        mov r10, rcx
        mov rcx, proxy_call_fakestack_size

        cmp rcx, 0
        jz skip_fakecallstack

        lea r8, [rcx * 8]
        sub rsp, r8

        ; backup register

        mov r8, rsi
        mov r9, rdi

        mov rsi, proxy_call_fakestack
        mov rdi, rsp

        rep movsq

        ; restore registers

        mov rsi, r8
        mov rdi, r9

    skip_fakecallstack:
        mov rcx, r10

        ; stack align

        mov r8, rcx
        and r8, 15

        mov r8, rcx
        jnz stack_aligned

        push 0
        add r8, 8

    stack_aligned:

        ; build callstack

        push_value:

        cmp rcx, 0
        jz do_call

        push [rdx + rcx - 8]

        sub rcx, 8
        jmp push_value

    do_call:

        add r8, 20h
        ; psuedo sub rsp, 20h

        push 0
        push 0
        push 0
        push 0

        ; push proper return address

        lea r9, proxy_call_returns
        mov r9, [r9 + r8]
        push r9

        mov r9, [rdx - 38h]                ; restore original r9
        mov r8, [rdx - 40h]                ; restore original r8
        mov rcx, [rdx - 50h]               ; restore original rcx
        mov rdx, [rdx - 48h]               ; restore original rdx

        xor r12, r12
        xor r14, r14

        jmp rax                            ; call function

    cleanup_call:

        add rsp, 28h
        ret

    proxy_call_stub ENDP

END

C++:
#pragma once
#include <windows.h>
#include <cstdint>

#include <map>
#include <vector>

namespace safe_utils
{
    extern "C" void proxy_call_stub();
    extern "C" std::uintptr_t proxy_call_returns[];

    extern "C" std::size_t proxy_call_fakestack_size;
    extern "C" std::uintptr_t * proxy_call_fakestack;

    template <typename return_type, typename... Args> __forceinline auto spoof_call(uintptr_t procedure, Args... args)
    {
        return reinterpret_cast<return_type(__cdecl*)(Args..., std::uint64_t, void*)>(proxy_call_stub)(Args(args)..., 0x21376969, reinterpret_cast<void*>(procedure));
    }

    __forceinline void* __cdecl safe_memset(void* dest, int value, size_t num)
    {
        __stosb(static_cast<unsigned char*>(dest),
            static_cast<unsigned char>(value), num);
        return dest;
    }

    __forceinline void* __cdecl safe_memcpy(void* dest, const void* src, size_t num)
    {
        __movsb(static_cast<unsigned char*>(dest),
            static_cast<const unsigned char*>(src), num);
        return dest;
    }

    void prepare_proxy_for_module(std::uint8_t* module, std::uint32_t max_fakestack = 12)
    {
        std::map<std::int8_t, std::vector<std::uintptr_t>> proxy_clean_returns;

        auto dos = reinterpret_cast<IMAGE_DOS_HEADER*>(module);
        auto nt = reinterpret_cast<IMAGE_NT_HEADERS*>(module + dos->e_lfanew);
        auto image_size = nt->OptionalHeader.SizeOfImage;

        auto section = IMAGE_FIRST_SECTION(nt);

        MEMORY_BASIC_INFORMATION mbi;

        for (auto i = 0; i < nt->FileHeader.NumberOfSections; i++)
        {
            if ((section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0)
            {
                auto address = module + section->VirtualAddress;
        
                while (true)
                {
                    safe_memset(&mbi, 0, sizeof(mbi));

                    if (!VirtualQuery(address, &mbi, sizeof(mbi)))
                        break;

                    auto base_page = (std::uint8_t*) mbi.BaseAddress;

                    if (mbi.Protect == PAGE_EXECUTE_READ ||
                        mbi.Protect == PAGE_EXECUTE_READWRITE ||
                        mbi.Protect == PAGE_EXECUTE_WRITECOPY)
                    {
                        for (auto i = 0u; i < (mbi.RegionSize - 0x10); i++)
                        {
                            // add rsp, 0xX
                            // ret
                            if (base_page[i] == 0x48 &&
                                base_page[i + 1] == 0x83 &&
                                base_page[i + 2] == 0xC4 &&
                                base_page[i + 4] == 0xC3)
                            {
                                proxy_clean_returns[base_page[i + 3]].push_back(std::uintptr_t(base_page + i));
                            }
                        }
                    }

                    address = base_page + mbi.RegionSize;
            
                    if (address >= (module + section->VirtualAddress + section->Misc.VirtualSize))
                        break;
                }
            }

            section++;
        }

        std::vector<std::int8_t> proxy_clean_returns_keys;
        proxy_clean_returns_keys.reserve(proxy_clean_returns.size());

        std::vector<std::uintptr_t> fakestack;
        fakestack.reserve(max_fakestack * 2);

        for (auto& it : proxy_clean_returns)
        {
            const auto index = (it.first / sizeof(std::uintptr_t));
            proxy_call_returns[index] = it.second.at(__rdtsc() % it.second.size());

            if (index < 10 && index % 2 == 1) //for stack align
                proxy_clean_returns_keys.push_back(it.first);
        }

        while (fakestack.size() < max_fakestack)
        {
            const auto pseudo_random_number = __rdtsc();
            const auto return_length = proxy_clean_returns_keys.at(pseudo_random_number % proxy_clean_returns_keys.size());
            const auto params = (return_length / sizeof(std::uintptr_t));
            const auto& address_array = proxy_clean_returns[return_length];
            const auto random_address = address_array.at(pseudo_random_number % address_array.size());

            fakestack.push_back(random_address);
    
            for (auto i = 0u; i < params; i++)
                fakestack.push_back(std::uintptr_t(module) + (__rdtsc() % image_size));
        }

        proxy_call_fakestack_size = fakestack.size();
        proxy_call_fakestack = new std::uintptr_t[fakestack.size()];

        safe_memcpy(proxy_call_fakestack, fakestack.data(), proxy_call_fakestack_size * sizeof(std::uintptr_t));
    }
}

C++:
auto kernel32_base = GetModuleHandleA("kernel32.dll");
auto beep_func = reinterpret_cast<uintptr_t>(GetProcAddress(kernel32_base, "Beep"));

constexpr int32_t fake_stack_size = 12;

safe_utils::prepare_proxy_for_module(reinterpret_cast<uint8_t*>(kernel32_base), fake_stack_size);

DWORD dwFreq = 1000;
DWORD dwDuration = 100;

using tBeep = decltype(&Beep);

safe_utils::spoof_call<tBeep>(beep_func, dwFreq, dwDuration);

 
Последнее редактирование:
АМБАССАДОР ЩИТПОСТА
Пользователь
Статус
Оффлайн
Регистрация
24 Мар 2022
Сообщения
178
Реакции[?]
42
Поинты[?]
3K
1700682688884.png
1700683575541.pngспуф колл один хуй понос потому что реальный адрес есть один хуй
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
2 Фев 2022
Сообщения
69
Реакции[?]
14
Поинты[?]
19K
Посмотреть вложение 264326
Посмотреть вложение 264327спуф колл один хуй понос потому что реальный адрес есть один хуй
Ну все равно лучше чем ничего, по крайней мере хотя бы не та поебень 2018-го года которую каждый второй дебик абузит :roflanEbalo:
Кому надо - рекоднут стабчик чтоб реальный адрес нельзя было найти)
 
Эксперт
Статус
Оффлайн
Регистрация
29 Мар 2021
Сообщения
1,605
Реакции[?]
607
Поинты[?]
48K
Obstruct Omicronium
Пользователь
Статус
Оффлайн
Регистрация
28 Авг 2022
Сообщения
67
Реакции[?]
78
Поинты[?]
66K
Это будет работать до первого бинаря с ASLR, потом страдать только :CoolStoryBob:
 
Сверху Снизу