如何在windows程式中讀取bios內容(實體記憶體內容) (5千字)

看雪資料發表於2003-03-02

標題:如何在windows程式中讀取bios內容(實體記憶體內容)
作者: 火翼[CCG]
組織 : [CCG]  (China Cracking Group)
源程式下載

    今天和夜月兄討論了一下在windows nt/2000/xp下如何讀取bios資訊,現在把
結果向大家彙報一下。
    大家都知道,windows接管了對實體記憶體的直接存取,而bios資訊存在實體記憶體
的f000:0000處,關鍵就是如何讀取實體記憶體。
    查閱了msdn的文章後,發現以下有幾個函式和實體記憶體訪問有關:
NTSTATUS  ZwOpenSection(OUT PHANDLE  SectionHandle, IN ACCESS_MASK  DesiredAccess,IN POBJECT_ATTRIBUTES  ObjectAttributes);
NTSTATUS  ZwMapViewOfSection(IN HANDLE  SectionHandle,
                            IN HANDLE  ProcessHandle,
                            IN OUT PVOID  *BaseAddress,
                            IN ULONG  ZeroBits,
                            IN ULONG  CommitSize,
                            IN OUT PLARGE_INTEGER  SectionOffset  OPTIONAL,
                            IN OUT PSIZE_T  ViewSize,
                            IN SECTION_INHERIT  InheritDisposition,
                            IN ULONG  AllocationType,
                            IN ULONG  Protect
                            );
NTSTATUS  ZwUnmapViewOfSection(IN HANDLE  ProcessHandle,IN PVOID  BaseAddress);

用到的結構定義如下

typedef struct _UNICODE_STRING {
  USHORT  Length;//長度
  USHORT  MaximumLength;//最大長度
  PWSTR  Buffer;//快取指標,訪問實體記憶體時,此處指向UNICODE字串"\device\physicalmemory"
} UNICODE_STRING,*PUNICODE_STRING;


typedef struct _OBJECT_ATTRIBUTES {
    ULONG Length;//長度 18h
    HANDLE RootDirectory;//  00000000
    PUNICODE_STRING ObjectName;//指向物件名的指標
    ULONG Attributes;//物件屬性00000040h
    PVOID SecurityDescriptor;        // Points to type SECURITY_DESCRIPTOR,0
    PVOID SecurityQualityOfService;  // Points to type SECURITY_QUALITY_OF_SERVICE,0
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;



函式說明
第一個函式ZwOpenSection用來開啟section,第一個引數是指向HANDLE變數的指標,第二個是訪問引數,第三個是指向OBJECT_ATTRIBUTES的指標
第二個函式ZwMapViewOfSection用來建立實體記憶體和當前程式的一段實體記憶體的聯絡,引數很多,一會在例程裡再詳細解釋
第三個函式ZwUnmapViewOfSection用來斷開實體記憶體和當前程式中的對映斷開聯絡,第一個引數是程式控制程式碼,必須掉用第二個函式時一樣,第二
個是當前程式中對映的基址,由ZwMapViewOfSection返回

這三個函式都在ntdll.dll中,msdn裡的幫助說這幾個函式用在驅動編制上。
例程如下

//結構定義
typedef struct _UNICODE_STRING {
  USHORT  Length;//長度
  USHORT  MaximumLength;//最大長度
  PWSTR  Buffer;//快取指標
} UNICODE_STRING,*PUNICODE_STRING;

typedef struct _OBJECT_ATTRIBUTES {
    ULONG Length;//長度 18h
    HANDLE RootDirectory;//  00000000
    PUNICODE_STRING ObjectName;//指向物件名的指標
    ULONG Attributes;//物件屬性00000040h
    PVOID SecurityDescriptor;        // Points to type SECURITY_DESCRIPTOR,0
    PVOID SecurityQualityOfService;  // Points to type SECURITY_QUALITY_OF_SERVICE,0
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;

//函式指標變數型別生命
typedef DWORD  (__stdcall *ZWOS)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES);
typedef DWORD  (__stdcall *ZWMV)(HANDLE,HANDLE,PVOID,ULONG,ULONG,PLARGE_INTEGER,PSIZE_T,DWORD,ULONG,ULONG);
typedef DWORD  (__stdcall *ZWUMV)(HANDLE,PVOID);
//以上在程式開始定義全域性變數處定義

//以下在程式的主函式里
//變數宣告
        UNICODE_STRING struniph;
    OBJECT_ATTRIBUTES obj_ar;
    ZWOS ZWopenS;
    ZWMV ZWmapV;
    ZWUMV ZWunmapV;
    HANDLE hSection;
    DWORD ba;
    LARGE_INTEGER so;
    SIZE_T ssize;
    so.LowPart=0x000f0000;//實體記憶體的基址,就是f000:0000
    so.HighPart=0x00000000;
    ssize=0xffff;
    wchar_t strPH[30]=L"\\device\\physicalmemory";
//變數初始化
        ba=0;//聯絡後的基址將在這裡返回
        struniph.Buffer=strPH;
    struniph.Length=0x2c;//注意大小是按位元組算
    struniph.MaximumLength =0x2e;//也是位元組
        obj_ar.Attributes =64;//屬性
    obj_ar.Length =24;//OBJECT_ATTRIBUTES型別的長度
    obj_ar.ObjectName=&struniph;//指向物件的指標
    obj_ar.RootDirectory=0;
    obj_ar.SecurityDescriptor=0;
        obj_ar.SecurityQualityOfService =0;
//讀入ntdll.dll,得到函式地址
        hinstLib = LoadLibrary("ntdll.dll");
    ZWopenS=(ZWOS)GetProcAddress(hinstLib,"ZwOpenSection");
        ZWmapV=(ZWMV)GetProcAddress(hinstLib,"ZwMapViewOfSection");
    ZWunmapV=(ZWUMV)GetProcAddress(hinstLib,"ZwUnmapViewOfSection");
//呼叫函式,對實體記憶體進行對映
        ZWopenS(&hSection,4,&obj_ar);
    ZWmapV(
              (HANDLE)hSection,  //開啟Section時得到的控制程式碼
              (HANDLE)0xffffffff, //將要對映程式的控制程式碼,
              &ba,  //對映的基址
              0, //沒怎麼看明白,設為0就好了
              0xffff,  //分配的大小
              &so,  //實體記憶體的地址
              &ssize,  //指向讀取記憶體塊大小的指標
              1,  //子程式的可繼承性設定
              0,  //分配型別
              2  //保護型別
              );
        //執行後會在當前程式的空間開闢一段64k的空間,並把f000:0000到f000:ffff處的內容對映到這裡
        //對映的基址由ba返回,如果對映不在有用,應該用ZwUnmapViewOfSection斷開對映
BTW:
思路主要是來之上次跟蹤的聯想的安裝驗證程式,真的要感謝聯想的技術人員了:-)。

相關文章