注册

CpuDbg x96

查看: 283|回复: 0
收起左侧

禁用ASLR(下篇)

[复制链接]
发表于 2024-7-15 03:17:01 | 显示全部楼层 |阅读模式
PixPin_2024-07-15_10-49-56.png

这是维基上对ASLR的解释. 这里还要说明一下, 维基中说ASLR仅适用于动态链接库和可执行文件.
这样说是不严谨的. 因为可执行文件中如果没有重定位表, 也一样是不适用的.

咱们的cpudbg已经支持禁用ASLR功能了. 如图:

PixPin_2024-07-15_10-42-02.png

这个是通过 PE 结构中的 ntHeaders.OptionalHeader.DllCharacteristics  来实现禁用的.
禁用后另存为一份文件. 一次修改,终生有效.
具体的可以看之前的视频.



但有的时候, 目标程序有加外壳, 现在大多加密壳都有自校验, 如果直接修改, 运行就会报错.
那有没有什么办法, 不修改PE文件, 又同时能禁用ASLR呢? 答案是当然有.

刚开始我又尝试和GPT摆会龙门阵. GPT 告诉我很多方法, 其中包括但不限于:

1. 编译时通过IDE设置禁用
2. 通过注册表禁用
3. WINDBG命令 .disable_aslr
4. GDB命令 set disable-randomization on

GPT说的这些都不是我想要的, 我想要的是能一次性, 用完就又恢复的,同时又不修改自身,也不修改系统. 更不会使用三方库或调试器.
和GPT又扯了一会, 它又告诉我用 SetProcessMitigationPolicy 函数.

[C] 纯文本查看 复制代码
BOOL SetProcessMitigationPolicy(
  PROCESS_MITIGATION_POLICY MitigationPolicy,
  PVOID                     lpBuffer,
  SIZE_T                    dwLength
);


PixPin_2024-07-15_11-00-33.png

看了下这个函数都没有进程句柄,或PID. 大概率是修改自身的. 还是没卵用...
于是又和GPT扯了好久 好久. 然后它也开始天马行空的回答了.
它告诉我在PEB中有一个标志位(不存在), 那个标志位就是用来控制 ASLR开关的.
下面是GPT给的代码, 其中 flags 就是不存在的.

[C] 纯文本查看 复制代码
#include <windows.h>
#include <stdio.h>

BOOL DisableASLRAndLaunch(LPCSTR applicationName) {
    STARTUPINFOA si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    // Create the process in a suspended state
    if (!CreateProcessA(applicationName, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED | DEBUG_PROCESS, NULL, NULL, &si, &pi)) {
        printf("CreateProcess failed (%d).\n", GetLastError());
        return FALSE;
    }

    // Disable ASLR by modifying the process's PEB (Process Environment Block)
    CONTEXT ctx;
    ctx.ContextFlags = CONTEXT_FULL;
    if (!GetThreadContext(pi.hThread, &ctx)) {
        printf("GetThreadContext failed (%d).\n", GetLastError());
        TerminateProcess(pi.hProcess, 0);
        return FALSE;
    }

    // Adjust the PEB flags to disable ASLR
    PEB* peb = (PEB*)ctx.Rdx; // On x64, PEB address is in Rdx
    // On x86, use ctx.Ebx to get the PEB address instead

    // Read and modify the PEB flags to disable ASLR
    DWORD oldProtect;
    if (!VirtualProtectEx(pi.hProcess, &peb->Flags, sizeof(peb->Flags), PAGE_READWRITE, &oldProtect)) {
        printf("VirtualProtectEx failed (%d).\n", GetLastError());
        TerminateProcess(pi.hProcess, 0);
        return FALSE;
    }
    DWORD flags;
    if (!ReadProcessMemory(pi.hProcess, &peb->Flags, &flags, sizeof(flags), NULL)) {
        printf("ReadProcessMemory failed (%d).\n", GetLastError());
        TerminateProcess(pi.hProcess, 0);
        return FALSE;
    }
    flags &= ~0x4; // Clear the ASLR flag (0x4)
    if (!WriteProcessMemory(pi.hProcess, &peb->Flags, &flags, sizeof(flags), NULL)) {
        printf("WriteProcessMemory failed (%d).\n", GetLastError());
        TerminateProcess(pi.hProcess, 0);
        return FALSE;
    }
    if (!VirtualProtectEx(pi.hProcess, &peb->Flags, sizeof(peb->Flags), oldProtect, &oldProtect)) {
        printf("VirtualProtectEx restore failed (%d).\n", GetLastError());
        TerminateProcess(pi.hProcess, 0);
        return FALSE;
    }

    // Resume the process
    if (ResumeThread(pi.hThread) == -1) {
        printf("ResumeThread failed (%d).\n", GetLastError());
        TerminateProcess(pi.hProcess, 0);
        return FALSE;
    }

    // Wait for the process to exit
    WaitForSingleObject(pi.hProcess, INFINITE);

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return TRUE;
}

int main() {
    if (DisableASLRAndLaunch("C:\\Path\\To\\Your\\Application.exe")) {
        printf("ASLR disabled and application launched successfully.\n");
    } else {
        printf("Failed to disable ASLR and launch application.\n");
    }
    return 0;
}


聊到最后, GPT 终于说了一个看起来有亿点点靠谱的回答.

PixPin_2024-07-15_11-04-39.png

代码如下:

[C] 纯文本查看 复制代码
#include <windows.h>
#include <stdio.h>

BOOL DisableASLRAndLaunch(LPCSTR applicationName) {
    STARTUPINFOA si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    // Create the process in a suspended state
    if (!CreateProcessA(applicationName, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
        printf("CreateProcess failed (%d).\n", GetLastError());
        return FALSE;
    }

    // Get the PEB address
    CONTEXT ctx;
    ctx.ContextFlags = CONTEXT_FULL;
    if (!GetThreadContext(pi.hThread, &ctx)) {
        printf("GetThreadContext failed (%d).\n", GetLastError());
        TerminateProcess(pi.hProcess, 0);
        return FALSE;
    }

#ifdef _WIN64
    PEB* peb = (PEB*)ctx.Rdx; // On x64, PEB address is in Rdx
#else
    PEB* peb = (PEB*)ctx.Ebx; // On x86, PEB address is in Ebx
#endif

    // Adjust the PEB flags to disable ASLR
    DWORD oldProtect;
    if (!VirtualProtectEx(pi.hProcess, peb, sizeof(PEB), PAGE_READWRITE, &oldProtect)) {
        printf("VirtualProtectEx failed (%d).\n", GetLastError());
        TerminateProcess(pi.hProcess, 0);
        return FALSE;
    }

    PEB pebCopy;
    if (!ReadProcessMemory(pi.hProcess, peb, &pebCopy, sizeof(pebCopy), NULL)) {
        printf("ReadProcessMemory failed (%d).\n", GetLastError());
        TerminateProcess(pi.hProcess, 0);
        return FALSE;
    }

    pebCopy.ImageBaseAddress = (PVOID)0x00400000; // Set ImageBaseAddress to disable ASLR

    if (!WriteProcessMemory(pi.hProcess, peb, &pebCopy, sizeof(pebCopy), NULL)) {
        printf("WriteProcessMemory failed (%d).\n", GetLastError());
        TerminateProcess(pi.hProcess, 0);
        return FALSE;
    }

    if (!VirtualProtectEx(pi.hProcess, peb, sizeof(PEB), oldProtect, &oldProtect)) {
        printf("VirtualProtectEx restore failed (%d).\n", GetLastError());
        TerminateProcess(pi.hProcess, 0);
        return FALSE;
    }

    // Resume the process
    if (ResumeThread(pi.hThread) == -1) {
        printf("ResumeThread failed (%d).\n", GetLastError());
        TerminateProcess(pi.hProcess, 0);
        return FALSE;
    }

    // Wait for the process to exit
    WaitForSingleObject(pi.hProcess, INFINITE);

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return TRUE;
}

int main() {
    if (DisableASLRAndLaunch("C:\\Path\\To\\Your\\Application.exe")) {
        printf("ASLR disabled and application launched successfully.\n");
    } else {
        printf("Failed to disable ASLR and launch application.\n");
    }
    return 0;
}


GPT是直接修改PEB中的基址.看起来好像没问题,先编译个GPT的代码来加载一个支持ASLR的程序试试.

PixPin_2024-07-15_11-11-13.png

运行后,直接报错了...
GPT中的方法,是通过系统第一次中断,从CONTEXT中拿到PEB, 然后直接修改PEB中的imagebase.
将原先的基址,强制修改成 0x00400000. 这看着好像没有问题.
但由于系统第一次中断时, 时机已经晚了. 原始的ASLR基址已经被系统分配了.
而转到 0x00400000 还是未分配状态. 因此报错是正常的.

那这样还有办法动态禁用ASLR吗? 当然答案是有的. 只是会麻烦些...

(群里有朋友强烈建议先更新调试器的核心功能. 其它附属功能等调试器稳定后再更新.这个禁用ASLR的功能就等以后出正式版之后再更新吧...)
--------------------------------------------------------------------
to be continued...
回复

使用道具 举报

游客
回复
您需要登录后才可以回帖 登录 | 注册

QQ|Archiver|手机版| CpuDbg x96

GMT, 2024-10-14 06:05 , Processed in 0.062500 second(s), 20 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表