久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

【原創(chuàng)】內核讀寫只讀內存方法總結[Delphi描述]

 quasiceo 2013-11-29
【原創(chuàng)】內核讀寫只讀內存方法總結[Delphi描述]
Anskya 當前離線

標 題: 【原創(chuàng)】內核讀寫只讀內存方法總結[Delphi描述]
作 者: Anskya
時 間: 2008-04-26,16:24:39
鏈 接: http://bbs./showthread.php?t=63791


以下代碼均已Delphi描述...至于為什么...
首先我是一個Delphi Coder...雖然我大部分時間使用的是ASM編譯器和C編譯器
但是我喜歡Delphi...好了不廢話了...

已知的三種方法:如果各位有更好的意見歡迎大家提出

[1]使內存可讀寫

1.stl+cr0:
這個方法大家想必經常使用...
名稱:  cr0.jpg
查看次數: 787
文件大小:  9.4 KB
(參考I-32.3A文檔)
由于cr0是一個32位寄存器...假設大家的CPU是32位的.沒有64位測試環(huán)境
按照圖這個結構我們可以了解到的信息
第16位:WP——Write Protect,當設置為1時只提供讀頁權限
第0位:PE——Paging,當設置為1時提供分頁
第1位:MP——Protection Enable,當設置為1時進入保護模式

按照這個說明寫出代碼:
//1 關閉寫保護
asm
  push eax
  mov eax, CR0
  and eax, 0FFFEFFFFh
  mov CR0, eax
  pop eax
end;

//2 打開寫保護
asm
  push eax
  mov eax, CR0
  or eax, NOT 0FFFEFFFFh
  mov CR0, eax
  pop eax
end;
也許大家看得有點模糊.其實這個代碼就是修改第16位
NOT 0FFFEFFFFh = 00010000h
因為要設置第16位為1...所以結果也就是代碼那種效果...
鄂~我也不知道說什么了.也就是位操作你也可以直接使用
//1 關閉寫保護
asm
  push  eax
  mov   eax, cr0
  and   eax, not 000010000h
  mov   cr0, eax
  pop   eax
end;

//2 打開寫保護
asm
  push  eax
  mov   eax, cr0
  or    eax, 000010000h
  mov   cr0, eax
  pop   eax
end;

一般使用的時候我們都會加上cli和sti,由于這兩個指令只能控制當前CPU對于
多核系統(tǒng)是無法起到有效的互斥的...所以一般都是配合"自轉鎖"使用
關于自轉鎖的話題我們下面會詳細的說的


2.通過內存描述表(MDL)中描述一塊內存區(qū)域,,MDL包含此內存區(qū)域的起始地址,
擁有者進程,字節(jié)數量以及標志.(據說是Bill提供的方法.難道和VirtualProtect一樣?)
代碼:
type
  PMDL = ^_MDL;
  _MDL = packed record
    Next: PMDL;
    Size: USHORT;
    MdlFlags: USHORT;
    Process: Pointer;
    MappedSystemVa: PVOID;
    StartVa: PVOID;
    ByteCount: ULONG;
    ByteOffset: ULONG;
  end;
  MDL = _MDL;

const
  MDL_MAPPED_TO_SYSTEM_VA     = $0001;
  MDL_PAGES_LOCKED            = $0002;
  MDL_SOURCE_IS_NONPAGED_POOL = $0004;
  MDL_ALLOCATED_FIXED_SIZE    = $0008;
  MDL_PARTIAL                 = $0010;
  MDL_PARTIAL_HAS_BEEN_MAPPED = $0020;
  MDL_IO_PAGE_READ            = $0040;
  MDL_WRITE_OPERATION         = $0080;
  MDL_PARENT_MAPPED_SYSTEM_VA = $0100;
  MDL_LOCK_HELD               = $0200;
  MDL_PHYSICAL_VIEW           = $0400;
  MDL_IO_SPACE                = $0800;
  MDL_NETWORK_HEADER          = $1000;
  MDL_MAPPING_CAN_FAIL        = $2000;
  MDL_ALLOCATED_MUST_SUCCEED  = $4000;

//  讀寫只讀內存(源于Gates大叔)
function WriteReadOnlyMemoryGates(lpDest, lpSource: Pointer; Length: Integer): 

NTSTATUS;
var
  tempSpinLock: KSPIN_LOCK;
  oldirql: KIRQL;
  mdl: PMDL;
  writableAddress: Pointer;
begin
  Result := STATUS_UNSUCCESSFUL;
  mdl := MmCreateMdl(nil, lpDest, Length);
  if (mdl <> nil) then
  begin
    MmBuildMdlForNonPagedPool(mdl);
    mdl^.MdlFlags := mdl^.MdlFlags or MDL_MAPPED_TO_SYSTEM_VA;
    writableAddress := MmMapLockedPages(mdl, KernelMode);
    if (writableAddress <> nil) then
    begin
      oldirql := 0;

      KeInitializeSpinLock(@tempSpinLock);
      fast_KfAcquireSpinLock(@tempSpinLock);
      memcpy(writableAddress, lpSource, Length);
      fast_KfReleaseSpinLock(@tempSpinLock, oldirql);

      MmUnmapLockedPages(writableAddress, mdl);
      Result := STATUS_SUCCESS;

    end;
    MmUnlockPages(mdl);
    IoFreeMdl(mdl);
  end;
end;
關鍵一步就是修改mdl的屬性.讓他可寫....

下面來看看第三種方法
3.使用IoAllocateMdl來得到可寫內存...
源于Mark早期寫的代碼...我這里直接翻譯了...至于原理
大家參考一下DDK吧...我發(fā)現自己表達能力有限...
代碼:
//  寫只讀內存(源于Mark代碼)
function WriteReadOnlyMemoryMark(lpDest, lpSource: Pointer; Length: Integer): 

NTSTATUS;
var
  tempSpinLock: KSPIN_LOCK;
  oldirql: KIRQL;
  mdl: PMDL;
  writableAddress: Pointer;
begin
  Result := STATUS_UNSUCCESSFUL;
  mdl := IoAllocateMdl(lpDest, Length, False, False, nil);
  if (mdl <> nil) then
  begin
    MmBuildMdlForNonPagedPool(mdl);
    MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
    writableAddress := MmMapLockedPages(mdl, KernelMode);
    if (writableAddress <> nil) then
    begin
      oldirql := 0;

      KeInitializeSpinLock(@tempSpinLock);
      fast_KfAcquireSpinLock(@tempSpinLock);
      memcpy(writableAddress, lpSource, Length);
      fast_KfReleaseSpinLock(@tempSpinLock, oldirql);

      MmUnmapLockedPages(writableAddress, mdl);
      Result := STATUS_SUCCESS;
    end;
    MmUnlockPages(mdl);
    IoFreeMdl(mdl);
  end;
end;
代碼源于Mark早期編寫的代碼
相信看到這份代碼和上面的第二種方法相信大家似乎都明白了什么...
是不是覺得兩種方法都差不多區(qū)別就是在于
一個是直接修改MDL屬性:MDL_MAPPED_TO_SYSTEM_VA
一個是MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
來改寫屬性...其實這兩種方法...嘿嘿~自己看看就明白了...

[2]改寫內存!
平時我們修改內存單核下沒有什么顧慮.stl|代碼|cli
開關中斷以后就可以自己操作了...
因為現在雙核和多核越來越興起了...
這么說吧.內存在沒有完全修改完畢的時候...其他線程去讀取的話...
就會造成讀取錯誤的數據或者斷碼...
如果您是單核的話可以直接修改
1.stl+cli
代碼:
    asm
      cli                                               //disable WP bit
      push  eax
      mov   eax, cr0                                    //move CR0 register 

into EAX
      and   eax, not 000010000h                         //disable WP bit
      mov   cr0, eax                                    //write register back
      pop   eax
    end;

    //改寫的代碼

    asm
      push  eax                                           //enable WP bit
      mov   eax, cr0                                      //move CR0 register 

into EAX
      or    eax, 000010000h                               //enable WP bit
      mov   cr0, eax                                      //write register 

back
      pop   eax
      sti
    end;
2.利用原子互斥操作
比如說我們需要SSDT,Shadow,etc Hook
修改地址等操作的話...我們有一個簡單的方法
使用...Interlocked系函數
修改地址推薦使用InterlockedExchange...
釋放方法很簡單
代碼:
ZwOpenProcessNextHook := TZwOpenProcess(InterlockedExchange(SystemServiceName

(GetImportFunAddr(@ZwOpenProcess)), LONG(@ZwOpenProcessNextHook)));
提示一下這個函數使用的是fastcall調用方式,如果你使用的是Delphi的話建議你最好
注意一下使用方法...fastcall和Delphi的register的是有區(qū)別的
fastcall:
第一個參數:edx
第二個參數:ecx
register:
第一個參數:eax
第二個參數:edx
第三個參數:ecx

提供以下InterlockedExchange的源代碼
代碼:
FORCEINLINE
LONG
FASTCALL
InterlockedExchange(
    IN OUT LONG volatile *Target,
    IN LONG Value
    )
{
    __asm {
        mov     eax, Value
        mov     ecx, Target
        xchg    [ecx], eax
    }
}
3.自轉鎖
自轉鎖是內核中的一種同步機制...
關于自轉鎖的介紹請大家去看
<<Programming the Microsoft Windows Driver Model>>這本書...
這本書剛開始看許多東西暫時還不太理解...
當線程獲取自轉鎖的時候...會將當前線程提升到DISPATCH_LEVEL級別
這個時候內核將不會分配時間片給其他的CPU.這樣就不會有其他線程
在你寫操作的時候去訪問你沒有寫完的地方了...放心大膽的寫了...
怎么寫?暈...這個問題這個問題...呵呵我可以不回答嗎?memcpy總會用吧...

自轉鎖使用起來很簡單...
(有個疑問.為什么獲取和釋放自轉鎖的函數在hal.dll函數中,初始化自轉鎖的函數
卻在ntoskrnl.exe模塊中...)

使用方法:
KeInitializeSpinLock(@TemSpinLockp);
KeAcquireSpinLock(@TemSpinLockp, &oldirql);
.
.
你的操作代碼
.
.
KeReleaseSpinLock(@TemSpinLockp, oldirql);
如果有其他內核線程已經獲取自轉鎖的時候你的線程是不會被分配到時間片的
所以你不用擔心你會進去破壞代碼(除非~除非~你提升到更高的級別...)
當你獲取自轉鎖成功后..其他線程將進入自轉狀態(tài)..你可以理解為互斥
(EnterCriticalSection,LeaveCriticalSection)
[警告]請千萬不要連續(xù)使用兩次KeAcquireSpinLock!否則機器會(卡)死的很難看的

etc...
其他方法暫時不清楚.暫時由于自轉鎖的這種特殊效果.
所以大家能不用的時候盡量不要使用...使用的時候盡量減少自轉時間.以達到更高的
效能...

小弟初學驅動編程.如果有不對的地方請各位大牛補充說明...這里拜過

特別感謝:
<<如何寫windows系統(tǒng)已保護的內存區(qū)域>>的作者.由于被轉載了不知道多少次
當我看到這篇文章的時候...作者已經不知道是誰了...感謝這位無名英雄...謝謝
鳴謝:
zhuwg,FlowerCode,農夫大哥,冷風(烤鴨),旋轉"AV"群里的各位神牛們

希望感興趣的Delphi Fans可以PM我大家一起交流一下開發(fā)經驗...

回復時引用此帖 返回頂端

sudami 的頭像

高級會員
高級會員

資 料:
注冊日期: Oct 2006
帖子: 1,420 sudami 品行端正
精華: 25
現金: 499 Kx
致謝數: 3
獲感謝文章數:6
獲會員感謝數:89
2 舊 2008-04-26, 16:30:29 默認
sudami 當前離線

LZ是個 Delphi大王啊,。

不懂 Delphi 和JAVA。 

特來膜拜下大牛 
123456~

回復時引用此帖 返回頂端

bzhkl 的頭像

中級會員
中級會員

資 料:
注冊日期: Dec 2006
帖子: 388 bzhkl 品行端正
精華: 6
現金: 405 Kx
致謝數: 1
獲感謝文章數:1
獲會員感謝數:1
3 舊 2008-04-26, 17:59:39 默認
bzhkl 當前離線

delphi 讓人愛不釋手 轉DELPHI用了一個多星期的時間 達到能以前寫的程序能正常翻譯= =

回復時引用此帖 返回頂端

高級會員
高級會員

資 料:
注冊日期: Jul 2005
帖子: 684 zhuwg 品行端正
精華: 11
現金: 286 Kx
致謝數: 11
獲感謝文章數:1
獲會員感謝數:1
4 舊 2008-04-26, 18:28:14 默認
zhuwg 當前離線

進來膜拜1下女王大牛

回復時引用此帖 返回頂端

初級會員
初級會員

資 料:
注冊日期: Sep 2006
帖子: 72 十指緊扣 品行端正
精華: 0
現金: 202 Kx
致謝數: 0
獲感謝文章數:0
獲會員感謝數:0
5 舊 2008-04-27, 08:47:34 默認
十指緊扣 當前離線

文章中多處sti錯寫成了stl

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多