Windows平台相关基础知识

0x00
一、Windows API编程相关知识

  • Windows的工作模式、Windows的内存管理、异常处理
  • Windows应用程序的编程环境
  • Win32汇编程序结构
  • Windows API
    二、Win32汇编语言程序设计
  • 80x86处理器寄存器
  • IA-32指令系统,标号、变量和数据结构
  • 使用子程序(参数传递、堆栈平衡等)

0x01

Windows工作模式及内存管理

1、Windows系统的特点

  • 图形用户界面。告别命令行,所见即所得;
  • 多任务系统。多个程序同时运行,提高效率;
  • 大量的函数调用。程序员可把精力放在程序逻辑结构和用户界面上;
  • 和设备的无关性。应用程序不用关心具体的硬件型号;
  • 内存管理。内存分页和虚拟内存,4GB地址空间。
    2、 Windows工作模式
  • 实模式 :提供不受保护的段,用于实现早期处理器的16位执行环境;使用20位地址线。
  • 保护模式:32位地址线,寻址空间达到4GB。支持多任务和程序优先级。保护模式出现的原因是:保护进程地址空间。
  • 虚拟86模式:是以任务形式在保护模式上执行。支持任务切换和内存分页。虚拟86模式采用和实模式一样的寻址方式,寻址空间为1MB=1024KB。

注意:实模式可以切换到保护模式,保护模式可以和虚拟86模式相互切换,从实模式切换到保护模式是通过控制寄存器CR0的控制位PE。不支持从实模式直接切换到虚拟86模式。

Windows工作模式比较
https://img-blog.csdnimg.cn/20191005221347797.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODE0Nzc3,size_16,color_FFFFFF,t_70注意:虚拟86模式以保护模式为基础,是以任务形式在保护模式上执行。利用分页机制,将不同虚拟86任务的地址空间映射到不同物理地址上。每个虚拟86任务都认为自己在使用独享的1MB地址空间。

0x02

Windows的内存管理

实模式下的内存寻址方式 实模式支持内存分段模型。逻辑地址由16位段选择器和16位段内偏移地址组成。16位段选择器用于确定一个20位的段基址;再与16位段内偏移地址相加,得到逻辑地址对应的线性地址。由于段内偏移地址是16位的,因此,线性地址空间由一系列64KB大的段组成(一个地址上存放一个字节)。实模式不支持内存分页,因此,线性地址即为物理地址。
https://img-blog.csdnimg.cn/20191005222053236.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxODE0Nzc3,size_16,color_FFFFFF,t_70注:xxxx:yyyy格式的虚拟地址在内存中的实际位置是:xxxx*10h+yyyy
20位地址线,寻址空间1M

保护模式下内存寻址:

  • 保护模式支持内存分段模型。保护模式与实模式的主要区别在于:段寄存器中存放的不再是段基址,而是描述符表的索引。保护模式下对内存的分段是强制的,分页是可选的。
  • 保护模式下内存寻址时,16位的段寄存器存放的不是段基地址,而是描述符表的索引地址,段内偏移地址长度32位;段描述符是64位,因为需要包含地址空间定义的一些安全属性;
  • GDT/GDTR, LDT/LDTR;
  • 段选择器高13位表示索引,第0,1位表示段选择器的请求特权级,第2位TI表示段描述符的位置:TI=0表示在GDT中,TI=1表示在LDT中。
  • 段描述符中的32位线性基地址与32位段内偏移地址相加,得到线性地址,如果不分页则线性地址与物理地址直接对应。
  • 保护模式下,线性地址空间大小为4G,32位地址线。
    我爱你
    注意:保护模式下,16位的段寄存器存放的不是段地址,而是段选择器;
    段选择器高13位表示索引,第0,1位表示城区的当前优先级,第2位TI表示段描述符的位置

在这里插入图片描述全局描述符表GDT:
在这里插入图片描述在 32 位保护模式下,段地址是 32 位的线性地址,如果未开启分页功能,该线性地址就是物理地址。

保护模式下,16位的段寄存器存放的不是段地址,而是段选择器;
段选择器高13位表示索引,第2位TI表示段描述符的位置在这里插入图片描述内存分页机制:

CR0寄存器中第31位(PG位)决定是否分页:

  • PG=0不启用分页,线性地址即为物理地址;
  • PG=1启用分页,线性地址经过页表映射得到物理地址;
    在这里插入图片描述
  • 一级页表的映射:
    32位虚拟内存地址=20位页表索引+12位页内偏移
  • 二级页表的映射方式:
    32位虚拟内存地址=10位页目录索引+10位页表索引+12位页内偏移

从Windows的内存安排看Win32编程中的几个重要概念:

  • 每个应用程序都有自己的4GB寻址空间,用于存放操作系统、系统DLL、用户的DLL代码,应用程序代码、数据等。
  • 不同应用程序的线性地址空间是隔离的。在某个程序所属的时间片中,其他程序的代码和数据没有被映射到可寻址的线性地址中,所以是不可访问的。
  • DLL程序没有自己的私有空间,它们总被映射到其他应用程序的地址空间中,当做其他应用程序的一部分运行。
    在这里插入图片描述
    0x03

Windows的特权保护

80386实模式下的中断和异常处理:

  • 发生n号中断或异常,或者执行到int n 指令时,CPU到n*4的地址取出中断服务程序地址;
  • 将标志寄存器、CS,IP寄存器值压入堆栈;
  • 执行中断服务程序;
  • 服务程序执行到iret时,CPU从堆栈中弹出标志寄存器、取出CS、IP并返回。
    woaini注:每个中断向量4字节

80386保护模式下的中断和异常处理

  • 异常处理往往是从用户程序切换到系统程序,低优先级切换到高优先级;

  • 那么,怎样确保高优先级代码能够安全的被低优先级代码调用?

  • 中断门,自陷门,任务门

  • 中断描述符:门的种类&入口地址,8字节,放在中断描述符表中
    在这里插入图片描述
    80386的保护机制

  • 段的类型检查:
    段的类型由段描述符指定,主要属性有是否可执行,是否可读写。
    CS/DS/SS等段选择器是否能装入某种类型的段描述符是有限制的。
    例如,不可执行的段不能装入CS;不可写的段不能装入SS。

  • 访问数据时的级别检查:
    低优先级的代码不能访问高优先级的数据段。
    80386 GDT中的DPL域(描述符优先级)指定了这个段可以被访问的最低优先级;
    段选择器中的RPL域(请求优先级)指定了当前执行代码的优先级;
    DPL≥RPL,该段才能访问,否则产生保护异常;

0x04

Windows应用程序的编程环境

在这里插入图片描述MASM编译器和链接器:
在这里插入图片描述

0x05

Win32汇编程序结构

  • 使用的指令集
    内存模式:win32 程序代码和数据使用同一个4GB段;CS/DS/SS/ES全部使用平坦模式
    子程序/API调用方式:参数传递、堆栈平衡

  • .data/.data?/.const/.code.data
    可读可写的已定义变量, .data段存放在可执行文件的_data节区
    .data?可读可写的未初始化数据段, .data?段存放在可执行文件的_BSS节区
    .const不能写的常量段

  • 代码段一般放在PE文件的_TEXT节区;
    程序在运行时,代码段可写吗?
    For example,UPX…….

在这里插入图片描述

0x06

Windows API

  • API(应用程序接口)是windows操作系统提供的一套编程函数库,提供应用程序运行所需的窗口管理,图形设备接口、内存管理等各项服务功能。这些函数采用DLL实现。
  • Win32 API的核心由三个DLL提供:
    KERNEL 32.DLL——系统服务功能。任务管理,动态链接、内存管理等
    GDI32.DLL——图形设备接口。利用显卡驱动程序显示文本、图像等
    USER32.DLL——用户服务接口。建立窗口、传送消息等
  • 调用API的过程:利用堆栈传递参数,调用者把参数压入堆栈,DLL中的函数再从堆栈中取出参数处理。
    在这里插入图片描述注意:在源程序编译链接程可执行文件后,call MessageBox语句中的MessageBox会被换成一个指向可执行文件导入表的地址。而导入表中指向MessageBox函数的实际地址由系统根据User32.dll在内存中的位置动态填入。

API函数的返回值:

  1. 返回值存放在eax寄存器中;如果返回的内容超过了一个eax所能容纳的长度,怎么办?
  2. Answer:Win32 API采用的方法一般是eax中返回一个指向返回数据的指针。
    Win32 环境下,和字符串相关的API函数有两类,分别对应不同字符集:
    ANSI字符集:每个字符一个字节宽,API函数名尾部带“A”
    Unicode字符集:每个字符两个字节宽, API函数名尾部带“W”
  3. User32.dll中只有MessageBoxA和MessageBoxW,why源程序中仍可以用MessageBox?
    在这里插入图片描述
  4. include语句:将程序调用到的API函数所在的DLL文件包含进来
    include <DLL名.inc> 例如: include <user32.inc>
    Includelib语句:告诉链接器在链接的时候到指定的库文件中去找API函数的位置
    includelib 库文件名 例如: includelib user32.lib

0x07

80x86处理器的寄存器

通用寄存器、指令寄存器、段寄存器、标志寄存器、系统地址寄存器(GDTR/LDTR)、控制寄存器(CR0,CR2,CR3)

CR0:保护模式允许位、任务切换位
CR1:页故障地址寄存器
CR2:页表目录寄存器,存放页表目录的物理基地址

在这里插入图片描述

  • 指令指针寄存器
    32位指令指针寄存器EIP存放指令指针,即当前代码段中将被执行的下一条指令的线性地址偏移。程序运行时,CPU根据CS段寄存器和EIP寄存器的地址偏移读取下一条指令,然后将EIP寄存器的值自增,增大的大小为被读取指令的字节数。
    EIP寄存器更改的途径:一是通过跳转和函数调用返回指令JMP,CALL,RET等,二是通过中断或异常进行修改。

  • 段寄存器
    6个16位的段寄存器: CS,SS,DS,ES,FS,GS分别用于存储保护模式下逻辑地址中的段选择器。
    代码段寄存器CS:存放应用程序代码所在的段的段描述符索引(代码段线性基址),CS+EIP得到下一条指令的线性地址。
    栈段寄存器SS:存放栈段的段描述符索引(栈段的线性基址)
    数据段寄存器(DS,ES,FS,GS):DS数据段含有程序使用的大部分数据;ES数据段可以为某些串指令存放目的数据;FS段寄存器可用于计算结构化异常处理SEH, 线程环境块TEB,进程环境块PEB。

0x08

IA-32指令系统

在这里插入图片描述以funadd(arg1,arg2)为例,在Win32环境下,采用stdcall调用方式,堆栈的变化过程:
在这里插入图片描述要求:能够根据汇编指令分析出堆栈内容、堆栈指针的整个变化过程
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章