C#內嵌彙編代碼的討論

來源:互聯網
上載者:User
很久之前整理了一篇《C# 調用非託管程式》文章,在部落格園zhongzf同學《在.net程式中嵌入asm彙編代碼》進行了簡單的討論,現在才有時間整理。
《C# 調用非託管程式》最後一種方法通俗的講是構造符合彙編代碼(機器代碼)格式的資料,把該資料當作可執行代碼執行。Windows提供了DEP(Data Execution Prevention 資料執行防止)機制,也就是Windows會試圖阻止程式運行非可執行記憶體地區的可執行代碼。如果開啟DEP,《C# 調用非託管程式》一文中最後一種方法執行會失敗;如果關閉DEP,Windows XP SP2中執行該代碼會成功,但Vista/Win7由於安全性增強原因,該代碼執行會失敗。
是不是這用嵌入彙編代碼的方式在開啟DEP及Vista/Win7中一定不能使用呢?答案在下面分析中得出。
如果我們把儲存彙編代碼的記憶體地區標記為可執行,上面的方法也許可用。

Win API VirtualAlloc中有參數,可以指定新分配記憶體的許可權。
使用完記憶體後,調用VirtualFree釋放。

沿著這樣的思路,將《C# 調用非託管程式》一文中最後一種方法修改如下(篇幅原因簡化了注釋):/*修改記錄
    2008-5-11 8:07 曲濱
        >> 基本實現預期功能
        [!] 明天進行最佳化

    2008-5-12 15:54 曲濱
        [E] 最佳化完成
        [N] 加入 NativeCodeHelper 類便於使用 

    2010-6-17 周振興 
        修改相容性,可在開啟DEP及Vista/Win7中運行。
*/

namespace NShellNativeCode
{
    using System;
    using System.Runtime.InteropServices;

    delegate int AddProc(int p1, int p2);
    class Program
    {
        static void Main(string[] args)
        {
            byte[] codeBytes = {
                  0x8B, 0x44, 0x24, 0x08    // mov eax,[esp+08h]
                , 0x8B, 0x4C, 0x24, 0x04    // mov ecx,[esp+04h]
                , 0x03, 0xC1                // add    eax,ecx
                , 0xC3                        // ret
                };

            /*
            上面的位元組數組,就是下面函數的機器碼;
            int add(int x,int y) {
                return x+y;
            }
            
            */

            IntPtr handle = IntPtr.Zero;
            handle = VirtualAlloc(
                IntPtr.Zero,
                codeBytes.Length,
                MEM_COMMIT | MEM_RESERVE,
                PAGE_EXECUTE_READWRITE);

            try
            {

                Marshal.Copy(codeBytes, 0, handle, codeBytes.Length);

                AddProc add
                   = Marshal.GetDelegateForFunctionPointer(handle, typeof(AddProc)) as AddProc;

                int r = add(1976, 1);

                Console.WriteLine("機器碼返回:{0}", r);

            }
            finally
            { 
                VirtualFree(handle, 0, MEM_RELEASE);
            }

            Console.ReadLine();
        }

        //Windows API
        [DllImport("Kernel32.dll", EntryPoint = "VirtualAlloc")]
        public static extern IntPtr VirtualAlloc(IntPtr address, int size, uint allocType, uint protect);

        [DllImport("Kernel32.dll", EntryPoint = "VirtualFree")]
        public static extern bool VirtualFree(IntPtr address, int size, uint freeType);

        //flags
        const uint MEM_COMMIT = 0x1000;
        const uint MEM_RESERVE = 0x2000;

        const uint PAGE_EXECUTE_READWRITE = 0x40;

        const uint MEM_RELEASE = 0x8000;
    }
}

事實證明,這種嵌入彙編代碼的方式在開啟DEP及Vista/Win7可運行。
Win7 (X86)開啟DEP環境下測試通過。
註:codeBytes數組中是X86彙編代碼,如果要在X64中運行,需修改該代碼!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.