13.04.2022, 12:02
Try this, change PASS and IP as needed. The script handles the authentication part, after that you can issue commands, read status info etc.
Code:
function calcpass(pass, nonce)
local flag = true
local num1 = 0
local num2 = 0
local password = tonumber(pass, 10)
for i = 1, #nonce do
local c = nonce:sub(i, i)
if c ~= '0' then
if flag then
num2 = password
end
flag = false
end
if c == '1' then
num1 = bit.band(num2, 0xFFFFFF80)
num1 = bit.rshift(num1, 7)
num2 = bit.lshift(num2, 25)
num1 = num1 + num2
elseif c == '2' then
num1 = bit.band(num2, 0xFFFFFFF0)
num1 = bit.rshift(num1, 4)
num2 = bit.lshift(num2, 28)
num1 = num1 + num2
elseif c == '3' then
num1 = bit.band(num2, 0xFFFFFFF8)
num1 = bit.rshift(num1, 3)
num2 = bit.lshift(num2, 29)
num1 = num1 + num2
elseif c == '4' then
num1 = bit.lshift(num2, 1)
num2 = bit.rshift(num2, 31)
num1 = num1 + num2
elseif c == '5' then
num1 = bit.lshift(num2, 5)
num2 = bit.rshift(num2, 27)
num1 = num1 + num2
elseif c == '6' then
num1 = bit.lshift(num2, 12)
num2 = bit.rshift(num2, 20)
num1 = num1 + num2
elseif c == '7' then
num1 = bit.band(num2, 0x0000FF00)
num1 = num1 + bit.lshift(bit.band(num2, 0x000000FF), 24)
num1 = num1 + bit.rshift(bit.band(num2, 0x00FF0000), 16)
num2 = bit.rshift(bit.band(num2, 0xFF000000), 8)
num1 = num1 + num2
elseif c == '8' then
num1 = bit.band(num2, 0x0000FFFF)
num1 = bit.lshift(num1, 16)
num1 = num1 + bit.rshift(num2, 24)
num2 = bit.band(num2, 0x00FF0000)
num2 = bit.rshift(num2, 8)
num1 = num1 + num2
elseif c == '9' then
num1 = bit.bnot(num2)
elseif c == '0' then
num1 = num2
end
num2 = num1
end
if num1 < 0 then
num1 = num1 + 4294967296
end
return tostring(num1)
end
function read(sock)
local buf = {}
while true do
local ch, err = sock:receive(1)
if ch then
local pr = buf[ #buf ]
buf[ #buf + 1 ] = ch
if ch == '#' and pr == '#' then
break
end
else
return nil, err
end
end
return table.concat(buf)
end
ACK = '*#*1##'
NACK = '*#*0##'
OPEN = '*99*0##'
PASS = '12345'
IP = '127.0.0.1'
PORT = 20000
function openwebnetinit()
local sock = require('socket').tcp()
local res, err
sock:settimeout(1)
res, err = sock:connect(IP, PORT)
if not res then
alert('connect failed ' .. tostring(err))
return
end
res, err = read(sock)
if res ~= ACK then
alert('no initial ack ' .. tostring(res or err))
return
end
sock:send(OPEN)
res, err = read(sock)
if not res then
alert('no nonce ' .. tostring(err))
return
end
local nonce = res:match('%d+')
local pass = calcpass(PASS, nonce)
sock:send('*#' .. pass .. '##')
res, err = read(sock)
if res ~= ACK then
alert('auth failed ' .. tostring(res or err))
return
end
return sock
end
sock = openwebnetinit()
if sock then
alert('connection ok')
-- do something here
sock:close()
end