সম্পূর্ণরূপে একটি পরিচালিত। নেট ভাষায় একটি জেআইটি সংকলক (নেটিভ কোডে) লিখতে কি সম্ভব?


84

আমি একটি জেআইটি সংকলক লেখার ধারণাটি নিয়ে যাচ্ছি এবং কেবল ভাবছি যে পুরোপুরি ব্যবস্থাপনার কোডটিতে লেখার জন্য তাত্ত্বিকভাবে সম্ভব কি না। বিশেষত, একবার আপনি বাইট অ্যারেতে এসেম্বলারের জেনারেট করেছেন কীভাবে আপনি কার্যকর করতে শুরু করতে এতে ঝাঁপিয়ে পড়বেন?


আমি বিশ্বাস করি না - যেখানে আপনি পরিচালিত ভাষাগুলিতে কোনও সময় অনিরাপদ প্রসঙ্গে কাজ করতে পারেন, আমি বিশ্বাস করি না যে আপনি কোনও পয়েন্টার থেকে কোনও প্রতিনিধি সংশ্লেষ করতে পারেন - এবং কীভাবে আপনি উত্পন্ন কোডটিতে ঝাঁপিয়ে যাবেন?
ড্যামিয়েন_এ_বিশ্বাসীরা

@ ড্যামিয়েন: অনিরাপদ কোড আপনাকে কোনও ফাংশন পয়েন্টারে লিখতে দেবে না?
হেন্ক হলটারম্যান

4
"কীভাবে নিয়ন্ত্রণহীন কোডে পরিবর্তনশীলভাবে নিয়ন্ত্রণ স্থানান্তর করতে হয়" এর মতো একটি শিরোনাম সহ আপনার বন্ধ হওয়ার ঝুঁকি কম হতে পারে। এটি বিষয়টি আরও বেশি দেখায়। কোড তৈরি করা সমস্যা নয়।
হেন্ক হলটারম্যান

8
সবচেয়ে সহজ ধারণাটি হ'ল কোনও ফাইলে বাইট অ্যারে লিখুন এবং ওএসকে এটি চালিয়ে দেওয়া হোক। সর্বোপরি, আপনার একটি সংকলক প্রয়োজন , কোনও দোভাষী না (যা পাশাপাশি সম্ভব হবে, তবে আরও জটিল)।
ভ্লাদ

4
আপনি যখন চান কোডটি JIT একবার সংকলন করলেন, আপনি উইন 32 এপিআই ব্যবহার করতে পারেন কিছু নিয়ন্ত্রণহীন মেমোরি বরাদ্দ করতে (এক্সিকিউটেবল হিসাবে চিহ্নিত), সংকলিত calliকোডটিকে সেই মেমরি স্পেসে অনুলিপি করতে পারেন, তারপরে সংকলিত কোডটিতে কল করতে আইএল অপকোড ব্যবহার করুন ।
জ্যাক পি।

উত্তর:


71

এবং ধারণার সম্পূর্ণ প্রমাণের জন্য এখানে জেআইটিতে রাসমাসের এফ # তে যাওয়ার সম্পূর্ণরূপে অনুবাদ অনুবাদ

open System
open System.Runtime.InteropServices

type AllocationType =
    | COMMIT=0x1000u

type MemoryProtection =
    | EXECUTE_READWRITE=0x40u

type FreeType =
    | DECOMMIT = 0x4000u

[<DllImport("kernel32.dll", SetLastError=true)>]
extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType flAllocationType, MemoryProtection flProtect);

[<DllImport("kernel32.dll", SetLastError=true)>]
extern bool VirtualFree(IntPtr lpAddress, UIntPtr dwSize, FreeType freeType);

let JITcode: byte[] = [|0x55uy;0x8Buy;0xECuy;0x8Buy;0x45uy;0x08uy;0xD1uy;0xC8uy;0x5Duy;0xC3uy|]

[<UnmanagedFunctionPointer(CallingConvention.Cdecl)>] 
type Ret1ArgDelegate = delegate of (uint32) -> uint32

[<EntryPointAttribute>]
let main (args: string[]) =
    let executableMemory = VirtualAlloc(IntPtr.Zero, UIntPtr(uint32(JITcode.Length)), AllocationType.COMMIT, MemoryProtection.EXECUTE_READWRITE)
    Marshal.Copy(JITcode, 0, executableMemory, JITcode.Length)
    let jitedFun = Marshal.GetDelegateForFunctionPointer(executableMemory, typeof<Ret1ArgDelegate>) :?> Ret1ArgDelegate
    let mutable test = 0xFFFFFFFCu
    printfn "Value before: %X" test
    test <- jitedFun.Invoke test
    printfn "Value after: %X" test
    VirtualFree(executableMemory, UIntPtr.Zero, FreeType.DECOMMIT) |> ignore
    0

যে আনন্দের সাথে ফলন কার্যকর করে

Value before: FFFFFFFC
Value after: 7FFFFFFE

আমার উত্থাপিত হওয়া সত্ত্বেও, আমি পৃথক হতে অনুরোধ করছি: এটি স্বেচ্ছাসেবীর কোড কার্যকর করা , জেআইটি নয় - জেআইটি মানে "সময় সংকলন কেবল ", তবে আমি এই কোড উদাহরণ থেকে "সংকলন" দিকটি দেখতে পাচ্ছি না।
রবিং

4
@ রওং: "সংকলন" দিকটি মূল প্রশ্ন উদ্বেগের আওতায় ছিল না। আইএল -> নেটিভ কোড ট্রান্সফর্মেশন প্রয়োগের পরিচালিত কোড ক্ষমতাটি প্রকট is
জিন বেলিটস্কি

70

হ্যা, তুমি পারো. আসলে, এটি আমার কাজ :)

আমি জিপিইউ.এনইটি সম্পূর্ণ এফ # তে লিখেছি (আমাদের ইউনিট পরীক্ষাগুলি মডিউল করে দেয়) - এটি আসলে নেট-সিএলআর যেমন রান-টাইমে আলাদা করে দেয় এবং জেআইটি আইএলকে। আপনি যে অন্তর্নিহিত ত্বরণ ডিভাইসটি ব্যবহার করতে চান তার জন্য আমরা স্থানীয় কোড নির্গত করি; বর্তমানে আমরা কেবল এনভিডিয়া জিপিইউকেই সমর্থন করি, তবে আমি আমাদের সিস্টেমটি ন্যূনতম কাজের সাথে রিটার্জেটেবল হতে ডিজাইন করেছি যাতে সম্ভবত আমরা ভবিষ্যতে অন্যান্য প্ল্যাটফর্মগুলিকে সমর্থন করব।

পারফরম্যান্সের জন্য, ধন্যবাদ জানাতে আমার কাছে এফ # রয়েছে - যখন অনুকূলিত মোডে (টেলকলগুলি সহ) সংকলিত হয়, তখন আমাদের জেআইটি সংকলকটি সম্ভবত সিএলআরের অভ্যন্তরে সংকলক (যা সি ++, আইআইআরসি তে লিখিত আছে) প্রায় তত দ্রুত।

মৃত্যুদন্ড কার্যকর করার জন্য, জিটযুক্ত কোডটি চালানোর জন্য আমাদের হার্ডওয়্যার ড্রাইভারের নিয়ন্ত্রণ নিয়ন্ত্রণ করতে সক্ষম হওয়ার সুবিধা রয়েছে; যাইহোক, সিপিইউতে এটি করা খুব কঠিন হবে না যেহেতু .NET অপরিকল্পিত / স্থানীয় কোডের ফাংশন পয়েন্টারগুলিকে সমর্থন করে (যদিও আপনি সাধারণত নেট দ্বারা সরবরাহিত কোনও সুরক্ষা / সুরক্ষা হারাবেন)।


4
NoExecute এর পুরো পয়েন্টটি নয় যে আপনি নিজেরাই তৈরি করেছেন এমন কোডটিতে লাফ দিতে পারবেন না? ফাংশন পয়েন্টারের মাধ্যমে নেটিভ কোডে ঝাঁপ দেওয়া সম্ভব হওয়ার চেয়ে: ফাংশন পয়েন্টারের মাধ্যমে নেটিভ কোডে ঝাঁপ দেওয়া কি সম্ভব নয় ?
ইয়ান বয়ড

অসাধারণ প্রকল্প, যদিও আমি মনে করি আপনি যদি অলাভজনক অ্যাপ্লিকেশনগুলির জন্য এটি বিনামূল্যে করে থাকেন তবে আপনারা ছেলেরা আরও অনেক বেশি এক্সপোজার পেয়ে যাবেন। আপনি "উত্সাহী" স্তর থেকে কুঁচকে-পরিবর্তন হারাবেন, তবে এটি ব্যবহার করে বেশি লোকের বর্ধিত এক্সপোজারের জন্য এটি যথেষ্ট উপযুক্ত হবে! (আমি জানি আমি অবশ্যই করব ! )) !
ব্লুরাজা - ড্যানি প্লেফুঘুফুট

@ আইয়ানবয়েড নো এক্সেকিউট বেশিরভাগ ক্ষেত্রে বাফার ওভারআনগুলি এবং সম্পর্কিত সমস্যাগুলি থেকে ঝামেলা এড়ানোর আরও একটি উপায়। এটি আপনার নিজের কোড থেকে কোনও সুরক্ষা নয়, অবৈধ কোড কার্যকরকরণ প্রশমিত করতে এটি এমন কিছু something
লুয়ান

51

কৌতুক হওয়া উচিত VirtualAlloc সঙ্গে EXECUTE_READWRITE-flag এবং (পি / ডাকা প্রয়োজন) Marshal.GetDelegateForFunctionPointer

এখানে ঘোরান পূর্ণসংখ্যার উদাহরণের একটি পরিবর্তিত সংস্করণ দেওয়া আছে (নোট করুন এখানে কোনও অনিরাপদ কোডের প্রয়োজন নেই):

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate uint Ret1ArgDelegate(uint arg1);

public static void Main(string[] args){
    // Bitwise rotate input and return it.
    // The rest is just to handle CDECL calling convention.
    byte[] asmBytes = new byte[]
    {        
      0x55,             // push ebp
      0x8B, 0xEC,       // mov ebp, esp 
      0x8B, 0x45, 0x08, // mov eax, [ebp+8]
      0xD1, 0xC8,       // ror eax, 1
      0x5D,             // pop ebp 
      0xC3              // ret
    };

    // Allocate memory with EXECUTE_READWRITE permissions
    IntPtr executableMemory = 
        VirtualAlloc(
            IntPtr.Zero, 
            (UIntPtr) asmBytes.Length,    
            AllocationType.COMMIT,
            MemoryProtection.EXECUTE_READWRITE
        );

    // Copy the machine code into the allocated memory
    Marshal.Copy(asmBytes, 0, executableMemory, asmBytes.Length);

    // Create a delegate to the machine code.
    Ret1ArgDelegate del = 
        (Ret1ArgDelegate) Marshal.GetDelegateForFunctionPointer(
            executableMemory, 
            typeof(Ret1ArgDelegate)
        );

    // Call it
    uint n = (uint)0xFFFFFFFC;
    n = del(n);
    Console.WriteLine("{0:x}", n);

    // Free the memory
    VirtualFree(executableMemory, UIntPtr.Zero, FreeType.DECOMMIT);
 }

সম্পূর্ণ উদাহরণ (এখন এক্স 86 এবং এক্স 64 উভয়ের সাথে কাজ করে)।


30

অনিরাপদ কোড ব্যবহার করে, আপনি একটি প্রতিনিধি "হ্যাক" করতে পারেন এবং এটি একটি স্বেচ্ছাসেবী সমাবেশ কোডের দিকে নির্দেশ করতে পারেন যা আপনি কোনও অ্যারে তৈরি করেছেন এবং সংরক্ষণ করেছেন। ধারণাটি হ'ল প্রতিনিধিদের একটি _methodPtrক্ষেত্র রয়েছে, যা প্রতিচ্ছবি ব্যবহার করে সেট করা যেতে পারে। এখানে কিছু নমুনা কোড রয়েছে:

এটি অবশ্যই একটি নোংরা হ্যাক যা। নেট রানটাইম পরিবর্তনের সময় যে কোনও সময় কাজ বন্ধ করে দিতে পারে।

আমার ধারণা, নীতিগতভাবে, পুরোপুরি পরিচালিত নিরাপদ কোডটিকে জেআইটি প্রয়োগের অনুমতি দেওয়া যাবে না, কারণ এটি রানটাইম নির্ভর করে এমন কোনও সুরক্ষা অনুমানকে ভেঙে ফেলবে। (যদি না, উত্পন্ন সমাবেশ কোডটি একটি মেশিন-চেকযোগ্য প্রমাণ নিয়ে আসে যা এটি অনুমানগুলি লঙ্ঘন করে না ...)


4
দুর্দান্ত হ্যাক। সম্ভবত আপনি ভাঙা লিঙ্কগুলির সাথে পরবর্তী সমস্যাগুলি এড়াতে এই পোস্টে কোডের কিছু অংশ অনুলিপি করতে পারেন। (বা কেবল এই পোস্টে একটি ছোট বর্ণনা লিখুন)।
ফেলিক্স কে।

আমি AccessViolationExceptionযদি আপনার উদাহরণ চালানোর চেষ্টা করি তবে আমি একটি পেয়েছি। আমি অনুমান করি এটি কেবল তখনই কার্যকর হয় যদি ডিইপি অক্ষম থাকে।
রাসমাস ফ্যাবার

4
তবে আমি যদি EXECUTE_READWRITE পতাকার সাথে মেমরি বরাদ্দ করি এবং _ মেমোডিপিআরটি ক্ষেত্রে এটি কার্যকর হয়। রটার-কোডটি দেখে মনে হচ্ছে এটি মূলত মার্শাল.গেটডেলিগেট ফোর্স ফাংশনপয়েন্টার () যা করে তা ব্যতীত, এটি স্ট্যাক স্থাপন এবং সুরক্ষা পরিচালনার জন্য কোডটির চারপাশে কিছু অতিরিক্ত অংশ যোগ করে।
রাসমাস ফ্যাবার

আমি মনে করি লিঙ্কটি মারা গেছে, হায়, আমি এটি সম্পাদনা করব, তবে আমি আসলটির স্থানান্তর পাইনি।
আবেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.