2008-12-14 61 views
18

Trong chương trình C++ của tôi (trên Windows), tôi đang cấp phát một khối bộ nhớ và có thể đảm bảo rằng nó vẫn bị khóa (không được thay đổi và tiếp giáp) trong bộ nhớ vật lý (tức là sử dụng VirtualAllocEx(), MapUserPhysicalPages() vv).Làm thế nào để dịch địa chỉ bộ nhớ ảo sang địa chỉ thực?

Trong bối cảnh quá trình của tôi, tôi có thể lấy địa chỉ bộ nhớ ảo của khối đó, nhưng tôi cần phải tìm ra địa chỉ bộ nhớ vật lý của nó để vượt qua nó để một số thiết bị bên ngoài.


1. Có cách nào tôi có thể dịch địa chỉ ảo sang địa chỉ ảo trong chương trình của tôi, ở chế độ USER không?

2. Nếu không, tôi có thể tìm bản đồ ảo này với vật lý chỉ trong chế độ KERNEL. Tôi đoán nó có nghĩa là tôi phải viết một trình điều khiển để làm điều đó ...? Bạn có biết về bất kỳ trình điều khiển/DLL/API sẵn có nào mà tôi có thể sử dụng, mà ứng dụng (chương trình) của tôi sẽ giao tiếp với bản dịch không?

3. Trong trường hợp tôi phải tự mình viết trình điều khiển, làm cách nào để thực hiện bản dịch này? tôi sử dụng chức năng nào? Có phải là mmGetPhysicalAddress()? Làm thế nào để tôi sử dụng nó?

4. Ngoài ra, nếu tôi hiểu chính xác, mmGetPhysicalAddress() trả về địa chỉ vật lý của địa chỉ cơ sở ảo trong ngữ cảnh của quá trình gọi. Nhưng nếu quá trình gọi là trình điều khiển, và tôi đang sử dụng ứng dụng của mình để gọi trình điều khiển cho chức năng đó, tôi đang thay đổi ngữ cảnh và tôi không còn trong ngữ cảnh của ứng dụng khi thường trình mmGetPhysicalAddress được gọi là ... làm cách nào để dịch địa chỉ ảo trong không gian bộ nhớ của ứng dụng (chế độ người dùng), không phải trình điều khiển?

Bất kỳ câu trả lời, mẹo và trích đoạn mã nào sẽ được đánh giá cao !!

Cảm ơn

+0

Tôi tò mò, thiết bị bên ngoài có thể làm gì với địa chỉ bộ nhớ vật lý? – jyoung

+0

Nếu không đi vào chi tiết, nó là một thiết bị trên máy có quyền truy cập trực tiếp vào RAM của máy, nhưng không biết về ánh xạ hệ điều hành (đó là lý do tại sao địa chỉ ảo hoặc sử dụng đối tượng bộ nhớ chia sẻ sẽ không hoạt động). –

Trả lời

4

1) Không

2) Có, bạn phải viết một trình điều khiển. Tốt nhất sẽ là trình điều khiển ảo hoặc thay đổi trình điều khiển cho thiết bị đặc biệt bên ngoài.

3) Điều này rất khó hiểu ở đây. MmGetPhysicalAddress phải là phương thức bạn đang khóa, nhưng tôi thực sự không biết địa chỉ vật lý được ánh xạ tới ngân hàng/chip/etc như thế nào. trên bộ nhớ vật lý.

4) Bạn không thể sử dụng bộ nhớ được phân trang, vì bộ nhớ đó sẽ được di chuyển. Bạn có thể khóa bộ nhớ được phân trang bằng MmProbeAndLockPages trên MDL mà bạn có thể xây dựng trên bộ nhớ được chuyển từ ngữ cảnh gọi chế độ người dùng. Nhưng nó là tốt hơn để phân bổ bộ nhớ không paged và bàn tay đó để ứng dụng chế độ người dùng của bạn.

PVOID p = ExAllocatePoolWithTag(NonPagedPool, POOL_TAG); 
PHYSICAL_ADDRESS realAddr = MmGetPhysicalAddress(p); 

// use realAddr 
12

Trong chương trình của tôi C++ (trên Windows), tôi đang phân bổ một khối bộ nhớ và có thể chắc chắn rằng nó vẫn bị khóa (unswapped và tiếp giáp) trong bộ nhớ vật lý (tức là sử dụng VirtualAllocEx(), MapUserPhysicalPages() v.v.)

Không, bạn thực sự không thể đảm bảo rằng nó vẫn bị khóa. Điều gì sẽ xảy ra nếu quá trình của bạn bị lỗi hoặc thoát sớm? Nếu người dùng giết nó thì sao? Bộ nhớ đó sẽ được tái sử dụng cho một thứ khác và nếu thiết bị của bạn vẫn đang thực hiện DMA, điều đó cuối cùng sẽ dẫn đến mất dữ liệu/tham nhũng hoặc kiểm tra lỗi (BSOD).

Ngoài ra, MapUserPhysicalPages là một phần của Windows AWE (Tiện ích mở rộng địa chỉ cửa sổ), để xử lý hơn 4 GB RAM trên các phiên bản Windows Server 32 bit. Tôi không nghĩ rằng nó được dự định sẽ được sử dụng để hack DMA chế độ người dùng.

1. Có cách nào để tôi có thể dịch địa chỉ ảo sang địa chỉ thực trong chương trình của tôi, ở chế độ USER không?

Có trình điều khiển cho phép bạn thực hiện việc này, nhưng bạn không thể lập trình DMA từ chế độ người dùng trên Windows và vẫn có hệ thống ổn định và bảo mật. Để một quá trình chạy như một tài khoản người dùng hạn chế đọc/ghi bộ nhớ vật lý cho phép quá trình sở hữu hệ thống. Nếu điều này là cho một hệ thống một lần hoặc một mẫu thử nghiệm, điều này có thể chấp nhận được, nhưng nếu bạn mong đợi những người khác (đặc biệt là khách hàng trả tiền) sử dụng phần mềm và thiết bị của bạn, bạn nên viết một trình điều khiển.

2. Nếu không, tôi có thể tìm hiểu bản đồ ảo này với vật lý chỉ trong chế độ KERNEL. Tôi đoán nó có nghĩa là tôi phải viết một trình điều khiển để làm điều đó ...?

Đó là cách được đề xuất để tiếp cận vấn đề này.

Bạn có biết bất kỳ trình điều khiển/API/API sẵn có nào mà tôi có thể sử dụng, mà ứng dụng (chương trình) của tôi sẽ giao tiếp với bản dịch không?

Bạn có thể sử dụng MDL (Memory Descriptor List) để khóa bộ nhớ tùy ý, bao gồm bộ đệm được sở hữu bởi quy trình chế độ người dùng và dịch địa chỉ ảo của nó thành địa chỉ thực. Bạn cũng có thể có Windows tạm thời tạo MDL cho bộ đệm được chuyển vào cuộc gọi đến DeviceIoControl bằng cách sử dụng METHOD_IN_DIRECT hoặc METHOD_OUT_DIRECT.

Lưu ý rằng các trang tiếp giáp trong không gian địa chỉ ảo hầu như không bao giờ tiếp giáp trong không gian địa chỉ thực. Hy vọng rằng thiết bị của bạn được thiết kế để xử lý điều đó.

3. Trong trường hợp tôi phải tự mình viết trình điều khiển, làm cách nào để thực hiện bản dịch này? tôi sử dụng chức năng nào? Có phải mmGetPhysicalAddress() không? Làm thế nào để tôi sử dụng nó?

Có nhiều thứ để viết trình điều khiển hơn là chỉ cần gọi một vài API. Nếu bạn định viết trình điều khiển, tôi khuyên bạn nên đọc nhiều tài liệu liên quan như bạn có thể từ MSDNOSR. Ngoài ra, hãy xem các ví dụ trong số Windows Driver Kit.

4. Ngoài ra, nếu tôi hiểu chính xác, mmGetPhysicalAddress() trả về địa chỉ vật lý của địa chỉ cơ sở ảo trong ngữ cảnh của quá trình gọi. Nhưng nếu quá trình gọi là trình điều khiển, và tôi đang sử dụng ứng dụng của mình để gọi trình điều khiển cho chức năng đó, tôi đang thay đổi ngữ cảnh và tôi không còn trong ngữ cảnh của ứng dụng khi thường trình mmGetPhysicalAddress được gọi là ... làm cách nào để dịch địa chỉ ảo trong không gian bộ nhớ của ứng dụng (chế độ người dùng), không phải trình điều khiển?

Trình điều khiển không phải là quy trình. Một trình điều khiển có thể chạy trong bối cảnh của bất kỳ quá trình nào, cũng như các bối cảnh nâng cao khác nhau (các trình xử lý ngắt và các DPC).

4

Bạn thực sự không được thực hiện các công cụ như thế này trong usermode; như Christopher nói, bạn cần phải khóa các trang để mm không quyết định trang ra bộ nhớ sao lưu của bạn trong khi một thiết bị đang sử dụng nó, mà cuối cùng sẽ làm hỏng các trang bộ nhớ ngẫu nhiên.

Nhưng nếu quá trình gọi là trình điều khiển và tôi đang sử dụng ứng dụng của mình để gọi trình điều khiển cho chức năng đó, tôi đang thay đổi ngữ cảnh và tôi không còn trong ngữ cảnh của ứng dụng khi tham số mmGetPhysicalAddress được gọi là

Trình điều khiển không có ngữ cảnh như ứng dụng chế độ người dùng làm; nếu bạn đang gọi vào một trình điều khiển thông qua một IOCTL hoặc một cái gì đó, bạn thường (nhưng không được bảo đảm!) để được trong bối cảnh thread của người dùng gọi điện thoại. Nhưng thực sự, điều này không quan trọng đối với những gì bạn đang hỏi, bởi vì bộ nhớ chế độ lõi (bất cứ thứ gì trên 0x80000000) là ánh xạ giống nhau cho dù bạn đang ở đâu và bạn sẽ phân bổ bộ nhớ ở phía nhân. Nhưng một lần nữa, viết trình điều khiển thích hợp. Sử dụng WDF (http://www.microsoft.com/whdc/driver/wdf/default.mspx), và nó sẽ làm cho văn bản một trình điều khiển chính xác dễ dàng hơn nhiều (mặc dù vẫn khá khó khăn, viết trình điều khiển Windows không phải là dễ dàng)

EDIT: Chỉ cần nghĩ tôi sẽ đưa ra một vài cuốn sách tham khảo để giúp bạn , bạn nên chắc chắn (ngay cả khi bạn không theo đuổi viết trình điều khiển) đọc Windows Internals bởi Russinovich và Solomon (http://www.amazon.com/Microsoft-Windows-Internals-4th-Server/dp/0735619174/ref=pd_bbs_sr_2?ie=UTF8&s=books&qid=1229284688&sr=8-2); Lập trình Mô hình Trình điều khiển Microsoft Windows cũng tốt (http://www.amazon.com/Programming-Microsoft-Windows-Driver-Second/dp/0735618038/ref=sr_1_1?ie=UTF8&s=books&qid=1229284726&sr=1-1)

-2

Chờ, có nhiều hơn. Đối với đặc quyền của runnning trên Vista 64 bit của khách hàng của bạn, bạn nhận được nhiều thời gian và tiền bạc để có được trình điều khiển chế độ kernal của bạn từ chức Microsoft của tôi,

4

Bạn có một bộ đệm hầu như continguous trong ứng dụng của bạn. Đó là phạm vi của bộ nhớ ảo, như bạn đã lưu ý, chỉ có sẵn trong bối cảnh của ứng dụng của bạn và một số của nó có thể được paged ra bất cứ lúc nào. Vì vậy, để truy cập bộ nhớ từ một thiết bị (có nghĩa là, thực hiện DMA), bạn cần phải khóa cả hai thiết bị và nhận được một mô tả có thể được truyền đến một thiết bị.

Bạn có thể nhận được mô tả về bộ đệm được gọi là MDL hoặc Danh sách mô tả bộ nhớ bằng cách gửi IOCTL (thông qua chức năng DeviceControl) tới trình điều khiển của bạn bằng METHOD_IN_DIRECT hoặc METHOD_OUT_DIRECT. Xem trang sau để thảo luận về việc xác định IOCTL.

http://msdn.microsoft.com/en-us/library/ms795909.aspx

Bây giờ bạn có một mô tả của bộ đệm trong một trình điều khiển cho thiết bị của bạn, bạn có thể khóa nó xuống để bộ đệm vẫn còn trong bộ nhớ cho toàn bộ thời gian mà thiết bị của bạn có thể hoạt động trên đó. Tra cứu MmProbeAndLockPages trên MSDN.

Thiết bị của bạn có thể hoặc không thể đọc hoặc ghi tất cả bộ nhớ trong bộ đệm. Thiết bị chỉ có thể hỗ trợ DMA 32 bit và máy có thể có nhiều hơn 4GB RAM. Hoặc bạn có thể giao dịch với một máy có IOMMU, GART hoặc một số công nghệ dịch địa chỉ khác. Để chứa điều này, hãy sử dụng các API DMA khác nhau để có được một tập hợp các địa chỉ hợp lý tốt cho thiết bị của bạn sử dụng. Trong nhiều trường hợp, các địa chỉ hợp lý này sẽ tương đương với các địa chỉ vật lý mà câu hỏi của bạn được hỏi về, nhưng không phải lúc nào cũng vậy.

API DMA nào bạn sử dụng tùy thuộc vào việc thiết bị của bạn có thể xử lý danh sách phân tán/thu thập dữ liệu hay không. Trình điều khiển của bạn, trong mã thiết lập của nó, sẽ gọi IoGetDmaAdapter và sử dụng một số hàm được trả về bởi nó.

Thông thường, bạn sẽ quan tâm đến GetScatterGatherList và PutScatterGatherList. Bạn cung cấp một chức năng (ExecutionRoutine) mà thực sự chương trình phần cứng của bạn để làm việc chuyển giao.

Có rất nhiều chi tiết liên quan. Chúc may mắn.

4

Bạn không thể truy cập các bảng trang từ không gian người dùng, chúng được ánh xạ trong hạt nhân.

Nếu bạn đang ở trong hạt nhân, bạn có thể chỉ cần kiểm tra giá trị của CR3 để định vị địa chỉ trang cơ sở và sau đó bắt đầu giải quyết.

This blog series có giải thích tuyệt vời về cách thực hiện việc này. Bạn không cần bất kỳ cơ sở/API hệ điều hành nào để giải quyết virtual < -> địa chỉ thực.

ảo Địa chỉ: f9a10054

1: kd> .formats 0xf9a10054 
Binary: 11111001 10100001 00000000 01010100 

Page Directory Pointer Index(PDPI)  11      Index into 

bảng 1 (trang thư mục con trỏ Bảng) trang thư mục Index (PDI) Index
111.001 101 vào bảng 2 (trang mục Bảng) Trang Bảng Index (PTI)
00001 0000 Chỉ mục vào thứ 3 bảng (Bảng trang) Chỉ số Byte
0000 01010100 0x054, số bù vào trang bộ nhớ vật lý

Trong ví dụ của mình, họ sử dụng windbg,! dq là bộ nhớ vật lý đã đọc.

enter image description here

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