01. PWN基础知识

一.什么是溢出?

1.概念:在计算机中,当要表示的数据超出计算机所使用的数据的表示范围时,则产生数据溢出

2.产生的原因:
*使用非安全类型(non -type-safe)的语言如C/C++等
*以不可靠的方式存取或者复制内存缓冲区
*编译器设置的内存缓冲区太靠近关键数据结构;

二.什么是PWN?

概念:
在计算机中,当要表示的数据超出计算机所使用的数据表示范围时,则产生数据的溢出。
“pwn”是一个黑客语法的俚语词,是指攻破设备或者系统。发音类似“砰”,对于黑客而言,这就是成功实施黑客攻击的声音—-砰的一声,被“黑”的电脑或手机就被操控。

三.复习寄存器

ESP: 用来储存函数调用得的栈顶指针,在压栈和退栈时发生变化
EBP: 用来存储当前函数状态的基地址,在函数运行时不变,可以用来索引确定函数参数或局部变量的位置
EIP: 用来储存即将执行的程序指令的地址

四.复习汇编

*32位x86架构下汇编指令有两种格式intel与AT&T
*Intel:寄存器名称和数值前无符号 AT&T:寄存器名称前加”%“,数值前加”$”
*在.gdbinit配置文件中可以配置:set disassembly-flavor intel

五.栈帧

栈帧就是一个函数执行的环境:函数参数、局部变量、函数执行后返回到哪里等等。每一个栈帧代表的就是一个未执行完的函数

    ps: [ebp - xx]一般都是局部变量
        [ebp + xx]一般都是参数

六.分析函数执行时堆栈变化

1. 在linux的控制台编译C文件

要求:熟悉Linux常用命令和Vi编辑器

首先进入root用户模式 sudo su:
图片
ls 命令 显示文件目录:
图片
命令cd 切换到指定目录:

1
cd 桌面

命令mkdir 创建目录:

1
mkdir PWN

命令chmod 修改文件或目录权限:

1
chmod 777             //最高权限

命令touch 创建相关文件:

1
touch heilo.c

进入Vi编辑器打开文本:

1
vi hello.c

之后按下 i 才能进行编辑,输入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<stdio.h>

int test(int a,int b)
{
int c=a+b;
return c;
}

int main()
{
int d=test(1,2);
return 0;
}

然后按Esc后输入 :wq 才能保存并且退出!

命令gcc 编译.c文件:

1
2

gcc -m32 -o hello hello.c

2. 运行gdb

1
gdb hello 

图片

1
disass main          反汇编查看main函数

图片

1
disass test                                                           查看test函数

图片

1
b *0x565554ed                                          加断点 

图片

1
2
3
4
5
run                                                              运行
r是运行
n是单步执行,next遇到函数不会进入函数内部
si是步入,step会执行到函数内部c是继续运行,调试时,使用continue命令继续执行程序。程序遇到断电后再次暂停执行;
如果没有断点,就会一直执行到结束

图片
这里即使到了我们的断点。

然后按 n 单步执行,注意观察堆栈变化:
push ebp就是把寄存器ebp的值,也就是ebp的地址压入堆栈中
图片

mov ebp,esp就是把esp的地址传给epd,因ebp会上移动到esp所在的位置
图片

sub esp,0x10就是把esp的地址减去了16字节,外观上看就是把esp上移了4行
图片

call __x86.get_pc_thunk.ax 这个就先不管啦
add eax, 0x1ae4 也是先不管

mov edx, dword ptr [ebp + 8] 这个其实就是esp寻址,把参数1放到edx
mov eax, dword ptr [ebp + 0xc] 这个其实也是,把参数2放到eax
此时看的该是寄存器:
图片

add eax, edx 把edx的值和eax相加后保存到eax
图片

此时堆栈都还没发生变化,主要是在实现函数的主要功能

mov dword ptr [ebp - 4], eax 就是把eax存储的最后计算结果转存到堆栈中
图片

mov eax, dword ptr [ebp - 4] 又把计算结果返回给EAX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
leave是汇编语言中用来关闭栈帧的指令名,通常用于函数末尾
在16位汇编下相当于:
mov sp,bp
pop bp

在32位汇编下相当于:
mov esp,ebp;
//将ebp指向(ebp内部应当保存一个地址,所谓指向即这个地址对应的空间)的值赋给esp
pop ebp

/* leave指令将EBP寄存器的内容复制到ESP寄存器中,
以释放分配给该过程的所有堆栈空间。然后,它从堆栈恢复EBP寄存器的旧值。*/
enter有时在函数开头,正好相反,相当于:
push ebp
mov ebp,esp

图片
ret 返回,把当前栈顶的值放入EIP,并且使栈顶指针加地址4默认,可以看到上面,esp储存的就是main函数内存地址
代码块跳转变化:
图片

堆栈变化:
图片

add esp, 8 平衡堆栈,esp+8,就是esp地址下移动8字节,两行
图片

mov dword ptr [ebp - 4], eax 又是把eax的数据转存到堆栈
mov eax, 0 把eax清零
leave
图片

ret 从main函数再返回就到结束阶段了,后面不解释
图片

delete 最后删除所有断点

1
2
3
4
5
掌握函数调用的流程,以及函数调用约定,
就像今天的例子压入1,2,3,用高级语言进行汇编,所以压入栈内就是321了,
了解栈的特性:先进后出。栈的生长方向 ,堆栈平衡的操作。
要继续熟悉掌握汇编语言,会看x86的汇编指令,了解eflag标志寄存器的变化。
了解掌握gdb调试(pwndbg,peda)的使用,和相关指令。