01Editor最新破解

news2024/11/16 7:22:17

文章目录

  • 01Editor最新版注册算法逆向
    • 1.定位注册算法代码
    • 2.整体注册算法
    • 3.Check1算法分析
    • 4.Check2算法分析
    • 5.获得正确的任意用户名对应的序列号

01Editor最新版注册算法逆向

1.定位注册算法代码

【版本】 13.0.1   64 b i t \textcolor{green}{【版本】13.0.1\ 64bit} 【版本】13.0.1 64bit

注册的提示信息还有界面的提示信息很丰富,这为我们定位关键代码提供了充分的线索。将01Editor拖入IDA分析,直接字符串搜索“Thank you for purchasing 010 Editor!”就来到了关键位置( R V A = 0 x 210520 \textcolor{orange}{RVA = 0x210520} RVA=0x210520)。

2.整体注册算法

  1. 判断序列号是否包含空格,有空格就是非法的序列号

在这里插入图片描述

  1. 判断序列号格式是否符合XXXX-XXXX-XXXX-XXXX

在这里插入图片描述

  1. 对序列号进行简单的字符替换

在这里插入图片描述

  1. 进入序列号和用户名加密运算验证(*重点部分,后面再说。这里用 C h e c k 1 \textcolor{cornflowerblue}{Check1} Check1代替),会返回一个结果,这里用rs1代替。

  2. 进入第二处验证,用 C h e c k 2 \textcolor{cornflowerblue}{Check2} Check2代替,返回结果用rs2代替。

  3. 网络验证。发现最新版没有走网络验证。。。。因为有处条件永不满足

在这里插入图片描述

  1. 用rs1和rs2作为注册的最终结果进行反馈,可以确定 r s 2 = = 0 x D B \textcolor{orange}{rs2 == 0xDB} rs2==0xDB就是我们期望的结果

在这里插入图片描述

3.Check1算法分析

  1. 先判断用户名和序列号的长度均不为0才能往下验证,否则直接返回0x93

  2. 再次检查序列号格式,并按照自定义方法将序列号转成16进制的字节数组

在这里插入图片描述

  • 序列号的长度分为两种0x130x18

  • 转换结果用hb代称,hb中的每一个元素都是 serial 中除 ‘-’ 元素外的两两元素组合而成。 C h a r _ T r a n s F o r m \textcolor{cornflowerblue}{Char\_TransForm} Char_TransForm实现:

  • __int64 __fastcall Jmp_CharTransForm(__int64 a1, char a2)
    {
      if ( (unsigned __int8)(a2 - 0x30) <= 9u )
        return (unsigned int)(a2 - 0x30);
      if ( ((a2 - 'O') & 0xDF) == 0 )               // 只有a2 == 'O' 才满足,但是前面预处理的时候将'O'换成了0,
                                                    // 因此这里永不满足。
        return 0i64;
      if ( a2 == 'l' )
        return 1i64;
      if ( (unsigned __int8)(a2 - 'a') <= 0x19u )
        return a2 - (unsigned int)'W';
      if ( (unsigned __int8)(a2 - 'A') <= 0x19u )
        return a2 - (unsigned int)'7';
      else
        return 0i64;
    }
    

    注意:这个函数是多对一的,所以这个函数的反函数就成了一对多。例如原函数输入一个‘ l ’或者‘ 1 ’,输出都是 1 ,反函数输入一个 1 ,输出可以任选‘ l ’和‘ 1 ’其一。 \textcolor{BrickRed}{注意:这个函数是多对一的,所以这个函数的反函数就成了一对多。例如原函数输入一个‘l’或者‘1’,输出都是1,反函数输入一个1,输出可以任选‘l’和‘1’其一。} 注意:这个函数是多对一的,所以这个函数的反函数就成了一对多。例如原函数输入一个l或者‘1’,输出都是1,反函数输入一个1,输出可以任选l‘1’其一。

    要对其进行求逆 R e C h a r T o B y t e \textcolor{cornflowerblue}{ReCharToByte} ReCharToByte,可以写成如下形式:

    char ReCharToByte(unsigned char chr)
    {
        if (chr > 1 && chr <= 9)
            return chr + 0x30;
        if (chr == 0)
        {
            // 原输入有3种情况,这里随机选一种
            switch (rand() % 3)
            {
            case 0:return chr + 0x30;
            case 1:return 'O';
            case 2:return 'o';
            }
        }
        if (chr == 1)
        {
    		switch (rand() % 2)
    		{
    		case 0:return chr + 0x30;
    		case 1:return 'l';
    		}
        }
        // 其余情况就是原本的输入是字母a-z/A-Z
        if (chr + '7' <= 'Z')
            return chr + '7';
        return chr + 'W';
    }
    
  1. 如果 U s e r N a m e [ 0 ] = = ‘ C ’ \textcolor{orange}{UserName[0] == ‘C’} UserName[0]==C ,且 U s e r N a m e [ 1 ] = = ‘ O ’ \textcolor{orange}{UserName[1] == ‘O’} UserName[1]==O,则serial不能全等于某一个字符数组(byte_B9A578)前0xA个元素的倒序;如果 U s e r N a m e [ 0 ] = = ‘ J ’ \textcolor{orange}{UserName[0] == ‘J’} UserName[0]==J ,且 U s e r N a m e [ 1 ] = = ‘ U ’ \textcolor{orange}{UserName[1] == ‘U’} UserName[1]==U,则serial不能全等于 b y t e B 9 A 578 + 0 x C \textcolor{orange}{byte_B9A578+0xC} byteB9A578+0xC0xA个元素的倒序。

在这里插入图片描述

实际这个位置的校验没多大用处。 \textcolor{green}{实际这个位置的校验没多大用处。} 实际这个位置的校验没多大用处。

  1. 根据 h b [ 3 ] \textcolor{orange}{hb[3]} hb[3]的取值,分三种处理情况:

    switch ( BYTE3(HexBytes) )                  // HexBytes[3]
        {
          case 0x9C:
            v19 = (unsigned __int8)(BYTE5(HexBytes) ^ BYTE2(HexBytes))// HexBytes[5] ^ HexBytes[2]
                + ((unsigned __int8)(HIBYTE(HexBytes) ^ BYTE1(HexBytes)) << 8);// (HexBytes[1] ^ HexBytes[7]) << 8
            ri->X1 = (unsigned __int8)Xor_1((unsigned __int8)(BYTE6(HexBytes) ^ (unsigned __int8)HexBytes));// ((a1 ^ 0x18) + 0x3D) ^ 0xA7
            v20 = (unsigned __int16)Calc_1(v19);
            ri->X2 = (unsigned __int16)v20;
            X1 = ri->X1;
            if ( X1 && (unsigned int)(v20 - 1) <= 0x3E7 )
            {
              v22 = 0;
              if ( X1 < 2 )
                v22 = ri->X1;
    End:
              QString::toUtf8(&ri->UserName, v36);  // UserName
              LOBYTE(v4) = v18 != (char)0xFC;
              v24 = QByteArray::data((QByteArray *)v36);
              v25 = Calc_2((__int64)v24, v4, v22, (unsigned int)ri->X2);
              if ( BYTE4(HexBytes) == (_BYTE)v25
                && (_BYTE)v14 == BYTE1(v25)
                && BYTE6(HexBytes) == BYTE2(v25)
                && HIBYTE(HexBytes) == HIBYTE(v25) )
              {
                if ( v18 == (char)0x9C )
                {
                  if ( v34 > ri->X1 )
                  {
                    v26 = 0x4E;
    LABEL_41:
                    QByteArray::~QByteArray((QByteArray *)v36);
                    return v26;
                  }
    LABEL_33:
                  v26 = 0x2D;
                  goto LABEL_41;
                }
                if ( v18 == (char)0xFC )
                {
                  v27 = Calc_3((unsigned __int8)HexBytes + (BYTE1(HexBytes) << 8) + (BYTE2(HexBytes) << 0x10), v25);
                  if ( v27 )
                  {
                    ri->X0 = v27;
                    v26 = 0x93;
                    goto LABEL_41;
                  }
                }
                else if ( v29 )
                {
                  if ( v35 > v29 )
                  {
                    v26 = 0x4E;
                    goto LABEL_41;
                  }
                  goto LABEL_33;
                }
              }
              v26 = 0xE7;
              goto LABEL_41;
            }
            break;
          case 0xFC:
            v22 = 0xFF;
            ri->X1 = 0xFF;
            ri->X2 = 1;
            ri->field_40 = 1;
            goto End;
          case 0xAC:
            ri->X1 = 2;
            v23 = Calc_1((unsigned __int16)((unsigned __int8)(v14 ^ v15) + ((unsigned __int8)(HIBYTE(HexBytes) ^ v16) << 8)));
            ri->X2 = v23;
            if ( (unsigned int)v23 - 1 <= 0x3E7 )
            {
              v29 = Calc_3(
                      (BYTE6(HexBytes) ^ v17)
                    + ((v14 ^ HexBytes_Off_9) << 0x10)
                    + ((HexBytes_Off_8 ^ (unsigned int)BYTE4(HexBytes)) << 8),
                      0x5B8C27i64);
              ri->field_44 = v29;
              v22 = v29;
              goto End;
            }
            break;
        }
        return 0xE7i64;
      }
      return 0x93i64;
    }
    

    由于编译器优化,这部分代码可读性比较差,手动分析整理之后得到伪代码:

    /*
    	Check1后部分的逻辑
    */
    if(len(UserName)==0 || len(Serial) == 0)
    	return 0x93;
    
    v29 = 0;
    // case 0x9C:
    v19 = (hb[5] ^ hb[2]) + ((hb[1] ^ hb[7])<<8);
    v21 = Xor_1(hb[6] ^ hb[0]); // v21
    v20 = Calc_1(v19);  //
    if(v21 && (v20-1) <= 999)
    {
    	v22 = 0;
    	if(v21 < 2)
    		v22 = v21;
    	v25 = Calc_2(UserName, True, v22, v20); // v25 是4字节长度
    	if(hb[4] == v25[0] && hb[5] == v25[1] && hb[6] == v25[2] && hb[7] == v25[3])
    	{
    		if(0xE > v21)
    			return 0x4E;
    		return 0x2D;
    	}
    }	
    return 0xE7;
    //case 0xFC:
    v25 = Calc_2(UserName, False, 0xFF, 1); // v25 是4字节长度
    if(hb[4] == v25[0] && hb[5] == v25[1] && hb[6] == v25[2] && hb[7] == v25[3])
    {
    	v27 = Calc_3(hb[0] + (hb[1] << 8) + (hb[2] << 0x10), v25);
    	if(v27)
    	{
    		*(_DWORD *)(a1 + 0x28) = v27;
    		return 0x93;
    	}
    }
    return 0xE7;
    
    //case 0xAC:
    v23 = Calc_1((hb[5] ^ hb[2]) + ((hb[7] ^ hb[1]) << 8));
    if ( (unsigned int)v23 - 1 <= 0x3E7 )
    {
      v29 = Calc_3(
    		  (hb[6] ^ hb[0]) + ((hb[5] ^ v41) << 0x10) + ((v40 ^ hb[4]) << 8),
    		  0x5B8C27);
      
      v25 = Calc_2(UserName, False, v29, v23); // v25 是4字节长度
      if(hb[4] == v25[0] && hb[5] == v25[1] && hb[6] == v25[2] && hb[7] == v25[3])
      {
    	  if(v29)
    	  {
    		if(0x4B2>v29)
    			return 0x4E;
    	  }
      }
    }
    return 0xE7;
    

    其中有几个函数需要关注:

    • X o r _ 1 \textcolor{cornflowerblue}{Xor\_1} Xor_1

      • char __fastcall sub_36D330(char a1)
        {
          return ((a1 ^ 0x18) + 0x3D) ^ 0xA7;
        }
        
      • 这个函数可逆,单射。逆函数 R e X o r _ 1 \textcolor{cornflowerblue}{ReXor\_1} ReXor_1

        • return ((a1 ^ 0xA7) - 0x3D) ^ 0x18;
          
    • C a l c _ 1 \textcolor{cornflowerblue}{Calc\_1} Calc_1

      • __int64 __fastcall sub_36D2A0(__int16 a1)
        {
          unsigned int v1; // r8d
        
          v1 = (unsigned __int16)((a1 ^ 0x7892) + 0x4D30) ^ 0x3421;
          if ( v1 % 0xB )
            return 0i64;
          else
            return (unsigned __int16)(v1 / 0xB);
        }
        
      • 此函数条件为真的分支存在多对1情况,导致逆函数不能保证得到正确的原函数输入,而原函数的输入在后面验证的时候还需要用到。因此,这个函数的逆函数没有意义。

    • C a l c _ 2 \textcolor{cornflowerblue}{Calc\_2} Calc_2

      • __int64 __fastcall sub_36D380(BYTE *UserName, int a2, char a3, __int64 a4)
        {
        ...
          v5 = 0;
          if ( len_username > 0 )
          {
            i = 0i64;
            v9 = 0;
            v10 = 0xF * a4;
            v11 = 0;
            v12 = 0x11 * a3;
            do
            {
              v13 = toupper(UserName[i]);
              v14 = &g_Box[v12];
              v15 = v5 + g_Box[v13];
              v16 = &g_Box[v10];
              if ( a2 )
              {
                v17 = g_Box[(unsigned __int8)(v13 + 0xD)];
                v18 = (unsigned __int8)(v13 + 0x2F);
                v19 = v9;
              }
              else
              {
                v17 = g_Box[(unsigned __int8)(v13 + 0x3F)];
                v18 = (unsigned __int8)(v13 + 0x17);
                v19 = v11;
              }
              v12 += 9;
              v10 += 13;
              v9 += 19;
              v11 += 7;
              ++i;
              v5 = *v16 + *v14 + g_Box[v19] + g_Box[v18] * (v15 ^ v17);
            }
            while ( i < len_username );
          }
          return v5;
        }
        

        此函数是将UserName编码,记为ans,用来和序列号某个部分进行对比的,所以该函数也不用求逆。

4.Check2算法分析

在这里插入图片描述

这部分校验只要返回0xDB,就表示注册成功了,这就要求Check1返回0x2D,所以重点还是在Check1。

以上就是所有注册算法流程,接下来考虑如何获得正确的任意用户名的序列号。

5.获得正确的任意用户名对应的序列号

我们期望Check1返回0x2D。通过分析,得知只有一条路径可以返回,即 h b [ 3 ]   = =   0 x 9 C \textcolor{orange}{hb[3]\ ==\ 0x9C} hb[3] == 0x9C时,满足:

v19 = (hb[5] ^ hb[2]) + ((hb[1] ^ hb[7])<<8);
v20 = Calc_1(v19);
v20 - 1 < 999;
v25 = Calc_2(user, true, 0, v20);
char* a1 = reinterpret_cast<char*>(&v25);
hb[4] == a1[0] && hb[5] == a1[1] && hb[6] == a1[2] && hb[7] == a1[3]
Xor_1(hb[6] ^ hb[0]) > 0xE

从条件约束中发现,其实serial长度应该是20。我们可以先枚举hb下标为1,2,5,7对应的元素,这样枚举空间就在 25 6 4   =   4294967296 \textcolor{orange}{256^4\ =\ 4294967296} 2564 = 4294967296内,还能接受。在满足条件3、6和7,就能确定hb中的所有元素,然后反求得serial。

综合以上条件得到注册机的代码:

unsigned char g_Data[24] = { 0x43,0x4f,0x57,0xd6,0x30,0xe3,0xca,0xb9,0xac,0xab,0xa1,0xc4,0x4a,0x55,0x59,0x2a,0x35,0xe2,0xc4,0x65,0xac,0xd3,0xa4,0xcb };
unsigned int g_Box[308] = { 0x39cb44b8,0x23754f67,0x5f017211,0x3ebb24da,0x351707c6,0x63f9774b,0x17827288,0xfe74821,0x5b5f670f,0x48315ae8,0x785b7769,0x2b7a1547,0x38d11292,0x42a11b32,0x35332244,0x77437b60,0x1eab3b10,0x53810000,0x1d0212ae,0x6f0377a8,0x43c03092,0x2d3c0a8e,0x62950cbf,0x30f06ffa,0x34f710e0,0x28f417fb,0x350d2f95,0x5a361d5a,0x15cc060b,0xafd13cc,0x28603bcf,0x3371066b,0x30cd14e4,0x175d3a67,0x6dd66a13,0x2d3409f9,0x581e7b82,0x76526b99,0x5c8d5188,0x2c857971,0x15f51fc0,0x68cc0d11,0x49f55e5c,0x275e4364,0x2d1e0dbc,0x4cee7ce3,0x32555840,0x112e2e08,0x6978065a,0x72921406,0x314578e7,0x175621b7,0x40771dbf,0x3fc238d6,0x4a31128a,0x2dad036e,0x41a069d6,0x25400192,0xdd4667,0x6afc1f4f,0x571040ce,0x62fe66df,0x41db4b3e,0x3582231f,0x55f6079a,0x1ca70644,0x1b1643d2,0x3f7228c9,0x5f141070,0x3e1474ab,0x444b256e,0x537050d9,0xf42094b,0x2fd820e6,0x778b2e5e,0x71176d02,0x7fea7a69,0x5bb54628,0x19ba6c71,0x39763a99,0x178d54cd,0x1246e88,0x3313537e,0x2b8e2d17,0x2a3d10be,0x59d10582,0x37a163db,0x30d6489a,0x6a215c46,0xe1c7a76,0x1fc760e7,0x79b80c65,0x27f459b4,0x799a7326,0x50ba1782,0x2a116d5c,0x63866e1b,0x3f920e3c,0x55023490,0x55b56089,0x2c391fd1,0x2f8035c2,0x64fd2b7a,0x4ce8759a,0x518504f0,0x799501a8,0x3f5b2cad,0x38e60160,0x637641d8,0x33352a42,0x51a22c19,0x85c5851,0x32917ab,0x2b770ac7,0x30ac77b3,0x2bec1907,0x35202d0,0xfa933d3,0x61255df3,0x22ad06bf,0x58b86971,0x5fca0de5,0x700d6456,0x56a973db,0x5ab759fd,0x330e0be2,0x5b3c0ddd,0x495d3c60,0x53bd59a6,0x4c5e6d91,0x49d9318d,0x103d5079,0x61ce42e3,0x7ed5121d,0x14e160ed,0x212d4ef2,0x270133f0,0x62435a96,0x1fa75e8b,0x6f092fbe,0x4a000d49,0x57ae1c70,0x4e2477,0x561e7e72,0x468c0033,0x5dcc2402,0x78507ac6,0x58af24c7,0xdf62d34,0x358a4708,0x3cfb1e11,0x2b71451c,0x77a75295,0x56890721,0xfef75f3,0x120f24f1,0x1990ae7,0x339c4452,0x27a15b8e,0xba7276d,0x60dc1b7b,0x4f4b7f82,0x67db7007,0x4f4a57d9,0x621252e8,0x20532cfc,0x6a390306,0x18800423,0x19f3778a,0x462316f0,0x56ae0937,0x43c2675c,0x65ca45fd,0xd604ff2,0xbfd22cb,0x3afe643b,0x3bf67fa6,0x44623579,0x184031f8,0x32174f97,0x4c6a092a,0x5fb50261,0x1650174,0x33634af1,0x712d18f4,0x6e997169,0x5dab7afe,0x7c2b2ee8,0x6edb75b4,0x5f836fb6,0x3c2a6dd6,0x292d05c2,0x52244db,0x149a5f4f,0x5d486540,0x331d15ea,0x4f456920,0x483a699f,0x3b450f05,0x3b207c6c,0x749d70fe,0x417461f6,0x62b031f1,0x2750577b,0x29131533,0x588c3808,0x1aef3456,0xf3c00ec,0x7da74742,0x4b797a6c,0x5ebb3287,0x786558b8,0xed4ff2,0x6269691e,0x24a2255f,0x62c11f7e,0x2f8a7dcd,0x643b17fe,0x778318b8,0x253b60fe,0x34bb63a3,0x5b03214f,0x5f1571f4,0x1a316e9f,0x7acf2704,0x28896838,0x18614677,0x1bf569eb,0xba85ec9,0x6aca6b46,0x1e43422a,0x514d5f0e,0x413e018c,0x307626e9,0x1ed1dfa,0x49f46f5a,0x461b642b,0x7d7007f2,0x13652657,0x6b160bc5,0x65e04849,0x1f526e1c,0x5a0251b6,0x2bd73f69,0x2dbf7acd,0x51e63e80,0x5cf2670f,0x21cd0a03,0x5cff0261,0x33ae061e,0x3bb6345f,0x5d814a75,0x257b5df4,0xa5c2c5b,0x16a45527,0x16f23945,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 };

void ReStrsToHexBytes(unsigned char* hb,  char* serial);
void BruteForce(char* user);

int main()
{
	char user[] = "";
	BruteForce(user);
    return 0;
}

void BruteForce(char* user)
{
    char serial[0x19] = { 0 };
    unsigned char hb[8] = { 0 };
    bool bGo = true;
    hb[3] = 0x9C;
    // 根据hb爆破serial,先找出符合条件的1,2,5,7下标对应的元素
    for(unsigned char i1 = 0;i1<0xFF && bGo;i1++)
        for (unsigned char i2 = 0; i2 < 0xFF && bGo; i2++)
            for (unsigned char i5 = 0; i5 < 0xFF && bGo; i5++)
                for (unsigned char i7 = 0; i7 < 0xFF && bGo; i7++)
                {
                    unsigned short v19 = (i5 ^ i2) + ((i1 ^ i7) << 8);
                    unsigned int v20 = Calc_1(v19);
                    if((v20-1)>=999)
                        continue;
                    unsigned int v25 = Calc_2(user, true, 0, v20);
                    char* a1 = reinterpret_cast<char*>(&v25);
                    if (i5 == a1[1]  && i7 == a1[3])
                    {
                        hb[1] = i1;
                        hb[2] = i2;
                        hb[4] = a1[0];
                        hb[5] = i5;
                        hb[6] = a1[2];
                        hb[7] = i7;
                        hb[0] = ReXor_1(0xF)^hb[6];
                        bGo = false;
                        break;
                    }
                }

    ReStrsToHexBytes(hb, serial);
    printf("UserName: %s\nSerial: %s\n",user,serial);
}   

void ReStrsToHexBytes(unsigned char* hb,  char* serial)
{
    serial[0] = ReCharToByte(hb[0] >> 4);
    serial[1] = ReCharToByte(hb[0] & 0xF);
	serial[2] = ReCharToByte(hb[1] >> 4);
	serial[3] = ReCharToByte(hb[1] & 0xF);
    serial[4] = '-';
	serial[5] = ReCharToByte(hb[2] >> 4);
	serial[6] = ReCharToByte(hb[2] & 0xF);
	serial[7] = ReCharToByte(hb[3] >> 4);
	serial[8] = ReCharToByte(hb[3] & 0xF);
	serial[9] = '-';
	serial[0xA] = ReCharToByte(hb[4] >> 4);
	serial[0xB] = ReCharToByte(hb[4] & 0xF);
	serial[0xC] = ReCharToByte(hb[5] >> 4);
	serial[0xD] = ReCharToByte(hb[5] & 0xF);
	serial[0xE] = '-';
	serial[0xF] = ReCharToByte(hb[6] >> 4);
	serial[0x10] = ReCharToByte(hb[6] & 0xF);
	serial[0x11] = ReCharToByte(hb[7] >> 4);
	serial[0x12] = ReCharToByte(hb[7] & 0xF);
}

由于没有网络验证,所以同一个用户名和序列号可无限使用。这里给出一组可用的用户名和序列号:

Username:Brucy

Serial:218o-1A9C-EA2E-5227

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/129291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis集群系列七 —— 散列插槽分析

集群状态日志分析 Redis 分片集群引入了一个逻辑上的插槽或哈希槽概念&#xff0c;将集群划分为16384&#xff08;0~16383&#xff09;个槽位&#xff0c;集群中的每个节点占据一部分槽位数&#xff0c;在逻辑上将集群中的所有节点构成了一块完整的内存空间。 这个日志中可以通…

对象定义-解构-枚举属性遍历以及对象内函数

属性名表达式 定义对象的属性有两种方式 1、直接使用标识符作为属性名 obj.name 2、以表达式作为属性名 obj[ab] 10 let obj {} obj.name 孙悟空 // 孙悟空 obj[a b] 10 // 10 console.log(obj); // {name: 孙悟空, ab: 10}es5中字面量定义对象只能使用一种方法 var …

4.3.3、划分子网的 IPv4 地址

若有一个大型的局域网需要连接到因特网 若需要申请一个 C 类网络地址&#xff0c;其可分配的 IP 地址数量只有 254254254 个&#xff0c;不够使用 因此申请了一个 B 类网络地址&#xff0c;其可分配的 IP 地址数量达到了 655346553465534 个 给每台计算机和路由器的接口分配一…

实验九、消除互补输出级交越失真方法的研究

一、题目 互补输出级交越失真消除方法的研究。 二、仿真电路 基本互补电路和消除交越失真互补输出级如图1所示。晶体管采用 NPN 型晶体管 2N3904 和 PNP 型晶体管 2N3906。二极管采用 1N4009。 在实际的实验中&#xff0c;几乎不可能得到具有理想对称性的 NPN 型和 PNP 型管…

网络编程套接字----UDP协议

文章目录前言一、理解源IP地址和目的IP地址二、认识端口号理解"端口号"和"进程ID"理解源端口号和目的端口号三、认识TCP协议四、认识UDP协议五、网络字节序六、socket编程接口socket常见APIsockaddr结构sockaddr结构sockaddr_in 结构in_addr结构七、地址转…

第三方软件测试▏有效保障软件产品质量的关键性步骤

软件测试作为软件产品生命周期中不可或缺的重要步骤&#xff0c;被许多软件企业所重视。主要是通过对软件产品进行全面的测试&#xff0c;确保软件质量以及满足用户需求。但软件测试不仅仅是个简单的检测工作&#xff0c;而是一个系统性的、有组织性的测试过程&#xff0c;包含…

Linux:安装 telnet 命令

我是 ABin-阿斌&#xff1a;写一生代码&#xff0c;创一世佳话&#xff0c;筑一览芳华。如果小伙伴们觉得不错就一键三连吧~ 声明&#xff1a;原文地址&#xff1a;https://www.pudn.com/news/6332b44a272bb74d44053074.html 其他参考文章&#xff1a;https://www.cnblogs.com…

尚医通-上传医院接口-需求准备(十七)

目录&#xff1a; &#xff08;1&#xff09;数据接口-上传医院接口-需求准备 &#xff08;1&#xff09;数据接口-上传医院接口-需求准备 在医院接口设置的时候说过&#xff0c;我们做的是预约挂号平台&#xff0c;里面有数据的显示&#xff0c;挂号等等相关业务&#xff0c;…

计算机组成原理【by王道考研计算机】

文章目录第一章1. 什么是计算机系统2. 硬件的发展3. 计算机硬件的基本组成冯诺依曼结构现代计算机结构主存储器运算器控制器工作过程实例4. 计算机系统的层次结构五层结构三种级别的语言5. 计算机的性能指标存储器的容量CPU其他常用时间单位第二章1. 进制转换2. 字符与字符串3.…

下一代,容器工具Podman

一、简介 Kubernetes 团队发布了最新的 1.20 版本时&#xff0c;有一枚重磅炸弹&#xff1a;正式宣布弃用 Docker 支持的功能。弃用 Docker 之后&#xff0c;开发者们对其替代品的讨论逐渐热烈&#xff0c;其中 Containerd 和 Podman 倍受期待。 Podman 是一个开源的容器运行…

云原生、20.3k Star......时序数据库 TDengine 的 2022 年精彩纷呈

日月其迈&#xff0c;时盛岁新 2022 的进度条已经加载至“100%” 疫情肆虐下&#xff0c;毫无疑问 这仍然是头顶风雪攀登山峰的一年 好在如今曙光已现 回望这一年&#xff0c;TDengine 也硕果满满 2022 年是 TDengine 创立的第六个年头 我们付出着&#xff0c;也在收获着…

英伟达Orin芯片平台使用TensorRT加速部署YOLO

前言 自动驾驶行业想要在开发板上部署一套算法还是需要花费很大功夫的&#xff0c;因为计算资源的限制以及实时性要求高。并不像在服务器端部署算法那样粗犷。接下来就记录一下YOLO系列部署的过程&#xff0c;后期会把开发板上的问题都记录在此。 一、部署环境 计算平台&…

11.简单的CSS按钮悬停特效

效果 源码 <!DOCTYPE html> <html> <head><title>Button Hover Effects</title><link rel="stylesheet" type="text/css" href="style.css"> </head> <body><a href="#"><…

信贷产品年终总结之风控评分模型

叮咚&#xff0c;信贷年终总结的又一个专题来了&#xff0c;作为报告总结类的系列型文章&#xff0c;近期我们番茄知识星球平台陆续发布了相关年终总结专题&#xff0c;依次为客群特征画像、贷中行为分析、贷后逾期表现等&#xff0c;以上文章可详见之前陆续发布的内容。该业务…

nacos配置部署与管理

nacos配置部署与管理配置文件配置获取顺序&#xff1a;nacos配置热部署方式一&#xff1a;RefreshScope方式二&#xff1a;ConfigurationProperties配置文件 首先新建配置文件 Data ID&#xff1a;配置文件的名称&#xff08;唯一&#xff09;命名规范&#xff1a;服务名称-运…

广州车展|继原力技术之后,长安深蓝半固态电池呼之欲出

新年将至&#xff0c;万象更新。12月30日&#xff0c;2022第二十届广州国际汽车展览会在广州中国进出口商品交易会展馆隆重举办。全新数字纯电品牌长安深蓝携旗下首款战略车型深蓝SL03重磅参展&#xff0c;并邀请深蓝SL03车主亲临车展现场&#xff0c;或进行产品讲解&#xff0…

面向对象分析与设计的底层逻辑

作者&#xff1a;高福来 阿里全球化业务平台团队 在面向对象出现之前&#xff0c;已有面向过程的分析方法&#xff0c;那为什么面向对象被提出了呢&#xff1f;究其本质&#xff0c;人们发现面向过程并非按照人正常认识事物的方式去分析软件。面向过程是一种归纳的分析方法&a…

virtio技术(3)virtqueue机制

virtio技术&#xff08;3&#xff09;virtqueue机制 virtio的关键技术是virtqueue机制&#xff0c;其提供了一套统一的用于virito前端和后端的通信机制。virtqueue的核心数据结构是vring&#xff0c;这是virtio前端驱动和后端Hypervisor虚拟设备之间传输数据的载体。 vring数…

Word处理控件Aspose.Words功能演示:使用 Java 将 RTF 转换为 PDF

Aspose.Words 是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和打印文档&#xff0c;而无需在跨平台应用程序中直接使用Microsoft Word。此外&#xff0c; Aspose API支持流行文件格式处…

改变podman的存储路径

使用podman容器时&#xff0c;podman会默认使用/var/lib/containers路径作为存储路径&#xff0c;可能会导致根磁盘空间占用过大&#xff0c;那如何修改podman的存储路径呢&#xff1f;本文将带你一起来探讨。 前几天公司的服务器根目录磁盘空间不足了&#xff0c;经过查找问题…