C# ASM

本文介绍了一种在C#中编写ASM类的方法,旨在使内嵌或CALL汇编代码更加简洁,类似于易语言的模块。通过借鉴Super-EC和随风EC的源码,在MDebug和Visual Studio 2012环境下调试,作者创建了一个不支持x64的x86汇编类。类中包含不同类型的函数,如带返回值和参数的标准函数,无参无返回值的子程序,以及用于乘法运算的无参函数。ASM类仅支持内部无参Invoke,若要注入外部进程,需自行编写相关代码。此外,还讨论了Asm::Context属性的用途,它可以存储和执行内嵌汇编的机器代码。
摘要由CSDN通过智能技术生成

从前天开始到今天编写了一个ASM的类,主要是为了方便C#内嵌或者写CALL代码看起来与

易语言的汇编模块差不多

对的,我借鉴了一下Super-EC及随风EC中的部分源代码 在MDebug && Visual Studio 2012

获取或附加调试部分代码

注:创建一个控制台或窗体项目,成功后Alter+Enter或右键项目选择属性选项然后如上图

一般选择生成更改目标平台为x86(必须)此类不支持x64下的汇编

public static void Main(string[] args)
        {
            using (Asm asm = new Asm())
            {
                asm.begin();
                asm.mov_eax((int)Marshal.GetFunctionPointerForDelegate(new Action(test)));
                asm.call_eax();
                asm.end();
                Console.WriteLine(asm.Invoke());
            }
        }

        public static void test()
        {
            Console.WriteLine("好讨厌:");
            Console.WriteLine("被人调用了");
            Console.ReadKey(false);
        }

上方是一个标准的函数,拥有返回值支持有参调用ASM::begin 我特意编写的一个函数功能

等价于函数的左大花括号 是按照Win32函数堆栈布局汇编 而ASM::end等价于右大花括号是

Win32函数堆栈的清除布局的汇编

        public static void Main(string[] args)
        {
            using (Asm asm = new Asm())
            {
                asm.pushad();
                asm.mov_edi((int)Marshal.GetFunctionPointerForDelegate(new Action(test)));
                asm.call_edi();
                asm.popad();
                asm.ret();
                asm.Invoke();
            }
        }

        public static void test()
        {
            Console.WriteLine("好讨厌:");
            Console.WriteLine("被人调用了");
            Console.ReadKey(false);
        }

上方是一个另类的函数,属于无参无返回值称子程序吧一般写游戏(外挂)CALL

大多是这种形式pushad先保存当前寄存器的值执行完局部代码后在popad恢复

        public static void Main(string[] args)
        {
            using (Asm asm = new Asm())
            {
                asm.begin();
                asm.mov_eax(3);
                asm.imul_eax(5);
                asm.end();
                Console.WriteLine(asm.Invoke());
            }
            Console.ReadKey(false);
        }

上方是一个无参函数,压入3到(eax)32-bit累积寄存器中,imul相乘指令

eax = eax*5在相乘之前eax中为3所以返回15

但是ASM类的设计只支持内部无参Invoke,简单的说如果使用本类嵌入汇编 注

入代码到外部进程的话 需要你自己编写这一块的代码、

当然你也可以扩展汇编指令 如同乘法的汇编指令一般 在ASM类上特别之少当然

如果你们在类上扩展的汇编指令函数,可以共享出来的话 那肯定是最好不过

本类可以基本满足游CALL与内部CALL的调用 当然可以使用dmsoft的汇编内嵌函数

        public static void Main(string[] args)
        {
            using (Asm asm = new Asm())
            {
                asm.begin();
                asm.mov_eax(7);
                asm.inc_eax();
                asm.end();
                Console.WriteLine(asm.Invoke());

                asm.Context = null;
                asm.begin();
                asm.mov_eax(6);
                asm.dec_eax();
                asm.end();
                Console.WriteLine(asm.Invoke());
            }
            Console.ReadKey(false);
        }

上方的代码中需要注解一处,inc递加指令 / dec递减指令 当然上面的代码主要是阐述

Asm::Context = [null / byte[0]];的一些注意事项,在本类设计中如果该属性被赋值会自

动释放内部的汇编代码资源并重新构建新的代码数据 当然你可以为它赋入你所编写的

机器代码 该属性可以获得内嵌的汇编的机器代码形式当然你要调用汇编代码也需要它
Asm.cs / source code.

namespace ASM
{
    using System;
    using System.IO;
    using System.Runtime.InteropServices;

    public partial class Asm : IDisposable
    {
        private MemoryStream __asm;
        private BinaryWriter __emit;
        private bool __disposed = false;

        ~Asm()
        {
            Dispose(false);
        }

        public Asm()
        {
            __asm = new MemoryStream();
            __emit = new BinaryWriter(__asm);
        }

        public byte[] Context
        {
            get
            {
                return __asm != null ? __asm.ToArray() : null;
            }
            set
            {
                if (__emit != null && __asm != null)
                {
                    __asm.Dispose();
                    __emit.Dispose();
                }
                __asm = new MemoryStream();
                __emit = new BinaryWriter(__asm);
                if (value != null && value.Length > 0)
                {
                    __emit.Write(value);
                }
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (__disposed == false && disposing)
            {
                __disposed = !__disposed;
                if (__asm != null) __asm.Dispose();
                if (__emit != null) __emit.Dispose();
            }
        }
    }

    public partial class Asm
    {
        public void pushad()
        {
            __asm.WriteByte((byte)96);
        }

        public void popad()
        {
            __asm.WriteByte((byte)97);
        }

        public void begin()
        {
            // push        ebp
            // mov         ebp,esp
            // sub         esp,0C0h
            // push        ebx
            // push        esi
            // push        edi
            // lea         edi,[ebp-0C0h]
            // mov         ecx,30h
            // mov         eax,0CCCCCCCCh
            // rep stos    dword ptr es:[edi]
            __emit.Write((byte)85);
            __emit.Write((byte)139);
            __emit.Write((byte)236);
            __emit.Write((byte)129);
            __emit.Write((byte)236);
            __emit.Write((byte)192);
            __emit.Write((byte)0);
            __emit.Write((byte)0);
            __emit.Write((byte)0);
            __emit.Write((byte)83);
            __emit.Write((byte)86);
            __emit.Write((byte)87);
            __emit.Write((byte)141);
            __emit.Write((byte)189);
            __emit.Write((byte)64);
            __emit.Write((byte)255);
            __emit.Write((byte)255);
            __emit.Write((byte)255);
            __emit.Write((byte)185);
            __emit.Write((byte)48);
            __emit.Write((byte)0);
            __emit.Write((byte)0);
            __emit.Write((byte)0);
            __emit.Write((byte)184);
            __emit.Write((byte)204);
            __emit.Write((byte)204);
            __emit.Write((byte)204);
            __emit.Write((byte)204);
            __emit.Write((byte)243);
            __emit.Write((byte)171);
        }

        public void end(bool ret = true)
        {
            // pop         edi
            // pop         esi
            // pop         ebx
            // mov         esp,ebp
            // pop         ebp
            // ret
            __emit.Write((byte)95);
            __emit.Write((byte)94);
            __emit.Write((byte)91);
            __emit.Write((byte)139);
            __emit.Write((byte)229);
            __emit.Write((byte)93);
            if (ret) __emit.Write((byte)195);
        }
    }

    public partial class Asm
    {
        public void push(int value)
        {
            if (value >= -128 && value <= 127)
            {
                __emit.Write((byte)106);
                __emit.Write((byte)value);
            }
            else
            {
                __emit.Write((byte)104);
                __emit.Write(value);
            }
        }

        public void nop()
        {
            __emit.Write((byte)144);
        }

        public void ret()
        {
            __emit.Write((byte)195);
        }

        public void retn(short n)
        {
            __emit.Write((byte)0xC2);
            __emit.Write(n);
        }

        public void call(int rva)
        {
            __emit.Write((byte)232);
            __emit.Write(rva + 5);
        }

        public void leave()
        {
            __emit.Write((byte)201);
        }

        public void jmp(int rva)
        {
            // 0046433E  E9 28010000   jmp     0046446B
            // 00401023  EB 00         jmp     short 00401025
            if ((rva - 2) >= -128 && (rva - 2) <= 127)
            {
                __emit.Write((byte)235); // EB
                __emit.Write((byte)(rva - 2)); 
            }
            else
            {
                __emit.Write((byte)233); // E9
                __emit.Write(rva - 5); 
            }
        }

        public void je(int rva)
       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值