This is part of what Hexray decompiled. I can find simple buffer overflow from custom. The challenge didn’t give player a libc, so I need to find libc address. Fortunately, there is no PIE. :)
Solve
Remember to return to the main when you leak libc address.
If the stack is not aligned, you can add a ret assembly.
int __cdecl main(int argc, constchar **argv, constchar **envp) { int not_flag; // [rsp+14h] [rbp-Ch] BYREF int flag; // [rsp+18h] [rbp-8h] BYREF int fd; // [rsp+1Ch] [rbp-4h]
init(); fd = open("/dev/urandom", 0); if ( fd == -1 ) { puts("Open failed"); return-1; } elseif ( read(fd, &flag, 4uLL) == 4 ) { close(fd); puts("Wellcome to the restaurant V2!"); fflush(stdout); fgets(buff, 1024, stdin); printf(buff); // fsb puts("Show me your ticket to pass: "); fflush(stdout); __isoc99_scanf("%x", ¬_flag); if ( flag == not_flag ) restaurant(); else puts("Permission denied!\n"); return0; } else { puts("Read failed\n"); return-1; } }
I need a ticket(flag) for a restaurant. But how to know flag? The flag is from /dev/urandom. I obviously can’t predict this. But I can leak this from stack. Because there is a format string bug(fsb)!
The flag is stored on the stack. So I can leak this using fsb. If I leaked the required flag, the challenge is already over. (The rest is the same as the previous bistro.)
Read books for inspiration so you know what to write! Flag format: CTF{sha256} Medium
Until I decompiled, I thought this challenge might be heap related. But I was completely wrong. lol
There are 6 methods, but I only focused on 2(print_todo, store_todo).
1 2 3 4 5 6 7 8 9 10 11 12
intprint_todo() { int v1; // [rsp+Ch] [rbp-4h]
printf("Which entry would you like to read? "); fflush(stdout); v1 = read_int(); if ( v1 <= 128 ) returnprintf("Your NOTE: %s\n", &todos[48 * v1]); else returnputs("Sorry but this model only supports 128 NOTE list entries.\n"); }
I always pay attention whenever I see an index. It can refer to memory you didn’t intend.
The index 0 starts at 0x555555558140. For debugging convenience, I put AAAA at index 0. :) I can put the index as a negative number, so I can leak the got address.
1 2 3 4 5 6 7 8 9 10 11 12 13
intstore_todo() { int v1; // [rsp+Ch] [rbp-4h]
printf("In which slot would you like to store the new entry? "); fflush(stdout); v1 = read_int(); if ( v1 > 128 ) returnputs("Sorry but this model only supports 128 NOTE list entries.\n"); printf("What's your NOTE? "); fflush(stdout); return read_line(&todos[48 * v1], 48LL); }
The same vulnerability as the previous function(print_todo) occurs. But this time, I can overwrite the address.
I decided to overwrite atoi with system. The atoi is good to overwrite system. Becuase It has an argument of pointer.
And luckily it’s located next to open_got. I can simply put open_got and system_addr. :)
Leak the entire system, but wait this is not zeenbleed. Flag format: CTF{sha256} Easy
This challenge makes me confused. lol There was an FSB, but all mitigation were applied. Since the difficulty level was Easy, I tried to think of it as easy.
1 2 3 4 5 6 7
printf("Enter the log level (LOG_INFO, LOG_WARNING, LOG_ERR, etc.): "); __isoc99_scanf(" %[^\n]", &pri); // bof printf("Enter the message to write to syslog: "); fgets(s, 512, stdin); fgets(s, 512, stdin); syslog((unsignedint)&savedregs - 538, s); // fsb closelog();
This is a part of main. I can find easily bof and fsb. Since now there was no clue, I had to figure out what to do.
I started to print all of stacks, finally I got flag.
The %[^\n] essentially means “read characters until a newline character is encountered.” It is the same as entering a string with gets. So this can cause bof.
syslog can cause fsb. There was difficulty in leaking the address. So I made a loop for this.
1 2 3 4 5 6 7 8
# let's find the libc address for i inrange(1, 101): payload = '%' + str(i) + '$p' payload = payload.encode() write_syslog(payload) read_syslog() leak = p.recvuntil(b'==========').split(b'syslog-write: ')[-1].split(b'\n\n')[0] print(i, leak)
I just printed them out one by one to find the libc address and hoped it would be the same as the offset in the remote environment. In the past, when leaking addresses using fsb, I had an experience where the local offset and remote offset were different.