CTF中pwn题的搭建

2017年5月11日 补:
1、socat 中有参数reuseaddr,使用的时候加上这个,顾名思义,这个参数的意思就是地址(端口)重用,是为了防止socat绑定失败或者由于某些情况退出时,重新使用此端口需要等待2分钟的时间。

如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,指明”地址已经使用中”。如果你的服务程序停止后想立即重启,而新套接字依旧使用同一端口,此时SO_REUSEADDR 选项非常有用。必须意识到,此时任何非期望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不可能。

2、引申一下,nohup是永久执行,&是指在后台运行
nohup:http://www.cnblogs.com/allenblogs/archive/2011/05/19/2051136.html
&:http://blog.sina.com.cn/s/blog_963453200102uya7.html
区别:http://blog.csdn.net/zhang_red/article/details/52789691

3、关闭地址空间随机化PIE(ASLR)
一般情况下NX(Windows平台上称其为DEP)和地址空间分布随机化(ASLR)会同时工作。

内存地址随机化机制(address space layout randomization),有以下三种情况

0 - 表示关闭进程地址空间随机化。
1 - 表示将mmap的基址,stack和vdso页面随机化。
2 - 表示在1的基础上增加栈(heap)的随机化。

之前提到可以使用命令sudo -s echo 0 > /proc/sys/kernel/randomize_va_space来关闭ASLR,但是经提醒,这样关闭了所有程序的随机化还是有一定的风险的,所以可以在程序编译的时候增加参数-no-pie关闭程序的pie,只关闭此程序的随机化,而其它的程序不变

《CTF中pwn题的搭建》 可以看到开启了pie的程序地址会一直变化

我们尝试关闭系统的随机化保护sudo -s echo 0 > /proc/sys/kernel/randomize_va_space

《CTF中pwn题的搭建》 两个程序地址都不变化了

所以最后得出的结论:
第一天,系统关闭随机化保护
一个程序战战兢兢地问系统:“老大,我能不能开启随机化保护?”,
系统:“滚蛋,我都没有开启随机化保护,你还想开?”

第二天,系统开启随机化保护
一个程序战战兢兢地问系统:“老大,我能不能关闭随机化保护?”,系统:“你开心就好~”

一般情况下,我们搭建的题目的时候还是选择关闭单个程序的随机化保护,而对于系统的随机化保护还是选择开启吧~

补充:

在ubuntu16.10后gcc编译时默认加上了参数-pie,也就是运行地址随机化,可以更好的抵挡攻击,防pwn,但是出题就比较坑爹了
只需要编译时加上参数-no-pie即可

本文中的测试环境为ubuntu-16.10-server-amd64

一般情况下,现在的CTF pwn题都会将题设置在linux上,不是因为Windows不重要,而是用Windows容易被人搞出事……下面介绍一下在Ubuntu中搭建pwn题的步骤:

1.准备好题
  题目需要自己搞好,比如最简单的一个pwn:

//pwn1.c
#include <stdio.h>
int main(int argc, char** argv)
{
    int modified;
    char buffer[10];
    modified = 0;
    gets(buffer);        // 引发缓冲区溢出
    if (modified != 0)
    {
        printf("Congratulations, you pwned it.\n");
    }
    else
    {
        printf("Please try again.\n");
    }
    return 0;
}

2.gcc/g++编译
  这时候直接使用命令gcc pwn1.c -o pwn1是不行的,不信你试试~

./pwn1
1111111111111111111111
*** stack smashing detected ***: ./3 terminated
Aborted
#stack smashing是GCC的一种检测“缓存溢出”的保护机制

我们使用如下命令:

gcc -fno-stack-protector -z execstack -mpreferred-stack-boundary=4  -o pwn1 pwn1.c
#Ubuntu下面的GCC默认开启了Stack Smashing Protector,
#如果想在这个系统中学习缓冲区溢出的原理,在编译时要加上fno-stack-protector选项,
#否则运行时会出现*** stack smashing detected ***: xxx terminated,
#而不是期望的Segmentation fault。同时还需要加上允许栈执行的选项。

#-fno-stack-protector用来关闭gcc编译器gs验证码机制
#-z execstack用来关闭ld链接器堆栈段不可执行机制

3.关闭地址空间随机化(ASLR)
  首先确认系统中ASLR是否打开,cat /proc/sys/kernel/randomize_va_space,如果结果为2,则ASLR开启。
  关闭方法:sudo echo 0 > /proc/sys/kernel/randomize_va_space,即将randomize_ca_space文件内数字置0即可。

接下来,就随便浪去吧……~

2017年4月19日08:23:12,补充:额,可能是我当时写的时候比较赶,后面部分可能忘记写了……
如果你想将题目挂载在服务器的端口,socat工具真的很方便:

sudo apt-get install socat
socat tcp-l:端口号,fork exec:程序位置

另外,如果你想你的程序即使关闭虚拟终端也可以运行的话,使用nohup命令

#首先编写一个.sh脚本
#!/bin/sh
#name:pwn1.sh
socat tcp-l:9999,fork exec:./pwn1

Next:

sudo chmod u+x ./pwn.sh
nohup ./pwn.sh &

这样的话就可以了,如果是在本地虚拟机中搭建的话,至少局域网中的人都能访问到,但是如果想让更多的人了解的话,那就需要一个公网ip咯,这个怎么做。。。要么去申请一个,要么就买个服务器呗~
之后访问的话,nc这个不需要多介绍了吧…懒得写了,逃~~~

2019/4/29

补充一下知识点,pie 跟 aslr 不一样,不要被上述的描述误导了。
ASLR 和 PIE

1.ASLR
Linux 下的 ASLR 总共有 3 个级别,0、1、2

0 就是关闭 ASLR,没有随机化,堆栈基地址每次都相同,而且 libc.so 每次的地址也相同。
1 是普通的 ASLR。mmap 基地址、栈基地址、.so 加载基地址都将被随机化,但是堆没用随机化
2 是增强的 ASLR,增加了堆随机化(等同于 brk 随机?)

查询randomize_va_space当前设置:
$ sysctl -n kernel.randomize_va_space
1

//这就是个文件,里面记录着等级
$ cat /proc/sys/kernel/randomize_va_space
1

关闭ASLR:
$ sysctl -w kernel.randomize_va_space=0
# 或
$ echo 0 > /proc/sys/kernel/randomize_va_space

2.PIE
PIE 叫做代码部分地址无关,PIE 能使程序像共享库一样在主存任何位置装载,这需要将程序编译成位置无关,并链接为 ELF 共享对象。

如果不开启 PIE 的话,那么每次 ELF 文件加载的地址都是相同的。如果开启 PIE,那么每次都会不同。

开启 ASLR+PIE 的一个直接的困扰就是,你会发现没有地方可以写,所有的 got 表、plt 表、bss 段地址都是不确定的,只有通过泄漏才可以确定地址。

    原文作者:一纸笔墨
    原文地址: https://www.jianshu.com/p/a659924515f7
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞