【Python微信机器人】第二篇:将python注入到其他进程

news2024/12/26 0:55:50

目录修整

目前的系列目录(后面会根据实际情况变动):

  1. 在windows11上编译python
  2. 将python注入到其他进程并运行
  3. 使用C++写一个python的pyd库,用于实现inline hook
  4. Python ctypes库的使用
  5. 使用ctypes主动调用进程内的任意函数
  6. 使用汇编引擎调用进程内的任意函数(为了调用不遵守任何一个调用约定的x86函数)
  7. 注入python到微信实现在Python终端收发消息
  8. 优化使用方法,允许Python加载运行py脚本,而不是打开Python终端
  9. Bug修复和细节优化
注入器

在注入Python之前,先使用Python写一个注入器。原理和C++的远程线程注入是一样的,使用CreateRemoteThread在进程内部调用LoadLibrary加载dll。

核心代码如下:

# 通过微信进程pid获取进程句柄
hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
# 在微信进程中申请一块内存
lpAddress = VirtualAllocEx(hProcess, None, MAX_PATH, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
# 往内存中写入要注入的dll的绝对路径
WriteProcessMemory(hProcess, lpAddress, c_wchar_p(dllpath), MAX_PATH, byref(c_ulong()))
# 因为注入的微信是32位的,所以运行的Python也需要是32位的
if platform.architecture()[0] != '32bit':
        raise Exception("需要使用32位Python才能正常执行,请更换后重试!")
# 在微信进程内调用LoadLibraryW加载dll
hRemote = CreateRemoteThread(hProcess, None, 0, LoadLibraryW, lpAddress, 0, None)
time.sleep(0.1)
# 关闭句柄
CloseHandle(hProcess)
CloseHandle(hRemote)

其中像OpenProcess这样的函数都是Windows提供的API,在Python中可以使用ctypes库调用它们。完整代码这里就不放了,想了解的可以看后面的github。另外,后面会有一篇文章单独讲ctypes,里面就会涉及调用Windows API和定义C结构体

打包Python为dll

众所周知,Python的核心函数都在python310.dll里,然后再加上pyd、dll和py这些基础库和一些exe可执行文件,python.exe和pythonw.exe只是调用了python310.dll里的导出函数。

1、猜想

既然核心都在python310.dll,我是不是只需要将这个dll注入到其他进程,然后参考python.exe的代码进行初始化就能完成Python的注入。

实际上有一个Python库(Pymem)就是这么干的:Injecting a python interpreter into any process,不过测试下来局限性很大,首先是调用远程函数的API是CreateRemoteThread,它只支持调用的函数传递一个参数,虽然可以是结构体,但是Python构造结构体也不方便,然后是代码比较繁琐,所以还是自己研究了。

先看看python.exe的代码: 1.png

可以看到整个exe只调用了一个函数Py_Main,如果我用C++写一个exe,在里面加载python310.dll,然后调用Py_Main是不是能写一个python.exe

先测试一下,这里我不去引入python的头文件和lib库,而是使用LoadLibraryW加载python310.dll

C++代码如下:

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

int wmain(int argc, wchar_t* argv[]) {
    // 指定要加载的DLL,这里我打算放到同一目录,就不写绝对路径了
    const wchar_t* dllFileName = L"python310.dll";
    // 加载DLL
    HMODULE hModule = LoadLibraryW(dllFileName);
    // 获取导出函数地址
    FARPROC Py_Main_addr = GetProcAddress(hModule, "Py_Main"); // 替换为导出函数的名称
    // 定义函数指针和调用函数
    typedef int(*Py_Main_Type)(int, wchar_t**);
    Py_Main_Type Py_Main = (Py_Main_Type)Py_Main_addr;

    int result = Py_Main(argc, argv);

    return 0;
}

编译后把它放到python310.dll同级目录,然后双击运行,测试发现和python.exe的功能是一模一样的

也支持参数传递和运行py文件 2.png

2、将python.exe打包成dll

因为dll无法传递进程参数,所以我将argv写死了,python310.dll也使用绝对路径,完整代码如下:

#include "pch.h"

void run_python() {
    const wchar_t* dllFileName = L"T:\\Code\\compile_python\\Inject_dll\\python-3.10.11-embed-win32\\python38.dll";
    HMODULE hModule = LoadLibraryW(dllFileName);

    FARPROC Py_Main_addr = GetProcAddress(hModule, "Py_Main");
    typedef int(*Py_Main_Type)(int, wchar_t**);
    Py_Main_Type Py_Main = (Py_Main_Type)Py_Main_addr;

    // 获取当前进程可执行文件的路径
    wchar_t exePath[MAX_PATH];
    GetModuleFileNameW(NULL, exePath, MAX_PATH);

    int argc = 1;
    wchar_t* argv[2];
    argv[0] = exePath;
    argv[1] = nullptr;

    Py_Main(argc, argv);
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH: {
        run_python();
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

当我将编译好的dll注入到其他进程内却什么也没有发生,为了不受其他进程影响,我先把他注入到我自己写的进程里,就用之前帖子写的SubProcess了。

3、无法运行的原因

先验证下python有没有运行成功,调用PyRun_SimpleString来执行代码写文件测试看看

将上面的Py_Main(argc, argv);换成PyRun_SimpleString("with open('D:\\\\1.txt', 'w') as f: f.write('aaaaa')");

文件并没有被写到指定的路径,谷歌搜索了下,是因为没有调用Py_InitializeEx或Py_Initialize初始化,加上下面两行代码就可以了。

Py_SetProgramName(exePath);
Py_InitializeEx(1);
PyRun_SimpleString("with open('D:\\\\1.txt', 'w') as f: f.write('aaaaa')");

这时候交互式终端也正常打开 3.png

4、其他进程交互式终端无法打开

我用同样的dll注入到微信时,界面没有什么变化,但是文件正常写到指定路径,说明Python执行没有问题。猜想可能是Py_Main不会自己打开终端,因为之前的进程本来就是控制台程序,注入之后能看到Python输出再控制台。而微信没有控制台,所以没办法看到。

那么看看能不能打开进程的控制台,搜索发现还真有这样的函数,一行代码即可AllocConsole();,另外还需要三行代码来将Python的输入输出重定向到这个控制台,不然还是看不到Python的输出和交互式终端

freopen("CONIN$", "r+t", stdin);
freopen("CONOUT$", "w+t", stdout);
freopen("CONOUT$", "w+t", stderr);

这样需要添加一个宏来允许不安全的函数,或者用下面的代码

FILE* conin = stdin;
FILE* conout = stdout;
FILE* conerr = stderr;
freopen_s(&conin, "conin$", "r+t", stdin);
freopen_s(&conout, "conout$", "w+t", stdout);
freopen_s(&conout, "conout$", "w+t", stderr);

这样就能在注入dll后打开Python的交互式终端,查看进程id也是注入进程的id,到此本篇文章的目的已经达到了。 4.png 这里有个特别无语的坑,freopen函数无法在Debug模式下生效,也就是说如果你dll编译成Debug的话,能打开终端,但是看不到Python输出和交互式终端,为此我还谷歌了搜了一天,以为是freopen没效果。

5、意外发现一些没什么用的知识

在知道上面不显示交互式终端是因为Debug模式不生效之前,我还尝试了一些操作,比如这篇

PyObject* sys = PyImport_ImportModule("sys");
PyObject* io = PyImport_ImportModule("io");
PyObject* pystdout = PyObject_CallMethod(io, "open", "ss", "CONOUT$", "wt");
if (-1 == PyObject_SetAttrString(sys, "stdout", pystdout)) {
    /* Announce your error to the world */
}
Py_DECREF(sys);
Py_DECREF(io);
Py_DECREF(pystdout);

如果不想去Python源码里拷贝PyObject的定义,可以直接定义成void *,然后定义PyObject_SetAttrString函数指针时参数也是void*类型的就可以

改完以后的代码(Py_DECREF不是导出函数,调用起来比较麻烦就不调了):

void* sys = PyImport_ImportModule("sys");
void* io = PyImport_ImportModule("io");
void* pystdout = PyObject_CallMethod(io, "open", "ss", "CONOUT$", "wt");
if (-1 == PyObject_SetAttrString(sys, "stdout", pystdout)) {
}

在c代码中设置sys.stdout来将Python输出打印到终端,测试是可以将print显示到终端的。上面的代码应该和freopen("CONOUT$", "w+t", stdout);是一样的,所以只要在加上设置stdin和stderr的就能打开交互式终端。这里我就不测试了。

另外,我还尝试了多种打开终端的方式

  1. python -i test.py: 在执行python脚本时,可以指定-i选项进入交互式终端,当然也可以不指定脚本用python -i,见这篇。 大概意思是,Python只有在启动是控制台应用时才会打开终端,必须指定-i选项强制打开终端
  2. import code;code.interact(): 这两行代码也能打开交互式终端,可以在代码任意位置插入,就能访问当前的变量
  3. code.InteractiveConsole(locals()).interact(): 这个和上面的一样,只是添加到locals里的变量到终端
  4. import os;os.environ["PYTHONINSPECT"] = "1": 可以通过设置PYTHONINSPECT这个环境变量来控制python打开交互式终端,不一样要代码设置,在系统添加这个环境变量也可以

静态链接

上面是通过LoadLibraryW来动态加载Python的dll,这里我测试下通过lib库和头文件来链接Python。这样做的优点是可以不用写函数指针这种,少了很多代码。

代码如下:

#include "pch.h"
#include "Python.h"
#include <iostream>

DWORD WINAPI run_python(PVOID pParam) {
    AllocConsole();
    freopen("CONIN$", "r+t", stdin);
    freopen("CONOUT$", "w+t", stdout);
    freopen("CONOUT$", "w+t", stderr);

    wchar_t exePath[MAX_PATH];
    GetModuleFileNameW(NULL, exePath, MAX_PATH);

    int argc = 1;
    wchar_t* argv[2];
    argv[0] = exePath;
    argv[1] = nullptr;

    Py_SetProgramName(exePath);
    Py_InitializeEx(1);

    PyRun_SimpleString("print('hello')");

    Py_Main(argc, argv);
    return 0;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH: {
        CreateThread(NULL, 0, run_python, NULL, 0, NULL);
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

另外还需要添加Python的头文件库和lib库 5.png 6.png

这里又出现个比较麻烦的问题,编译后的dll和python里的所有文件都得放到被注入进程的目录才能生效,这个应该是跟Windows下dll搜索路径有关。对Windows编程不是很熟悉,搜了下也没找到解决办法,有知道的大佬请指教下

在功能上和上面使用LoadLibraryW基本一样,所以这样写会简洁很多,不用定义那么多的函数指针和类型

以上用到的所有代码

https://github.com/kanadeblisst00/PyRobot-part2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1126054.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pdf误删恢复如何恢复?分享4种恢复方法!

如何将pdf误删恢复&#xff1f;使用电脑的时候&#xff0c;经常会需要使用到pdf文件&#xff0c;但是有时候&#xff0c;因为一些操作上的失误&#xff0c;我们会丢失一些重要的文件。如果你不小心将pdf误删了&#xff0c;该如何进行恢复呢&#xff1f; PDF文件丢失的原因可以…

Bertopic 运行中报错记录

1、下载模型报错ConnectionError: (ProtocolError(‘Connection aborted.’, ConnectionResetError(54, ‘Connection reset by peer’)) 运行代码&#xff1a; topics, probabilities model.fit_transform(docs)报错内容&#xff1a; ConnectionError: (ProtocolError(‘C…

【Unity】渲染性能开挂GPU Animation, 动画渲染合批GPU Instance

GPU Instance和SRP Batcher合批渲染只对静态MeshRenerer有效&#xff0c;对SkinMeshRenderer无效。蒙皮动画性能堪忧&#xff0c;对于海量动画物体怎么解决呢&#xff1f;针对这个问题&#xff0c;GPU Animation就是一个常见又简单的解决方案。 GPU动画实现原理&#xff1a; …

【深圳1024开发者城市聚会定向征文】

在这个周末&#xff0c;我有幸参加了1024程序员节活动&#xff0c;这是一个专门为程序员们举办的活动&#xff0c;旨在庆祝程序员这个特殊的群体。在这个活动中&#xff0c;我不仅感受到了浓厚的编程氛围&#xff0c;还收获了许多宝贵的经验和知识。 活动在深圳湾科技生态园举…

漏洞复现--金和OASQL注入

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…

坚固可靠的多合一轨道交通天线让您的赏秋路途不再枯燥

今年的法定节假日余额已清零&#xff0c;虽然国庆已过&#xff0c;但秋天正是出游的大好时节。在出游计划中&#xff0c;首先面临的就是交通工具的选择这个大难题&#xff0c;到底是选择自由度更高的自驾前往&#xff1f;还是更省心的公共交通&#xff1f;高铁上的信号质量依旧…

ATA-5510前置微小信号放大器在半导体测试中的具体应用

在现代电子技术领域&#xff0c;半导体器件的测试是非常重要的一环。而前置微小信号放大器在半导体测试中扮演着至关重要的角色。本文将介绍前置微小信号放大器在半导体测试中的原理和应用。 在半导体测试中&#xff0c;通常需要测试非常微弱的信号&#xff0c;这些信号可能受到…

大数据分析平台Splunk Enterprise结合cpolar实现公网远程访问

文章目录 前言1. 搭建Splunk Enterprise2. windows 安装 cpolar3. 创建Splunk Enterprise公网访问地址4. 远程访问Splunk Enterprise服务5. 固定远程地址 前言 Splunk Enterprise是一个强大的机器数据管理平台&#xff0c;可帮助客户分析和搜索数据&#xff0c;以及可视化数据…

福建泉州航海快艇蓝光三维扫描全尺寸测量船只外观设计三维建模-CASAIM中科广电

造船行业是一个与全球经济发展密切相关的关键行业。近年来&#xff0c;随着全球经济的快速发展&#xff0c;造船行业也不断进步和发展。快艇制造业作为小型、快速的船只的产业&#xff0c;所生产的船只通常用于娱乐、旅游、商业等方面&#xff0c;因此这种类型的快艇对于外观设…

科普:数控机床主轴的结构选型及维护保养

数控机床主轴是数控机床的重要组成部分&#xff0c;它的性能直接影响到数控机床的加工精度和加工效率。本文将详细介绍数控机床主轴的结构、性能指标、品牌选型以及维护保养等方面的知识&#xff0c;以便更好地了解和掌握数控机床主轴的相关知识。 一、数控机床主轴的结构 数…

react createElement 和 cloneElement 有什么区别?

前言 什么是react React是一个用于构建用户界面的JavaScript库。它旨在帮助开发人员构建可维护、高性能的应用程序界面。React的核心思想是组件化&#xff0c;它允许开发人员将用户界面划分为小块组件&#xff0c;每个组件负责自己的渲染和行为。这种组件化的方法使得代码更容易…

【python入门篇】字符串(4)

这一章节来说下字符串的使用&#xff0c;字符串是 Python 中最常用的数据类型&#xff0c;我们可以使用单引号( &#xff09;或 双引号&#xff08; " )来创建字符串&#xff0c;那么接下来就进入本章节的一个学习。 一、环境配置 我这边python的环境是3.7.8版本的&…

图像压缩(1)RGB888与RGB565图像

图像压缩&#xff08;1&#xff09;RGB888与RGB565图像 前言一. 图像数据格式1.1 不同RGB格式(1)RGB16(2)RGB24(3)RGB32(4)ARGB32 1.2 RGB565与RGB888对比(1)区别(2)各自优缺点 二. 图像格式转换2.1 取位与补位2.2 其他转换方法 三. 图像压缩3.1 G6压缩法&#xff08;16位真彩色…

最新2023版完美可用的聚合支付系统源码,全开源无后门,适合二开

最新2023版完美可用的聚合易支付系统源码&#xff0c;全开源无后门&#xff0c;真正安全可用。 更新日志&#xff1a; 1.新增微信公众号消息提醒功能 2.重构转账付款功能&#xff0c;支持通过插件扩展 3.商户后台新增代付功能 4.后台新增付款记录列表 5.支付宝插件新增预…

城市公安可视化大数据展示平台预测预警,防患未然

在当今数字化、信息化的时代背景下&#xff0c;数字化浪潮席卷着全国各地公安系统&#xff0c;以数字孪生为底座的智慧公安数字孪生可视化管控平台已经成为公共安全领域的一大发展趋势&#xff0c;以其独特的优势为公安机关的日常管理和警务指挥带来了革命性的变革。 智慧公安解…

【FPGA】IIC协议通用主机接口的设计与实现详解

一、认识IIC IIC&#xff08;I2C&#xff09;协议是一种串行通信协议&#xff0c;用于连接微控制器和外围设备。IIC协议只需要两根信号线&#xff08;时钟线SCL和数据线SDA&#xff09;就能完成设备之间的通信&#xff1b;支持多主机和多从机通信&#xff0c;通过设备地址区分不…

cmd命令快速打开MATLAB

文章目录 复制快捷方式添加 -nojvm打开 复制快捷方式 添加 -nojvm 打开 唯一的缺点是无法使用plot&#xff0c;这一点比不上linux系统&#xff0c;不过打开速度还是挺快的。

模式识别——贝叶斯决策理论

模式识别——贝叶斯决策理论BDR 须知基本原则0-1损失下的BDRMAP&#xff08;极大后验&#xff09;log trick 须知 所有内容在分类问题下讨论。 基本原则 定义 X X X为观测 Y Y Y为状态 g ( x ) g(x) g(x)用 x x x对 y y y进行预测预测损失为 L [ g ( x ) , i ] L[g(x),i] L[…

LVS---负载均衡

集群&#xff1a;为解决某个特定问题将多个计算机组合起来形成一个单系统 提高性能的两个方向 垂直扩展&#xff1a;向上扩展&#xff0c;增加单个机器的性能。升级硬件。硬件升级是由瓶颈的水平扩展:向外扩展&#xff0c;增加设备。并行的运行多个服务,通过网络和算法&…

Linux系统编程(4)

分配数组 int *x, *y; x malloc(50*sizeof(int)); if(!x) {perror("malloc");return 1; }y calloc(50, sizeof(int)); if (!y) {perror("calloc");return 1; } calloc会将所申请的内存全部填充0&#xff0c;malloc则不会。 调整内存分配的大小 #incl…