2009-08-03 17 views
8

Tôi muốn nhúng tiện ích dòng lệnh trong ứng dụng C# của mình, để tôi có thể lấy byte của nó dưới dạng mảng và chạy tệp thực thi mà không bao giờ lưu nó vào đĩa tệp (tránh lưu trữ tệp thực thi dưới dạng tệp riêng biệt và tránh khả năng ghi tệp tạm thời ở bất kỳ đâu).Làm thế nào để chạy không thể quản lý thực thi từ bộ nhớ thay vì đĩa

Tôi không thể tìm thấy phương thức để chạy tệp thi hành chỉ từ luồng byte của nó. Có cửa sổ yêu cầu nó được trên một đĩa, hoặc là có một cách để chạy nó từ bộ nhớ? Nếu các cửa sổ yêu cầu nó nằm trên đĩa, có cách nào dễ dàng trong .NET framework để tạo một ổ đĩa ảo/tệp tin nào đó và ánh xạ tệp đó tới luồng bộ nhớ của tệp thực thi không?

+0

Bạn có thể sử dụng tiện ích như imdisk – Martin

Trả lời

1

Tạo RAM hoặc bán mã vào bộ nhớ và sau đó thực hiện cả hai khả năng, nhưng các giải pháp cực kỳ phức tạp (có thể nhiều hơn như vậy trong mã được quản lý).

Ứng dụng có cần thực thi không? Nếu bạn đóng gói nó như một assembly, bạn có thể sử dụng Assembly.Load() từ một luồng bộ nhớ - một vài dòng mã nhỏ.

Hoặc nếu nó thực sự phải là tệp thực thi, điều gì thực sự sai khi viết tệp tạm thời? Nó sẽ mất một vài dòng mã để đổ nó vào một tập tin tạm thời, thực hiện nó, chờ cho nó để thoát ra, và sau đó xóa các tập tin tạm thời - nó có thể thậm chí không nhận được ra khỏi bộ nhớ cache đĩa trước khi bạn đã xóa nó! Đôi khi giải pháp đơn giản, rõ ràng là giải pháp tốt nhất.

+0

Tệp thực thi chỉ là một loạt byte và tôi không thấy lý do nào khiến hệ điều hành nên quan tâm xem các byte có nguồn gốc từ đĩa hay bộ nhớ hay không, miễn là cả hai loại vị trí đều có thể bị khóa (và họ có thể). Hệ điều hành dường như DEPEND trên một tập tin thực thi được đặt trong một hệ thống tập tin, tại sao? Nếu chúng ta có thể nhớ các tập tin bản đồ, tại sao không dễ dàng làm ngược lại bằng cách đăng ký một đường dẫn UNC duy nhất cho một tập tin ảo chỉ được hỗ trợ bởi một vùng nhớ bị khóa? Windows 7 vẫn không thể gắn kết một ảnh ISO vào ổ đĩa ảo một cách tự nhiên mà không có phần mềm của bên thứ 3, mặc dù tất cả các công cụ của Microsoft đều được phân phối dưới dạng ảnh ISO. – Triynko

+0

Tôi không nghĩ rằng tôi có thể gói một tiện ích dòng lệnh không được quản lý của bên thứ ba được biên dịch trong C++ như một assembly có thể được sử dụng với Assembly.Load. Điều duy nhất sai với các tập tin temp viết là tôi không nghĩ rằng nó cần thiết, và nó đòi hỏi tôi phải tìm một thư mục tạm thời và đảm bảo quyền truy cập ghi, cũng không cần thiết. Chỉ có tất cả các bước không cần thiết có thể gây ra các vấn đề mà tôi đang cố gắng tránh, nhưng hệ điều hành và khung công tác .NET làm cho việc này trở nên khó khăn. – Triynko

+0

Tôi đồng ý với bạn. Tôi chỉ nghĩ rằng bạn sẽ có một thời gian khó tìm kiếm bất cứ điều gì dễ dàng để thực hiện và kiểm tra như viết một tập tin tạm thời. –

2

Hãy xem phần "Trong bộ nhớ" của bài báo này. Nhận ra rằng nó từ góc độ tiêm DLL từ xa, nhưng khái niệm phải giống nhau.

Remote Library Injection

+1

Thú vị, nhưng tôi đang tìm cách sử dụng một cái gì đó như Quy trình.Bắt đầu, truyền mảng byte thay vì tên tệp. Tôi không thích sự biện minh của họ vì không tung ra các quy trình từ bộ nhớ vì "máy quét virus không thể quét các chương trình không bao giờ tồn tại trên đĩa" ... một cảnh sát ra sao. Nếu họ muốn xây dựng hệ điều hành để chạy các chương trình một cách an toàn để bắt đầu, quy tắc "phải có nguồn gốc trên đĩa" sẽ là không cần thiết. – Triynko

+0

Ý của bạn là gì? Không có quy tắc như vậy. Nó chỉ là một thực tế của cuộc sống mà máy quét virus (mà không được viết bởi MS) có được nghi ngờ bất cứ lúc nào một quá trình đột nhiên bắt đầu thực hiện tự sửa đổi mã. Âm thanh như hành vi thích hợp với tôi, bất kể hệ điều hành máy quét đang chạy. Nếu bạn không muốn dựa vào máy quét vi-rút cho loại bảo vệ này, tốt, đó là lý do tại sao Windows đã có DPE được xây dựng trong nhiều năm. –

+0

Khuôn khổ .NET thực thi một quy tắc ngụ ý rằng "mã thực thi phải bắt nguồn trên đĩa" bằng cách cung cấp quá tải Process.Start mà cuối cùng sẽ chỉ chấp nhận một tên tệp làm con trỏ đến mã thực thi. Nó sẽ không chấp nhận một mảng byte được quản lý cũng như một con trỏ tới các byte không được quản lý có chứa mã thực thi. – Triynko

11

Bạn đang yêu cầu một mức độ thấp rất, tính năng nền tảng cụ thể được thực hiện trong một trình độ cao, môi trường quản lý. Bất cứ điều gì cũng có thể xảy ... nhưng không ai biết nó sẽ được dễ dàng ...

(BTW, tôi không biết tại sao bạn nghĩ rằng quản lý tập tin tạm thời là lựa chọn hợp lý Các BCL nào đó cho bạn:. http://msdn.microsoft.com/en-us/library/system.io.path.gettempfilename.aspx)


  1. Phân bổ đủ bộ nhớ để giữ tệp thực thi. Nó không thể cư trú trên heap được quản lý, tất nhiên, vì vậy giống như hầu như tất cả mọi thứ trong bài tập này, bạn sẽ cần phải PInvoke. (Tôi khuyên bạn nên sử dụng C++/CLI, để không tự lái xe quá phát điên). Đặc biệt chú ý đến các bit thuộc tính mà bạn áp dụng cho các trang bộ nhớ được phân bổ: làm cho chúng sai và bạn sẽ mở lỗ hổng bảo mật hoặc quá trình DEP của bạn bị tắt (tức là bạn sẽ gặp sự cố). Xem http://msdn.microsoft.com/en-us/library/aa366553(VS.85).aspx

  2. Định vị tệp thực thi trong thư viện tài nguyên của hội đồng của bạn và nhận được pinned handle cho nó.

  3. Memcpy() mã từ vùng được ghim của vùng được quản lý vào khối gốc.

  4. Miễn phí GCHandle.

  5. Gọi VirtualProtect để tránh ghi thêm vào khối bộ nhớ thực thi.

  6. Tính địa chỉ của hàm chính của tệp thi hành trong không gian địa chỉ ảo của tiến trình, dựa trên xử lý bạn nhận được từ VirtualAlloc và phần bù trong tệp như được hiển thị bởi DUMPBIN hoặc các công cụ tương tự.

  7. Đặt đối số dòng lệnh mong muốn trên ngăn xếp. (Windows Stdcall convention). Bất kỳ con trỏ nào cũng phải trỏ đến khu vực bản xứ hoặc được ghim, tất nhiên.

  8. Chuyển đến địa chỉ được tính toán. Có lẽ dễ nhất để sử dụng _call (ngôn ngữ lắp ráp nội tuyến).

  9. Cầu nguyện với Chúa rằng hình ảnh thực thi không có bất kỳ bước nhảy tuyệt đối nào trong đó có thể đã được sửa bằng cách gọi LoadLibrary theo cách thông thường. (Trừ khi, tất nhiên, bạn cảm thấy như tái triển khai bộ não của LoadLibrary trong bướC# 3).

  10. Truy xuất giá trị trả về từ thanh ghi @eax.

  11. Gọi VirtualFree.

Các bướC# 5 và # 11 phải được thực hiện trong khối cuối cùng và/hoặc sử dụng mẫu IDisposable.


Tùy chọn chính khác là tạo RAMdrive, viết tệp thực thi ở đó, chạy và dọn dẹp. Điều đó có thể an toàn hơn một chút vì bạn không cố gắng viết mã tự sửa đổi (điều này rất khó trong mọi trường hợp, nhưng đặc biệt là khi mã không phải là của bạn). Nhưng tôi khá chắc chắn nó sẽ yêu cầu các cuộc gọi API nền tảng hơn là tùy chọn tiêm mã động - tất cả chúng đều yêu cầu C++ hoặc PInvoke, một cách tự nhiên.

+1

Nhìn lại tất cả các bước và lời cầu nguyện, tôi hy vọng nó rõ ràng lý do tại sao các "mã phải được trên đĩa" quy tắc là rất nguy hiểm. Vì mã thực thi cuối cùng được nạp vào bộ nhớ, tôi có thể chạy nó trực tiếp từ bộ nhớ, hoặc tải nó từ đĩa vào bộ nhớ và sau đó chạy nó. Hiện tại .NET API sẽ yêu cầu tôi để lấy mã trong bộ nhớ, ghi nó vào đĩa, làm việc với một hệ thống quản lý tập tin tạm thời, chỉ để đọc nó ngay vào bộ nhớ, nơi nó đã được ở nơi đầu tiên! Đây chỉ là minh chứng cho những gì xảy ra khi bạn quấn một công nghệ cũ vào quần áo mới và đặt cho nó một cái tên mới. – Triynko

+1

Ngoài ra, tính năng "cấp thấp, nền tảng cụ thể" này đã có trong khung .NET được quản lý ở mức cao là "Process.Start". Vấn đề là loại con trỏ duy nhất mà nó chấp nhận đối với các byte mã thực thi là một tên tệp, ngụ ý rằng một đĩa là mã duy nhất có nguồn gốc. – Triynko

+0

Tôi không nghĩ rằng các tập tin cho phép nên bao giờ cần phải đi vào hỗn hợp ở tất cả, và tiếc là với các tập tin tạm thời họ làm. Xem nhận xét trên MSDN cho Path.GetTempFilename: trong môi trường quyền thấp, ví dụ: trong một số cấu hình ASP.NET, chức năng này sẽ thất bại với một ngoại lệ bảo mật ... vì nó cần phải tìm thư mục tạm thời và đó là đọc "Môi trường" ... nó yêu cầu EnvironmentPermission để truy cập không bị giới hạn vào các biến môi trường. Liên kết liệt kê: PermissionState.Unrictricted – Triynko

-1

Điều này rõ ràng không được phép trong Vista +. Bạn có thể sử dụng một số cuộc gọi Win32 API không có giấy tờ trong XP để làm điều này nhưng nó đã bị hỏng trong Vista + bởi vì nó là một lỗ hổng bảo mật lớn và chỉ những người sử dụng nó là các nhà văn độc hại.

+1

Cũng thật là kỳ cục. Một luồng các byte là một luồng các byte bất kể bạn nhìn vào nó như thế nào hoặc nó xuất phát từ đâu. Buộc các byte đó đến từ FILE thay vì MEMORY để chạy không phục vụ mục đích nào. Phần mềm độc hại? Nghiêm túc? Hãy cho tôi một break ... vì vậy họ chỉ cần viết nó vào một tập tin đầu tiên để chạy nó. Bạn đang nói có một lỗ hổng bảo mật trong API (Ok, tôi đoán), hoặc bạn đang nói có một lỗ hổng bảo mật trong ý tưởng chạy mã từ một luồng bộ nhớ của byte chứ không phải là một luồng tệp byte (chắc chắn KHÔNG). – Triynko

+0

Nó không quan trọng, và nó không phải là vô lý. Ví dụ; làm thế nào để bạn xác nhận đúng cách và an toàn chữ ký của một hình ảnh thực thi nếu tập tin không có trên đĩa? Làm thế nào sẽ lọc trình điều khiển làm việc ngay bây giờ mà bạn đang thực hiện từ một hình ảnh bộ nhớ? Làm thế nào sẽ hỗ trợ hình ảnh làm việc ngay bây giờ mà bạn đang ăn trong một dòng bộ nhớ chứ không phải là một tên tập tin? Đây chỉ là một vài, nhưng bạn vẫn có một triệu trường hợp góc, như đối phó với các tùy chọn thực thi tệp hình ảnh, mâu thuẫn với gỡ lỗi, v.v. Nó thực sự là tầm thường để chỉ cần viết ra các tập tin, điều này là đối phó với ruột của một rất phức tạp Hệ điều hành. –

+0

Xác thực chữ ký bằng cách đọc các byte từ khối bộ nhớ thay vì các khối đĩa! Không nên có sự khác biệt; đó là thiết kế kém. Trình điều khiển bộ lọc không liên quan, vì chúng ta đang nói về mã đã thực thi, yêu cầu một số mã cụ thể khác bắt đầu chạy và không có bộ lọc nào can thiệp vào mã đó. Nếu bạn thực sự cần bộ lọc, hệ điều hành có thể cung cấp các móc cấp thấp để cho phép các bộ lọc quét bộ nhớ ngay trước khi nó được bảo vệ và bắt đầu thực hiện. Một lần nữa, không có gì đặc biệt về dữ liệu nằm trên đĩa, đó là một kiến ​​trúc kém. – Triynko

Các vấn đề liên quan