.net也能写内存挂

news2024/11/20 11:46:01

最近在研究.net的内存挂。

写了很久的c++,发现c#写出来的东西实在太香。

折腾c#外挂已经有很长时间了。都是用socket和c++配合。

这个模式其实蛮成功的,用rpc调用的方式加上c#的天生await 非常好写逻辑

类似这样

最近想换个口味。注入托管dll到非托管进程

这样做只是为了解决我目前遇见的一个问题。

在一个多线程的程序上逆向,我挂了很多钩子,导致我读写数据和储存我自己的数据

非常容易出现多线程冲突问题,换到.net里以后

lock 和Monitor 在.net里是同线程不互锁。这样能让我不容易出现互锁现象。

有一段时间正在烦恼那些卖驱动的,只有读写功能为什么还能实现很多功能。

在我的认知里,要调用游戏部分函数才能更方便自己做出更有用的功能

当然这里确实有些外挂是只读取角色顶点就能绘制的。

后来细想一下其实不需要调用功能通过写入代码的方式获取执行就可以了。

就是只要有读写就可以了。

游戏外挂无非就是 读写和调用。 调用是可以通过写来实现。

比如hook某个dx的函数。或者修改虚函数表的地址,然后jmp 到自己的函数里

达到获取执行权限。

好比挂钩了GetTickCount  这个API ,然后目标游戏不断的调用这个API

我们在这里插入自己的调用逻辑就可以了。

想明白了这个,于是我就干起了注入托管dll 到游戏进程里的勾当

当然这个托管dll实在是太大了(因为会用Costura.Fody把第三方库都打包在一起)

想法是这样,注入到游戏进程里以后申请内存空间,然后通过asm编译成bytes

然后写入到内存后,再去调用他就可以了

这里要安利一个asm的库 

GitHub - icedland/iced: Blazing fast and correct x86/x64 disassembler, assembler, decoder, encoder for Rust, .NET, Java, Python, Lua

这个库很香

在c#里写asm长这样子,大概就是写好asm以后编译成bytes的过程

然后要介绍在c#内怎么完成thiscall

游戏大部分是thiscall  所以我在内存中申请一段asm

然后通过c#去调用这个段代码就可以了

asm 的作用就是把传入的参数 push到堆栈然后call

之后返回eax 这样就完整的跑通调用了。

用iced把asm生成好,然后通过c#的委托去调用这段asm代码即可

最后实现的效果类是这样

至于读写就更简单了。C#自带Marshal可以直接读写。

而且c#也支持不安全指针 直接 *(int*)(0x123456) = 100;

然后我们无限的包装自己的读写函数,比如byte float int string 之类的读写就可以

至于hook 也可以通过委托回调到自己的c#代码,hook在c#完成编译以后写入到目标地址

至此,完整的c#外挂需要的功能都实现了。

例子分3个工程

TestApp:测试工程模拟调用目标程序比如游戏

InjectionDLL:注入DLL,负责加载.net的dll,如果是远线程注入,就注入这个DLL即可,例子工程是主动loadlibrary

CShareLoadModule : c#的主要工作dll

附上源码一份

netInjection.rar

//以下是补充 2022 10 09

/

因为上面代码是用asm作为Thiscall 调用的,后来发现c#是自带调用约定的可以更优美的实现thiscall 调用

        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_0(IntPtr ptr);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_1(IntPtr ptr, IntPtr p1);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_2(IntPtr ptr, IntPtr p1, IntPtr p2);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_3(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_4(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_5(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_6(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_7(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_8(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_9(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_10(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_11(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_12(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11, IntPtr p12);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_13(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11, IntPtr p12, IntPtr p13);
        [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
        public delegate IntPtr ThisCall_14(IntPtr ptr, IntPtr p1, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, IntPtr p9, IntPtr p10, IntPtr p11, IntPtr p12, IntPtr p13, IntPtr p14);

        unsafe public static IntPtr ThisCall(IntPtr address, IntPtr dwECX, params object[] args)
        {
            IntPtr p1 = IntPtr.Zero;


            IntPtr[] paramPtr = new IntPtr[args.Length*2];
            int addParamCount = 0;
            for (int i = 0; i < args.Length; i++)
            {
                var paramtype = args[i].GetType();
                if (paramtype == typeof(float))
                {
                    var v = (float)args[i];
                    paramPtr[addParamCount] = *(IntPtr*)&v;
                }
                else if (paramtype == typeof(double))
                {
                    var v = (double)args[i];
                    paramPtr[addParamCount] = *(IntPtr*)&v;
                    addParamCount++;
                    paramPtr[addParamCount] = *(IntPtr*)((&v) +4);
                }
                else if (paramtype == typeof(long))
                {
                    var v = (long)args[i];
                    paramPtr[addParamCount] = *(IntPtr*)&v;
                    addParamCount++;
                    paramPtr[addParamCount] = *(IntPtr*)((&v) + 4);
                }
                else if (paramtype == typeof(IntPtr))
                {
                    var v = (IntPtr)args[i];
                    paramPtr[addParamCount] = v;
                }
                else if (paramtype == typeof(PtrGameUIWindow))
                {
                    paramPtr[addParamCount] = (args[i] as PtrGameUIWindow).ptr;
                }
                else
                {
                    paramPtr[addParamCount] = (IntPtr)Convert.ToInt32(args[i]);
                }
                addParamCount++;
            }
            Log.Console($"ThisCall:0x{address.ToString("X8")} ECX:0x{dwECX.ToString("X8")} {paramPtr.ArrayToString(0, addParamCount)}");
            switch (args.Length)
            {
                case 0:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_0>(address).Invoke(dwECX);
                    break;
                case 1:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_1>(address).Invoke(dwECX, paramPtr[0]);
                    break;
                case 2:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_2>(address).Invoke(dwECX, paramPtr[0], paramPtr[1]);
                    break;
                case 3:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_3>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2]);
                    break;
                case 4:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_4>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3]);
                    break;
                case 5:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_5>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4]);
                    break;
                case 6:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_6>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5]);
                    break;
                case 7:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_7>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6]);
                    break;
                case 8:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_8>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7]);
                    break;
                case 9:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_9>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7], paramPtr[8]);
                    break;
                case 10:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_10>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7], paramPtr[8], paramPtr[9]);
                    break;
                case 11:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_11>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7], paramPtr[8], paramPtr[9], paramPtr[10]);
                    break;
                case 12:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_12>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7], paramPtr[8], paramPtr[9], paramPtr[10], paramPtr[11]);
                    break;
                case 13:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_13>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7], paramPtr[8], paramPtr[9], paramPtr[10], paramPtr[11], paramPtr[12]);
                    break;
                case 14:
                    p1 = Marshal.GetDelegateForFunctionPointer<ThisCall_14>(address).Invoke(dwECX, paramPtr[0], paramPtr[1], paramPtr[2], paramPtr[3], paramPtr[4], paramPtr[5], paramPtr[6], paramPtr[7], paramPtr[8], paramPtr[9], paramPtr[10], paramPtr[11], paramPtr[12], paramPtr[13]);
                    break;
                default:
                    Log.Error(new Exception("ThisCall 参数个数未预测"));
                    p1 = IntPtr.Zero;
                    break;
            }

            return p1;
        }

因为c#会定期GC的问题,导致c#自身函数可能会被GC修改函数位置

所以需要固定住代码位置新增一下函数固定Delegate

        [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
        public delegate IntPtr Delegate_NewStringID2String(IntPtr dwESP);
        
        
        public uint LockDelegate(Delegate func)
        {
            GCHandleList.Add(GCHandle.Alloc(func));
            GCHandleList.Add(GCHandle.Alloc(Marshal.GetFunctionPointerForDelegate(func), GCHandleType.Pinned));
            GCHandleList.Add(GCHandle.Alloc(func.Method.MethodHandle.GetFunctionPointer()));
            return (uint)Marshal.GetFunctionPointerForDelegate(func);
        }
        
        
        //使用方法
        
        public static IntPtr MyStringID2String(IntPtr dwESP)
        {
            var ret = IntPtr.IntPtr.Zero;
            return ret;
        }
        
        public override void Start()
        {
                var asm = new Assembler(32);
                asm.pushad();
                asm.mov(eax, esp);
                asm.add(eax, 0x20);
                asm.push(eax);
                asm.mov(eax, LockDelegate(new Delegate_NewStringID2String(MyStringID2String)));
                asm.call(eax);
                asm.mov(__[esp + 0x1c], eax);
                asm.popad();
                asm.ret();
    
                var newJmpCode = PatchSelfHelper.AllocMem(0x30);
                PatchSelfHelper.WriteAssembler(newJmpCode, asm);
        }

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

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

相关文章

基于 SOFAJRaft 实现注册中心

文章目录 1.前言2.git 示例地址3.官网示例分析3.SOFAJRAFT 注册中心实现&#xff08;服务端&#xff09;3.1 核心功能3.2 模块设计3.3 请求消息数据结构设计3.3.1 Registration 注册消息3.3.2 GetServiceInstancesRequest 获取服务实例请求3.3.3 GetServiceInstancesResponse 获…

Android中级——ListView和RecycleView解析

ListView和RecycleView ListViewRecycleView ListView 使用步骤可看Android基础——ListView&#xff0c;其setAdapter()如下&#xff0c;回调getCount()获取Item个数 Override public void setAdapter(ListAdapter adapter) {if (mAdapter ! null && mDataSetObserv…

v-model绑定input、textarea、checkbox、radio、select

1.input <div><!-- v-model绑定input --><input type"text" v-model"message"><h2>{{message}}</h2></div><script>const App{template:#my-app,data() {return {message:Hello World,}},}Vue.createApp(App).…

Java:设计模式之结构型-装饰者模式(decorator pattern)

装饰者模式(decorator pattern): 动态地将责任附加到对象上 意图&#xff1a;为对象动态添加功能 类图 实现 设计不同种类的饮料&#xff0c;饮料可以添加配料&#xff0c;比如可以添加牛奶&#xff0c;并且支持动态添加新配料。每增加一种配料&#xff0c;该饮料的价格就…

微信怎么查看名下所有微信号?

一般大家都会有两个或者更多的微信号&#xff0c;那怎么知道自己名下有几个微信号呢&#xff1f; 微信号要使用支付或者其他一些功能是要实名才可以使用的&#xff0c;有时候不知道自己的名下绑定了多少微信号&#xff0c;怎么查询呢&#xff1f; 微信最近出了开通小号的功能&…

当下测试行业中UI自动化面临的难点及如何解决

经常有人会问&#xff0c;什么样的项目才适合进行UI自动化测试呢&#xff1f;UI自动化测试相当于模拟手工测试&#xff0c;通过程序去操作页面上的控件。而在实际测试过程中&#xff0c;经常会遇到无法找到控件&#xff0c;或者因控件定义变更而带来的维护成本等问题。 哪些场…

Python数组添加元素append的时间复杂度分析

由于数组需要连续的存储空间&#xff0c;append&#xff08;&#xff09;函数的时间复杂度可能为1也可能为n&#xff0c;主要看在后面添加元素时&#xff0c;当前位置是否可以添加&#xff0c;有位置可以添加的话&#xff0c;则直接在后面添加&#xff0c;此时时间复杂度为1&am…

工学云打卡签到自动完成在异地的问题就解决了|蘑菇钉

工学云打卡助手&#xff0c;能解决你在异地时每天不间断签到的问题&#xff0c;仔细看图哦 1.自动签到 2.自定义打卡地区 3.生成日周月报与总结自动发表 4.支持随机通用内容 5.支持打卡结果推送 对于许多即将步入职场的新人来说&#xff0c;实习是一个非常重要的阶段。实习…

【算法挨揍日记】day13—— DP34 【模板】前缀和、DP35 【模板】二维前缀和

DP34 【模板】前缀和 【模板】前缀和_牛客题霸_牛客网 题目描述&#xff1a; 给定一个长度为n的数组. 接下来有q次查询, 每次查询有两个参数l, r. 对于每个询问, 请输出 输入描述: 第一行包含两个整数n和q.第二行包含n个整数, 表示.接下来q行,每行包含两个整数 l和r. …

聊聊Android签名检测7种核心检测方案详解

聊聊Android签名检测总结与反思 背景&#xff1a; 这篇文章只讲Android端签名检测&#xff0c;安卓发展到现在&#xff0c;因为国内环境没有谷歌市场&#xff0c;所以很多官方推荐的Api没法使用 &#xff0c;所以国内的签名检测方式也是“千奇百怪” 。发展至今每种方法都有一…

智安网络|揭开云服务的神秘面纱:其含义和功能的综合指南

随着信息技术的不断发展&#xff0c;云服务已经成为了我们生活中的一个不可或缺的部分。无论是在个人生活中还是在商业领域&#xff0c;云服务都具有广泛的应用。 什么是云服务&#xff1f; 云服务是一种基于互联网的计算和存储资源提供方式&#xff0c;它允许用户通过互联网访…

CTF Misc(3)流量分析基础以及原理

前言 流量分析在ctf比赛中也是常见的题目&#xff0c;参赛者通常会收到一个网络数据包的数据集&#xff0c;这些数据包记录了网络通信的内容和细节。参赛者的任务是通过分析这些数据包&#xff0c;识别出有用的信息&#xff0c;例如登录凭据、加密算法、漏洞利用等等 工具安装…

智能优化算法常用指标一键导出为EXCEL,CEC2017函数集最优值,平均值,标准差,最差值,中位数,秩和检验,箱线图...

声明&#xff1a;对于作者的原创代码&#xff0c;禁止转售倒卖&#xff0c;违者必究&#xff01; 之前出了一篇关于CEC2005函数集的智能算法指标一键统计&#xff0c;然而后台有很多小伙伴在询问其他函数集该怎么调用。今天采用CEC2017函数集为例&#xff0c;进行展示。 为了突…

手动下载/安装Xcode的simulator

目录 前言解决方案1.获取simulator包下载地址1.1 Apple后台1.2 手动 2.使用三方下载工具下载3.使用命令安装simulator 前言 Xcode某个版本更新之后不带iOS的Simulator,导致全新下载一个Xcode后没法编译项目.公司的网又很坑,每次断掉点重试都重新下载,导致完全没法下下来.特别影…

lazada商品列表数据接口,关键词搜索lazada商品数据接口

在网页抓取方面&#xff0c;可以使用 Python、Java 等编程语言编写程序&#xff0c;通过模拟 HTTP 请求&#xff0c;获取lazada网站上的商品页面。在数据提取方面&#xff0c;可以使用正则表达式、XPath 等方式从 HTML 代码中提取出有用的信息。值得注意的是&#xff0c;lazada…

大规模语言模型人类反馈对齐--强化学习

​OpenAI 推出的 ChatGPT 对话模型掀起了新的 AI 热潮&#xff0c; 它面对多种多样的问题对答如流&#xff0c; 似乎已经打破了 机器和人的边界。这一工作的背后是大型语言模型 (Large Language Model&#xff0c;LLM) 生成领域的新训练范式&#xff1a;RLHF (Reinforcement Le…

专题二:二叉树的深搜【递归、搜索、回溯】

深度优先遍历&#xff08;DFS&#xff0c;全称为DepthFirstTraversal&#xff09;&#xff0c;是我们树或者图这样的数据结构中常用的⼀种遍历算法。这个算法会尽可能深的搜索树或者图的分⽀&#xff0c;直到⼀条路径上的所有节点都被遍历完毕&#xff0c;然后再回溯到上⼀层&a…

为什么要做CRM?

客户管理的痛点&#xff1a; 1、销售经常性漏跟错跟客户&#xff0c;客户转化率低造成资源浪费 2、客户信息繁杂&#xff0c;难整理和查找 3、销售离职带走客户资源&#xff0c;损失大 4、传统报价审批流程长&#xff0c;效率低 企业做CRM系统有以下几点好处&#xff1a; …

纸、纸板和纸制品 有效回收组分的测定

声明 本文是学习GB-T 42944-2023 纸、纸板和纸制品 有效回收组分的测定. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件描述了纸、纸板和纸制品中有效回收组分的测定方法。 本文件适用于各种纸、纸板和纸制品&#xff0c;也适用于铝箔…

Paddle GPU版本需要安装CUDA、CUDNN

完整的教程 深度学习环境配置&#xff1a;linuxwindows系统下的显卡驱动、Anaconda、Pytorch&Paddle、cuda&cudnn的安装与说明 - 知乎这篇文档的内容是尽量将深度学习环境配置(使用GPU)所需要的内容做一些说明&#xff0c;由于笔者只在windows和linux下操作过&#xf…