飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 1199|回复: 0

[C/C++] WindowsNoExec -滥用现有指令,在不分配可执行内存的情况下执行任意代码

[复制链接]
  • TA的每日心情
    开心
    2019-3-15 11:00
  • 签到天数: 262 天

    [LV.8]以坛为家I

    发表于 2022-2-11 17:41:51 | 显示全部楼层 |阅读模式
    本帖最后由 梦幻的彼岸 于 2022-2-11 17:47 编辑

    翻译
    原文地址:https://www.x86matthew.com/view_post?id=windows_no_exec
    功能:滥用现有指令,在不分配可执行内存的情况下执行任意代码


    这个概念验证允许我们 "重新使用 "ntdll.dll中的现有指令来执行我们自己的代码。目标代码只存在于数据部分,这意味着这种方法规避了非可执行内存的保护。这种方法的一个副作用意味着它很难被调试,并绕过了静态代码分析。

    有趣的是,这种技术只需要一个API - RtlAddVectoredExceptionHandler。我的代码还使用了GetModuleHandle来检索ntdll.dll的基本地址,但如果有必要,这也是一个很容易重新创建的函数。如果你有足够的创造力,你也可以通过扫描ntdll.dll来找到vectored异常处理程序列表指针,然后手动添加条目,从而消除RtlAddVectoredExceptionHandler调用。
    1.gif
    这个代码的工作原理如下:
    1. 创建一个数据结构,包含所有我们要执行的汇编指令。
    2. 在ntdll.dll的代码部分搜索上述每条指令,并存储其地址。
    3. 使用RtlAddVectoredExceptionHandler在我们的程序中添加一个自定义的异常处理程序。
    4. 使用int 3触发一个断点。
    5. 现在程序已经进入了我们的自定义异常处理程序。存储原来的线程上下文以备后用。
    6. 将EIP寄存器设置为我们列表中的第一个目标指令(在ntdll.dll中)。
    7. 如果当前指令是一个 "调用",使用Dr0调试寄存器在调用后的指令上设置一个硬件断点--我们要 "跨过 "调用。否则,用EFlags |= 0x100设置单步标志,在下一条指令上断开。
    8. 更新当前指令所需的任何其他寄存器的值。
    9. 使用EXCEPTION_CONTINUE_EXECUTION继续执行。下一条指令将引发另一个异常,我们将从第6步继续,直到所有的指令都依次运行完毕。
    10. 在所有的目标指令执行完毕后,恢复步骤#5中的原始线程上下文,以继续程序的原始流程。
    下面的数据结构将调用MessageBoxA:
    [C++] 纯文本查看 复制代码
    InstructionEntryStruct Global_InstructionList[] =
    {
            // allocate 1kb buffer for messagebox title using GlobalAlloc
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 1024, 0, 0, 0, FLAG_ECX },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, GMEM_FIXED, 0, 0, 0, FLAG_ECX },
            { "call eax ; (GlobalAlloc)", { 0xFF, 0xD0 }, 2, 0, (DWORD)GlobalAlloc, 0, 0, 0, 0, 0, FLAG_EAX | FLAG_CALL },
    
            // set messagebox title to "www.x86matthew.com"
            { "mov ebx, eax", { 0x8B, 0xD8 }, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'w' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'w', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'w' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'w', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'w' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'w', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '.' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '.', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'x' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'x', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '8' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '8', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '6' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '6', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'm' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'm', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'a' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'a', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'h' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'h', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'e' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'e', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'w' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'w', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '.' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '.', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'c' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'c', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'o' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'o', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'm' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'm', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; (null) ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '\0', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
    
            // store messagebox title ptr in edi register
            { "mov edi, eax", { 0x8B, 0xF8 }, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
    
            // allocate 1kb buffer for messagebox text using GlobalAlloc
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 1024, 0, 0, 0, FLAG_ECX },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, GMEM_FIXED, 0, 0, 0, FLAG_ECX },
            { "call eax ; (GlobalAlloc)", { 0xFF, 0xD0 }, 2, 0, (DWORD)GlobalAlloc, 0, 0, 0, 0, 0, FLAG_EAX | FLAG_CALL },
    
            // set messagebox text to "A message box from ntdll.dll"
            { "mov ebx, eax", { 0x8B, 0xD8 }, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'A' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'A', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: ' ' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, ' ', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'm' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'm', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'e' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'e', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 's' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 's', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 's' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 's', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'a' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'a', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'g' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'g', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'e' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'e', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: ' ' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, ' ', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'b' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'b', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'o' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'o', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'x' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'x', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: ' ' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, ' ', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'f' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'f', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'r' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'r', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'o' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'o', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'm' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'm', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: ' ' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, ' ', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'n' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'n', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'd' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'd', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'l' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'l', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'l' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'l', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '.' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '.', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'd' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'd', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'l' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'l', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'l' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'l', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; (null) ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '\0', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
    
            // call MessageBoxA
            { "push ecx", { 0x51 }, 1, 0, 0, 0, MB_OK, 0, 0, 0, FLAG_ECX },
            { "push edi", { 0x57 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "push eax", { 0x50 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 0, 0, 0, 0, FLAG_ECX },
            { "call eax ; (MessageBoxA)", { 0xFF, 0xD0 }, 2, 0, (DWORD)MessageBoxA, 0, 0, 0, 0, 0, FLAG_EAX | FLAG_CALL },
    };
    

    该结构头包含以下字段:
    [Shell] 纯文本查看 复制代码
    struct InstructionEntryStruct
    {
            char *pLabel;
    
            BYTE bInstruction[16];
            DWORD dwInstructionLength;
    
            DWORD dwInstructionAddr;
    
            DWORD dwEax;
            DWORD dwEbx;
            DWORD dwEcx;
            DWORD dwEdx;
            DWORD dwEdi;
            DWORD dwEsi;
            DWORD dwInstructionFlags;
    };

    pLabel
    这个字段仅用于记录/调试的目的。

    bInstruction
    这个字段包含目标指令的操作码--例如0x50用于推送eax。

    dwInstructionLength
    bInstruction字段的长度。

    dwInstructionAddr
    这个字段由程序填充 - ntdll.dll被扫描以找到匹配指令的地址。

    dwEax / dwEbx / dwEcx / dwEdx / dwEdi / dwEsi
    这些字段在当前指令执行前设置指定的寄存器值。

    dwInstructionFlags
    这个字段指定哪些寄存器的值应该被更新(见上文)。它还用于指定当前指令是否为 "调用"。

    重要的是要注意我们选择的指令操作码。例如,如果我们想加入一条push 0x12345678指令,我们可以这样做:
    [Shell] 纯文本查看 复制代码
    { "push 0x12345678", { 0x68, 0x44, 0x33, 0x22, 0x11 }, 5, 0, 0, 0, 0, 0, 0, 0, 0 }

    ...但这不会起作用。这是因为ntdll.dll非常不可能在代码部分包含一个包含[0x68, 0x44, 0x33, 0x22, 0x11]的序列。这段代码利用了我们可以在指令执行前在异常处理程序内操作寄存器这一事实,这意味着我们可以用以下方式代替:
    [Shell] 纯文本查看 复制代码
    { "push eax", { 0x50 }, 1, 0, 0x11223344, 0, 0, 0, 0, 0, FLAG_EAX }

    上面的条目只依赖于在ntdll.dll代码部分找到一个0x50(push eax)的字节。eax寄存器的值将在指令执行前被异常处理程序设置为0x11223344。

    下面的数据结构演示了一个稍微复杂的例子--这创建了一个文件(x86matthew.txt),并将 "由ntdll创建的文本文件 "写入返回的句柄。
    [C++] 纯文本查看 复制代码
    InstructionEntryStruct Global_InstructionList[] =
    {
            // allocate 1kb buffer for filename using GlobalAlloc
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 1024, 0, 0, 0, FLAG_ECX },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, GMEM_FIXED, 0, 0, 0, FLAG_ECX },
            { "call eax ; (GlobalAlloc)", { 0xFF, 0xD0 }, 2, 0, (DWORD)GlobalAlloc, 0, 0, 0, 0, 0, FLAG_EAX | FLAG_CALL },
    
            // set filename to "x86matthew.txt"
            { "mov ebx, eax", { 0x8B, 0xD8 }, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'x' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'x', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '8' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '8', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '6' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '6', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'm' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'm', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'a' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'a', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'h' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'h', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'e' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'e', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'w' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'w', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '.' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '.', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'x' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'x', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; (null) ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '\0', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
    
            // call CreateFileA
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 0, 0, 0, 0, FLAG_ECX },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, FILE_ATTRIBUTE_NORMAL, 0, 0, 0, FLAG_ECX },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, CREATE_ALWAYS, 0, 0, 0, FLAG_ECX },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 0, 0, 0, 0, FLAG_ECX },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 0, 0, 0, 0, FLAG_ECX },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, GENERIC_WRITE, 0, 0, 0, FLAG_ECX },
            { "push eax", { 0x50 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "call eax ; (CreateFileA)", { 0xFF, 0xD0 }, 2, 0, (DWORD)CreateFileA, 0, 0, 0, 0, 0, FLAG_EAX | FLAG_CALL },
    
            // store file handle in esi register
            { "mov esi, eax", { 0x8B, 0xF0 }, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, // mov esi, eax (esi=hFile)
    
            // allocate 1kb buffer for file content using GlobalAlloc
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 1024, 0, 0, 0, FLAG_ECX },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, GMEM_FIXED, 0, 0, 0, FLAG_ECX },
            { "call eax ; (GlobalAlloc)", { 0xFF, 0xD0 }, 2, 0, (DWORD)GlobalAlloc, 0, 0, 0, 0, 0, FLAG_EAX | FLAG_CALL },
    
            // set file content buffer to "Text file created by ntdll"
            { "mov ebx, eax", { 0x8B, 0xD8 }, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'T' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'T', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'e' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'e', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'x' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'x', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: ' ' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, ' ', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'f' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'f', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'i' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'i', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'l' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'l', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'e' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'e', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: ' ' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, ' ', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'c' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'c', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'r' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'r', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'e' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'e', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'a' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'a', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'e' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'e', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'd' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'd', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: ' ' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, ' ', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'b' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'b', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'y' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'y', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: ' ' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, ' ', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'n' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'n', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'd' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'd', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'l' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'l', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'l' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'l', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; (null) ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '\0', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
    
            // call WriteFile (and allocate a local variable on the stack for the lpNumberOfBytesWritten value)
            { "push ebp", { 0x55 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "push 0", { 0x6A, 0x00 }, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov ebp, esp", { 0x8B, 0xEC }, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 0, 0, 0, 0, FLAG_ECX },
            { "push ebp", { 0x55 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 26, 0, 0, 0, FLAG_ECX },
            { "push eax", { 0x50 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "push esi", { 0x56 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "call eax ; (WriteFile)", { 0xFF, 0xD0 }, 2, 0, (DWORD)WriteFile, 0, 0, 0, 0, 0, FLAG_EAX | FLAG_CALL },
            { "pop ecx", { 0x59 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "pop ebp", { 0x5D }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
    
            // call CloseHandle
            { "push esi", { 0x56 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "call eax ; (CloseHandle)", { 0xFF, 0xD0 }, 2, 0, (DWORD)CloseHandle, 0, 0, 0, 0, 0, FLAG_EAX | FLAG_CALL },
    };

    以下是完整的代码:
    [C++] 纯文本查看 复制代码
    #include <stdio.h>
    #include <windows.h>
    
    #define FLAG_EAX 0x00000001
    #define FLAG_EBX 0x00000002
    #define FLAG_ECX 0x00000004
    #define FLAG_EDX 0x00000008
    #define FLAG_EDI 0x00000010
    #define FLAG_ESI 0x00000020
    #define FLAG_CALL 0x00000040
    
    struct InstructionEntryStruct
    {
            char *pLabel;
    
            BYTE bInstruction[16];
            DWORD dwInstructionLength;
    
            DWORD dwInstructionAddr;
    
            DWORD dwEax;
            DWORD dwEbx;
            DWORD dwEcx;
            DWORD dwEdx;
            DWORD dwEdi;
            DWORD dwEsi;
            DWORD dwInstructionFlags;
    };
    
    DWORD dwGlobal_CurrInstruction = 0;
    CONTEXT Global_OrigContext;
    
    InstructionEntryStruct Global_InstructionList[] =
    {
            // allocate 1kb buffer for messagebox title using GlobalAlloc
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 1024, 0, 0, 0, FLAG_ECX },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, GMEM_FIXED, 0, 0, 0, FLAG_ECX },
            { "call eax ; (GlobalAlloc)", { 0xFF, 0xD0 }, 2, 0, (DWORD)GlobalAlloc, 0, 0, 0, 0, 0, FLAG_EAX | FLAG_CALL },
    
            // set messagebox title to "www.x86matthew.com"
            { "mov ebx, eax", { 0x8B, 0xD8 }, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'w' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'w', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'w' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'w', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'w' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'w', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '.' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '.', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'x' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'x', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '8' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '8', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '6' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '6', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'm' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'm', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'a' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'a', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'h' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'h', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'e' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'e', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'w' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'w', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '.' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '.', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'c' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'c', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'o' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'o', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'm' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'm', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; (null) ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '\0', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
    
            // store messagebox title ptr in edi register
            { "mov edi, eax", { 0x8B, 0xF8 }, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
    
            // allocate 1kb buffer for messagebox text using GlobalAlloc
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 1024, 0, 0, 0, FLAG_ECX },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, GMEM_FIXED, 0, 0, 0, FLAG_ECX },
            { "call eax ; (GlobalAlloc)", { 0xFF, 0xD0 }, 2, 0, (DWORD)GlobalAlloc, 0, 0, 0, 0, 0, FLAG_EAX | FLAG_CALL },
    
            // set messagebox text to "A message box from ntdll.dll"
            { "mov ebx, eax", { 0x8B, 0xD8 }, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'A' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'A', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: ' ' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, ' ', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'm' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'm', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'e' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'e', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 's' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 's', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 's' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 's', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'a' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'a', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'g' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'g', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'e' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'e', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: ' ' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, ' ', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'b' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'b', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'o' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'o', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'x' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'x', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: ' ' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, ' ', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'f' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'f', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'r' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'r', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'o' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'o', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'm' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'm', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: ' ' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, ' ', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'n' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'n', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 't' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 't', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'd' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'd', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'l' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'l', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'l' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'l', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: '.' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '.', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'd' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'd', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'l' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'l', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; character: 'l' ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, 'l', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "mov byte ptr [ebx], dl ; (null) ", { 0x88, 0x13 }, 2, 0, 0, 0, 0, '\0', 0, 0, FLAG_EDX },
            { "inc ebx", { 0x43 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
    
            // call MessageBoxA
            { "push ecx", { 0x51 }, 1, 0, 0, 0, MB_OK, 0, 0, 0, FLAG_ECX },
            { "push edi", { 0x57 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "push eax", { 0x50 }, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
            { "push ecx", { 0x51 }, 1, 0, 0, 0, 0, 0, 0, 0, FLAG_ECX },
            { "call eax ; (MessageBoxA)", { 0xFF, 0xD0 }, 2, 0, (DWORD)MessageBoxA, 0, 0, 0, 0, 0, FLAG_EAX | FLAG_CALL },
    };
    
    LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *pExceptionInfo)
    {
            InstructionEntryStruct *pCurrInstruction = NULL;
    
            // ensure this is a breakpoint / single step exception
            if(pExceptionInfo->ExceptionRecord->ExceptionCode != STATUS_BREAKPOINT && pExceptionInfo->ExceptionRecord->ExceptionCode != STATUS_SINGLE_STEP)
            {
                    // this is not the exception that we expected - pass this exception to the next handler
                    return EXCEPTION_CONTINUE_SEARCH;
            }
    
            // reset hardware breakpoints
            pExceptionInfo->ContextRecord->Dr0 = 0;
            pExceptionInfo->ContextRecord->Dr7 = 0;
    
            if(dwGlobal_CurrInstruction == 0)
            {
                    // store original context
                    memcpy((void*)&Global_OrigContext, (void*)pExceptionInfo->ContextRecord, sizeof(CONTEXT));
            }
            else if(dwGlobal_CurrInstruction >= (sizeof(Global_InstructionList) / sizeof(Global_InstructionList[0])))
            {
                    // finished executing all instructions - restore original context
                    memcpy((void*)pExceptionInfo->ContextRecord, (void*)&Global_OrigContext, sizeof(CONTEXT));
    
                    // move to the next instruction (after int3)
                    pExceptionInfo->ContextRecord->Eip++;
    
                    // continue execution
                    return EXCEPTION_CONTINUE_EXECUTION;
            }
    
            // get current instruction entry
            pCurrInstruction = &Global_InstructionList[dwGlobal_CurrInstruction];
    
            // set instruction ptr to next instruction
            pExceptionInfo->ContextRecord->Eip = pCurrInstruction->dwInstructionAddr;
    
            // check register flags
            if(pCurrInstruction->dwInstructionFlags & FLAG_EAX)
            {
                    // set eax
                    printf("<InternalExHandler> mov eax, 0x%x\n", pCurrInstruction->dwEax);
                    pExceptionInfo->ContextRecord->Eax = pCurrInstruction->dwEax;
            }
            else if(pCurrInstruction->dwInstructionFlags & FLAG_EBX)
            {
                    // set ebx
                    printf("<InternalExHandler> mov ebx, 0x%x\n", pCurrInstruction->dwEbx);
                    pExceptionInfo->ContextRecord->Ebx = pCurrInstruction->dwEbx;
            }
            else if(pCurrInstruction->dwInstructionFlags & FLAG_ECX)
            {
                    // set ecx
                    printf("<InternalExHandler> mov ecx, 0x%x\n", pCurrInstruction->dwEcx);
                    pExceptionInfo->ContextRecord->Ecx = pCurrInstruction->dwEcx;
            }
            else if(pCurrInstruction->dwInstructionFlags & FLAG_EDX)
            {
                    // set edx
                    printf("<InternalExHandler> mov edx, 0x%x\n", pCurrInstruction->dwEdx);
                    pExceptionInfo->ContextRecord->Edx = pCurrInstruction->dwEdx;
            }
            else if(pCurrInstruction->dwInstructionFlags & FLAG_EDI)
            {
                    // set edi
                    printf("<InternalExHandler> mov edi, 0x%x\n", pCurrInstruction->dwEdi);
                    pExceptionInfo->ContextRecord->Edi = pCurrInstruction->dwEdi;
            }
            else if(pCurrInstruction->dwInstructionFlags & FLAG_ESI)
            {
                    // set esi
                    printf("<InternalExHandler> mov esi, 0x%x\n", pCurrInstruction->dwEsi);
                    pExceptionInfo->ContextRecord->Esi = pCurrInstruction->dwEsi;
            }
    
            // print current instruction label
            printf("<ntdll: 0x%08X> %s\n", pCurrInstruction->dwInstructionAddr, pCurrInstruction->pLabel);
    
            // check if this is a 'call' instruction
            if(pCurrInstruction->dwInstructionFlags & FLAG_CALL)
            {
                    // set a hardware breakpoint on the first instruction after the 'call'
                    pExceptionInfo->ContextRecord->Dr0 = pCurrInstruction->dwInstructionAddr + pCurrInstruction->dwInstructionLength;
                    pExceptionInfo->ContextRecord->Dr7 = 1;
            }
            else
            {
                    // single step
                    pExceptionInfo->ContextRecord->EFlags |= 0x100;
            }
    
            // move to the next instruction
            dwGlobal_CurrInstruction++;
    
            // continue execution
            return EXCEPTION_CONTINUE_EXECUTION;
    }
    
    DWORD GetModuleCodeSection(DWORD dwModuleBase, DWORD *pdwCodeSectionStart, DWORD *pdwCodeSectionLength)
    {
            IMAGE_DOS_HEADER *pDosHeader = NULL;
            IMAGE_NT_HEADERS *pNtHeader = NULL;
            IMAGE_SECTION_HEADER *pCurrSectionHeader = NULL;
            char szCurrSectionName[16];
            DWORD dwFound = 0;
            DWORD dwCodeSectionStart = 0;
            DWORD dwCodeSectionLength = 0;
    
            // get dos header ptr (start of module)
            pDosHeader = (IMAGE_DOS_HEADER*)dwModuleBase;
            if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
            {
                    return 1;
            }
    
            // get nt header ptr
            pNtHeader = (IMAGE_NT_HEADERS*)((BYTE*)pDosHeader + pDosHeader->e_lfanew);
            if(pNtHeader->Signature != IMAGE_NT_SIGNATURE)
            {
                    return 1;
            }
    
            // loop through all sections
            for(DWORD i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++)
            {
                    // get current section header
                    pCurrSectionHeader = (IMAGE_SECTION_HEADER*)((BYTE*)pNtHeader + sizeof(IMAGE_NT_HEADERS) + (i * sizeof(IMAGE_SECTION_HEADER)));
    
                    // pCurrSectionHeader->Name is not null terminated if all 8 characters are used - copy it to a larger local buffer
                    memset(szCurrSectionName, 0, sizeof(szCurrSectionName));
                    memcpy(szCurrSectionName, pCurrSectionHeader->Name, sizeof(pCurrSectionHeader->Name));
    
                    // check if this is the main code section
                    if(strcmp(szCurrSectionName, ".text") == 0)
                    {
                            // found code section
                            dwFound = 1;
                            dwCodeSectionStart = dwModuleBase + pCurrSectionHeader->VirtualAddress;
                            dwCodeSectionLength = pCurrSectionHeader->SizeOfRawData;
    
                            break;
                    }
            }
    
            // ensure the code section was found
            if(dwFound == 0)
            {
                    return 1;
            }
    
            // store values
            *pdwCodeSectionStart = dwCodeSectionStart;
            *pdwCodeSectionLength = dwCodeSectionLength;
    
            return 0;
    }
    
    DWORD ScanForInstructions()
    {
            DWORD dwInstructionCount = 0;
            DWORD dwCurrSearchPos = 0;
            DWORD dwBytesRemaining = 0;
            DWORD dwFoundAddr = 0;
            DWORD dwCodeSectionStart = 0;
            DWORD dwCodeSectionLength = 0;
    
            // calculate instruction count
            dwInstructionCount = sizeof(Global_InstructionList) / sizeof(Global_InstructionList[0]);
    
            // find ntdll code section range
            if(GetModuleCodeSection((DWORD)GetModuleHandle("ntdll.dll"), &dwCodeSectionStart, &dwCodeSectionLength) != 0)
            {
                    return 1;
            }
    
            // scan for instructions
            for(DWORD i = 0; i < dwInstructionCount; i++)
            {
                    // check if an address has already been found for this instruction
                    if(Global_InstructionList[i].dwInstructionAddr != 0)
                    {
                            continue;
                    }
    
                    // find this instruction in the ntdll code section
                    dwCurrSearchPos = dwCodeSectionStart;
                    dwBytesRemaining = dwCodeSectionLength;
                    dwFoundAddr = 0;
                    for(;;)
                    {
                            // check if the end of the code section has been reached
                            if(Global_InstructionList[i].dwInstructionLength > dwBytesRemaining)
                            {
                                    break;
                            }
    
                            // check if the instruction exists here
                            if(memcmp((void*)dwCurrSearchPos, (void*)Global_InstructionList[i].bInstruction, Global_InstructionList[i].dwInstructionLength) == 0)
                            {
                                    dwFoundAddr = dwCurrSearchPos;
                                    break;
                            }
    
                            // update search indexes
                            dwCurrSearchPos++;
                            dwBytesRemaining--;
                    }
    
                    // ensure the opcode was found
                    if(dwFoundAddr == 0)
                    {
                            printf("Error: Instruction not found in ntdll: '%s'\n", Global_InstructionList[i].pLabel);
    
                            return 1;
                    }
    
                    // store address
                    Global_InstructionList[i].dwInstructionAddr = dwFoundAddr;
    
                    // copy this instruction address to any other matching instructions in the list
                    for(DWORD ii = 0; ii < dwInstructionCount; ii++)
                    {
                            // check if the instruction lengths match
                            if(Global_InstructionList[ii].dwInstructionLength == Global_InstructionList[i].dwInstructionLength)
                            {
                                    // check if the instruction opcodes match
                                    if(memcmp(Global_InstructionList[ii].bInstruction, Global_InstructionList[i].bInstruction, Global_InstructionList[i].dwInstructionLength) == 0)
                                    {
                                            // copy instruction address
                                            Global_InstructionList[ii].dwInstructionAddr = Global_InstructionList[i].dwInstructionAddr;
                                    }
                            }
                    }
            }
    
            return 0;
    }
    
    int main()
    {
            PVOID (WINAPI *RtlAddVectoredExceptionHandler)(DWORD dwFirstHandler, void *pExceptionHandler);
            DWORD dwThreadID = 0;
            HANDLE hThread = NULL;
    
            printf("WindowsNoExec - [url=http://www.x86matthew.com]www.x86matthew.com[/url]\n\n");
    
            // get RtlAddVectoredExceptionHandler function ptr
            RtlAddVectoredExceptionHandler = (void *(__stdcall *)(unsigned long,void *))GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlAddVectoredExceptionHandler");
            if(RtlAddVectoredExceptionHandler == NULL)
            {
                    return 1;
            }
    
            printf("Adding exception handler...\n");
    
            // add exception handler
            if(RtlAddVectoredExceptionHandler(1, (void*)ExceptionHandler) == NULL)
            {
                    return 1;
            }
    
            printf("Scanning ntdll to populate instruction list...\n");
    
            // scan for instructions
            if(ScanForInstructions() != 0)
            {
                    return 1;
            }
    
            printf("Starting...\n\n");
    
            // breakpoint to trigger exception handler
            _asm int 3
    
            printf("\nFinished\n");
    
            return 0;
    }
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

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