0x000000fc (ATTEMPTED EXECUTE OF NOEXECUTE MEMORY)

Using Direct I/O

  • 06/16/2017
  • 2 minutes to read

Drivers for devices that can transfer large amounts of data at a time should use direct I/O for those transfers. Using direct I/O for large transfers improves a driver's performance, both by reducing its interrupt overhead and by eliminating the memory allocation and copying operations inherent in buffered I/O.html

Generally, mass-storage device drivers request direct I/O for transfer requests, including lowest-level drivers that use direct memory access (DMA) or programmed I/O (PIO), as well as any intermediate drivers chained above them.c++

The I/O manager determines that an I/O operation is using direct I/O as follows:git

Drivers that use direct I/O will sometimes also use buffered I/O to handle some IRPs. In particular, drivers typically use buffered I/O for some I/O control codes for IRP_MJ_DEVICE_CONTROL requests that require data transfers, regardless of whether the driver uses direct I/O for read and write operations.因此這時候不能用DeviceIoControl,而是用write便可將buffer傳到Mdl,即p=MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);此時p可執行。windows

Setting up a direct I/O transfer varies slightly, depending on whether DMA or PIO is being used. For more information, see:less

Using Direct I/O with DMAide

Using Direct I/O with PIO函數

Drivers must take steps to maintain cache coherency during DMA and PIO transfers. For more information, see Maintaining Cache Coherency.ui

https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-direct-i-o

//斷點相關


bp + 地址 設置斷點
bl  顯示已經設定的斷點
bu + 地址 設置斷點,可是這種類型斷點再下一次啓動時被記錄
bc 清除斷點
對於斷點範圍,能夠用*匹配,-表示一個範圍,表達多個可用,號隔開

程序入口僞寄存器
WinDbg裏有個僞寄存器叫$exentry,裏面記錄了程序的入口點。因此咱們只要在命令輸入欄裏輸入
bp $exentry
(bp就是用來下斷點的命令,詳細用法能夠參考WinDbg的幫助文檔)

//調試符號

ld kernerl32 //加載kernerl32模塊的符號
lm   m k*        //顯示已經加載的,以k開頭的模塊
ln         //顯示最近操做過的模塊名
dt dbg2     //檢測模塊

[[[[[[[[[[[[]]]]]]]]]]]]
x kernerl32!k* 顯示模塊kernerl32中全部以k開頭的函數
dv 顯示局部變量值
dv /i/t/v 顯示局部變量的類型,值相關信息。
x <module>!* / ? 顯示指定模塊的符號
x argc 查看變量argc的值。
dt argc 查看變量值
dt _PEB 7ffdd00 將內存地址7ffdd00開始的內容以PEB結構的方式顯示出來。
dd 12000 L4 查看地址12000 後面的四個字
dds 12000 L100 查看堆棧上地址12000開始,後面的100個dword的內容,若是有調試符號,會將符號顯示。此方法來追蹤堆棧。(先看ebp,再用此方法)
dd ebp + 4, 返回地址, ebp + 8 第一個參數

[[[[[[[[[]]]]]]]]]
.kill 殺死調試進程
.restart 從新調試

[[[[[]]]]]]]]]]]]]]
k 顯示調用堆棧
,kn加序號而已。
kb 顯示前三個參數。第一個參數ebp+8;第二個ebp+0x0C;第三個ebp+0x10;dd ebp+0x14是第四個參數
kp 顯示函數參數類型,數值
kp f f開關顯示相鄰棧基之差,從而能夠推斷出棧的健康情況。

[[[[[[[[[[]]]]]]]]]]
| 顯示進程
~顯示線程
~0 s 切換到 0號線程

[[[[[[[[[]]]]]]]]]
dv 顯示函數參數&局部變量,注意,dv是跟棧幀相關的,對不一樣的棧幀顯示不一樣的局部變量。
@1, kn 顯示全部棧幀
@2, .frame選擇想要查看的棧幀
@3, dv /i/v/t顯示該棧幀裏局部變量信息
@3, dv /i /V /t 顯示變量基於棧幀的地址
若是沒有私有符號,dv是不能顯示變量信息的。
vc 生成的調試符號*.pdb windbg不認識,須要設置爲c++/General/DebugInfo= C7 compatible
=====
sympath + c:\nasm 添加符號搜索路徑
.sympath 顯示符號搜索路徑
//顯示必定範圍內存
!db L 32 : results in 32 bytes being displayed (as hexadecimal bytes),
//查看pe信息
!dh [Options] Address : 查看模塊pe信息
!dh -f : display file headers
!dh -s : section headers
!dh -a : all header informations
查看結構體成員
dt nt!_EPROCESS
查看當前的irql
!irql
查看Verifier 檢測統計信息
!verifier
查看某個內存地址屬於那一個模塊
!pool 地址
!lmi Address  : 查看模塊的主要信息
!pcr 能夠查看當前執行的線程及irql, 等信息
//
Why doesn't the WinDBG command !irql always return the correct IRQL for my target?
[Answer by Jake Oshins, jakeo_at_windows_dot_microsoft_dot_com. Workaround provided by James Antognini, antognini_at_mindspring_dot_nospam_dot_com, 27 August 2003]
!irql currently only produces useful results on a crashdump, not a live system. To retrieve the current IRQL on a live system you should instead use the !pcr command.
!processfield:列出EPROCESS的成員
該命令前的!號,意味着它來自於調試器的擴展模塊―kdextx86.dll。該命令可顯示內核用來表明一個進程的EPROCESS結構(該結構並無正式的說明文檔)的成員及其偏移量。
儘管該命令僅列出了成員的偏移量,但你也能很容易的猜出其正確的類型。例如,LockEvent位於0x70處,其下一個成員的偏移量爲0x80。則該成員佔用了16個字節,這與KEVENT結構很是相似。

!threadfields:列出ETHREAD成員
這是kdextx86.dll提供的另外一個強大的選項。和!processfields相似,它列出未文檔化的ETHREAD結構的成員及其偏移量。內核使用它表示一個線程.

//進程信息
!tep
!peb ,顯示peb(進程信息)

//顯示相關
dt ntdll!*teb* 列出匹配通配符的結構名
dt -v -r ntdll!_TEB
列出結構_TEB的成員信息

//顯示變量地址
r $peb 顯示模塊peb的地址

//查看錯誤信息
!gle

//設置斷點的技巧
能夠直接把斷點設在: kernel32!BaseProcessStart
1), 先用lm 顯示全部已經加載的模塊
2), dt our_exe_name!*main*  //在咱們的程序模塊中搜索包含main的地址(注意:若是未加載symbol是不能顯示的!)
3), 若是存在,在our_exe_name!*main 處設置斷點
=======
Command     SoftICE OllyDbg
Run         F5     F9
Step Into     F11 F7
Step Over     F10 F8
Set Break Point F8 F2
搜索內存

五、查找字符串
在步驟1咱們運行程序時就記錄了提示註冊錯誤的字符串「Wrong Serial, try again!」,如今咱們就要在內存找到該字符串的位置。
輸入命令
s –a 00400000 L53000 「Wrong」
該命令的意思是以ASCII碼形式在內存地址00400000日後53000個字節搜索字符串「Wrong」。
s,就是要調用查找的命令
-a,指定使用ASCII碼的形式查找
00400000,指定要開始尋找的內存地址。
L53000,說明要在00400000日後的53000字節搜索。這個數值和00400000均可以從Stud_PE得到。00400000是程序的裝 入地址,而53000是映像的大小,也就是程序載入內存後佔用的內存大小。使用這兩個數值,基本上能夠搜索到程序使用的整個內存範圍。
「Wrong」,就不用多解釋了,就是咱們要尋找的字符串。不過WinDbg不支持模糊搜索,因此這裏輸入的字符串一定要徹底正確。
內存訪問斷點

六、下內存訪問斷點
WinDbg中,ba命令表明Break On Access,即訪問時中斷。
咱們在命令行輸入:
ba r 1 0044108c
命令的意思是在內存0044108c的位置下字節的讀斷點。命令中各元素的含義能夠參考幫助文檔,這裏不囉嗦。
輸入bl,查看斷點使用狀況:

地址運算
? 0x33 + 0x44
運行後將獲得計算和

3.查看和修改數據
調試中不可避免的要查看和修改數據
查看內存:
db/dw/dd/dq [Address]       字節/字/雙字/四字方式查看數據
da/du [Address]           ASCII字符串/Unicode字符串方式查看指定地址
其它經常使用的如查看結構
dt nt!_EPROCESS
dt nt!_EPROCESS 89330da0 (把0x89330da0做爲對象指針)
修改內存:
eb/ew/ed/eq/ef/ep Address [Values]
字節/字/雙字/四字/浮點數/指針/
ea/eu/eza/ezu Address [Values]
ASCII字符串/Unicode字符串/以NULL結尾的ASCII字符串/以NULL結尾的Unicode字符串
搜索內存:
s -[b/w/d/q/a/u] Range Target
搜索字節/字/雙字/四字/ASCII字符串/Unicode字符串

2.斷點 斷點之於調試固然是很是重要的 經常使用命令: bp [Address]or[Symbol] 在指定地址下斷 可使用地址或符號,如 bp 80561259(Windbg默認使用16進制) bp MyDriver!GetKernelPath bp MyDriver!GetKernelPath+0x12 bp [Address] /p eprocess 僅噹噹前進程爲eprocess時才中斷 這個很經常使用,好比你bp nt!NtTerminateProcess,可是隻想在某一進程觸發此斷點時才斷下來,那就加上這個參數吧,由於內核中的代碼是各個進程共用的,因此此 命令很實用 bp [Address] /t ethread 僅噹噹前線程爲ethread時才中斷,用法跟/p參數相似 bu [Address]or[Symbol] 下一個未解析的斷點(就是說這個斷點須要延遲解析) 這個也很經常使用,好比咱們的驅動名爲MyDriver.sys,那麼在驅動加載以前下斷bu MyDriver!DriverEntry, 而後加載這個驅動時就能夠斷在驅動入口,而且這個是不須要調試符號支持的 bl 列出全部斷點,L=List bc[id] 清除斷點,c=Clear,id是bl查看時的斷點編號 bd[id] 禁用斷點,d=Disable,id即斷點編號 be[id] 啓用斷點,e=Enable,id爲斷點編號

相關文章
相關標籤/搜索