zoukankan      html  css  js  c++  java
  • C# inline-asm / 嵌入x86汇编

    C#可不可以嵌入汇编 可以 在我眼中C#作为一个介于中上层语言是不可能不可以

    置入汇编代码的 为什么会被我认为中上层语言呢 从C#保留指针就可以看出 我知

    道有很多人一定不会相信C#可以使用汇编代码 不过C#会比较麻烦C#不可以直接

    内联汇编(inline-asm)准确的说C#只可以使用(auto-asm)动态汇编 这种技术不是

    C#独有的 易语言、VB、C++ 三种语言都可以 不过动态汇编我见过最多的是被应

    用在外挂方面 及远程汇编注入 实际上是属于动态汇编技术的一种扩展 不过很难

    说JIT在编译代码后是通过在远程把汇编代码写入托管进程执行的 又或者说是一种

    寄生在外壳程序中运行的技术及“内存运行” 懒得讨论这些一想到就头大。

    从上图中你可以看见一份简单的x86 / call汇编在C#中内嵌并被调用

    执行一看你会发现并不是太难 我的一篇博文 写了一大堆废话就是说

    这个东西不过是易语言的 http://blog.csdn.net/u012395622/article/details/46400569

    我们知道软件运行时所有代码会放在虚拟内存中 而可执行的代码在内存中

    内存保护一般是PAGE_EXECUTE_READ及32不过经过我研究.NET上的

    可执行代码应该是PAGE_EXECUTE_READWIRTE及64 如果是P/invoke

    上执行DLL中的保护是32 就可以我们在内嵌汇编时不可以使用只读保护

    如果我们需要使用由.NET去委托去Call那么必须是可读可写 如果通过Win32

    API去Call那么使用32就可以 有些区别 、我曾研究过易语言上字节集在内存

    中的内存保护到底是多少结果与C#是一致 4 / PAGE_READWRITE 不过为什

    么易语言可以CALL而C#不可以CALL一直是让我感到较为迷惑的事情 可能是

    托管堆与非托管堆之间不同造成的 不过我更希望有大神出来帮忙指点一下下。

    由于是X86汇编 首先需要把目标平台切换为x86 这样才不会造成C#调用汇编

    代码时出错 一定不要省略这个步骤

    首先你需要定义一个有参数的委托 重点在于在汇编中有这样一句话

    call        dword ptr[ebp+8] // call 参数一

    [csharp] view plaincopy
    1. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]  
    2. public delegate IntPtr CallMethod(IntPtr ptr);  

    由于是在VC下内联的汇编 最后移植到C# 一般在VC下函数的调用方式是cdcel

    何况下面的是按照cdcel导出函数格式进行的 所以不可以使用__stdcall的方式

    [csharp] view plaincopy
    1. [STAThread]  
    2. static void Main(string[] args)  
    3. {  
    4.     byte[] buf_asm = {  
    5.         // push        ebp  
    6.         // mov         ebp,esp  
    7.         // sub         esp,0C0h  
    8.         // push        ebx  
    9.         // push        esi  
    10.         // push        edi  
    11.         // lea         edi,[ebp-0C0h]  
    12.         // mov         ecx,30h  
    13.         // mov         eax,0CCCCCCCCh  
    14.         // rep stos    dword ptr es:[edi]  
    15.         85, 139, 236, 129, 236, 192, 0, 0, 0, 83, 86, 87, 141, 189, 64,  
    16.         255, 255, 255, 185, 48, 0, 0, 0, 184, 204, 204, 204, 204, 243, 171,  
    17.         // call        dword ptr[ebp+8]  
    18.         255, 85, 8,  
    19.         // pop         edi  
    20.         // pop         esi  
    21.         // pop         ebx  
    22.         // mov         esp,ebp  
    23.         // pop         ebp  
    24.         // ret  
    25.         95, 94, 91, 139, 229, 93, 195  
    26.     };  
    27.     IntPtr ptr_asm = SetHandleCount(buf_asm);  
    28.     VirtualProtect(ptr_asm, buf_asm.Length);  
    29.     CallMethod call_method = Marshal.GetDelegateForFunctionPointer(ptr_asm, typeof(CallMethod)) as CallMethod;  
    30.     call_method(Marshal.GetFunctionPointerForDelegate(new Action(Hello_x86)));  
    31. }  

    首先把你需要嵌入的汇编以字节数组的格式写出来 然后通过

    SetHandleCount函数是用于取地址指针的 

    [csharp] view plaincopy
    1. static void VirtualProtect(IntPtr ptr, int size)  
    2. {  
    3.     int outMemProtect;  
    4.     if (!VirtualProtect(ptr, size, 64, out outMemProtect))  
    5.         throw new Exception("Unable to modify memory protection.");  
    6. }  

    上面的函数用于修改内存保护 不过是为了让委托可以进行交互 包括汇编代码可以被互调用

    [csharp] view plaincopy
    1. static void Hello_x86()  
    2. {  
    3.     Console.Title = ((new StackFrame()).GetMethod()).Name;  
    4.     Console.WriteLine("I was x86 assembly call a test function.");  
    5.     Console.ReadKey(false);  
    6. }  

    上面的函数是一个测试函数 这个函数没有太大意义 只是表现利用了汇编调用

    本函数 然后本函数输出一个回应的信息 用于提示该函数被写入内存汇编调用

    依赖的外部函数

    [csharp] view plaincopy
    1. [DllImport("kernel32.dll", CharSet = CharSet.Auto)]  
    2. public static extern IntPtr SetHandleCount(byte[] value);  
    3.   
    4. [DllImport("kernel32.dll", SetLastError = true)]  
    5. public static extern bool VirtualProtect(IntPtr lpAddress, int dwSize, int flNewProtect, out int lpflOldProtect);  

    依赖的命名空间

    [csharp] view plaincopy
    1. using System;  
    2. using System.Runtime.InteropServices;  
    3. using System.Diagnostics;  

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    win10 安装anaconda+tensorflow
    CNN 理论
    mac 调出任何来源方法
    git忽略文件权限检查
    ios plist获取权限
    Vue-从入门到第三次世界大战_1
    libc++abi.dylib: terminating with uncaught exception of type NSException
    unity3d导出xcode项目使用afnetworking 3框架导致_kUTTagClassMIMEType 问题解决方案
    ios cannot use "@throw" with objective-c exceptions disabled 问题解决方案
    关于iOS APP转让
  • 原文地址:https://www.cnblogs.com/gc2013/p/4660430.html
Copyright © 2011-2022 走看看