PWN学习资料整理——(二)基础

在PWN中,永远离不开汇编,包括汇编指令,寄存器等

1. 大小端模式

至于为什么要区分大小端,这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit。
但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于 8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。

例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于 大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。
小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以随时在程序中(在ARM Cortex 系列使用REV、REV16、REVSH指令 [1] )进行大小端的切换。

大端模式

所谓的大端模式是指数据的高字节,保存在内存的低地址中,而数据的低字节, 保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处 理:地址由小向大增加,而数据从高位往低位放;

例如:对于0x12345678的大端模式存储如下

低地址————>高地址
0x120x340x560x78
小端模式

所谓的小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权 有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻 辑方法一致。

例如:对于0x12345678的小端模式存储如下

低地址————>高地址
0x780x560x340x12

2. 寄存器

寄存器是中央处理器(CPU)内的组成部 分。寄存器是有限存贮容量的高速存贮部件, 它们可用来暂存指令、数据和地址。在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算 术及逻辑部件中,寄存器有累加器(ACC)。

通用寄存器
32位寄存器16位寄存器8位寄存器描述
EAXAXAH | AL累加寄存器
EBXBXBH | BL基址寄存器
ECXCXCH | CL计数寄存器
EDXDXDH | DL数据指针寄存器
ESPSP栈顶指针寄存器
EBPBP扩展基址指针寄存器
ESISI源变址寄存器
EDIDI目的变址寄存器
EIPIP指令指针寄存器
EFLAGS标志寄存器

在这里插入图片描述

标志寄存器

这是一个16位的存放条件标志、控制标志寄存器,主要用于反映处理器的状态和ALU运算结果的某些特征及控制指令的执行。

在这里插入图片描述
CF(进位标志位)
若上一个运算产生进位,则其值为1,否则其值为0。
ZF(零标志位)
若上一个运算结果为 0,则其值为1,否则其值为0。
OF(溢出标志位)
若上一个运算产生溢出,则其值为1,否则其值为0。

百度百科解释

标志位(外语缩写)标志位名称及外语全称=1=0
CF进位标志/Carry FlagCY/Carry/进位NC/No Carry/无进位
PF奇偶标志/Parity FlagPE/Parity Even/偶PO/Parity Odd/奇
AF辅助进位标志/Auxiliary Carry FlagAC/Auxiliary Carry/进位NA/No Auxiliary Carry/无进位
ZF零标志/Zero FlagZR/Zero/等于零NZ/Not Zero/不等于零
SF符号标志/Sign FlagNG/Negative/负PL/Positive/非负
TF跟踪标志/Trace Flag
IF中断标志/Interrupt FlagEI/Enable Interrupt/允许DI/Disable Interrupt/禁止
DF方向标志/Direction FlagDN/Down/减少UP/增加
OF溢出标志/Overflow FlagOV/Overflow/溢出NV/Not Overflow/未溢出

这些标志位,在我们执行一些比较和跳转的汇编指令时,会被用到。

段寄存器

• 在8086CPU中 ,寄存器的寻址范围为0~0xFFFF,程序可用空间十分有限,于是出现了段寄存器。
• 段寄存器相当于一个基址,段寄存器 * 0x10000 + 偏移 = 寻址地址
• 不同的段寄存器寻址功能不同

代码段寄存器CS(Code Segment)
存放当前正在运行的程序代码所在段的段基址,表示当前使用的指令代码可以从 该段寄存器指定的存储器段中取得,相应的偏移量则由IP提供。
数据段寄存器DS(Data Segment)
指出当前程序使用的数据所存放段的最低地址,即存放数据段的段基址。
堆栈段寄存器SS(Stack Segment)
指出当前堆栈的底部地址,即存放堆栈段的段基址。
附加段寄存器ES(Extra Segment)
指出当前程序使用附加数据段的段基址,该段是串操作指令中目的串所在的段。

3. 内存

程序执行前,硬盘中的数据(可以使用winhex查看)在这里插入图片描述
程序执行后(可以使用IDA查看)

在这里插入图片描述
未开启 ASLR(地址随机化)时
地址 = 基址 + 程序在硬盘中的数据的偏移
由图可知,该程序的基址为:0x400000

4. 堆栈

栈本质上是一块内存,每块内存有对应的地址编号,只不过这块内存被程序用来作为一 个特殊的存储区,主要功能是暂时存放数据或地址,通常用来保护断点和现场

可以参考这个文章中的案例

5. 函数调用约定

x86下函数调用约定(cdecl、stdcall)

函数参数在栈上按照从右至左的顺序依次压入栈中,返回值 存放在 EAX 中。
可以继续参考这个文章中的案例

x64下函数调用约定

Windows下参数1、参数2、参数3、参数4分别保存在 RCX、RDX、R8D、R9D这四个通用寄存器中,剩下的 参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 RAX 中。

Linux下前6个参数分别被存放在RDI,RSI,RDX,RCX,R8,R9寄存器中,剩下的参数从右往左依次入栈,被调用 者实现栈平衡,返回值存放在 RAX 中。

6. 系统调用(Linux平台)

内核提供的一组实现特殊功能的子程序供程序员在编写自己的程序时调用,以减轻编程的工作 量。汇编语言中系统调用的功能有很多,涉及屏幕显示、文件管理、I/O管理等等,每个子程序都有一个功能号,所有 的功能调用的格式都是一致的。

调用的步骤大致如下:
1)系统功能号送到寄存器AX中;
2)入口参数送到指定的寄存器中;
3)执行相关系统调用指令;
4)根据出口参数分析功能调用执行情况。

32位程序 的系统调用由0x80中断完成(int 0x80指令),各个通用寄存器用于传递参数,EAX寄存器用于表示系统 调用的接口号,比如:

  • EAX = 1表示退出进程(exit);
  • EAX = 2表示创建进程(fork);
  • EAX = 3表示读取文件或 IO(read);
  • EAX = 4表示写文件或IO(write)等,

每个系统调用都对应于内核源代码中的一个函数,它们都是 以“sys_”开头的,比如exit调用对应内核中的sys_exit函数。

根据系统调用参数数量的不同,依次将参数放入EBX、ECX、EDX、ESI、EDI和EBP这6个寄存器中传递。注(如 今的32位程序多用SYSENTER快速系统调用来实现)

64位程序 的系统调用由syscall指令完成,系统调用号存放在rax寄存器中,参数和64位函数调用存放一致。
具体的函数调用表,参考这里

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值