C# inline-asm / 嵌入x86彙編

C#可不能夠嵌入彙編 能夠 在我眼中C#做爲一個介於中上層語言是不可能不能夠web

置入彙編代碼的 爲何會被我認爲中上層語言呢 從C#保留指針就能夠看出 我知數組

道有不少人必定不會相信C#可使用匯編代碼 不過C#會比較麻煩C#不能夠直接app

內聯彙編(inline-asm)準確的說C#只可使用(auto-asm)動態彙編 這種技術不是函數

C#獨有的 易語言、VB、C++ 三種語言均可以 不過動態彙編我見過最多的是被應oop

用在外掛方面 及遠程彙編注入 其實是屬於動態彙編技術的一種擴展 不過很難測試

說JIT在編譯代碼後是經過在遠程把彙編代碼寫入托管進程執行的 又或者說是一種this

寄生在外殼程序中運行的技術及「內存運行」 懶得討論這些一想到就頭大。url

從上圖中你能夠看見一份簡單的x86 / call彙編在C#中內嵌並被調用spa

執行一看你會發現並非太難 個人一篇博文 寫了一大堆廢話就是說.net

這個東西不過是易語言的 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;  
相關文章
相關標籤/搜索