Как создать область / раздел памяти со следующими свойствами (проверено QueryWorkingSetEx и VirtualQuery)? - PullRequest
0 голосов
/ 03 июля 2018

Мне нужно сделать область памяти / секцию со следующими свойствами:

VirtualQuery функция, проверенная в таком регионе, должна вернуть:

  • Распределение защиты: 0x20 [PAGE_EXECUTE_READ]
  • Защита: 0x20 [PAGE_EXECUTE_READ]
  • Состояние: 0x1000 [MEM_COMMIT]
  • Тип: 0x40000 [MAPPED]

QueryWorkingSetEx функция, проверенная в таком регионе, должна вернуть:

  • Действительный: 1
  • Общий: 1
  • ShareCount: 2
  • Узел: 0
  • LargePage: 0
  • Заблокировано: 0
  • Плохо: 0
  • Win32Защита: 0x20 [PAGE_EXECUTE_READ]

Кроме того, этот регион не может быть сопоставлен с файлом диска (INVALID_HANDLE_VALUE при создании раздела сопоставленного файла). Кроме того, он должен быть заполнен желаемыми данными, прежде чем он получит только PAGE_EXECUTE_READ доступ.

Более того, невозможно изменить защиту такого сектора (используя функцию VirtualProtect) на PAGE_READONLY или PAGE_WRITECOPY, несмотря на то, что PAGE_EXECUTE_READ. Это указывает на то, что оно может иметь недокументированное свойство SEC_NO_CHANGE.

Это возможно сделать, потому что он существует в вредоносной программе, которую я отлаживаю, но мне сложно копировать, также несколько человек в команде не смогли, я буду впечатлен, если кто-то предоставит мне информацию о том, как создать это.

1 Ответ

0 голосов
/ 04 июля 2018

здесь нет ничего сложного - нам действительно нужно создать раздел с

#define SEC_NO_CHANGE 0x00400000

из createsec.c

SEC_NO_CHANGE - После сопоставления файла защита не может не может быть изменено, и представление не может быть отображено. представление не отображается при удалении процесса. Не может использоваться с SEC_IMAGE.

поэтому нужно просто создать раздел с этим флагом. затем сначала сопоставьте его с PAGE_READWRITE защитой страницы и запустите данные. чем распаковать и снова сопоставить с защитой PAGE_EXECUTE_READ. все. ничего особенного или сложного.

#define SEC_NO_CHANGE 0x00400000

NTSTATUS ghty(PVOID* pBaseAddress, ULONG SectionSize = 0x10000)
{
    HANDLE hSection;
    LARGE_INTEGER MaxSize = { SectionSize };
    NTSTATUS status = ZwCreateSection(&hSection, 
        SECTION_MAP_READ|SECTION_MAP_WRITE|SECTION_MAP_EXECUTE, 0, &MaxSize, 
        PAGE_EXECUTE_READWRITE, SEC_COMMIT|SEC_NO_CHANGE, 0);

    if (0 <= status)
    {
        PVOID BaseAddress = 0;
        SIZE_T ViewSize = 0;

        if (0 <= (status = ZwMapViewOfSection(hSection, NtCurrentProcess(), 
            &BaseAddress, 0, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_READWRITE)))
        {

            memset(BaseAddress, 0xc3, ViewSize);
            ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);

            *pBaseAddress = 0;
            status = ZwMapViewOfSection(hSection, NtCurrentProcess(), 
                pBaseAddress, 0, 0, 0, &(ViewSize = 0), ViewUnmap, 0, PAGE_EXECUTE_READ);
        }

        NtClose(hSection);
    }

    return status;
}

void test()
{
    PVOID BaseAddress;
    if (0 <= ghty(&BaseAddress))
    {
        //++ test
        ULONG op;
        SIZE_T Size = 1;
        PVOID pv = BaseAddress;
        ZwProtectVirtualMemory(NtCurrentProcess(), &pv, &Size, PAGE_READONLY, &op);
        // STATUS_INVALID_PAGE_PROTECTION will be
        // if we use SEC_NO_CHANGE
        // -- test

        ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
    }
}

также только что нашел эту ссылку Код самопреобразования . возможный код, который вы отлаживаете, делают то же самое. думаю, смысл делать это - вы не можете устанавливать точки останова (int 3) в этом коде - потому что память не может быть записана и не может быть сделана доступной для записи. в результате невозможно вставить bp

...