import ctypes from copy import deepcopy from datetime import datetime from random import choice, randint import pytz import requests from apscheduler.schedulers.blocking import BlockingScheduler URL = 'http://192.168.88.1/jsproxy' HEADERS = { 'Accept-Language': '', 'Content-Type': 'msg', 'Cookie': 'username=root', } def int_overflow(val) -> int: maxint = 2147483647 if not -maxint - 1 <= val <= maxint: val = (val + (maxint + 1)) % (2 * (maxint + 1)) - maxint - 1 return val & 0xFFFFFFFF def unsigned_right_shift(n, i) -> int: """实现无符号右移""" if n < 0: n = ctypes.c_uint32(n).value if i < 0: return -int_overflow(n << abs(i)) return int_overflow(n >> i) class Buffer(object): def __init__(self) -> None: self.MASK_FTYPE = 0xf8000000 self.FT_BOOL = int_overflow(0 << 27) self.FT_U32 = int_overflow(1 << 27) self.FT_U64 = int_overflow(2 << 27) self.FT_ADDR6 = int_overflow(3 << 27) self.FT_STRING = int_overflow(4 << 27) self.FT_MESSAGE = int_overflow(5 << 27) self.FT_RAW = int_overflow(6 << 27) self.FT_BOOL_ARRAY = int_overflow(16 << 27) self.FT_U32_ARRAY = int_overflow(17 << 27) self.FT_U64_ARRAY = int_overflow(18 << 27) self.FT_ADDR6_ARRAY = int_overflow(19 << 27) self.FT_STRING_ARRAY = int_overflow(20 << 27) self.FT_MESSAGE_ARRAY = int_overflow(21 << 27) self.FT_RAW_ARRAY = int_overflow(22 << 27) self.FS_SHORT = int_overflow(1 << 24) self.arr = [0] * 64 * 1024 self.pos = 0 def msg2buffer(self, msg): self.arr[self.pos] = 0x4d self.pos += 1 self.arr[self.pos] = 0x32 self.pos += 1 for r in msg: pfx = r[0] if pfx == '_': continue val = msg[r] if pfx == 'b': self.write_id(self.FT_BOOL | ( self.FS_SHORT if val else 0), r) elif pfx == 'u': val = val if val is not None else -1 if 0 <= val < 256: self.write_id(self.FT_U32 | self.FS_SHORT, r) self.arr[self.pos] = val self.pos += 1 else: self.write_id(self.FT_U32, r) self.write_32(val) elif pfx == 'q': self.write_id(self.FT_U64, r) self.write_64(val) elif pfx == 'a': self.write_id(self.FT_ADDR6, r) for i in range(16): self.arr[self.pos] = val[i] self.pos += 1 elif pfx == 's': if len(val) < 256: self.write_id(self.FT_STRING | self.FS_SHORT, r) self.arr[self.pos] = len(val) self.pos += 1 else: self.write_id(self.FT_STRING, r) self.write_16(len(val)) for i in range(len(val)): self.arr[self.pos] = ord(val[i]) self.pos += 1 elif pfx == 'r': if len(val) < 256: self.write_id(self.FT_RAW | self.FS_SHORT, r) self.arr[self.pos] = len(val) self.pos += 1 else: self.write_id(self.FT_RAW, r) self.write_16(len(val)) for i in range(len(val)): self.arr[self.pos] = val[i] self.pos += 1 elif pfx == 'm': x = self.msg2buffer(val) if len(x) < 256: self.write_id(self.FT_MESSAGE | self.FS_SHORT, r) self.arr[self.pos] = len(x) self.pos += 1 else: self.write_id(self.FT_MESSAGE, r) self.write_16(len(x)) for item in x[::-1]: self.arr[self.pos] = item self.pos += len(x) elif pfx == 'B': self.write_id(self.FT_BOOL_ARRAY, r) self.write_16(len(val)) for i in range(len(val)): self.arr[self.pos] = val[i] self.pos += 1 elif pfx == 'U': self.write_id(self.FT_U32_ARRAY, r) self.write_16(len(val)) for i in range(len(val)): self.write_32(val[i]) elif pfx == 'Q': self.write_id(self.FT_U64_ARRAY, r) self.write_16(len(val)) for i in range(len(val)): self.write_64(val[i]) elif pfx == 'A': self.write_id(self.FT_ADDR6_ARRAY, r) self.write_16(len(val)) for i in range(len(val)): for k in range(16): self.arr[self.pos] = val[i][k] self.pos += 1 elif pfx == 'S': self.write_id(self.FT_STRING_ARRAY, r) self.write_16(len(val)) for i in range(len(val)): self.write_16(len(val[i])) for k in range(len(val[i])): self.arr[self.pos] = ord(val[i][k]) self.pos += 1 elif pfx == 'R': self.write_id(self.FT_RAW_ARRAY, r) self.write_16(len(val)) for i in range(len(val)): self.write_16(len(val[i])) for k in range(len(val[i])): self.arr[self.pos] = val[i][k] self.pos += 1 elif pfx == 'M': self.write_id(self.FT_MESSAGE_ARRAY, r) self.write_16(len(val)) for i in range(len(val)): x = self.msg2buffer(val[i]) self.write_16(len(x)) for item in x[::-1]: self.arr[self.pos] = item self.pos += len(x) return self.arr[:self.pos] def buffer2msg(self, arr, offset: int = 0): self.arr, self.pos, ret = arr, 2, dict() if self.arr[0] != 0x4d or self.arr[1] != 0x32: return ret while self.pos < len(self.arr): _id = self.read_32() if _id & self.MASK_FTYPE == self.FT_BOOL: ret['b' + self.idnum2hex(_id)] = 1 if (_id & self.FS_SHORT) else 0 elif _id & self.MASK_FTYPE == self.FT_U32: if _id & self.FS_SHORT: ret['u' + self.idnum2hex(_id)] = self.arr[self.pos] self.pos += 1 else: ret['u' + self.idnum2hex(_id) ] = self.int2num(self.read_32()) elif _id & self.MASK_FTYPE == self.FT_U64: ret['q' + self.idnum2hex(_id)] = self.read_64() elif _id & self.MASK_FTYPE == self.FT_ADDR6: a = [] for i in range(16): a[i] = self.arr[self.pos] self.pos += 1 ret['a' + self.idnum2hex(_id)] = a elif _id & self.MASK_FTYPE == self.FT_STRING: length = self.arr[self.pos] self.pos += 1 if not (_id & self.FS_SHORT): length |= self.arr[self.pos] << 8 self.pos += 1 s = '' for i in range(length): s = s + chr(self.arr[self.pos]) self.pos += 1 ret['s' + self.idnum2hex(_id)] = s elif _id & self.MASK_FTYPE == self.FT_RAW: length = self.arr[self.pos] self.pos += 1 if not (_id & self.FS_SHORT): length |= self.arr[self.pos] << 8 self.pos += 1 a = [0] * length for i in range(length): a[i] = self.arr[self.pos] self.pos += 1 ret['r' + self.idnum2hex(_id)] = a elif _id & self.MASK_FTYPE == self.FT_MESSAGE: length = self.arr[self.pos] self.pos += 1 if not (_id & self.FS_SHORT): length |= self.arr[self.pos] << 8 self.pos += 1 ret['m' + self.idnum2hex(_id)] = self.buffer2msg( self.arr[offset + self.pos:offset + self.pos + length]) self.pos += length offset += self.pos elif _id & self.MASK_FTYPE == self.FT_BOOL_ARRAY: length = self.read_16() a = [0] * length for i in range(length): a[i] = not (not self.arr[self.pos]) self.pos += 1 ret['B' + self.idnum2hex(_id)] = a elif _id & self.MASK_FTYPE == self.FT_U32_ARRAY: length = self.read_16() a = [0] * length for i in range(length): a[i] = self.int2num(self.read_32()) ret['U' + self.idnum2hex(_id)] = a elif _id & self.MASK_FTYPE == self.FT_U64_ARRAY: length = self.read_16() a = [0] * length for i in range(length): a[i] = self.read_64() ret['Q' + self.idnum2hex(_id)] = a elif _id & self.MASK_FTYPE == self.FT_ADDR6_ARRAY: length = self.read_16() a = [0] * length for i in range(length): x = [0] * 16 for k in range(16): x[k] = self.arr[self.pos] self.pos += 1 a[i] = x ret['A' + self.idnum2hex(_id)] = a elif _id & self.MASK_FTYPE == self.FT_STRING_ARRAY: length = self.read_16() a = [0] * length for i in range(length): x = '' x_len = self.read_16() for k in range(x_len): x = x + chr(self.arr[self.pos]) self.pos += 1 a[i] = x ret['S' + self.idnum2hex(_id)] = a elif _id & self.MASK_FTYPE == self.FT_RAW_ARRAY: length = self.read_16() a = [0] * length for i in range(length): x_len = self.read_16() x = [0] * x_len for k in range(x_len): x[k] = self.arr[self.pos] self.pos += 1 a[i] = x ret['R' + self.idnum2hex(_id)] = a elif _id & self.MASK_FTYPE == self.FT_MESSAGE_ARRAY: length = self.read_16() a = [0] * length for i in range(length): x_len = self.read_16() a[i] = self.buffer2msg(self.arr[offset + self.pos:offset + self.pos + x_len], offset + self.pos) self.pos += x_len offset += self.pos ret['M' + self.idnum2hex(_id)] = a return ret def buffer2msgs(self, arr, offset: int = 0): ret, pos = [], 0 while pos + 2 <= len(arr): length = (arr[pos] << 8) | arr[pos + 1] arr[pos] = 0x4d arr[pos + 1] = 0x32 msg = self.buffer2msg(arr[:offset + pos + length], offset + pos) pos += length ret.append(msg) return ret def write_id(self, id_type, id_str): x = int(id_str[1:], 16) self.arr[self.pos] = x & 0xff self.pos += 1 self.arr[self.pos] = (x >> 8) & 0xff self.pos += 1 self.arr[self.pos] = (x >> 16) & 0xff self.pos += 1 self.arr[self.pos] = (id_type >> 24) & 0xff self.pos += 1 def write_16(self, val): self.arr[self.pos] = val & 0xff self.pos += 1 self.arr[self.pos] = (val >> 8) & 0xff self.pos += 1 def write_32(self, val): for i in range(4): self.arr[self.pos] = (val >> (i * 8)) & 0xff self.pos += 1 def write_64(self, val): for i in range(4): self.arr[self.pos] = (val >> (i * 8)) & 0xff self.pos += 1 temp = int(val / 4294967296) for i in range(4): self.arr[self.pos] = (temp >> (i * 8)) & 0xff self.pos += 1 def num2hex(self, ccc): if ccc < 10: return chr(ccc + 48) return chr(ccc + 87) def idnum2hex(self, _id): ret = '' for i in range(6): x = (_id >> (20 - (i * 4))) & 0xf if len(ret) == 0 and not x: continue ret = ret + self.num2hex(x) if len(ret) == 0: ret = '0' return ret def read_16(self): ret = 0 for i in range(2): ret |= int_overflow(self.arr[self.pos] << (i * 8)) self.pos += 1 return ret def read_32(self): ret = 0 for i in range(4): ret |= int_overflow(self.arr[self.pos] << (i * 8)) self.pos += 1 return ret def read_64(self): ret = 0 for i in range(4): ret |= int_overflow(self.arr[self.pos] << (i * 8)) self.pos += 1 temp = 0 for i in range(4): temp |= int_overflow(self.arr[self.pos] << (i * 8)) self.pos += 1 return self.int2num(ret) + temp * 4294967296 def int2num(self, v): return 0x100000000 + v if v < 0 else v class Curve(object): @classmethod def curve_a2u(cls, a): r = [0] * 32 for i in range(32): r[i >> 1] |= a[31 - i] << (i & 1) * 8 return r @classmethod def curve_u2a(cls, a): r = [0] * 32 for i in range(32): r[31 - i] = (a[i >> 1] >> ((i & 1) * 8)) & 0xff return r @classmethod def byte2str(cls, b): b &= 0xff return chr(b if b else 256) @classmethod def word2str(cls, w): return cls.byte2str(w >> 24) + cls.byte2str(w >> 16) + cls.byte2str(w >> 8) + cls.byte2str(w) @classmethod def str2byte(cls, s, off): return s[off] & 0xff @classmethod def str2word(cls, s, off): return int_overflow(cls.str2byte(s, off) << 24) | int_overflow(cls.str2byte(s, off + 1) << 16) | int_overflow( cls.str2byte(s, off + 2) << 8) | int_overflow(cls.str2byte(s, off + 3)) @classmethod def str2a(cls, s): res = [] for i in range(len(s)): res.append(s[i] & 0xff) return res @classmethod def a2str(cls, a): x = [] for i in range(len(a)): x.append(cls.byte2str(a[i])) return ''.join(x) @classmethod def c255lgetbit(cls, n, c): return (n[c >> 4] >> (c & 0xf)) & 1 @classmethod def c255lzero(cls): return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] @classmethod def c255lone(cls): return [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] @classmethod def c255lbase(cls): return [9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] @classmethod def c255lsqr8h(cls, a7, a6, a5, a4, a3, a2, a1, a0): r = [0] * 16 v = a0 * a0 r[0] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a0 * a1 r[1] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a0 * a2 + a1 * a1 r[2] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a0 * a3 + 2 * a1 * a2 r[3] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a0 * a4 + 2 * a1 * a3 + a2 * a2 r[4] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a0 * a5 + 2 * a1 * a4 + 2 * a2 * a3 r[5] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a0 * a6 + \ 2 * a1 * a5 + 2 * a2 * a4 + a3 * a3 r[6] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a0 * a7 + \ 2 * a1 * a6 + 2 * a2 * a5 + 2 * a3 * a4 r[7] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a1 * a7 + \ 2 * a2 * a6 + 2 * a3 * a5 + a4 * a4 r[8] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a2 * a7 + 2 * a3 * a6 + 2 * a4 * a5 r[9] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a3 * a7 + 2 * a4 * a6 + a5 * a5 r[10] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a4 * a7 + 2 * a5 * a6 r[11] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a5 * a7 + a6 * a6 r[12] = v & 0xffff v = (0 | int(v / 0x10000)) + 2 * a6 * a7 r[13] = v & 0xffff v = (0 | int(v / 0x10000)) + a7 * a7 r[14] = v & 0xffff r[15] = 0 | int(v / 0x10000) return r @classmethod def c255lsqrmodp(cls, a): x = cls.c255lsqr8h(a[15], a[14], a[13], a[12], a[11], a[10], a[9], a[8]) z = cls.c255lsqr8h(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0]) y = cls.c255lsqr8h(a[15] + a[7], a[14] + a[6], a[13] + a[5], a[12] + a[4], a[11] + a[3], a[10] + a[2], a[9] + a[1], a[8] + a[0]) r = [0] * 16 v = 0x800000 + z[0] + (y[8] - x[8] - z[8] + x[0] - 0x80) * 38 r[0] = v & 0xffff for i in range(1, 8): v = 0x7fff80 + \ unsigned_right_shift( v, 16) + z[i] + (y[i + 8] - x[i + 8] - z[i + 8] + x[i]) * 38 r[i] = v & 0xffff for i in range(8, 15): v = 0x7fff80 + \ unsigned_right_shift( v, 16) + z[i] + y[i - 8] - x[i - 8] - z[i - 8] + x[i] * 38 r[i] = v & 0xffff r[15] = 0x7fff80 + \ unsigned_right_shift(v, 16) + \ z[15] + y[7] - x[7] - z[7] + x[15] * 38 cls.c255lreduce(r) return r @classmethod def c255lmul8h(cls, a7, a6, a5, a4, a3, a2, a1, a0, b7, b6, b5, b4, b3, b2, b1, b0): r = [0] * 16 v = a0 * b0 r[0] = v & 0xffff v = (0 | int(v / 0x10000)) + a0 * b1 + a1 * b0 r[1] = v & 0xffff v = (0 | int(v / 0x10000)) + a0 * b2 + a1 * b1 + a2 * b0 r[2] = v & 0xffff v = (0 | int(v / 0x10000)) + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0 r[3] = v & 0xffff v = (0 | int(v / 0x10000)) + a0 * b4 + \ a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0 r[4] = v & 0xffff v = (0 | int(v / 0x10000)) + a0 * b5 + a1 * \ b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0 r[5] = v & 0xffff v = (0 | int(v / 0x10000)) + a0 * b6 + a1 * b5 + \ a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0 r[6] = v & 0xffff v = (0 | int(v / 0x10000)) + a0 * b7 + a1 * b6 + a2 * \ b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0 r[7] = v & 0xffff v = (0 | int(v / 0x10000)) + a1 * b7 + a2 * b6 + \ a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1 r[8] = v & 0xffff v = (0 | int(v / 0x10000)) + a2 * b7 + a3 * \ b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2 r[9] = v & 0xffff v = (0 | int(v / 0x10000)) + a3 * b7 + \ a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3 r[10] = v & 0xffff v = (0 | int(v / 0x10000)) + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4 r[11] = v & 0xffff v = (0 | int(v / 0x10000)) + a5 * b7 + a6 * b6 + a7 * b5 r[12] = v & 0xffff v = (0 | int(v / 0x10000)) + a6 * b7 + a7 * b6 r[13] = v & 0xffff v = (0 | int(v / 0x10000)) + a7 * b7 r[14] = v & 0xffff r[15] = 0 | int(v / 0x10000) return r @classmethod def c255lmulmodp(cls, a, b): x = cls.c255lmul8h(a[15], a[14], a[13], a[12], a[11], a[10], a[9], a[8], b[15], b[14], b[13], b[12], b[11], b[10], b[9], b[8]) z = cls.c255lmul8h(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0], b[7], b[6], b[5], b[4], b[3], b[2], b[1], b[0]) y = cls.c255lmul8h(a[15] + a[7], a[14] + a[6], a[13] + a[5], a[12] + a[4], a[11] + a[3], a[10] + a[2], a[9] + a[1], a[8] + a[0], b[15] + b[7], b[14] + b[6], b[13] + b[5], b[12] + b[4], b[11] + b[3], b[10] + b[2], b[9] + b[1], b[8] + b[0]) r = [0] * 16 v = 0x800000 + z[0] + (y[8] - x[8] - z[8] + x[0] - 0x80) * 38 r[0] = v & 0xffff for i in range(1, 8): v = 0x7fff80 + \ unsigned_right_shift( v, 16) + z[i] + (y[i + 8] - x[i + 8] - z[i + 8] + x[i]) * 38 r[i] = v & 0xffff for i in range(8, 15): v = 0x7fff80 + \ unsigned_right_shift( v, 16) + z[i] + y[i - 8] - x[i - 8] - z[i - 8] + x[i] * 38 r[i] = v & 0xffff r[15] = 0x7fff80 + \ unsigned_right_shift(v, 16) + \ z[15] + y[7] - x[7] - z[7] + x[15] * 38 cls.c255lreduce(r) return r @classmethod def c255lreduce(cls, a): v = a[15] a[15] = v & 0x7fff v = (0 | int(v / 0x8000)) * 19 for i in range(15): v += a[i] a[i] = v & 0xffff v = unsigned_right_shift(v, 16) a[15] += v @classmethod def c255laddmodp(cls, a, b): r = [0] * 16 v = ((0 | unsigned_right_shift( a[15], 15)) + (0 | unsigned_right_shift(b[15], 15))) * 19 + a[0] + b[0] r[0] = v & 0xffff for i in range(1, 15): v = unsigned_right_shift(v, 16) + a[i] + b[i] r[i] = v & 0xffff r[15] = unsigned_right_shift( v, 16) + (a[15] & 0x7fff) + (b[15] & 0x7fff) return r @classmethod def c255lsubmodp(cls, a, b): r = [0] * 16 v = 0x80000 + ((0 | unsigned_right_shift(a[15], 15)) - ( 0 | unsigned_right_shift(b[15], 15)) - 1) * 19 + a[0] - b[0] r[0] = v & 0xffff for i in range(1, 15): v = unsigned_right_shift(v, 16) + 0x7fff8 + a[i] - b[i] r[i] = v & 0xffff r[15] = unsigned_right_shift( v, 16) + 0x7ff8 + (a[15] & 0x7fff) - (b[15] & 0x7fff) return r @classmethod def c255linvmodp(cls, a): c, i = a, 249 while i > 0: i -= 1 a = cls.c255lsqrmodp(a) a = cls.c255lmulmodp(a, c) a = cls.c255lsqrmodp(a) a = cls.c255lsqrmodp(a) a = cls.c255lmulmodp(a, c) a = cls.c255lsqrmodp(a) a = cls.c255lsqrmodp(a) a = cls.c255lmulmodp(a, c) a = cls.c255lsqrmodp(a) a = cls.c255lmulmodp(a, c) return a @classmethod def c255lmulasmall(cls, a): m, r = 121665, [0] * 16 v = a[0] * m r[0] = v & 0xffff for i in range(1, 15): v = (0 | int(v / 0x10000)) + a[i] * m r[i] = v & 0xffff r[15] = (0 | int(v / 0x10000)) + a[15] * m cls.c255lreduce(r) return r @classmethod def c255ldbl(cls, x, z): m = cls.c255lsqrmodp(cls.c255laddmodp(x, z)) n = cls.c255lsqrmodp(cls.c255lsubmodp(x, z)) o = cls.c255lsubmodp(m, n) x_2 = cls.c255lmulmodp(n, m) z_2 = cls.c255lmulmodp(cls.c255laddmodp(cls.c255lmulasmall(o), m), o) return [x_2, z_2] @classmethod def c255lsum(cls, x, z, x_p, z_p, x_1): p = cls.c255lmulmodp(cls.c255lsubmodp( x, z), cls.c255laddmodp(x_p, z_p)) q = cls.c255lmulmodp(cls.c255laddmodp( x, z), cls.c255lsubmodp(x_p, z_p)) x_3 = cls.c255lsqrmodp(cls.c255laddmodp(p, q)) z_3 = cls.c255lmulmodp(cls.c255lsqrmodp(cls.c255lsubmodp(p, q)), x_1) return [x_3, z_3] @classmethod def curve25519_raw(cls, f, c): x_1 = c a = cls.c255ldbl(x_1, cls.c255lone()) q = [deepcopy(x_1), cls.c255lone()] n = 255 while cls.c255lgetbit(f, n) == 0: n -= 1 if n < 0: return cls.c255lzero() n -= 1 while n >= 0: b = cls.c255lgetbit(f, n) a_or_q = [[0] * 16, [0] * 16] cls.cond_copy(a_or_q[0], q[0], a[0], b) cls.cond_copy(a_or_q[1], q[1], a[1], b) r = cls.c255lsum(a[0], a[1], q[0], q[1], x_1) s = cls.c255ldbl(a_or_q[0], a_or_q[1]) cls.cond_copy(q[0], s[0], r[0], b) cls.cond_copy(q[1], s[1], r[1], b) cls.cond_copy(a[0], r[0], s[0], b) cls.cond_copy(a[1], r[1], s[1], b) n -= 1 q[1] = cls.c255linvmodp(q[1]) q[0] = cls.c255lmulmodp(q[0], q[1]) cls.c255lreduce(q[0]) return q[0] @classmethod def cond_copy(cls, r, a, b, c): m2 = (-c) & 0xffff m1 = (~m2) & 0xffff n = 0 while n < 16: r[n] = (a[n] & m1) | (b[n] & m2) n += 1 @classmethod def curve25519(cls, f, c: list = None): if not c: c = cls.c255lbase() f[0] &= 0xFFF8 f[15] = (f[15] & 0x7FFF) | 0x4000 c[15] &= 0x7FFF return cls.curve25519_raw(f, c) @classmethod def sha1(cls, msg): length = len(msg) total_length = length + 9 total_length = (total_length + 63) & -64 padding = [0x80] padding.extend([0 for _ in range(length + 1, total_length)]) msg.extend(padding) cls.packbe(msg, total_length - 4, length * 8) h0, h1, h2, h3, h4, w = 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0, [ 0] * 80 for j in range(0, len(msg), 64): for i in range(16): w[i] = int_overflow(cls.unpackbe(msg, j + i * 4)) for i in range(16, 80): w[i] = int_overflow(cls.rrotate( w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 31)) a, b, c, d, e = h0, h1, h2, h3, h4 for i in range(80): if i < 20: f = int_overflow((b & c) | (~b & d)) k = 0x5A827999 elif i < 40: f = int_overflow(b ^ c ^ d) k = 0x6ED9EBA1 elif i < 60: f = int_overflow((b & c) | (b & d) | (c & d)) k = 0x8F1BBCDC else: f = int_overflow(b ^ c ^ d) k = 0xCA62C1D6 t = int_overflow(Curve.rrotate(a, 27) + f + e + k + w[i]) e = d d = c c = int_overflow(Curve.rrotate(b, 2)) b = a a = int_overflow(t << 0) h0 = int_overflow((h0 + a) << 0) h1 = int_overflow((h1 + b) << 0) h2 = int_overflow((h2 + c) << 0) h3 = int_overflow((h3 + d) << 0) h4 = int_overflow((h4 + e) << 0) res = [0] * 20 Curve.packbe(res, 0, h0) Curve.packbe(res, 4, h1) Curve.packbe(res, 8, h2) Curve.packbe(res, 12, h3) Curve.packbe(res, 16, h4) return res @classmethod def rrotate(cls, v, r): return unsigned_right_shift(v, r) | (v << (32 - r)) @classmethod def unpackbe(cls, a, off): v = 0 for i in range(4): v |= a[off + i] << (24 - (i * 8)) return v @classmethod def packbe(cls, a, off, v): for i in range(4): a[off + i] = (v >> (24 - i * 8)) & 0xff class RC4(object): def __init__(self): self.S = [] self.i = 0 self.j = 0 def set_key(self, key): self.S = [i for i in range(256)] S, j = self.S, 0 for i in range(256): j = (j + key[i % len(key)] + S[i]) & 255 S[i], S[j] = S[j], S[i] for _ in range(768): self.gen() def gen(self): S = self.S i = self.i = (self.i + 1) & 255 j = self.j = (self.j + S[i]) & 255 S[i], S[j] = S[j], S[i] return S[(S[i] + S[j]) & 255] def crypt_uint8array(self, dst, src, start): for i in range(len(src)): dst[start + i] = src[i] ^ self.gen() def encrypt(self, s): a = '' for i in range(len(s)): c = s[i] ^ self.gen() if c == 0: c = 256 a += chr(c) return a class RouterSession(object): def __init__(self): self.id = None self.pri_key = None self.pub_key = None self.padding = [32] * 8 self.rx_seq = 1 self.rx_enc = RC4() self.tx_seq = 1 self.tx_enc = RC4() def make_initial_request(self): self.pri_key = bytes([randint(0, 255) for _ in range(32)]) pub_key = Curve.curve_u2a( Curve.curve25519(Curve.curve_a2u(self.pri_key))) self.pub_key = Curve.word2str( 0) + Curve.word2str(0) + Curve.a2str(pub_key) self.pub_key = self.pub_key.encode() def key_exchange(self, body): self.id = Curve.str2word(body, 0) r_pub_key = Curve.str2a(body[8:]) master_key = Curve.curve_u2a(Curve.curve25519( Curve.curve_a2u(self.pri_key), Curve.curve_a2u(r_pub_key))) self.rx_enc.set_key(self.make_key(master_key, False, False)) self.tx_enc.set_key(self.make_key(master_key, True, False)) def make_key(self, master_key, is_send, is_server): magic_2 = 'On the client side, this is the send key; on the server side, it is the receive key.' magic_3 = 'On the client side, this is the receive key; on the server side, it is the send key.' v = deepcopy(master_key) v.extend([0 for _ in range(40)]) if is_send == is_server: v.extend(Curve.str2a(magic_3.encode())) else: v.extend(Curve.str2a(magic_2.encode())) v.extend([0xf2 for _ in range(40)]) return Curve.sha1(v)[:16] def encrypt_uint8array(self, arr): narr = [0] * (len(arr) + 16) narr[1] = self.id >> 16 narr[2] = self.id >> 8 narr[3] = self.id & 0xff narr[4] = self.tx_seq >> 24 narr[5] = self.tx_seq >> 16 narr[6] = self.tx_seq >> 8 narr[7] = self.tx_seq self.tx_enc.crypt_uint8array(narr, arr, 8) for i in range(len(arr) + 8, len(narr)): narr[i] = 32 xarr = narr[len(arr) + 8:len(arr) + 16] self.tx_enc.crypt_uint8array(narr, xarr, len(arr) + 8) self.tx_seq += len(arr) + 8 return bytes(narr) def decrypt_uint8array(self, arr): if len(arr) < 16: return False _id = int_overflow(arr[0] << 24) | int_overflow(arr[1] << 16) | int_overflow(arr[2] << 8) | arr[3] seq = int_overflow(arr[4] << 24) | int_overflow(arr[5] << 16) | int_overflow(arr[6] << 8) | arr[7] if _id != self.id: return False if seq != self.rx_seq: return True self.rx_seq += len(arr) - 8 self.rx_enc.crypt_uint8array(arr, arr[8:], 8) for i in range(len(arr) - 8, len(arr)): if arr[i] != 32: return False msgs = Buffer().buffer2msgs(arr[8:len(arr) - 8], 8) if msgs: for i in range(len(msgs)): print(msgs[i]) return True def encrypt(self, s): seq = self.tx_seq self.tx_seq += len(s) + 8 return (Curve.word2str(self.id) + Curve.word2str(seq)) + self.tx_enc.encrypt(s.encode()) + self.tx_enc.encrypt( self.padding) def encrypt_uri(self, uri): s = self.encrypt(uri) r = '' for i in range(len(s)): r += chr(ord(s[i]) & 0xff) return r def fetch(self, url, headers, data): data = self.encrypt_uint8array(Buffer().msg2buffer(data)) response = requests.post(url=url, headers=headers, data=data) body = list(response.content) self.decrypt_uint8array(body) def login(self): response = requests.post(url=URL, data=self.pub_key) body = [ord(item) for item in response.content.decode()] self.key_exchange(body) data = {'s1': 'root', 's3': ''} self.fetch(url=URL, headers=HEADERS, data=data) def change_vpn(self, vpn_idx, vpn_server): data = { "U1003c": [9, 0, 0, 0, 0, 0, 0, 0], "bdd": 0, "be1": 0, "be3": 0, "bfe000a": 0, "b1000e": 0, "ufe0001": vpn_idx + 48, "u10001": 34, "u10003": 0, "u10002": 16384, "uca": 1450, "ucb": 1450, "ud9": 4294967294, "udb": 30, "udc": 0, "ude": 60, "udf": 1, "sb0004": "disabled", "s10006": f"Vpn{vpn_idx}", "s1001e": "l2tp-out", "s10066": "", "se0": vpn_server, "se2": "", "sfe0009": "", "sd6": "123qqq", "sd7": "hnszs3ds", "Uff0014": [134217944], "Uff0001": [20, 0], "uff0007": 16646147 } self.fetch(url=URL, headers=HEADERS, data=data) class AdminSession(object): def __init__(self): self.username = '17600025055' self.password = 'zhangyong0712' self.headers = None def cookie2str(self, cookies): ret = [] for key, value in cookies.iteritems(): ret.append(f'{key}={value}') return '; '.join(ret) def login(self): url = 'https://hwq.yycyk.com/' self.headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Cache-Control': 'no-cache', 'Origin': 'https://hwq.yycyk.com', 'Pragma': 'no-cache', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36', } response = requests.get(url=url, headers=self.headers) self.headers.update({'Cookie': self.cookie2str(response.cookies)}) url = 'https://hwq.yycyk.com/passport/loginact' self.headers.update({ 'Accept': '*/*', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Referer': 'https://hwq.yycyk.com/passport/login', 'X-Requested-With': 'XMLHttpRequest', }) data = { 'phone': self.username, 'password': self.password, 'captcha': '', } response = requests.post(url=url, headers=self.headers, data=data) self.headers.update({'Cookie': self.cookie2str(response.cookies)}) def get_proxy_list(self): url = 'https://hwq.yycyk.com/welcome/dynamicLines' self.headers.update({'Referer': 'https://hwq.yycyk.com/welcome'}) data = { 'search_str': '', 'type': '3', } response = requests.post(url=url, headers=self.headers, data=data) obj = response.json() proxy_list = [] for item in obj.get('res', {}).get('data', {}).values(): proxy_list.append(item.get('info', {}).get('province_domain')) for sub_item in item.get('line', []): if int(sub_item.get('status', 0)) == 0: # 维护中的跳过 continue if int(sub_item.get('ping', 1000)) >= 200: # 延迟超过200ms的跳过 continue proxy_list.append(sub_item.get('domain')) return proxy_list def job(): admin_session = AdminSession() admin_session.login() vpn_server = choice(admin_session.get_proxy_list()) router_session = RouterSession() router_session.make_initial_request() router_session.login() router_session.change_vpn(vpn_idx=1, vpn_server=vpn_server) now = datetime.now(tz=pytz.timezone('Asia/Shanghai')).strftime('%Y-%m-%d %H:%M:%S') print(f'[+] {now} 切换代理地址为: {vpn_server}') def main(): scheduler = BlockingScheduler({ 'apscheduler.timezone': 'Asia/Shanghai', }) scheduler.add_job(job, 'cron', hour=12, minute=0, second=0) try: print('[+] 定时任务已启动') scheduler.start() except KeyboardInterrupt: print('[+] 定时任务已停止') if __name__ == '__main__': main()