Last active
December 25, 2019 19:58
-
-
Save hwhw/814a17a5cdbccc26ca558726aa83c5aa to your computer and use it in GitHub Desktop.
Pixelblaster_v6 by @HIlse
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
Pixelblaster_v6 by @hilse | |
Needs LuaJIT & ljsyscall (syscall.lua & syscall/...) | |
and lodepng | |
This is a perfect example on how to not do things correctly while still using Lua. | |
Run this with enough rights to send raw packets | |
Usage: | |
24bpp RGB from stdin (optionally, a continuous stream): | |
luajit flut.lua <interface> <our MAC> <our IPv6> <target/router MAC> <target IPv6> <xoffs> <yoffs> <width> <height> [cont] | |
PNG (alpha aware): | |
luajit flut.lua <interface> <our MAC> <our IPv6> <target/router MAC> <target IPv6> <xoffs> <yoffs> image.png | |
License: WAGTD 1.0 | |
§1: We're all going to die. | |
Changelog: | |
- now supports PNG & Alpha | |
- IPv6 now without any payload at all: 54 byte on ethernet layer - a whopping 12% increase in productivity! | |
--]] | |
local ffi=require"ffi" | |
local bit=require"bit" | |
local S=require"syscall" | |
ffi.cdef"unsigned int lodepng_decode32_file(unsigned char **, unsigned int *, unsigned int *, const char *);" | |
-- compile lodepng: gcc -shared -fPIC -o lodepng.so -c lodepng.c | |
local lodepng=ffi.load("./lodepng.so") | |
-- mwahahahahaha! | |
local s = S.socket(S.c.AF.PACKET,S.c.SOCK.RAW,S.c.IPPROTO.RAW) | |
-- interface index | |
local if_idx = S.util.if_nametoindex(arg[1],s) | |
local sll_dest = S.t.sockaddr_ll{ifindex=if_idx, addr=S.t.macaddr(arg[4])} | |
-- we build ourselves a nice and shiny package | |
local sbuf_l = 54 | |
local sbuf = ffi.new("uint8_t[?]", sbuf_l) | |
ffi.copy(sbuf, sll_dest.addr, 6) | |
ffi.copy(sbuf + 6, S.t.macaddr(arg[2]), 6) | |
sbuf[12]=0x86 | |
sbuf[13]=0xDD | |
sbuf[14]=0x60 | |
sbuf[15]=0 | |
sbuf[16]=0x48 -- H | |
sbuf[17]=0x57 -- W | |
sbuf[18]=0 -- packet length | |
sbuf[19]=0 -- packet length | |
sbuf[20]=59 -- next header: UDP | |
sbuf[21]=0xFF -- hop limit | |
ffi.copy(sbuf+22, S.t.in6_addr(arg[3]), 16) | |
ffi.copy(sbuf+38, S.t.in6_addr(arg[5]), 16) | |
local function set_px(x, y, r, g, b, a) | |
sbuf[46] = bit.rshift(x, 8) | |
sbuf[47] = bit.band(x, 255) | |
sbuf[48] = bit.rshift(y, 8) | |
sbuf[49] = bit.band(y, 255) | |
sbuf[50] = r | |
sbuf[51] = g | |
sbuf[52] = b | |
sbuf[53] = a | |
S.sendto(s, sbuf, sbuf_l, 0, sll_dest, ffi.sizeof(sll_dest)) | |
end | |
local dx=arg[6] | |
local dy=arg[7] | |
local w, h | |
local pic | |
local lframe = function() end | |
local bpp = 24 | |
if tonumber(arg[8]) and tonumber(arg[8]) > 0 then | |
w=arg[8] | |
h=arg[9] | |
-- read data from... stdin | |
pic=ffi.new("uint8_t[?]", w*h*3) | |
-- read one frame: | |
lframe = function() | |
local r = w*h*3 | |
local d = 0 | |
while true do | |
if(d == r) then return end | |
local res = S.read(0, pic+d, r-d) | |
if(res > 0) then | |
d = d + res | |
end | |
end | |
end | |
lframe() | |
else | |
bpp=32 | |
pic=ffi.new("uint8_t*[1]") | |
w = ffi.new("unsigned int[1]") | |
h = ffi.new("unsigned int[1]") | |
local err=lodepng.lodepng_decode32_file(pic, w, h, arg[8]) | |
if err>0 then | |
print("error opening file:", err) | |
os.exit(1) | |
end | |
w = w[0] | |
h = h[0] | |
pic = pic[0] | |
end | |
local function get_px(x, y) | |
local c | |
local a | |
if bpp==24 then | |
c = (y*w+x)*3 | |
a = 255 | |
elseif bpp==32 then | |
c = (y*w+x)*4 | |
a = pic[c+3] | |
end | |
return pic[c], pic[c+1], pic[c+2], a | |
end | |
local t=ffi.new("uint32_t[?]", w*h) | |
local act_px = w*h | |
local c=0 | |
for y=0,h-1 do | |
for x=0,w-1 do | |
local r,g,b,a = get_px(x, y) | |
if a==0 then | |
act_px = act_px - 1 | |
else | |
t[c]=bit.bor(bit.lshift(y, 16), x) | |
c=c+1 | |
end | |
end | |
end | |
-- Fisher - Yates shuffle: | |
math.randomseed(os.time()) | |
for i=act_px, 1, -1 do | |
local j=math.random(i) | |
t[i], t[j] = t[j], t[i] | |
end | |
-- one loop: | |
local function play() | |
-- send pic | |
for p=0,act_px-1 do | |
local x = bit.band(t[p], 0xffff) | |
local y = bit.rshift(t[p], 16) | |
local r,g,b,a = get_px(x, y) | |
if a > 0 then | |
set_px(dx+x, dy+y, r,g,b,a) | |
end | |
end | |
if arg[10] == "cont" then | |
-- continuous reading (e.g. from ffmpeg) | |
lframe() | |
end | |
end | |
while true do | |
play() | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment