【iOS逆向与安全】使用ollvm混淆你的源码

news2025/6/19 6:01:44

前言

当你在研究别人源码的时候,是不是期望着别人代码没有进行任何的防护和混淆。这时的你,是不是应该考虑一下自己代码的安全.本篇文章将告诉你,如何使用ollvm来混淆iOS端的代码【此文为入门贴,大佬请绕道】。

一、目标

编译ollvm工具,并在Xcode中来混淆你的ipa或动态库,增加别人破解你源码的难度。

二、工具

  • ollvm:下载地址:https://github.com/heroims/obfuscator
  • Xcode:iOS开发工具

三、步骤

1、基础知识

LLVM

LLVM(Low Level Virtual Machine)是一个开源的编译器基础架构,它包含了一组模块化、可重用的编译器和工具,支持多种编程语言和目标架构,包括x86、ARM和MIPS等。LLVM最初由美国伊利诺伊大学香槟分校(University of Illinois at Urbana–Champaign)的Chris Lattner教授开发,现在由LLVM社区进行维护和发展。

LLVM的核心思想是将编译器分为前端和后端两个部分,前端负责将源代码转换为中间表示(IR),后端负责将中间表示转换为目标机器的汇编代码。这种设计使得LLVM可以支持多种编程语言,因为只需要为每种语言编写一个前端,就可以利用后端的通用性支持多种目标架构。

除了编译器之外,LLVM还包括了一些工具,例如优化器、调试器、汇编器和反汇编器等,这些工具可以帮助开发者更好地分析和调试程序,提高代码的性能和可靠性。

LLVM已经成为了广泛使用的编译器基础架构,许多编程语言和工具链都采用了LLVM作为后端,例如C、C++、Objective-C、Swift、Rust、Go等。LLVM还被广泛应用于计算机体系结构研究、代码安全性分析、机器学习等领域。

Clang

Clang是基于LLVM框架的C、C++、Objective-C和Objective-C++编译器,它是一个开源项目,由LLVM社区进行开发和维护。Clang的设计目标是提供高质量的诊断、快速的编译速度、低内存占用和良好的可移植性。

Clang的编译器前端使用了现代的编译器架构,包括基于词法分析器和语法分析器的语法分析,生成抽象语法树(AST)并进行类型检查和语义分析等步骤。这些步骤的优化和并行化使得Clang能够快速地进行编译,同时提供了更好的错误和警告信息,有助于开发者更快地发现和修复代码中的问题。

除了作为独立的编译器之外,Clang还可以作为其他工具的库使用,例如静态分析工具、编辑器插件和代码重构工具等。Clang的模块化设计和良好的API使得它可以轻松地被集成到其他工具中,从而提供更好的编程体验。

由于Clang的优秀性能和良好的设计,它已经成为了许多项目的首选编译器,例如LLVM自身、macOS和iOS的默认编译器等。同时,许多开发者和组织也在积极地开发和贡献Clang的代码,使得它在未来仍有广阔的发展空间。

OLLVM

OLLVM(Obfuscator-LLVM)是基于LLVM框架的混淆器,它可以对程序进行混淆以提高程序的安全性。OLLVM的设计目标是提供一种灵活的、可定制的混淆方案,使得攻击者更难理解和分析程序的行为。

OLLVM通过对程序进行多种混淆操作来实现混淆效果,例如代码替换、函数内联、控制流平坦化、加密等。这些混淆操作可以改变程序的控制流图和数据流图,使得程序更难以被理解和逆向分析。同时,OLLVM还提供了一些额外的安全机制,例如加密程序的字符串、使用栈保护和位置无关代码等,以增加程序的安全性。

由于OLLVM是基于LLVM框架开发的,它可以与现有的LLVM工具和编译器集成,例如Clang和LLDB等。这使得开发者可以轻松地在现有的开发环境中使用OLLVM,并且可以使用现有的工具对混淆后的程序进行调试和分析。

尽管OLLVM的主要目的是提高程序的安全性,但它也可以用于其他领域,例如代码保护、代码压缩和代码优化等。由于其灵活性和可定制性,OLLVM已经被广泛应用于许多领域,例如网络安全、游戏开发和金融等。

IR之间的pass,就是混淆器工作的地方。相关代码位于obfuscator/llvm/lib/Transforms/Obfuscation/

2、编译ollvm

命令如下:

witchan@witchandeMacBook-Air ~ % git clone -b llvm-13.x https://github.com/heroims/obfuscator.git
witchan@witchandeMacBook-Air ~ % $cd obfuscator
witchan@witchandeMacBook-Air ~ % mkdir build
witchan@witchandeMacBook-Air ~ % cd build
witchan@witchandeMacBook-Air ~ % cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_CREATE_XCODE_TOOLCHAIN=ON -DLLVM_ENABLE_PROJECTS="clang;libcxx;libcxxabi" -DLLVM_ENABLE_NEW_PASS_MANAGER=OFF ../llvm
witchan@witchandeMacBook-Air ~ % make -j8
witchan@witchandeMacBook-Air ~ % sudo make install-xcode-toolchain
witchan@witchandeMacBook-Air ~ % mv /usr/local/Toolchains  /Library/Developer/

注:make -j8这命令编译的快慢,取决于你的硬件设备

挨个执行以上命令后,ollvm就编译并安装完成,效果如下:

3、混淆命令及效果对比

混淆命令简介

  • fla:该选项使用函数级别的混淆来隐藏程序的结构。这通过随机重命名函数、添加不必要的控制流和删除调用的函数来实现。这增加了反编译和分析代码的难度。
  • bcf:该选项使用基本块级别的混淆来隐藏代码的结构。这通过改变基本块之间的控制流、添加不必要的基本块和移除基本块之间的条件分支来实现。
  • -sub:该选项使用字符串混淆来隐藏代码中的常量字符串。这通过将字符串分成几个小块、将其存储在数组中并在运行时重新组合来实现。这使得分析代码和查找敏感信息更加困难。
  • split:该选项使用控制流混淆来增加程序的复杂性。这通过将函数分成几个基本块、添加随机的跳转指令和在运行时随机重组这些基本块来实现。这使得代码的流程更难以跟踪,从而增加了破解和反编译的难度。
  • sobf:该选项使用源代码混淆技术来隐藏代码的逻辑和结构。这通过使用类似加密的方式对代码进行变换,使其难以理解和分析。这可以通过运行时解密来执行,从而隐藏代码的真实功能。

示例代码如下:

- (void)testMethod {
    NSString *name = @"wit";
    int age = 18;
 
    NSArray *list = @[@1,@3,@5,@18];
    for (int i=0; i<list.count; i++) {
        int value = [list[i] intValue];
        if (value == age) {
            age += 10;
            name = @"chan";
        }
    }
    NSLog(@"name = %@", name);
    NSLog(@"age = %d", age);
}

未使用混淆:

__int64 __fastcall -[ViewController testMethod](__int64 a1, __int64 a2)
{
  void *v2; // x0
  __int64 v3; // ST70_8
  void *v4; // x0
  __int64 v5; // ST68_8
  void *v6; // x0
  __int64 v7; // ST60_8
  void *v8; // x0
  __int64 v9; // ST58_8
  void *v10; // x0
  void *v11; // x0
  void *v12; // ST20_8
  int v13; // ST2C_4
  __int64 result; // x0
  int i; // [xsp+7Ch] [xbp-54h]
  void *v16; // [xsp+80h] [xbp-50h]
  int v17; // [xsp+8Ch] [xbp-44h]
  __int64 v18; // [xsp+90h] [xbp-40h]
  __int64 v19; // [xsp+98h] [xbp-38h]
  __int64 v20; // [xsp+A0h] [xbp-30h]
  __int64 v21; // [xsp+A8h] [xbp-28h]
  __int64 v22; // [xsp+B0h] [xbp-20h]
  __int64 v23; // [xsp+B8h] [xbp-18h]
  __int64 v24; // [xsp+C0h] [xbp-10h]
  __int64 v25; // [xsp+C8h] [xbp-8h]
 
  v25 = *(_QWORD *)__stack_chk_guard_ptr;
  v20 = a1;
  v19 = a2;
  v18 = objc_retain(&stru_100008078);
  v17 = 18;
  v2 = objc_msgSend(off_10000D2D0, (const char *)off_10000D290, 1LL);
  v3 = objc_retainAutoreleasedReturnValue(v2);
  v21 = v3;
  v4 = objc_msgSend(off_10000D2D0, (const char *)off_10000D290, 3LL);
  v5 = objc_retainAutoreleasedReturnValue(v4);
  v22 = v5;
  v6 = objc_msgSend(off_10000D2D0, (const char *)off_10000D290, 5LL);
  v7 = objc_retainAutoreleasedReturnValue(v6);
  v23 = v7;
  v8 = objc_msgSend(off_10000D2D0, (const char *)off_10000D290, 18LL);
  v9 = objc_retainAutoreleasedReturnValue(v8);
  v24 = v9;
  v10 = objc_msgSend(off_10000D2D8, (const char *)off_10000D298, &v21, 4LL);
  v16 = (void *)objc_retainAutoreleasedReturnValue(v10);
  objc_release(v9);
  objc_release(v7);
  objc_release(v5);
  objc_release(v3);
  for ( i = 0; i < (unsigned __int64)objc_msgSend(v16, (const char *)off_10000D2A0); ++i )
  {
    v11 = objc_msgSend(v16, (const char *)off_10000D2A8, i);
    v12 = (void *)objc_retainAutoreleasedReturnValue(v11);
    v13 = (unsigned __int64)objc_msgSend(v12, (const char *)off_10000D2B0);
    objc_release(v12);
    if ( v13 == v17 )
    {
      v17 += 10;
      objc_storeStrong(&v18);
    }
  }
  NSLog(&stru_1000080B8);
  NSLog(&stru_1000080D8);
  objc_storeStrong(&v16);
  result = objc_storeStrong(&v18);
  *(_QWORD *)__stack_chk_guard_ptr;
  return result;
}

开启ollvm混淆:

 

 

 

 混淆参数:-mllvm -fla -mllvm -bcf -mllvm -sub -mllvm -split -mllvm -sobf

混淆后效果如下:

__int64 __fastcall -[ViewController testMethod](__int64 a1, __int64 a2)
{
  void *v2; // x0
  void *v3; // x0
  __int64 v4; // ST58_8
  void *v5; // x0
  __int64 v6; // ST50_8
  void *v7; // x0
  __int64 v8; // ST48_8
  void *v9; // x0
  void *v10; // x0
  signed int v11; // w8
  BOOL v12; // w9
  signed int v13; // w8
  BOOL v14; // w9
  signed int v15; // w8
  BOOL v16; // w14
  signed int v17; // w8
  void *v18; // x0
  void *v19; // ST20_8
  int v20; // ST2C_4
  BOOL v21; // w12
  signed int v22; // w8
  BOOL v23; // w9
  signed int v24; // w8
  BOOL v25; // w12
  signed int v26; // w8
  signed int v27; // w8
  BOOL v28; // w9
  signed int v29; // w8
  BOOL v30; // w12
  signed int v31; // w8
  BOOL v32; // w14
  signed int v33; // w8
  BOOL v34; // w9
  signed int v35; // w8
  void *v37; // x0
  void *v38; // ST08_8
  int v39; // ST14_4
  signed int v40; // [xsp+94h] [xbp-DCh]
  int v41; // [xsp+98h] [xbp-D8h]
  int v42; // [xsp+9Ch] [xbp-D4h]
  void *v43; // [xsp+A0h] [xbp-D0h]
  int v44; // [xsp+ACh] [xbp-C4h]
  __int64 v45; // [xsp+B0h] [xbp-C0h]
  __int64 v46; // [xsp+B8h] [xbp-B8h]
  __int64 v47; // [xsp+C0h] [xbp-B0h]
  __int64 v48; // [xsp+C8h] [xbp-A8h]
  __int64 *v49; // [xsp+D0h] [xbp-A0h]
  const char *v50; // [xsp+D8h] [xbp-98h]
  void *v51; // [xsp+E0h] [xbp-90h]
  __int64 v52; // [xsp+E8h] [xbp-88h]
  unsigned __int64 v53; // [xsp+F0h] [xbp-80h]
  const char *v54; // [xsp+F8h] [xbp-78h]
  void *v55; // [xsp+100h] [xbp-70h]
  void *v56; // [xsp+108h] [xbp-68h]
  __int64 v57; // [xsp+110h] [xbp-60h]
  bool v58; // [xsp+11Fh] [xbp-51h]
  __int64 *v59; // [xsp+120h] [xbp-50h]
  int v60; // [xsp+128h] [xbp-48h]
  int v61; // [xsp+12Ch] [xbp-44h]
  __int64 v62; // [xsp+130h] [xbp-40h]
  __int64 v63; // [xsp+138h] [xbp-38h]
  __int64 v64; // [xsp+140h] [xbp-30h]
  __int64 v65; // [xsp+148h] [xbp-28h]
  __int64 v66; // [xsp+150h] [xbp-20h]
  __int64 v67; // [xsp+158h] [xbp-18h]
 
  v67 = *(_QWORD *)__stack_chk_guard_ptr;
  v47 = a1;
  v46 = a2;
  v45 = objc_retain(&stru_10000C078);
  v44 = 18;
  v2 = objc_msgSend(off_1000112D0, (const char *)off_100011290, 1LL);
  v48 = objc_retainAutoreleasedReturnValue(v2);
  v63 = v48;
  v49 = &v64;
  v50 = (const char *)off_100011290;
  v51 = off_1000112D0;
  v40 = -1933834049;
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          while ( 1 )
          {
            while ( 1 )
            {
              while ( 1 )
              {
                while ( v40 == -1944675086 )
                {
                  v23 = x_24 * (x_24 - 1) % 2u == 0;
                  if ( ((unsigned __int8)v23 & (y_25 < 10) | v23 ^ (y_25 < 10)) & 1 )
                    v24 = -484710506;
                  else
                    v24 = -757913245;
                  v40 = v24;
                }
                if ( v40 != -1933834049 )
                  break;
                v3 = objc_msgSend(v51, v50, 3LL);
                v52 = objc_retainAutoreleasedReturnValue(v3);
                v40 = -1240448313;
              }
              if ( v40 != -1917278325 )
                break;
              v40 = 1916623537;
            }
            if ( v40 != -1863636706 )
              break;
            if ( v58 )
              v27 = -1295475565;
            else
              v27 = -706815919;
            v40 = v27;
          }
          if ( v40 != -1847141909 )
            break;
          v10 = objc_msgSend(v55, v54);
          if ( v53 >= (unsigned __int64)v10 )
            v11 = 1801130365;
          else
            v11 = 1380523063;
          v40 = v11;
        }
        if ( v40 != -1846767803 )
          break;
        v40 = -267481379;
      }
      if ( v40 != -1502917571 )
        break;
      v54 = (const char *)off_1000112A0;
      v55 = v43;
      v40 = -1847141909;
    }
    if ( v40 == -1361227290 )
      break;
    switch ( v40 )
    {
      case -1295475565:
        v44 += 10;
        v40 = 1987329712;
        break;
      case -1240448313:
        v4 = v52;
        *v49 = v52;
        v5 = objc_msgSend(off_1000112D0, (const char *)off_100011290, 5LL);
        v6 = objc_retainAutoreleasedReturnValue(v5);
        v65 = v6;
        v7 = objc_msgSend(off_1000112D0, (const char *)off_100011290, 18LL);
        v8 = objc_retainAutoreleasedReturnValue(v7);
        v66 = v8;
        v9 = objc_msgSend(off_1000112D8, (const char *)off_100011298, &v63, 4LL);
        v43 = (void *)objc_retainAutoreleasedReturnValue(v9);
        objc_release(v8);
        objc_release(v6);
        objc_release(v4);
        objc_release(v48);
        v42 = 0;
        v40 = -381231803;
        break;
      case -1088106110:
        v40 = -1361227290;
        break;
      case -1009849083:
        v61 = v60 + 1;
        v40 = -792637388;
        break;
      case -792637388:
        v42 = v61;
        v40 = -381231803;
        break;
      case -757913245:
        v40 = -484710506;
        break;
      case -706815919:
        v40 = 975706093;
        break;
      case -484710506:
        v58 = v41 == v44;
        v25 = x_24 * (x_24 - 1) % 2u == 0;
        if ( (!v25 ^ (y_25 >= 10) | (v25 && y_25 < 10)) & 1 )
          v26 = -1863636706;
        else
          v26 = -757913245;
        v40 = v26;
        break;
      case -381231803:
        v53 = v42;
        v40 = -1502917571;
        break;
      case -267481379:
        v56 = v43;
        v57 = v42;
        v14 = x_24 * (x_24 - 1) % 2u == 0;
        if ( ((unsigned __int8)v14 & (y_25 < 10) | v14 ^ (y_25 < 10)) & 1 )
          v15 = -1917278325;
        else
          v15 = -1846767803;
        v40 = v15;
        break;
      case 265667512:
        v60 = v42;
        v30 = x_24 * (x_24 - 1) % 2u == 0;
        if ( (!v30 ^ (y_25 >= 10) | (v30 && y_25 < 10)) & 1 )
          v31 = 1998138173;
        else
          v31 = 1042960370;
        v40 = v31;
        break;
      case 543048662:
        NSLog(&stru_10000C0B8);
        NSLog(&stru_10000C0D8);
        v34 = x_24 * (x_24 - 1) % 2u == 0;
        if ( ((unsigned __int8)v34 & (y_25 < 10) | v34 ^ (y_25 < 10)) & 1 )
          v35 = -1088106110;
        else
          v35 = 1393219629;
        v40 = v35;
        break;
      case 818848043:
        v37 = objc_msgSend(v56, (const char *)off_1000112A8, v57);
        v38 = (void *)objc_retainAutoreleasedReturnValue(v37);
        v39 = (unsigned __int64)objc_msgSend(v38, (const char *)off_1000112B0);
        objc_release(v38);
        v41 = v39;
        v40 = 1041770448;
        break;
      case 975706093:
        v28 = x_24 * (x_24 - 1) % 2u == 0;
        if ( ((unsigned __int8)v28 & (y_25 < 10) | v28 ^ (y_25 < 10)) & 1 )
          v29 = 265667512;
        else
          v29 = 1042960370;
        v40 = v29;
        break;
      case 1041770448:
        v18 = objc_msgSend(v56, (const char *)off_1000112A8, v57);
        v19 = (void *)objc_retainAutoreleasedReturnValue(v18);
        v20 = (unsigned __int64)objc_msgSend(v19, (const char *)off_1000112B0);
        objc_release(v19);
        v41 = v20;
        v21 = x_24 * (x_24 - 1) % 2u == 0;
        if ( (!v21 ^ (y_25 >= 10) | (v21 && y_25 < 10)) & 1 )
          v22 = 2069967268;
        else
          v22 = 818848043;
        v40 = v22;
        break;
      case 1042960370:
        v40 = 265667512;
        break;
      case 1146841418:
        v32 = x_24 * (x_24 - 1) % 2u == 0;
        if ( (v32 ^ (y_25 < 10) | (v32 && y_25 < 10)) & 1 )
          v33 = 543048662;
        else
          v33 = 1393219629;
        v40 = v33;
        break;
      case 1380523063:
        v12 = x_24 * (x_24 - 1) % 2u == 0;
        if ( ((unsigned __int8)v12 & (y_25 < 10) | v12 ^ (y_25 < 10)) & 1 )
          v13 = -267481379;
        else
          v13 = -1846767803;
        v40 = v13;
        break;
      case 1393219629:
        NSLog(&stru_10000C0B8);
        NSLog(&stru_10000C0D8);
        v40 = 543048662;
        break;
      case 1801130365:
        v62 = v45;
        v40 = 1146841418;
        break;
      case 1916623537:
        v16 = x_24 * (x_24 - 1) % 2u == 0;
        if ( (v16 ^ (y_25 < 10) | (v16 && y_25 < 10)) & 1 )
          v17 = 1041770448;
        else
          v17 = 818848043;
        v40 = v17;
        break;
      case 1987329712:
        v59 = &v45;
        v40 = 2123926658;
        break;
      case 1998138173:
        v40 = -1009849083;
        break;
      case 2069967268:
        v40 = -1944675086;
        break;
      case 2123926658:
        objc_storeStrong(v59);
        v40 = -706815919;
        break;
    }
  }
  objc_storeStrong(&v43);
  return objc_storeStrong(&v45);
}

总结

简单的入门文章,希望能帮助到你。

最后给大家准备了一份大礼包!

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

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

相关文章

【MybatisPlus快速入门】—— 拓展入门

逻辑删除 前面我们完成了基本的增删改查操作&#xff0c;但是对于删除操作来说&#xff0c;我们思考一个问题&#xff0c;在实际开发中我们真的会将数据完成从数据库中删除掉么&#xff1f;很多情况下我们是需要保留要删除的数据用来总结统计的&#xff0c;所以我们是不能将数…

从零学习SDK(5)SDK文档的学习和参考

要想充分利用SDK的优势&#xff0c;仅仅下载和安装SDK是不够的&#xff0c;还需要学习和参考SDK提供的文档和资源。文档和资源是SDK的重要组成部分&#xff0c;它们可以帮助开发者掌握SDK的基本概念、结构、用法、限制和最佳实践&#xff0c;以及解决常见的问题和错误。 查找…

(数字图像处理MATLAB+Python)第三章图像基本运算-第二节:图像代数运算

文章目录一&#xff1a;图像算数运算&#xff08;1&#xff09;加法运算A&#xff1a;概述B&#xff1a;程序&#xff08;2&#xff09;减法运算A&#xff1a;概述B&#xff1a;程序&#xff08;3&#xff09;乘法运算A&#xff1a;概述B&#xff1a;程序&#xff08;4&#xf…

C++模板基础(九)

完美转发与 lambda 表达式模板 void f(int& input) {std::cout << "void f(int& input)\t" << input << \n; }void f(int&& input) {std::cout << "void f(int&& input)\t" << input << \n;…

MYSQL8窗口函数

MYSQL8窗口函数MYSQL8窗口函数窗口函数分类序号函数--排行榜row_number()示例rank()示例dense_rank()示例partition by对每个分区内的行进行排名不加partition by全局排序开窗聚合函数分布函数CUME_DIST()PERCENT_RANK()前后函数LAG()的用法LEAD()头尾函数其他函数NTH_VALUE()N…

用Abp实现两步验证(Two-Factor Authentication,2FA)登录(二):Vue网页端开发

文章目录发送验证码登录退出登录界面控件获取用户信息功能项目地址前端代码的框架采用vue.js elementUI 这套较为简单的方式实现&#xff0c;以及typescript语法更方便阅读。首先添加全局对象&#xff1a; loginForm: 登录表单对象 twoFactorData: 两步验证数据&#xff0c; …

跨平台应用开发进阶(五十九):uni-app实现视屏播放小窗功能

文章目录一、前言二、解决方案三、拓展阅读一、前言 在业务功能开发过程中&#xff0c;需要实现视频直播、播放小窗功能。鉴于目前通过接入火山webSDK实现视频直播、点播功能。需要火山协助配合改造实现小窗功能。 uni-app插件市场也提供了若干插件&#xff0c;经试用效果并不…

从二叉树的角度看快速排序

快速排序本质上可以看作二叉树的前序遍历 快速排序是先将一个元素排好序&#xff0c;然后再将剩下的元素排好序 核心思路依然是分治 快排整体思路 准确的可以说是治分 > 先治 得到分界点后 再分 治&#xff1a;双指针技巧&#xff08;左右指针或者快慢指针&#xff0c;…

【Docker】11、IDEA集成Docker插件实现一键部署SpringBoot项目

日常开发项目的过程中&#xff0c;我们每次需要部署线上的时候&#xff0c;都需要安装一大堆的运行环境&#xff0c;例如&#xff1a;JDK、MySQL、Redis 等&#xff0c;非常花费时间、我们可以使用 Docker 的容器技术&#xff0c;方便快捷地搭建项目启动所需要的运行环境&#…

【微服务笔记15】微服务组件之Config配置中心实现用户认证、配置属性加解密

这篇文章&#xff0c;主要介绍微服务组件之Config配置中心实现用户认证、配置属性加解密。 目录 一、用户认证 1.1、引入security依赖 1.2、服务端ConfigServer添加访问配置 1.3、客户端ConfigClient添加访问配置 二、配置属性加解密 2.1、对称加密 &#xff08;1&#…

逍遥自在学C语言 | 位运算符^的高级用法

前言 在上一篇文章中&#xff0c;我们介绍了|运算符的高级用法&#xff0c;本篇文章&#xff0c;我们将介绍^ 运算符的一些高级用法。 一、人物简介 第一位闪亮登场&#xff0c;有请今后会一直教我们C语言的老师 —— 自在。 第二位上场的是和我们一起学习的小白程序猿 —— …

windows系统管理_文件系统授权规则

NTFS 权限规则 NFTS 权限有一些隐含规则&#xff0c;用户最终有效权限受这些规则的影响&#xff0c;了解并运用这些规则&#xff0c;才能 灵活的分配权限&#xff0c;符合实际需求。 1 权限的累加 如果在某个文件或文件夹的访问控制列表中为某个用户分配了操作权限&#xff…

猿辅导学员入选国家队,竞赛老师成为“最强辅助”

3月31日&#xff0c;国际数学奥林匹克竞赛&#xff08;IMO&#xff09;国家队名单正式出炉&#xff0c;猿辅导学员王淳稷、孙启傲分别以第一名和第二名的成绩位列其中&#xff0c;今年7月&#xff0c;他们将出征日本&#xff0c;代表中国参赛&#xff0c;为国争光。 自2020年以…

理解 与 计算 物联网产品的电池使用寿命

本文带你理解电池的容量以及教会你如何计算使用电池的产品的工作时长前言 在物联网领域&#xff0c;在保证产品性能的前提下&#xff0c;产品的功耗是做得越来越低&#xff0c;针对物联网领域的低功耗无线芯片的功耗也是越来越低。 作为研发人员&#xff0c;除了能够设计出满…

巧用千寻位置GNSS软件|点测量采集技巧

点测量是测量中重要的节点&#xff0c;在测量工作的信息处理分析中发挥着重要作用。本期将给各位带来使用千寻位置GNSS软件采集地形点、控制点、快速点、连续点、房角点和倾斜点的操作技巧。地形点地形点的设置如图 5.1-9所 示&#xff0c;每次采集一个点&#xff0c;该点需要满…

Docker通过Nginx容器代理部署Vue项目

一、打包构建dist 在vue.config.js 添加入口等配置&#xff1a; pages: {index: {// 入口entry: src/main.js}}, lintOnSave: false, publicPath: ./ 在package.json文件中编写build构建&#xff1a; 然后运行: npm run build 在项目根目录下就有构建好的dist包&#xff0…

物流路由线路配载前端算法逻辑实现方案

作者&#xff1a;京东物流 柳宏 1.前置知识 1.1 基本概念 1.1.1 配载 配载代表着某条线路是否具有发往某个方向&#xff08;区域、省市县、分拣等&#xff09;的能力&#xff0c;也可以说是网点&#xff08;分拣中心&#xff09;是否具有承载配载所指方向货物的能力。一般网…

Go 构建基础的事件调度器

&#x1f447;我在这儿 当我们需要在一段时间后的特定时间或间隔运行任务时&#xff0c;我们需要使用任务调度系统来运行任务&#xff1a;例如发送电子邮件、推送通知、午夜关闭账户、清空表格等。在本文中&#xff0c;我们将构建一个基本的事件调度程序&#xff0c;使用数据库…

基于springboot和ajax的简单项目 02.一直会出现的页面的上一页,下一页,分页与总页数 (下)

在各种功能中会一直出现页面分页的问题。 对此&#xff0c;可以使用pojo对象&#xff0c;来一直管理页面分页的功能。 01.创建相关的pojo对象。 由于属性是来辅助sql语句的&#xff0c;这个pojo对象。 Setter Getter ToString NoArgsConstructorpublic class PageObject<T&…

MySQL数据库实现主从同步

安装MySQL数据库8.0.32 前言 今天来学习数据库主从同步的原理及过程&#xff0c;数据库主要是用来存储WEB数据&#xff0c;在企业当中是极为重要的&#xff0c;下面一起来看下。 1.1 数据库做主从的目的 MySQL主从复制在中小企业&#xff0c;大型企业中广泛使用&#xff0c…