首页
社区
课程
招聘
「PWN系列」一、开篇 自己写题自己做
发表于: 2024-2-19 22:30 14464

「PWN系列」一、开篇 自己写题自己做

2024-2-19 22:30
14464

写一道基础的栈溢出PWN题,打开二进制安全的门缝

第一步,准备一道pwn题的源码

示例.c

第二步就是gcc编译了,因为还要牵扯到很多的开关,所以这里一步步来
1、【关闭】EP/NX(堆栈不可执行)

2、【关掉】Stack Protector/Canary(栈保护)

3、【关掉】程序ASLR/PIE(程序随机化保护)

4、【关闭】整个linux系统的ASLR保护

5.「打开」整个linux系统的ASLR保护

6.64位linux下面的GCC编译出一个32位可执行程序

第三步,我们在做题目的时候经常碰到的就是将题目作为一个服务绑定在一个服务器的一个端口上,所以接下来可以用socat

最后一步就是访问题目了

程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,导致与其相邻的栈中的变量的值被改变。这种问题是一种特定的缓冲区溢出漏洞,类似的还有堆溢出,bss段溢出等溢出方式。

发生的前提条件

程序必须向栈上写入数据

写入的数据大小没有被良好地控制

GPT

这段代码存在严重的安全问题,主要是因为使用了不安全的 gets 函数,容易导致缓冲区溢出。具体问题如下:

使用 gets 函数: gets 函数没有提供缓冲区边界检查,因此可能导致缓冲区溢出,允许攻击者覆盖栈上的关键数据。

栈溢出风险: 函数 vulnerable 中的字符数组 s 只有 12 个字节,但用户输入没有受到限制。这可能允许攻击者输入超过 12 个字节的数据,导致栈溢出。

system 函数调用: 函数 func 中使用 system 函数执行用户输入的命令,这可能导致命令注入攻击,尤其是由于缺乏输入验证。

为了解决这些问题,应该使用安全的输入函数替代 gets,例如 fgets,并确保对用户输入进行适当的验证和边界检查。此外,对于执行用户输入的命令,应该谨慎处理,避免命令注入漏洞。

我们所要达成的目的是让程序执行func函数

首先关闭ASLR

echo 0 > /proc/sys/kernel/randomize_va_space

使用如下指令进行编译,编译32位不带stack保护和pie保护的二进制文件

gcc -m32 -fno-stack-protector -no-pie main.c -o main

得到一个main二进制文件,使用checksec进行分析

gdb调试可看b站“国资社畜”的的pwn教学视频,讲得非常详细非常好。

国资社畜 你想有多PWN:https://www.bilibili.com/video/BV1mr4y1Y7fW

图片描述

函数:vulnerable()

080484b9 83 ec 14 SUB ESP,0x14 //缓冲区的大小(EBP到ESP:0x14)

080484e0 e8 3b fe CALL <EXTERNAL>::gets //⚠️危险函数 char * gets(char * __s)

main二进制文件中main函数反编译结果:

直接调用了vulnerable();和我们的源代码基本一致

主函数main

Ghidra反编译vulnerable函数结果,以下为伪代码:

为什么在源代码中[12]而这里却是[16]?

源代码中定义了一个大小为 12 的字符数组 s。然而,反编译的伪代码中,编译器可能进行了栈帧的调整和优化,将 s 的大小调整为 16 字节,这可能是为了实现更有效的栈内存布局或者对齐。

⚠️危险的system("/bin/sh");

图片描述

图片描述
至此,一道简单的pwn从写题到部署,再到寻找利用方式,最后到漏洞利用全部演示完毕

Pwn入门之基础栈溢出:https://zhuanlan.zhihu.com/p/587763752

c程序从编译开始到运行结束的过程:https://blog.csdn.net/tbsqigongzi/article/details/128137047

国资社畜 你想有多PWN:https://www.bilibili.com/video/BV1mr4y1Y7fW

#include<stdio.h>
int main()
{
        int a=1;
        float key=2018.81,input;
        if (a==2)
        {
                printf("input your key:\n");
                scanf("%f",&input);
                if(input==key)
                        printf("mctf{Hahahahaha_Y0u_C@n_use_GDB_N0W}");
        }
        return 0;
}
#include<stdio.h>
int main()
{
        int a=1;
        float key=2018.81,input;
        if (a==2)
        {
                printf("input your key:\n");
                scanf("%f",&input);
                if(input==key)
                        printf("mctf{Hahahahaha_Y0u_C@n_use_GDB_N0W}");
        }
        return 0;
}
gcc  -z execstack -o 编译完的文件名 待编译的文件名
gcc  -z execstack -o 编译完的文件名 待编译的文件名
gcc -fno-stack-protector -o 编译完的文件名 待编译的文件名
gcc -fno-stack-protector -o 编译完的文件名 待编译的文件名
gcc -no-pie 编译完的文件名 待编译的文件名
gcc -no-pie 编译完的文件名 待编译的文件名
sudo -s
echo 0 > /proc/sys/kernel/randomize_va_space
exit
sudo -s
echo 0 > /proc/sys/kernel/randomize_va_space
exit
sudo -s
echo 2 > /proc/sys/kernel/randomize_va_space
sudo -s
echo 2 > /proc/sys/kernel/randomize_va_space
gcc -m32 -z execstack -fno-stack-protector -o 编译完的文件名 待编译的文件名
gcc -m32 -z execstack -fno-stack-protector -o 编译完的文件名 待编译的文件名
socat tcp-l:端口号,fork exec:程序位置,reuseaddr
socat tcp-l:端口号,fork exec:程序位置,reuseaddr
nc IP地址 端口号
nc IP地址 端口号
#include <stdio.h>
#include <string.h>
 
int func(){
    system("/bin/sh");
    return 0;
}
void vulnerable() {
  char s[12];
  puts("请输入:");
  gets(s);
  puts(s);
  return;
}
int main(int argc, char **argv) {
  vulnerable();
  return 0;
}
#include <stdio.h>
#include <string.h>
 
int func(){
    system("/bin/sh");
    return 0;
}
void vulnerable() {
  char s[12];
  puts("请输入:");
  gets(s);
  puts(s);
  return;
}
int main(int argc, char **argv) {
  vulnerable();
  return 0;
}
Arch:     i386-32-little
// x86架构下的32位小端程序
RELRO:    Partial RELRO
//
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x8048000)
Arch:     i386-32-little
// x86架构下的32位小端程序
RELRO:    Partial RELRO
//
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x8048000)
标题 RELRO STACK CANARY(堆栈保护) NX (不可执行内存) PIE
示意 RELRO 是可执行文件中一个常见的保护特性。它的全称是 Relocation Read-Only(重定位只读),它的作用是防止针对 GOT 表的攻击。<br><br>RELRO 可以分为三种级别:<br><br>- Partial RELRO(部分 RELRO):在 program 的初始化阶段,只有 GOT 表中未被初始化的部分被保护起来。如果一个地址被初始化后,那么它就成为了漏洞的可能入口。<br> <br>- Full RELRO(完全 RELRO):在 program 的初始化阶段,GOT 表所有项都被标记为只读。这样一来,攻击者就无法改变 GOT 表中的地址来实现攻击。<br> <br>- Canary RELRO:这是 Full RELRO 的升级版,它还增加了内存区域的随机化,提高了安全性。 堆栈保护是一种通过检查函数返回地址是否被修改的技术。在执行函数时,函数返回地址会被压入栈中。堆栈保护插入了一个被称为“堆栈守卫”的随机值到返回地址之前,防止它被篡改。<br><br>如果堆栈保护是开启的,Checksec 将会显示“Canary found”,否则就是“No canary found”。 NX 是可执行文件中的一项重要安全特性,它通过将某些内存区域标记为不可执行来防止缓冲区溢出等攻击。<br><br>如果 NX 是开启的,Checksec 将会显示“NX enabled”,否则就是“NX disabled”。 PIE(Position Independent Executables)是在程序执行时将程序和依赖的库加载到内存中并且将其具体位位置放置在随机的内存地址中。这样,攻击者想要利用已知的内存位置来执行攻击时就很难了。<br><br>PIE 是增加安全性的有力手段。如果开启了 PIE,Checksec 将会显示“PIE enabled”,否则就是“No PIE”。
例子 Full RELRO Canary found NX enabled PIE enabled
                     **************************************************************
                     *                          FUNCTION                          *
                     **************************************************************
                     undefined vulnerable()
     undefined         AL:1           <RETURN>
     undefined4        Stack[-0x8]:4  local_8                                 XREF[1]:     080484f8(R) 
     undefined1        Stack[-0x18]:1 local_18                                XREF[2]:     080484dc(*),
                                                                                           080484eb(*
                     vulnerable                                      XREF[4]:     Entry Point(*), main:08048518(c),
                                                                                  080485f0, 080486a8(*
080484b5 55              PUSH       EBP
080484b6 89 e5           MOV        EBP,ESP
080484b8 53              PUSH       EBX
080484b9 83 ec 14        SUB        ESP,0x14 //缓冲区的大小(EBP到ESP:0x14
080484bc e8 ff fe        CALL       __x86.get_pc_thunk.bx                            undefined __x86.get_pc_thunk.bx()
         ff ff
080484c1 81 c3 3f        ADD        EBX,0x1b3f
         1b 00 00
080484c7 83 ec 0c        SUB        ESP,0xc
080484ca 8d 83 b8        LEA        EAX,[EBX + 0xffffe5b8]=>DAT_080485b8             = E8h
         e5 ff ff
080484d0 50              PUSH       EAX=>DAT_080485b8                                = E8h
080484d1 e8 5a fe        CALL       <EXTERNAL>::puts                                 int puts(char * __s)
         ff ff
080484d6 83 c4 10        ADD        ESP,0x10
080484d9 83 ec 0c        SUB        ESP,0xc
080484dc 8d 45 ec        LEA        EAX=>local_18,[EBP + -0x14]
080484df 50              PUSH       EAX
080484e0 e8 3b fe        CALL       <EXTERNAL>::gets    //⚠️危险函数                             char * gets(char * __s)
         ff ff
080484e5 83 c4 10        ADD        ESP,0x10
080484e8 83 ec 0c        SUB        ESP,0xc
080484eb 8d 45 ec        LEA        EAX=>local_18,[EBP + -0x14]
080484ee 50              PUSH       EAX
080484ef e8 3c fe        CALL       <EXTERNAL>::puts                                 int puts(char * __s)
         ff ff
080484f4 83 c4 10        ADD        ESP,0x10
080484f7 90              NOP
080484f8 8b 5d fc        MOV        EBX,dword ptr [EBP + local_8]
080484fb c9              LEAVE
080484fc c3              RET
                     **************************************************************
                     *                          FUNCTION                          *
                     **************************************************************
                     undefined vulnerable()
     undefined         AL:1           <RETURN>
     undefined4        Stack[-0x8]:4  local_8                                 XREF[1]:     080484f8(R) 
     undefined1        Stack[-0x18]:1 local_18                                XREF[2]:     080484dc(*),
                                                                                           080484eb(*
                     vulnerable                                      XREF[4]:     Entry Point(*), main:08048518(c),
                                                                                  080485f0, 080486a8(*

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 11
支持
分享
最新回复 (2)
雪    币: 2575
活跃值: (502)
能力值: ( LV2,RANK:85 )
在线值:
发帖
回帖
粉丝
2
学习思路不错
2024-2-20 18:08
1
雪    币: 224
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
虽然看不懂,还是赞一个!
2024-2-21 00:04
1
游客
登录 | 注册 方可回帖
返回
//