Blur exploit for Blender

Blender doesn’t have the blur node. That’s why I’ve created that exploit. It’s a texture with some unusual noise I’ve made. That noise reaches the Blender bug I’ve found, and puts some assembler code to both CPU and GPU. Inputs of exploit are width, height, width radius and height radius.
The blend file is on Google Drive. Try this on your computer if you’re not afraid!
https://drive.google.com/open?id=0B1O2IVzm6Yl6SjMwaDh4am9SRlE

Blue noise can burn out RAM too if used improperly ;).
Thanks for sharing idea!

I can share not only the idea but also the source code.


import math
import sys
import random
import itertools
import png


def chunks(l, n):
    n = max(1, n)
    return [l[i:i + n] for i in range(0, len(l), n)]

L=[]
Lm=0.0

for z in range (2**8):
    if z<128.0: L.append(2*math.pi*(1.0-z/127.0)*((z/127.0)**0.5))
    else: L.append(2*math.pi*(z-127.0)/128.0*(((z-128.0)/127.0)**0.5)/127.0)
    Lm+=math.floor(L[z]*1024.0)

M=[]

workaroundvalue=1.8

for z in range (2**16):
    y=int(math.ceil(L[int(math.floor(z%(2.0**8)))]*1024.0/Lm*(2.0**10)) * math.ceil(L[int(math.floor(z/(2.0**8)))]*1024.0/Lm*(2.0**10) - workaroundvalue))
    y=[0, y][0 < y]
    M.append(y)

S=[]
T=[]

for z in range (2**16):
    S.extend([int(255.0-z%256.0)]*M[z])
    T.extend([int(255.0-math.floor(z/256.0))]*M[z])

#print S
#print len(S)
U=list(range(len(S)))
random.shuffle(U)
#workaround
U=U*2
U=U[0:1048576]
random.shuffle(U)
#workaround
#print U
V=[]
W=[]

for z in U:
    V.append(S[z])
    W.append(T[z])

#print V
#print workaroundvalue, len(V)
X=[0]*1048576
Y=list(zip(V, W, X))
Y=list(itertools.chain(*Y))
p=chunks(Y,(1024*3))
print(p)
print(len(p))
f = open('blenderhack.png', 'wb')
w = png.Writer(1024, 1024)
w.write(f, p)
f.close()

Added untested code:


import math
import sys
import random
import itertools
import png


def chunks(l, n):
    n = max(1, n)
    return [l[i:i + n] for i in range(0, len(l), n)]

L=[]
Lm=0.0

for z in range (2**8):
    if z<128.0: L.append(2*math.pi*(1.0-z/127.0)*((z/127.0)**0.5))
    else: L.append(2*math.pi*(z-127.0)/128.0*(((z-128.0)/127.0)**0.5)/127.0)
    Lm+=math.floor(L[z]*1024.0)

M=[]

bias=1.8

for z in range (2**16):
    y=int(math.ceil(L[int(math.floor(z%(2.0**8)))]*1024.0/Lm*(2.0**10)) *  math.ceil(L[int(math.floor(z/(2.0**8)))]*1024.0/Lm*(2.0**10) -  bias))
    y=max(0,y)
    M.append(y)

S=[]
T=[]

for z in range (2**16):
    S.extend([int(255.0-z%256.0)]*M[z])
    T.extend([int(255.0-math.floor(z/256.0))]*M[z])

#print bias, len(S)
U=list(range(len(S)))
U=U*2
random.shuffle(U)
U=U[0:1048576]
#print U
V=[]
W=[]

for z in U:
    V.append(S[z])
    W.append(T[z])

X=[0]*1048576
Y=list(zip(V, W, X))
Y=list(itertools.chain(*Y))
p=chunks(Y,(1024*3))
print(p)
print(len(p))
f = open('blenderhack.png', 'wb')
w = png.Writer(1024, 1024)
w.write(f, p)
f.close()

Probably may be done even faster. I didn’t tried. (or haven’t?)
Added: probably the optimization won’t work. The trouble is in original example most of values used 1 times, some 2 and none 0. In optimized - most 2, some 0 and 1, what is bad.
Added: have noticed that 2*math.pi is extra action. There is no sin function. Originally it was, and it’s a sine-based blur. But now it’s done in another way based on 0…1 sine is (x/math.pi)**.5 .

I can see how this is a workaround to create a blur effect, but I’m not sure how the exploit comes in. Care to explain further?

I would be interested in a bit more explanation also. Lack of blur is an issue sometimes.

Hey, that’s generous! Thanks a lot!
I was already looking for the formulas to be honest and there’s the code :D.

Workaround is for fitting the value to 1048576. First, I’m subtracting 1.8 from each factor to control that integer sum of all factors will be close to 1048576. Then range, multiply range by 2, shuffle range, cut range to 1048576. It’s a bias. Renamed.

Sorry for the mess. Was editing the message with disabled javascript. Whew.

import math
import random
import itertools
import png

#trying to tidy the code

def chunks(list, count):
    count = max(1, count)
    return 
[list[i:i + count] for i in range(0, len(list), count)]

depth=8.0
space=2.0**depth
spaceless=space-1.0
spacehalf=space/2.0
spacehalfless=spacehalf-1.0
SineList=[]
SineListSum=0.0
precise=10.0
width=2.0**precise

for z in range (int(space)):
    if z<spacehalf: SineList.append((1.0-z/spacehalfless)*((z/spacehalfless)**0.5))
    else: SineList.append((z-spacehalfless)/spacehalf*(((z-spacehalf)/spacehalfless)**0.5)/spacehalfless)
    SineListSum+=math.floor(SineList[z]*width)

Chance=[]

bias=1.85

for z in range (int(space**2)):
    y=int(math.ceil(SineList[int(math.floor(z%(space)))]*width/SineListSum*width) * math.ceil(SineList[int(math.floor(z/(space)))]*width/SineListSum*width - bias))
    y=max(0, y)
    Chance.append(y)

Xunshuffled=[]
Yunshuffled=[]

for z in range (int(space**2)):
    Xunshuffled.extend([int(spaceless-z%space)]*Chance[z])
    Yunshuffled.extend([int(spaceless-math.floor(z/space))]*Chance[z])

#print Xunshuffled
print(bias, len(Xunshuffled))
ShuffleGen=list(range(len(Xunshuffled)))
random.shuffle(ShuffleGen)
ShuffleGen=ShuffleGen*2
ShuffleGen=ShuffleGen[:int(width**2)]
random.shuffle(ShuffleGen)
#print ShuffleGen
X=[]
Y=[]

for z in ShuffleGen:
    X.append(Xunshuffled[z])
    Y.append(Yunshuffled[z])

#print X
Z=[0]*int(width**2)
Image=list(zip(X, Y, Z))
Image=list(itertools.chain(*Image))
ImageSplit=chunks(Image,(int(width)*3))
#print(ImageSplit)
#print(len(ImageSplit))
File = open('blenderhack.png', 'wb')
Writer = png.Writer(int(width), int(width))
Writer.write(File, ImageSplit)
File.close()