redpwnCTF 2020 rev

# bubbly

By running `file`

on the binary, we see something very interesting.

bubbly: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=edb56d2d9355bcee01909f171d8a272a3e82d053, with debug_info, not stripped

This binary is not stripped and also contains `debug_info`

which makes it pretty easy to reverse.

# Decompile

By putting the binary in `ghidra`

and analyzing the code, we get a sense of what the functions do. There are 2 main functions we care about `main`

and `check`

.

I converted the functions and arguments into python code and here's the logic behind the binary

p=False import operator def check(): i=0 while(True): if(8<i): return True if(nums[i+1]<nums[i]): break i+=1 return False while(True): n=int(input()) if(n>8): break nums[n]=operator.xor(nums[n],nums[n+1]) nums[n+1]=operator.xor(nums[n+1],nums[n]) nums[n]=operator.xor(nums[n],nums[n+1]) print(nums) p=check() if(p): print("got it") else: print("nope")

These are some lines that we do care about.

This is the condition where `check()`

doesn't break and when `i`

increments over 8 returns true.

if(nums[i+1]<nums[i]):

By doing some experiments, we know that this is just changing the order of `nums[n]`

and `nums[n+1]`

by running `XOR`

3 times.

nums[n]=operator.xor(nums[n],nums[n+1]) nums[n+1]=operator.xor(nums[n+1],nums[n]) nums[n]=operator.xor(nums[n],nums[n+1])

So if we want `check`

to return true, we need to make every element in `nums`

greater than the previous element in `nums`

. Basically in incremental order.

## nums

We need to set nums, but what is nums? Well it's just a variable stored in memory, since we have full access to the memory of the binary, we could use `gdb`

and find out the values of `nums`

> x/24wx nums 0x4060 <nums>: 0x00000001 0x0000000a 0x00000003 0x00000002 0x4070 <nums+16>:0x00000005 0x00000009 0x00000008 0x00000007 0x4080 <nums+32>:0x00000004 0x00000006 Cannot access memory at address 0x4088

So we can see that there are `10`

elements in `nums`

and we could convert the hex to decimal by hand since they are pretty small.

Here's what I got.

nums=[1,10,3,2,5,9,8,7,4,6]

What we need to do now is find a series of indexes and swap the element at `i`

and `i+1`

and ultimately sort the array.

## The Exploit

By keeping track of the array on a piece of paper, I was able to find the set of moves to sort nums and trigger `check`

to return `true`

.

I hate my data structures class! Why can't I just sort by hand? 1 2 1 7 6 5 4 3 4 8 7 6 5 8 7 6 8 7 8 10 Well done! flag{4ft3r_y0u_put_u54c0_0n_y0ur_c011ege_4pp5_y0u_5t1ll_h4ve_t0_d0_th15_57uff}