[KCTF]CORE CrackMe v2.0

news2025/7/30 9:38:13

这个Reverse比较古老,已经有20多年了,但难度确实不小。

先查壳

upx压缩壳,0.72,废弃版本,工具无法解压。

反正不用IDA进行调试,直接x32dbg中,dump内存,保存后拖入IDA。

这里说一下,网上常规的脱壳都是OEP->dump->IAT表修复等步骤,如果不需要在IDA中进行调试,直接dump内存,就可以IDA分析静态代码,伪代码都是正常的。

int __usercall sub_4020A0@<eax>(int a1@<ecx>, int a2@<ebx>, int a3@<edi>, int a4@<esi>)
{
  int v4; // eax
  char *i; // ecx
  int v6; // ebx
  char *v7; // edi
  int v8; // eax
  int v9; // esi
  int v10; // eax
  char *j; // ecx
  int v12; // ebx
  int v14; // eax
  char v15[100]; // [esp+8Ch] [ebp-66Ch] BYREF
  char v16[500]; // [esp+F0h] [ebp-608h] BYREF
  char v17[500]; // [esp+2E4h] [ebp-414h] BYREF
  char v18[500]; // [esp+4D8h] [ebp-220h] BYREF
  int v19; // [esp+6CCh] [ebp-2Ch] BYREF
  int v20; // [esp+6D0h] [ebp-28h] BYREF
  int v21; // [esp+6D4h] [ebp-24h] BYREF
  _DWORD v22[4]; // [esp+6D8h] [ebp-20h] BYREF
  char v23[4]; // [esp+6E8h] [ebp-10h] BYREF
  char v24[4]; // [esp+6ECh] [ebp-Ch] BYREF
  char v25[4]; // [esp+6F0h] [ebp-8h] BYREF
  int v26; // [esp+6F4h] [ebp-4h]

  v26 = a1;
  if ( (unsigned int)dword_417158(a2, a4, a3) >= 0x80000000 )
    dword_4171D0(v15, aSoftwareMicros_0);
  else
    dword_4171D0(v15, aSoftwareMicros);
  memset(v16, 0, sizeof(v16));
  memset(v17, 0, sizeof(v17));
  memset(v18, 0, sizeof(v18));
  sub_412706((_DWORD *)(v26 + 0x5C), (int)v16, 100);// 获取name
  sub_412706((_DWORD *)(v26 + 0xAC), (int)v17, 100);// code
  strcpy(v18, v16);
  sub_408D70(v18);                              // 逆序
  strcat(v16, v18);
  dword_41700C(0x80000002, v15, &v19);
  v20 = 1;
  v21 = 256;
  dword_417008(v19, dword_422480, 0, &v20, v18, &v21);
  strcat(v16, v18);
  v20 = 1;
  v21 = 256;
  dword_417008(v19, dword_4224A0, 0, &v20, v18, &v21);
  strcat(v16, v18);
  v4 = 0;
  for ( i = v16; *i; ++v4 )
    ++i;
  v6 = v4;
  sub_4014E0(v22);
  v7 = &v16[v6];
  *(_DWORD *)v7 = 0;
  *((_DWORD *)v7 + 1) = 0;
  *((_DWORD *)v7 + 2) = 0;
  *((_DWORD *)v7 + 3) = 0;
  *((_DWORD *)v7 + 4) = 0;
  *((_DWORD *)v7 + 5) = 0;
  *((_DWORD *)v7 + 6) = 0;
  *((_DWORD *)v7 + 7) = 0;
  *((_DWORD *)v7 + 8) = 0;
  *((_DWORD *)v7 + 9) = 0;
  *((_DWORD *)v7 + 10) = 0;
  *((_DWORD *)v7 + 11) = 0;
  *((_DWORD *)v7 + 12) = 0;
  *((_DWORD *)v7 + 13) = 0;
  *((_DWORD *)v7 + 14) = 0;
  *((_DWORD *)v7 + 15) = 0;
  *((_DWORD *)v7 + 16) = 0;
  *((_DWORD *)v7 + 17) = 0;
  *((_DWORD *)v7 + 18) = 0;
  v7[76] = 0;
  v7[77] = 0;
  v7[78] = 0;
  v16[v6] = 0x80;
  v8 = 64 - (((_BYTE)v6 + 1) & 0x3F);
  if ( v8 <= 7 )
    v8 = 128 - (((_BYTE)v6 + 1) & 0x3F);
  v9 = v8 + v6 + 1;
  v10 = 0;
  for ( j = v16; *j; ++v10 )
    ++j;
  v12 = 0;
  for ( *(_DWORD *)&v16[v9 - 8] = 8 * v10; v12 < v9; v12 += 64 )
    sub_401500((int)&v16[v12], v22);
  if ( sub_404797((int)v17, (unsigned __int8 *)"%lx%lx%lx", v23, v24, v25) != 3 )// sscanf
    return sub_4115A6(aHmmmYouDonTEve, aFailed, 48);// MessageBox
  sub_401AD0((int *)v23, dword_41C2C0, dword_41C3C0);
  sub_401AD0((int *)v24, dword_41C4C0, dword_41C5C0);
  v14 = -3;
  while ( *(&v26 + v14) == v22[v14 + 3] )
  {
    if ( !++v14 )
      return sub_4115A6(aManYouReGoodEn, aWelcome, 64);// MessageBox
  }
  return sub_4115A6(aBetterLuckNext, aFailed, 48);// MessageBox
}

代码不多,整体逻辑并不复杂,首先获取name和code,然后name反转(指定的name是KCTF,反转就是FTCK),反转后的name拼接3次,再拼接原始name,最后组成FTCKFTCKFTCKKCTF,再调用sub_401500进行魔改hash计算,hash值是不可逆的,算code也不需要完全复现hash算法,根据调试,KCTF为用户名,得到的hash值是0D15B8BA2C8F30576BD8A9AEC0C6DBFA。

sub_404797就是sscanf,要求输入3个16进制字符串,再调用sub_401AD0,经过2次不同的掩码数组加密,得到3组_DWORD值,并将hash值看作_DWORD数组,数组的前三个值,与加密后的3组值一一对应。

int *__cdecl sub_401AD0(int *a1, _DWORD *a2, _DWORD *a3)
{
  int v5; // esi
  int v6; // edi
  int v7; // esi
  int v8; // edi
  int *result; // eax
  int *v10; // [esp+18h] [ebp-24h]
  unsigned __int8 v11; // [esp+1Ch] [ebp-20h]
  int v12; // [esp+1Ch] [ebp-20h]
  int v13; // [esp+20h] [ebp-1Ch]
  unsigned __int8 v14; // [esp+20h] [ebp-1Ch]
  int v15; // [esp+28h] [ebp-14h]

  v5 = 0;
  v6 = 0;
  v10 = a1 + 1;
  do
  {
    v13 = *a3 & *v10;
    v11 = sub_401AB0(*a2 & *a1);
    ++v5;
    ++a3;
    ++a2;
    v6 = ((unsigned __int8)sub_401AB0(v13) ^ v11) & 1 ^ (2 * v6);
  }
  while ( (unsigned __int8)v5 < 0x20u );
  v7 = 0;
  v15 = v6;
  v8 = 0;
  do
  {
    v12 = *a3 & *v10;
    v14 = sub_401AB0(*a2 & *a1);
    ++v7;
    ++a3;
    ++a2;
    v8 = ((unsigned __int8)sub_401AB0(v12) ^ v14) & 1 ^ (2 * v8);
  }
  while ( (unsigned __int8)v7 < 0x20u );
  result = a1;
  *a1 = v15;
  *v10 = v8;
  return result;
}
int __cdecl sub_401AB0(int a1)
{
  int v1; // edx
  int result; // eax

  v1 = a1;
  for ( result = 0; v1; v1 &= v1 - 1 )
    ++result;
  return result;
}

sub_401AB0是计算参数的二进制表示中,1的个数,也就是汉明距离。sub_401AD0中,将2次汉明距离异或后,与1做按位与运算,也就是汉明距离的奇偶性,并以此作为2进制值计算出v6和v8.

说实话,这个逆运算困扰了我很久,按照反编译的代码,根本找不到逆运算的任何思路。看雪论坛在当年有一个帖子解释这个程序里有一句话,汉明距离奇偶性的判断有另外的等效计算方法,而那个方法是可逆的。于是寻找奇偶性计算的替代方法。

其实,奇偶性计算就是一个偶消奇不消的过程,值为1的位数是奇数还是偶数,那么,把每一bit进行异或即可,但没必要运行那么多次,折半异或性能更好。于是找到替代函数

static int haming_weight(_QWORD x)
{
    x = (x >> 32) ^ (x & 0xffffffff);
    x = (x >> 16) ^ (x & 0xffff);
    x = (x >> 8) ^ (x & 0xff);
    x = (x >> 4) ^ (x & 0xf);
    x = (x >> 2) ^ (x & 0x3);
    x = (x >> 1) ^ (x & 0x1);
    return x;
}

同时,汉明距离异或值的奇偶性,等于汉明距离奇偶的异或值,这里就有一种豁然开朗的感觉,入参数组的data[0]和data[1]可以看作一个64位整数,两组key同时拼接为一组64为整数的数组,于是sub_401AD0可以等效替换为

static void __cdecl encrypt(_DWORD* Data, _DWORD* maskKey1, _DWORD* maskKey2)
{
    _DWORD v8 = 0;
    _DWORD v6 = 0;
    for (int i = 0;i < 32;++i)
    {
        _QWORD data = ((_QWORD)Data[1] << 32) | Data[0];
        _QWORD key = ((_QWORD)maskKey2[i] << 32) | maskKey1[i];
        _QWORD key2 = ((_QWORD)maskKey2[i + 32] << 32) | maskKey1[i + 32];
        //printf("Data:%llX, key:%llX, key2:%llX\n", data, key, key2);
        v6 = haming_weight(data & key) ^ (v6 << 1);
        v8 = haming_weight(data & key2) ^ (v8 << 1);
    }
    Data[0] = v6;
    Data[1] = v8;
}

但到了这里,解密仍然是个老大难问题,干脆把代码交给deepseek试试,AI给出的结论是要用逆矩阵来解密,逆矩阵用高斯消元法。于是,经过AI多次给出错误答案并修修补补后,得到最终解密函数

// 预计算密钥的奇偶性矩阵
static void build_key_matrix(_DWORD* maskKey1, _DWORD* maskKey2, _DWORD matrix[64][64]) {
    for (int i = 0; i < 32; ++i) {
        _QWORD key1 = ((_QWORD)maskKey2[31 - i] << 32) | maskKey1[31 - i];
        _QWORD key2 = ((_QWORD)maskKey2[63 - i] << 32) | maskKey1[63 - i];

        // 填充矩阵的奇数行(key1)和偶数行(key2)
        for (int j = 0; j < 64; ++j) {
            matrix[i][j] = (key1 >> j) & 1;
            matrix[i + 32][j] = (key2 >> j) & 1;
        }
    }
}

static bool matrix_inverse(_DWORD input[64][64], _DWORD output[64][64])
{
    _DWORD aug[64][128]; // 增广矩阵 [I | A]

    // 初始化增广矩阵
    for (int i = 0; i < 64; ++i) {
        for (int j = 0; j < 64; ++j) {
            aug[i][j] = input[i][j];
            aug[i][j + 64] = (i == j) ? 1 : 0; // 右侧初始化为单位矩阵
        }
    }

    // 高斯-若尔当消元法
    for (int col = 0; col < 64; ++col) {
        // 寻找主元
        int pivot = -1;
        for (int row = col; row < 64; ++row) {
            if (aug[row][col]) {
                pivot = row;
                break;
            }
        }
        if (pivot == -1) return false; // 矩阵不可逆

        // 交换行
        if (pivot != col) {
            for (int j = 0; j < 128; ++j) {
                uint8_t temp = aug[col][j];
                aug[col][j] = aug[pivot][j];
                aug[pivot][j] = temp;
            }
        }

        // 消元处理
        for (int row = 0; row < 64; ++row) {
            if (row != col && aug[row][col]) {
                for (int j = 0; j < 128; ++j) {
                    aug[row][j] ^= aug[col][j];
                }
            }
        }
    }

    // 提取逆矩阵
    for (int i = 0; i < 64; ++i) {
        for (int j = 0; j < 64; ++j) {
            output[i][j] = aug[i][j + 64];
        }
    }
    return true;
}

static void __cdecl decrypt(_DWORD* Data, _DWORD* maskKey1, _DWORD* maskKey2) {
    _DWORD key_matrix[64][64];
    _DWORD inv_matrix[64][64];

    // 预计算阶段
    build_key_matrix(maskKey1, maskKey2, key_matrix);
    matrix_inverse(key_matrix, inv_matrix); // 需实现矩阵求逆

    // 解密阶段
    _DWORD cipher_bits[64];
    for (int i = 0; i < 32; i++) {
        cipher_bits[i] = (Data[0] >> (i)) & 1;
        cipher_bits[i + 32] = (Data[1] >> (i)) & 1;
    }

    // 矩阵乘法恢复原始数据
    _QWORD plain = 0;
    for (int i = 0; i < 64; i++) {
        _DWORD bit = 0;
        for (int j = 0; j < 64; j++) {
            bit ^= inv_matrix[i][j] & cipher_bits[j];
        }
        plain ^= (_QWORD)bit << i;
    }

    Data[0] = (DWORD)(plain & 0xFFFFFFFF);
    Data[1] = (DWORD)(plain >> 32);
}

最后,解密过程为

    _DWORD dword_41C5C0[] = {
        0xDFCF8EDF, 0xFE7C76FE, 0xFCF8EDFC, 0xF9F1DBF9, 0xF3E3B7F2, 0xBF9F1DBF, 0x7F3E3B7F, 0xE7C76FE5,
        0xCF8EDFCB, 0x7C76FE5F, 0xF8EDFCBE, 0x9F1DBF97, 0x3E3B7F2F, 0x8EDFCBE0, 0x1DBF97C1, 0xC76FE5F0,
        0xF1DBF97C, 0xE3B7F2F8, 0x3B7F2F82, 0x76FE5F05, 0xBF97C156, 0x6FE5F055, 0xDBF97C15, 0xB7F2F82A,
        0xDFCBE0AB, 0xEDFCBE0A, 0xF97C1561, 0xF2F82AC3, 0xE5F05586, 0x7F2F82AC, 0xFE5F0558, 0xFCBE0AB0,
        0xCBE0AB0C, 0x97C15619, 0x2F82AC32, 0x5F055865, 0x7C156197, 0xF82AC32E, 0xF055865C, 0xE0AB0CB9,
        0xC1561973, 0x82AC32E7, 0xBE0AB0CB, 0x055865CE, 0x0AB0CB9C, 0x2AC32E72, 0x15619739, 0x55865CE4,
        0xAB0CB9C8, 0xAC32E723, 0x5865CE46, 0xB0CB9C8D, 0x6197391B, 0xC32E7236, 0x865CE46C, 0x0CB9C8D9,
        0x56197391, 0x65CE46CB, 0xCB9C8D96, 0x197391B2, 0x32E72365, 0x97391B2C, 0x2E723659, 0x5CE46CB3
    };
    _DWORD dword_41C4C0[] = {
        0xAE10E7F5, 0x7087FFB6, 0xE10FFF6D, 0x421FDEDF, 0x843FBDBF, 0xDC21EFEF, 0x3843FFDB, 0x887F5B7B,
        0x90FE96F3, 0x07F45782, 0x0FE8AF04, 0xA1FD0DE3, 0xC3FA3BC3, 0xFE8AF04F, 0x7D15C09B, 0x7F457827,
        0x1FD15E09, 0x3FA2BC13, 0xFA2B8136, 0x74572268, 0x15CA5A45, 0xC5728693, 0x515CA9A5, 0xA2B9534B,
        0x0AE52D22, 0xE8AE44D0, 0xDCA5845F, 0x394B28BB, 0x72965177, 0x2B94B48B, 0x57296916, 0xAE52D22D,
        0xE52CA2EF, 0x4A5965DB, 0x94B2CBB7, 0xA965B76A, 0x2596BDA5, 0x4B2D7B4A, 0x965AF695, 0xACB5CD2F,
        0xD96BBA5B, 0x32D754B3, 0xD2CB4ED0, 0x65AEA967, 0xCB5D52CE, 0x2D750B30, 0x16BA8598, 0x5AEA1660,
        0xB5D42CC0, 0x5750D30E, 0xAEA1A61D, 0xDD436C3E, 0x3A86F879, 0x750DF0F2, 0xEA1BE1E5, 0x5437E3CF,
        0xEBA87985, 0x21BF7E74, 0x437EFCE8, 0xA86FC79E, 0xD0DFAF38, 0x86FDF9D1, 0x8DFBD3A7, 0x9BF7874A
    };
    _DWORD dword_41C3C0[] = { 
        0x9B4D1349, 0x369A2692, 0xCDA689A4, 0xDA689A48, 0xB4D13490, 0x69A26921, 0xD344D243, 0x6D344D24,
        0xA689A486, 0x4D13490D, 0x9A26921A, 0x689A486B, 0x344D2435, 0xD13490D7, 0xA26921AE, 0x89A486BA,
        0x44D2435D, 0x13490D75, 0x26921AEA, 0x4D2435D5, 0x9A486BAA, 0x3490D754, 0x6921AEA9, 0xD2435D52,
        0xA486BAA5, 0x490D754B, 0x921AEA96, 0x2435D52C, 0x486BAA58, 0x90D754B1, 0x21AEA962, 0x435D52C4,
        0x86BAA589, 0x1AEA9624, 0x0D754B12, 0x35D52C48, 0x6BAA5890, 0xD754B120, 0x5D52C481, 0xBAA58902,
        0xAEA96240, 0xEA96240A, 0x754B1205, 0xAA58902A, 0x54B12055, 0xA96240AA, 0x52C48154, 0xD52C4815,
        0xA58902A9, 0x4B120553, 0x96240AA7, 0x2C48154E, 0x58902A9D, 0xB120553A, 0x6240AA75, 0xC48154EA,
        0x48154EAB, 0x902A9D56, 0x20553AAC, 0x8902A9D5, 0x120553AA, 0x240AA755, 0x8154EAB3, 0x40AA7559
    };
    _DWORD dword_41C2C0[] = { 
        0x0BCFEF35, 0x179FDE6B, 0xC5E7E798, 0x5E7F79AC, 0xBCFEF359, 0xF9FDC6B7, 0x73FBAD6A, 0x2F3FBCD6,
        0xE7F75AD5, 0x4FEE95AF, 0x9FDD2B5E, 0xFF74CD76, 0xBFBA76B9, 0x7EE9BAE8, 0xFDD375D1, 0xF74D974E,
        0x7BA6CBA7, 0x6E9B0E99, 0xDD361D32, 0x3A6C1A60, 0x74D834C0, 0xE9B06981, 0x5360F306, 0xA6C1E60C,
        0xCD83EC1D, 0x1B07F83F, 0x360FF07E, 0x6C1FE0FD, 0xD83FC1FA, 0x307FA3F0, 0x60FF47E1, 0xC1FE8FC2,
        0x03FD3F80, 0x0FF4FE02, 0x07FA7F01, 0x1FE9FC04, 0x3FD3F808, 0x7FA7F010, 0x7E9FE047, 0xFD3FC08E,
        0xFF4FE021, 0xF4FF4232, 0x7A7FA119, 0xD3FD48C3, 0x27FAB183, 0x4FF56306, 0x9FEAC60D, 0x69FEA461,
        0xBFD5AC1E, 0xFFAB7839, 0x7F56D076, 0xFEADA0ED, 0x7D5B61DE, 0xFAB6C3BC, 0x756DA77D, 0xEADB4EFA,
        0x2DB58F80, 0x5B6B1F00, 0xB6D63E01, 0x55B6BDF1, 0xAB6D7BE3, 0xD6DAD7C2, 0x5B589808, 0xEDAC5C06 
    };

    _DWORD Data[] = { 0xBAB8150D, 0x57308F2C, 0xAEA9D86B };

    decrypt(Data + 1, dword_41C4C0, dword_41C5C0);
    decrypt(Data, dword_41C2C0, dword_41C3C0);
    printf("%X %X %X\n", Data[0], Data[1], Data[2]);

附上程序内执行成功的截图

最后,吐槽一下看雪,答案提交上去显示错误,很好奇那3个人如何提交成功的。现在好多题都是提交答案无果,还有好多题没有附件,看来是没有人继续维护了。

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

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

相关文章

Ubuntu 安装 Mysql 数据库

首先更新apt-get工具&#xff0c;执行命令如下&#xff1a; apt-get upgrade安装Mysql&#xff0c;执行如下命令&#xff1a; apt-get install mysql-server 开启Mysql 服务&#xff0c;执行命令如下&#xff1a; service mysql start并确认是否成功开启mysql,执行命令如下&am…

Java高级 |【实验八】springboot 使用Websocket

隶属文章&#xff1a;Java高级 | &#xff08;二十二&#xff09;Java常用类库-CSDN博客 系列文章&#xff1a;Java高级 | 【实验一】Springboot安装及测试 |最新-CSDN博客 Java高级 | 【实验二】Springboot 控制器类相关注解知识-CSDN博客 Java高级 | 【实验三】Springboot 静…

设计模式-3 行为型模式

一、观察者模式 1、定义 定义对象之间的一对多的依赖关系&#xff0c;这样当一个对象改变状态时&#xff0c;它的所有依赖项都会自动得到通知和更新。 描述复杂的流程控制 描述多个类或者对象之间怎样互相协作共同完成单个对象都无法单独度完成的任务 它涉及算法与对象间职责…

实现p2p的webrtc-srs版本

1. 基本知识 1.1 webrtc 一、WebRTC的本质&#xff1a;实时通信的“网络协议栈”类比 将WebRTC类比为Linux网络协议栈极具洞察力&#xff0c;二者在架构设计和功能定位上高度相似&#xff1a; 分层协议栈架构 Linux网络协议栈&#xff1a;从底层物理层到应用层&#xff08;如…

第2篇:BLE 广播与扫描机制详解

本文是《BLE 协议从入门到专家》专栏第二篇,专注于解析 BLE 广播(Advertising)与扫描(Scanning)机制。我们将从协议层结构、广播包格式、设备发现流程、控制器行为、开发者 API、广播冲突与多设备调度等方面,全面拆解这一 BLE 最基础也是最关键的通信机制。 一、什么是 B…

开源 vGPU 方案:HAMi,实现细粒度 GPU 切分

本文主要分享一个开源的 GPU 虚拟化方案&#xff1a;HAMi&#xff0c;包括如何安装、配置以及使用。 相比于上一篇分享的 TimeSlicing 方案&#xff0c;HAMi 除了 GPU 共享之外还可以实现 GPU core、memory 得限制&#xff0c;保证共享同一 GPU 的各个 Pod 都能拿到足够的资源。…

盲盒一番赏小程序:引领盲盒新潮流

在盲盒市场日益火爆的今天&#xff0c;如何才能在众多盲盒产品中脱颖而出&#xff1f;盲盒一番赏小程序给出了答案&#xff0c;它以创新的玩法和优质的服务&#xff0c;引领着盲盒新潮流。 一番赏小程序的最大特色在于其独特的赏品分级制度。赏品分为多个等级&#xff0c;从普…

边缘计算设备全解析:边缘盒子在各大行业的落地应用场景

随着工业物联网、AI、5G的发展&#xff0c;数据量呈爆炸式增长。但你有没有想过&#xff0c;我们生成的数据&#xff0c;真的都要发回云端处理吗&#xff1f;其实不一定。特别是在一些对响应时间、网络带宽、数据隐私要求高的行业里&#xff0c;边缘计算开始“火”了起来&#…

Linux实现线程同步的方式有哪些?

什么是线程同步&#xff1f; 想象一下超市收银台&#xff1a;如果所有顾客&#xff08;线程&#xff09;同时挤向同一个收银台&#xff08;共享资源&#xff09;&#xff0c;场面会一片混乱。线程同步就是给顾客们发"排队号码牌"&#xff0c;确保&#xff1a; 有序访…

python学习day39

图像数据与显存 知识点回顾 1.图像数据的格式&#xff1a;灰度和彩色数据 2.模型的定义 3.显存占用的4种地方 a.模型参数梯度参数 b.优化器参数 c.数据批量所占显存 d.神经元输出中间状态 4.batchisize和训练的关系 import torch import torchvision import torch.nn as nn imp…

年度峰会上,抖音依靠人工智能和搜索功能吸引广告主

上周早些时候举行的第五届年度TikTok World产品峰会上&#xff0c;TikTok推出了一系列旨在增强该应用对广告主吸引力的功能。 新产品列表的首位是TikTok Market Scope&#xff0c;这是一个全新的分析平台&#xff0c;为广告主提供整个考虑漏斗的全面视图&#xff0c;使他们能够…

如何使用CodeRider插件在IDEA中生成代码

一、环境搭建与插件安装 1.1 环境准备 名称要求说明操作系统Windows 11JetBrains IDEIntelliJ IDEA 2025.1.1.1 (Community Edition)硬件配置推荐16GB内存50GB磁盘空间 1.2 插件安装流程 步骤1&#xff1a;市场安装 打开IDEA&#xff0c;进入File → Settings → Plugins搜…

电脑定时关机工具推荐

软件介绍 本文介绍一款轻量级的电脑自动关机工具&#xff0c;无需安装&#xff0c;使用简单&#xff0c;可满足定时关机需求。 工具简介 这款关机助手是一款无需安装的小型软件&#xff0c;文件体积仅60KB&#xff0c;下载后可直接运行&#xff0c;无需复杂配置。 使用…

前端异步编程全场景解读

前端异步编程是现代Web开发的核心&#xff0c;它解决了浏览器单线程执行带来的UI阻塞问题。以下从多个维度进行深度解析&#xff1a; 一、异步编程的核心概念 JavaScript的执行环境是单线程的&#xff0c;这意味着在同一时间只能执行一个任务。为了不阻塞主线程&#xff0c;J…

分布式光纤声振传感技术原理与瑞利散射机制解析

分布式光纤传感技术&#xff08;Distributed Fiber Optic Sensing&#xff0c;简称DFOS&#xff09;作为近年来迅速发展的新型感知手段&#xff0c;已广泛应用于边界安防、油气管道监测、结构健康诊断、地震探测等领域。其子类技术——分布式光纤声振传感&#xff08;Distribut…

RocketMQ 客户端负载均衡机制详解及最佳实践

延伸阅读&#xff1a;&#x1f50d;「RocketMQ 中文社区」 持续更新源码解析/最佳实践&#xff0c;提供 RocketMQ 专家 AI 答疑服务 前言 本文介绍 RocketMQ 负载均衡机制&#xff0c;主要涉及负载均衡发生的时机、客户端负载均衡对消费的影响&#xff08;消息堆积/消费毛刺等…

【SSM】SpringMVC学习笔记7:前后端数据传输协议和异常处理

这篇学习笔记是Spring系列笔记的第7篇&#xff0c;该笔记是笔者在学习黑马程序员SSM框架教程课程期间的笔记&#xff0c;供自己和他人参考。 Spring学习笔记目录 笔记1&#xff1a;【SSM】Spring基础&#xff1a; IoC配置学习笔记-CSDN博客 对应黑马课程P1~P20的内容。 笔记2…

C++课设:实现本地留言板系统(支持留言、搜索、标签、加密等)

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 专栏介绍&#xff1a;《编程项目实战》 目录 一、项目功能概览与亮点分析1. 核心功能…

【见合八方平面波导外腔激光器专题系列】用于干涉光纤传感的低噪声平面波导外腔激光器2

----翻译自Mazin Alalus等人的文章 摘要 1550 nm DWDM 平面波导外腔激光器具有低相位/频率噪声、窄线宽和低 RIN 等特点。该腔体包括一个半导体增益芯片和一个带布拉格光栅的平面光波电路波导&#xff0c;采用 14 引脚蝶形封装。这种平面波导外腔激光器设计用于在振动和恶劣的…

Xcode 16.2 版本 pod init 报错

Xcode 版本升级到 16.2 后&#xff0c;项目执行 pod init 报错&#xff1b; ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchron…