Last updated on:February 18, 2023 pm

1 win32的汇编开发流程

2 win32汇编源程序的结构

Hello world程序在DOS汇编:

;堆栈段
stack		segment stack
			db		100 dup (?)
stack 		ends

;数据段
data		segment
szHello		db		'Hello, world',0dh,0ah,'$'
data		ends

;代码段
code		segment
			assume	cs:code,ds:data,ss:stack
start:
			mov	ax,data
			mov ds,ax
		
			mov ah,9
			mov dx,offset,szHello
			int 21h
code		ends
			end		start

Hello world的Win32程序:

		.386
		.model flat,stdcall
		option casemap:none
;include定义
include		windows.inc
include 	user32.inc
include 	user32.lib
include		kernel32.inc
include 	kernel32.lib

;数据段
		.data
szCaption	db		'A MessageBox',0
szText		db		'Hello, world',0

;代码段
		.code
start:
		invoke	MessageBox, NULL, offset szText, offset szCaption, MB_OK
		invoke 	ExitProcess, NULL
		
		end 	start

2.1 模式定义

2.1.1 指定使用的指令集

.386是汇编的伪指令,用于告诉编译器在本程序中使用的指令集为80386所拥有的指令集。类似的指令还有:.8086, .186, .386p, .486/486p, .586/.586p等。后面带p的伪指令表示程序中可以使用**特权指令(必须在特权级0上运行的指令)**如:mov cr0, eax

2.1.2 .model语句

用来定义程序工作的模式。用法如下:

.model 内存模式 [, 语言模式] [, 其他模式]

模式 内存使用方式
tiny 用来建立 .com文件,所有代码、数据和堆栈都在同一个64KB段内
small 建立代码和数据分别别用一个64KB段的 .exe文件
medium 代码段可以有多个64KB段,数据段只有一个64KB段
compact 代码段只有一个64KB段,数据段可以有多个64KB段
large 代码段和数据段都可以由多个64KB段
huge 同large,并且数据段中的一个数组也可以超过64KB
flat Win32程序使用的模式,代码和数据段使用同一个4GB段

对于运行在保护模式下的win32程序,它只有一种内存模式——flat模式,即每一个应用程序都拥有其相互独立的4GB地址空间。

2.1.3 option语句

option casemap:none,该语句定义了程序中变量和子程序名是否对大小写敏感。由于Win32 API名称是区分大小写的,故在win32汇编程序中必须指定此语句

2.2 段的定义

2.2.1 段的概念

一个包含全部段的源程序结构:

.386
.model flat, stdcall
option casemap:none
<include statements>

.stack [堆栈段的大小]
.data
<一些初始化过的变量定义>
.data?
<一些没有初始化过的变量定义>
.const
<一些常量定义>
.code
<代码>
<开始标号>
	<语句>
end 开始标号
  • 其中.stack, .data, .data?, .const和.code都是分段伪指令。
  • Win32只有代码和数据段之分,因此.data, .data?和.const属于数据段,.code属于代码段。
  • 与DOS汇编不同,Win32汇编不必考虑堆栈,.stack段定义常常被忽略。

2.2.2 数据段

.data,.data?和.const定义在数据段,分别对应不同方式的数据定义,在最后生成的可执行文件中也放置在不同的节区(Section)。程序中的数据定义一般可以归纳为三类:

  1. 可读可写的已定义变量。被定义在.data段,具有以下性质:
    • 在源程序已经被定义了初始值。
    • 具有可读可写性。
    • 在程序装入完成之后,这些值存在于内存中。
    • .data段一般存放在可执行文件的_DATA节区内。
  2. 可读可写的未定义变量。可定义在.data段,也可以定义在.data?段,具有以下性质:
    • 一般用作缓冲区,或者程序执行后在开始使用。
    • 若定义在.data段,则编译器在生成可执行文件时会保留声明大小的空间,即使它们是全0
    • 若定义在.data?段,则编译器在生成可执行文件时只会记录空间大小信息,不会浪费磁盘空间,而是在程序执行时才会用到。
    • .data?段在可执行文件中一般放在_BSS节区。
  3. 常量。如一些要显示的字符串信息。
    • 它们在程序装入时就已经有效,但在整个执行过程中不需要修改。
    • 具有可读不可写性。
    • 如果程序对.const段进行写操作,会引起保护错误并结束程序。

2.2.3 代码段

  • .code段时代码段,所有的指令都必须写在代码段中
  • 在可执行文件中,代码段一般放在_TEXT节区。
  • Win32环境下的数据段是不可执行的,只有代码段有可执行的属性。(特权级0下运行的程序对所有段有读写权限)

2.2.4 堆栈段

  • Win32程序中不必定义堆栈段,系统会自动分配堆栈空间。
  • 堆栈段的内存属性是可读写并可执行的。(靠动态修改代码的反跟踪模块可以拷贝到堆栈中边修改边执行)

2.3 程序入口与结束

  • 汇编源程序中,并没有main函数来指定开始执行的地方。取而代之的是程序的最后一句的end语句end [开始地址]
  • 上述语句的开始地址就是源程序从代码段开始执行的地址。
  • 上述语句同时还表示源程序结束,所有代码都必须在end语句之前。
  • 多模块程序编写时,单一的模块可以没有入口标号,但是最后把多个模块连接在一起时,必须有一个主模块的入口地址被指明。

3 API的调用

3.1 API是什么

3.2 如何调用

3.3.1 invoke语句

3.3.2 函数的声明与返回值

3.3.3 include语句


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

CTF入门 Previous
x86汇编学习笔记(一) Next

 TOC

载入天数... 载入时分秒...