首页 > 其他分享 >PWN出题小记

PWN出题小记

时间:2024-04-11 10:56:08浏览次数:25  
标签:puts void ctf paper 出题 PWN home docker 小记

记录一下 PWN 出题的源码、环境部署。

PWN题环境部署

图方便的话可以使用 pwn_deploy_chroot 这个项目。

如何安全快速地部署多道ctf pwn比赛题目

也可以自己写 dockerfile 拉取镜像。

将题目名命名为 pwn,与 Dockerfile、ctf.xinetd、start.sh 三个文件放在同一目录下,下面提供相应配置文件的模板。

Dockerfile

FROM ubuntu:16.04
# 此处可以修改版本 直接修改版本号即可改变拉取的镜像版本 这里会直接到dockerhub拉取相应的镜像
# FROM ubuntu:22.04

RUN sed -i "s/http:\/\/archive.ubuntu.com/http:\/\/mirrors.tuna.tsinghua.edu.cn/g" /etc/apt/sources.list && \
    apt-get update && apt-get -y dist-upgrade && \
    apt-get install -y lib32z1 xinetd

RUN useradd -m ctf

WORKDIR /home/ctf

RUN cp -R /lib* /home/ctf && \
    cp -R /usr/lib* /home/ctf
# 使用 ubuntu 20.04 及以上版本的 libc 使用下面指令
# RUN cp -R /usr/lib* /home/ctf

RUN mkdir /home/ctf/bin && \
    cp /bin/sh /home/ctf/bin && \
    cp /bin/ls /home/ctf/bin && \
    cp /bin/cat /home/ctf/bin

COPY ./ctf.xinetd /etc/xinetd.d/ctf
COPY ./start.sh /start.sh
RUN echo "Blocked by ctf_xinetd" > /etc/banner_fail

RUN chmod +x /start.sh

COPY ./pwn /home/ctf/
RUN chown -R root:ctf /home/ctf && \
    chmod -R 750 /home/ctf

CMD ["/start.sh"]

EXPOSE 9999

ctf.xinetd

service ctf
{
    disable = no
    socket_type = stream
    protocol    = tcp
    wait        = no
    user        = root
    type        = UNLISTED
    port        = 9999
    bind        = 0.0.0.0
    server      = /usr/sbin/chroot
    server_args = --userspec=1000:1000 /home/ctf ./pwn
    banner_fail = /etc/banner_fail
    # safety options
    per_source  = 10 # the maximum instances of this service per source IP address
    rlimit_cpu  = 20 # the maximum number of CPU seconds that the service may use
    #rlimit_as  = 1024M # the Address Space resource limit for the service
    #access_times = 2:00-9:00 12:00-24:00
}

start.sh

#!/bin/sh
# Add your startup script
export FLAG="flag{c6f3396244adadd3c53c49cf13ca864e}"
echo $FLAG > /home/ctf/flag
chown root:ctf /home/ctf/flag
chmod 740 /home/ctf/flag
# 清环境变量
export FLAG=
# DO NOT DELETE
/etc/init.d/xinetd start;
sleep infinity;

如果需要设置动态 flag 的话,这里提供一种实现思路,首先肯定是需要靶场进行配合的,在拉镜像生成容器的时候,平台生成并记录一个随机数,传递随机数到容器的环境变量,然后通过环境变量写容器里的 flag 文件。

要设置 random 值为 flag,需要删除上面的 start.sh 中对 FLAG 赋值的 export FLAG="xx",并修改起容器的命令。

$ sudo docker run -itd --name [CONTAINER NAME] -p [PORT]:9999 -e FLAG=random [IMAGE ID]

写好这三个文件后,在当前文件夹路径下执行相关命令,拉镜像,起容器。

$ sudo docker build -t <image_name>:<tag> .			#拉取题目镜像
$ sudo docker images								#获取镜像id
$ sudo docker run -id --name [CONTAINER NAME] -p [PORT]:9999 [IMAGE ID]	#设置使用IMAGE ID镜像、生成的容器的容器名为CONTAINER NAME、将容器的9999端口映射主机的PORT端口

$ sudo docker ps -a									#查看正在所有容器名
$ sudo docker ps									#查看正在运行的容器名
$ sudo docker rm -f [CONTAINER NAME]				#删容器
$ sudo docker images								#获取镜像id
$ sudo docker rmi [IMAGE ID]						#删镜像
$ sudo docker start [CONTAINER ID]					#重启容器

进入对应容器的 shell。

$ sudo docker exec -it [CONTAINER NAME] /bin/bash

很显然,通过上述方法来生成容器的话会有些繁琐,docker-compose 这个工具就十分方便,它是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,可以使用 yml 文件来配置应用程序需要的所有服务。然后,使用一个简短的命令,就可以从 yml 文件配置中创建并启动所有服务。docker-compose 默认的配置文件为 docker-compose.yml,其用 YAML 语言编写。

YAML 的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、倾印调试内容、文件大纲(例如:许多电子邮件标题格式和 YAML 语法非常接近)。

docker-compose.yml 文件如下,也是与上述文件放在同一文件夹下。image_name 是生成的镜像名,port 是容器的外部端口。

version: "2"
services:
  pwn:
    build: .
    image: <image_name>
    restart: unless-stopped
    ports:
      - "[PORT]:9999"

然后启动服务。

$ docker-compose up -d

PWN出题

编译时设置 elf 文件的保护机制:

NX:-z execstack / -z noexecstack (关闭 / 开启) 栈上数据不可执行。

Canary:-fno-stack-protector /-fstack-protector / -fstack-protector-all (关闭 / 开启 / 全开启) 栈里插入 canary。

PIE-no-pie / -pie (关闭 / 开启) 地址随机化。

**RELRO: **-z norelro / -z lazy / -z now (关闭 / 部分开启 / 完全开启) 对GOT表的写权限。

常见报错:

/usr/bin/ld: /tmp/ccMFw2CH.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC

解决方法:在 gcc 编译时多添加一个参数 -fPIC

放些基础题的源码。

ret2text。

#include <stdio.h>
#include <stdlib.h>

void init()
{
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stderr, NULL, _IONBF, 0);
}

void func(void)
{
    char buf[40];
    read(0, buf, 60);
    return 0;
}

int main(void)
{
    init();
    puts("welcome to ctf!");
    func();
    return 0;
}

void backdoor(void)
{
    system("/bin/sh");
}

shellcode。

#include <stdio.h>
#include <unistd.h>

// char code[] = "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05";

void init()
{
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stderr, NULL, _IONBF, 0);
}

int main()
{
    init();
    char code[100];
    puts("execute: ");
    read(0, code, 0x20);
    (*(void (*)())code)();
    return 0;
}

关于堆的菜单题。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define PAPER_CNT (32)

struct paper_mgr
{
	char paper_time[48];
	char paper_content[32];
};

struct paper_mgr **array;

void backdoor()
{
	puts("Aha! Rock on!");
	system("/bin/sh");
}

void init()
{
	setvbuf(stdin, 0LL, 2, 0LL);
	setvbuf(stdout, 0LL, 2, 0LL);
	alarm(60); // 1 minute timeout
	array = (struct paper_mgr **)malloc(PAPER_CNT * sizeof(struct paper_mgr *));
	memset(array, 0, (PAPER_CNT * sizeof(struct paper_mgr *)));
}

void banner()
{
	printf("Welcome.\n");
	printf("\n");
}

void menu()
{
	puts("You have following choices:\n [1]: add a paper\n [2]: show a paper\n [3]: edit a paper\n [4]: finish a paper\n [5]: exit\nYour chocie:");
}

void get_input_custom(char *ptr, int len)
{
	if (!len)
		return;
	read(0, ptr, len);
}

void add_paper()
{
	int i;
	struct paper_mgr *paper_ptr;
	for (i = 0; i < PAPER_CNT; i++)
		if (!array[i])
			break;
	if (i == PAPER_CNT)
	{
		puts("paper manager is full :(");
		return;
	}

	paper_ptr = malloc(sizeof(struct paper_mgr));

	printf("creating paper with index-%d\n", i + 1);
	puts("please input the paper time");
	get_input_custom(paper_ptr->paper_time, 48);
	puts("please input the paper content");
	get_input_custom(paper_ptr->paper_content, 1024);
	puts("done");
	array[i] = paper_ptr;
}

void finish_paper()
{
	int index;
	puts("please input the paper index");
	scanf("%d", &index);
	index = index - 1;

	if (0 <= index && index < PAPER_CNT)
	{
		if (array[index])
		{
			free(array[index]);
			puts("done");
			return;
		}
	}
	puts("invalid paper index");
}

void show_paper()
{
	int index;
	puts("please input the paper index");
	scanf("%d", &index);
	index = index - 1;

	if (0 <= index && index < PAPER_CNT)
	{
		if (array[index])
		{
			printf("paper time: %s\n", array[index]->paper_time);
			printf("paper content: %s\n", array[index]->paper_content);
			puts("done");
			return;
		}
	}
	puts("invalid paper index");
}

void edit_paper()
{
	int index;
	puts("please input the paper index");
	scanf("%d", &index);
	index = index - 1;

	if (0 <= index && index < PAPER_CNT)
	{
		if (array[index])
		{
			struct paper_mgr *paper_ptr = array[index];
			puts("please input the new paper time");
			get_input_custom(paper_ptr->paper_time, 48);
			puts("please input the new paper content");
			get_input_custom(paper_ptr->paper_content, 1024);
			puts("done");
			return;
		}
	}
	puts("invalid paper index");
}

int main(int argc, char *argv[])
{
	int choice = 0;
	init();
	banner();
	while (1)
	{
		menu();
		scanf("%d", &choice);
		switch (choice)
		{
		case 1:
			add_paper();
			break;
		case 2:
			show_paper();
			break;
		case 3:
			edit_paper();
			break;
		case 4:
			finish_paper();
			break;
		case 5:
			puts("Bye!");
			exit(0);
		default:
			puts("Wrong!");
			break;
		}
	}
}

fmt、栈迁移。

SCUCTF 2020新生赛 PWN部分出题笔记-Pwn

这篇文章有介绍如何给 pwn 题布置沙箱。

Seccomp从0到1

标签:puts,void,ctf,paper,出题,PWN,home,docker,小记
From: https://www.cnblogs.com/ve1kcon/p/18128333

相关文章

  • STM32外部中断小记
    一、EXTI配置步骤//1.配置RCC时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟,AFIO:GPIO复用/重映射功能//2.配置EXTIGPIO端口及工作模式(输入模式)//3.配置EXTI中断线、模式(上升沿、下降沿......
  • PWN环境搭建
    序环境安装总能捣鼓半天,同样的坑重复踩,干脆记录下来,方便后续回看。VMware安装Ubuntu18虚拟机安装包地址如下,先直接down下来,存在一个方便找的地方。https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/18.04/ubuntu-18.04.6-desktop-amd64.iso然后安装教程如下,特别要提......
  • 格式化字符串走过的坑 pwn109
    格式化字符串走过的坑pwn109今天做的一道题有一个坑我调试半天终于打通了,格式化字符串的坑,确实不少,东西也比较多容易忘记,怎么说呢,功夫在平时,经验少了老规矩先看一下保护FullRELRO意味着got不能修改也就是不能通过格式化字符串漏洞来改got表,但是nx保护关闭了,也就是我们可以通......
  • newstart 部分题解和pwn相关的学习
    做newstart的pwnpieee题的pie的学习首先:对于pieee这道题很简单的栈溢出,除了NX其他的保护都开了,然后呢在左边也发现了后门函数相对偏移为0x1264(对于这里我们只用关心后三位,因为pie不会随机化地址的低12位,通俗点说就是我们十六进制地址的后三位)而一般而言后三位的地址能够确定我......
  • xss.pwnfunction-Mafia
     这个是利用的构造函数用source来获取构造函数的源码并转化成小写Function(/ALERT(1337)/.source.toLowerCase())()或parseInt(string,radix)string:要被解析的字符串。radix:解析时使用的基数(进制)。可选参数,默认为10。用parseint将alert转成进制这里为什么用30因为在......
  • 基于新版宝塔Docker部署在线客服系统过程小记
    我在业余时间开发维护了一款免费开源的升讯威在线客服系统,也收获了许多用户。对我来说,只要能获得用户的认可,就是我最大的动力。客服系统开发过程中,最让我意外的是对TCP/IP协议的认识。过去一直认为TCP/IP是可靠的连接,加上过去开发的软件网络环境比较稳定,很少在这个问题上纠结......
  • 鞅与停时定理小记
    赌博问题设\(X_i\)为第\(i\)轮赌博后的收益。根据常识,显然有\(E(X_i)=X_0=0\)离散时间鞅定义一组离散时间鞅为时间离散的随机过程\(\{X_0,X_1,X_2,...\}\),满足对于任意\(n\),都有\(|E(X_n)|<+\infty\),即取值是有限的。\(E(X_{n+1}-X_n|X_0,X_1,...,X_n)=0\),意思......
  • 关于pwn题的栈平衡中ret的作用
    以nssctf里的where_is_my_shell为例题目提供了一个system函数,和一个buf数组。数组的栈空间如图所示,这里不讨论怎么解题,只说明payload里的ret的作用。假设没有ret,栈溢出到ret的时候内容如下:第一个八字节:(图示位置)存储poprdi;ret;的地址它下面的八个字节存储要pop的参数。......
  • 劫持TLS绕过canary pwn89
    劫持TLS绕过canarypwn88首先了解一下这个东西的前提条件和原理前提:溢出字节够大,通常至少一个page(4K)创建一个线程,在线程内栈溢出原理:在开启canary的情况下,当程序在创建线程的时候,会创建一个TLS(ThreadLocalStorage),这个TLS会存储canary的值,而TLS会保存在stack高地址......
  • pwn知识——unlink(smallbins)
    是我的错觉么,总觉得unlink比UAF好懂好多...也有可能是我觉得做题模板比较好理解一点,真要深入的话我感觉一个头会比两个大emmmm原理及其条件原理unlink顾名思义,脱链,把一个空闲的chunk从unsortedbin里取出来,与物理相邻的chunk合成一个一个大堆块(分“前合”,“后合”’)。这里用图......