網頁

星期四, 5月 15, 2008

Windows下存取4G Memory方式

存取的方式有很多種,我就列幾種比較常看到的方式:

1. WinIo -有開放原始碼,有興趣的可以研究一下,透過Driver層下去做

2. 呼叫NTDll.dll內的函數 - 這是原本我在XP的做法如下!

wchar_t strPath[30]=L"\\device\\physicalmemory";

LoadLibrary("ntdll.dll");

然後使用下列函數:
ZwOpenSection
ZwMapViewOfSection
ZwUnmapViewOfSection

這些函數可以對實體記憶體映射,不過這個方式在Vista下會無法使用,看樣子VISTA基於安全性考量已經這些功能拿掉了!

3.而在Vista下我目前是直接寫IO Driver,然後AP去Call我自己寫的Driver來讀,作法其實是如同WinIO.. ,只是我把我要的功能抽取出來而已,這個方式就是我用來撰寫DumpBIOS這個工具的作法,原本是用方式2,但是Vista不支援因此才改成方式3,你可能會問我為什麼不用方式1 ?
沒為什麼,就是想自己寫個IO Driver而已~~

Reference
Microsoft
Google

14 則留言:

  1. 大大你好
    想請問一下利用WINIO怎樣透過底層DRIVER存取Memory,可以說的仔細一點ㄇ,
    另外IO Driver,網路上有沒有類似的source code 可以參考,不好意思,對Driver這部份比較弱一點,可以指教一下ㄇ,謝謝

    回覆刪除
  2. 你下載WinIO Source code後裡面會有範例程式,我貼一部份給你看:
    void main()
    {
    // Call InitializeWinIo to initialize the WinIo library.

    bResult = InitializeWinIo();

    if (bResult)
    {
    GetPortVal(0x378, &dwPortVal, 4);
    SetPortVal(0x378, 10, 4);
    GetPhysLong((PBYTE)0xA0000, &dwMemVal);

    SetPhysLong((PBYTE)0xA0000, 10);
    ShutdownWinIo();
    }

    }

    而WinIO也是一個IO Driver,它裡面也是透過Windows API的方式去存取實體記憶體位址,下面是他負責存取記憶體內容的函數宣告:

    NTSTATUS MapPhysicalMemoryToLinearSpace(PVOID pPhysAddress,
    ULONG PhysMemSizeInBytes,
    PVOID *ppPhysMemLin,
    HANDLE *pPhysicalMemoryHandle)

    回覆刪除
  3. 在視窗底下,我目前都是使用SE.EXE 來看IO或是記憶體的值,那請教一下SE.EXE是用哪種方式呢?可以寫的跟他一樣短小精幹嗎!

    回覆刪除
  4. SE.exe...你可能要問一下原作者!

    不過我猜他也是用IO Driver方式啦!
    因為在Windows 底下IO Driver最簡單!

    我猜他是直接把IO Driver包在執行檔內[Note1],然後在載入執行檔的過程中去分割出IO Driver,然後在透過此IO Driver去存取需要的硬體資訊.而讓OS載入IO Driver的這個做法就是透過SCM的方式啦[Note2]!


    Note1: 包在執行檔後面的方式可透過Copy /b方式.

    Note2:OS提供的SCM Services可以動態載入驅動程式

    回覆刪除
  5. 大大,你說需要改driver,然後從下面的code下手,但study winio一段時間,可以access memory到0xFFFFF,但access 4G memory還是沒有頭緒,driver要動很多地方ㄇ,可以多點提示ㄇ,只需要改driver就好,那DLL有需要修改ㄇ,謝謝
    NTSTATUS MapPhysicalMemoryToLinearSpace(PVOID pPhysAddress,
    ULONG PhysMemSizeInBytes,
    PVOID *ppPhysMemLin,
    HANDLE *pPhysicalMemoryHandle)

    回覆刪除
  6. PVOID MmMapIoSpace(
    IN PHYSICAL_ADDRESS PhysicalAddress,
    IN ULONG NumberOfBytes,
    IN MEMORY_CACHING_TYPE CacheType
    );

    F.Y.I

    回覆刪除
  7. harrison您好
    我是使用網路上的WinIO.dll
    目地是想要對某一個port做IO access
    在Windows 2000, XP, 2003,下都可以使用
    不過現在環境換到 Windows2008 64bit下就無法InitializeWinIO
    不曉得您了不了解這樣的狀況原因為何
    我在很多地方發問仍舊找不到解決方法
    只知道問題應該是出在32bit和64bit下應該是會造成這樣的影響
    如果您有任何想法或是意見的話
    還請不吝賜教
    謝謝

    jonyjo0915@yahoo.com.tw

    Edward

    回覆刪除
  8. harrison您好
    我是使用網路上的WinIO.dll
    目地是想要對某一個port做IO access
    在Windows 2000, XP, 2003,下都可以使用
    不過現在環境換到 Windows2008 64bit下就無法InitializeWinIO
    不曉得您了不了解這樣的狀況原因為何
    我在很多地方發問仍舊找不到解決方法
    只知道問題應該是出在32bit和64bit下應該是會造成這樣的影響
    如果您有任何想法或是意見的話
    還請不吝賜教
    謝謝

    jonyjo0915@yahoo.com.tw

    Edward

    回覆刪除
  9. PVOID MmMapIoSpace(
    IN PHYSICAL_ADDRESS PhysicalAddress,
    IN ULONG NumberOfBytes,
    IN MEMORY_CACHING_TYPE CacheType
    );

    F.Y.I

    请问具体怎么做啊,能不能给一个例子....

    回覆刪除
  10. How to Access I/O Ports in WindowsNT/2K/X
    http://mach.debagua.com/archives/2004/0721_000163.html

    回覆刪除
  11. I/O 埠讀寫的實現
    http://win.chinaunix.net/bbs/frame.php?frameon=yes&referer=http%3A//win.chinaunix.net/bbs/thread-11201-1-1.html

    回覆刪除
  12. 你好:
    因為我目前需在XP下存取Memory, 無論我用WinIO的GetPhysLong或是ZwMapViewOfSection等方法對於較後段的位置讀取都有錯誤, EX: 0xEFFC0000; 不知道是否能請你協助教導更直接的辦法, 例如你說的方法3, 若可以提供Sample Code就更感謝了! 謝謝!

    回覆刪除
  13. 抱歉, 補上我的e-Mail:
    raymond700429@gmail.com

    回覆刪除
  14. 你好,在網路上看到你的部落格,想向你討教一下,如果我在windows底下,用AP設陣列(例:A[10]),,然後讀取位置,再去實際的記憶體位地抓內容,發現裡面所存在的值不是我要的,是不是我們設定出來的陣列,所存在的記憶體位址是虛擬的?如果要去抓此陣列實際所存的記憶體位址要如何讀取呢?是有一定的公式做轉換嗎?謝謝(E-mail:chennick2001@hotmail.com)

    回覆刪除