MFC逆向之CrackMe Level3 过反调试 + 写注册机

今天我来分享一下,过反调试的方法以及使用IDA还原代码 + 写注册机的过程

由于内容太多,我准备分为两个帖子写,这个帖子主要是写IDA还原代码,下一个帖子是写反调试的分析以及过反调试和异常

这个CrackMe Level3是一个朋友发我的,我也不知道他在哪里弄的,我感觉挺好玩的,对反调试 异常 以及代码还原的学习有一些帮助

调试器:X64和OD

反编译工具:IDA

PE工具:Detect It Easy

反调试插件:OD的StrongOD和虫子的ScyllaHide

ARK工具:Pchunter

MFC工具:MfcSpy

初步分析

第一步先看看PE文件 工具说:软件是使用2008的MFC写的

上面得知是MFC写的软件,我们可以利用MFC的RTTI(动态类型识别)获取信息,如果不是MFC写的,我们可以运行一下软件看看,有没有报错信息

当然这个软件,输入注册码点击注册没有任何提示

 

打开调试器附加看看字符串,结果软件会闪退,无法附加,估计是有反调试,遇到这种情况我有三种方式可以解决

第一种:静态分析解决反调试

第二种:使用ARK工具把软件暂停,然后在用调试器附加

第三种:直接使用调试器打开程序,让软件断到入口或者系统断点

我们先使用第二种吧,因为X32调试器对中文字符串的支持不是很好,我没有装插件,所以先用OD看看字符串吧

验证函数中有一个异常 OD的反汇编已经出现了BUG,可以使用删除分析,我这里就不删除了 直接打开IDA F5吧 

 

虽然不能F5 但是我们可以很清晰的看到,两个GetWindowText 估计一个是获取用户名 一个是获取密码

至于为什么不能F5 是因为有一个jmp [ebx + 0xXXX] 这样的代码 IDA在解析代码的时候 它不知道跳到那里去 导致无法解析

我们直接把这个Jmp [ebp + var_8A8] 给nop掉就好了 然后删除这个函数的分析 接着在把这个函数分析为代码即可

我们可以向上看,在OD反汇编的时候也是到这个位置 反汇编失败了

下面是IDA F5后的代码 很明显 这IDA还原出来的根本不能用,这是需要我们进行修理变量的,另外我们给它重新命名一下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

int __thiscall sub_401810(CWnd *this)

{

  CWnd *DlgItem; // eax

  CWnd *v2; // eax

  int result; // eax

  char *v4; // [esp+10h] [ebp-8C8h]

  CHAR *v5; // [esp+14h] [ebp-8C4h]

  unsigned int v6; // [esp+18h] [ebp-8C0h]

  unsigned __int8 v8; // [esp+21h] [ebp-8B7h]

  unsigned __int8 v9; // [esp+22h] [ebp-8B6h]

  unsigned __int8 v10; // [esp+23h] [ebp-8B5h]

  int k; // [esp+24h] [ebp-8B4h]

  int j; // [esp+28h] [ebp-8B0h]

  int i; // [esp+2Ch] [ebp-8ACh]

  int v14; // [esp+34h] [ebp-8A4h]

  int v15; // [esp+34h] [ebp-8A4h]

  char v16; // [esp+38h] [ebp-8A0h] BYREF

  int v17[6]; // [esp+39h] [ebp-89Fh] BYREF

  char v18; // [esp+51h] [ebp-887h]

  char v19; // [esp+53h] [ebp-885h]

  char v20; // [esp+54h] [ebp-884h]

  int v21; // [esp+55h] [ebp-883h]

  int v22[5]; // [esp+59h] [ebp-87Fh] BYREF

  char v23; // [esp+6Dh] [ebp-86Bh]

  int v24; // [esp+70h] [ebp-868h]

  char v25; // [esp+74h] [ebp-864h]

  int v26; // [esp+75h] [ebp-863h]

  int v27; // [esp+79h] [ebp-85Fh]

  int v28; // [esp+7Dh] [ebp-85Bh]

  int v29; // [esp+81h] [ebp-857h]

  int v30; // [esp+85h] [ebp-853h]

  int v31; // [esp+89h] [ebp-84Fh]

  char v32; // [esp+8Dh] [ebp-84Bh]

  char v33; // [esp+93h] [ebp-845h]

  char v34; // [esp+94h] [ebp-844h]

  int v35; // [esp+95h] [ebp-843h]

  int v36[5]; // [esp+99h] [ebp-83Fh] BYREF

  char v37; // [esp+ADh] [ebp-82Bh]

  CHAR String[1028]; // [esp+B0h] [ebp-828h] BYREF

  int v39; // [esp+4B4h] [ebp-424h]

  CHAR v40[1028]; // [esp+4B8h] [ebp-420h] BYREF

  CPPEH_RECORD ms_exc; // [esp+8C0h] [ebp-18h]

  MEMORY[0] = 6530;

  ms_exc.registration.TryLevel = -2;

  v33 = sub_402D60();

  v14 = sub_402C60(v33);

  sub_402750(v14);

  v26 = 0;

  v27 = 0;

  v28 = 0;

  v29 = 0;

  v30 = 0;

  v31 = 0;

  v32 = 0;

  v35 = 0;

  memset(v36, 0, sizeof(v36));

  v37 = 0;

  v21 = 0;

  memset(v22, 0, sizeof(v22));

  v23 = 0;

  v25 = 48;

  v34 = 66;

  v20 = 98;

  for ( i = 1; i < 26; ++i )

  {

    *(&v25 + i) = *((_BYTE *)&v24 + i + 3) + 1;

    *(&v34 + i) = *(&v33 + i) + 1;

    *(&v20 + i) = *(&v19 + i) + 1;

  }

  CWnd::UpdateData(this, 1);

  memset(String, 0, 1024);

  memset(v40, 0, 1024);

  ms_exc.registration.Next = (struct _EH3_EXCEPTION_REGISTRATION *)1024;

  ms_exc.exc_ptr = (EXCEPTION_POINTERS *)String;

  DlgItem = CWnd::GetDlgItem(this, 1000);

  CWnd::GetWindowTextA(DlgItem, (LPSTR)ms_exc.exc_ptr, (int)ms_exc.registration.Next);

  ms_exc.registration.Next = (struct _EH3_EXCEPTION_REGISTRATION *)1024;

  ms_exc.exc_ptr = (EXCEPTION_POINTERS *)v40;

  v2 = CWnd::GetDlgItem(this, 1001);

  result = CWnd::GetWindowTextA(v2, (LPSTR)ms_exc.exc_ptr, (int)ms_exc.registration.Next);

  if ( String[7] )

  {

    result = String[8];

    if ( !String[8] && v40[23] && !v40[24] )

    {

      v39 = 16;

      v24 = 32;

      for ( j = 0; j < 8; ++j )

      {

        String[j] ^= j;

        String[j] ^= *(_BYTE *)(j + v39);

        String[j] ^= *(_BYTE *)(j + v24);

      }

      v16 = 0;

      memset(v17, 0, sizeof(v17));

      v18 = 0;

      for ( k = 0; k < 8; ++k )

      {

        v10 = (unsigned __int8)(String[k] & 0xE0) / 32;

        v8 = (String[k] & 0x1C) / 4;

        v9 = String[k] & 3;

        if ( k % 3 == 2 )

        {

          *(&v16 + 3 * k) = *(&v25 + v9);

          *((_BYTE *)v17 + 3 * k) = *((_BYTE *)v36 + v10 + 3);

          *((_BYTE *)v17 + 3 * k + 1) = *((_BYTE *)&v22[2] + v8 + 3);

        }

        if ( k % 3 == 1 )

        {

          *(&v16 + 3 * k) = *((_BYTE *)&v36[2] + v10 + 3);

          *((_BYTE *)v17 + 3 * k) = *((_BYTE *)v22 + v8 + 3);

          *((_BYTE *)v17 + 3 * k + 1) = *(&v25 + v9);

        }

        if ( !(k % 3) )

        {

          *(&v16 + 3 * k) = *((_BYTE *)&v36[2] + v8 + 3);

          *((_BYTE *)v17 + 3 * k) = *((_BYTE *)v22 + v9 + 3);

          *((_BYTE *)v17 + 3 * k + 1) = *(&v25 + v10);

        }

      }

      sub_401790();

      v33 = sub_402D90();

      v15 = sub_402C60(v33);

      sub_4028A0(v15);

      v6 = 24;

      v5 = v40;

      v4 = &v16;

      while ( v6 >= 4 )

      {

        result = (int)v5;

        if ( *(_DWORD *)v4 != *(_DWORD *)v5 )

          return result;

        v6 -= 4;

        v5 += 4;

        v4 += 4;

      }

      return CWnd::MessageBoxA(this, &Text, 0, 0);

    }

  }

  return result;

}

1.根据循环可以知道对应数组大小和数组首地址

2.根据MemSet也可以知道对应数组的大小和数组首地址

3.根据GetWindowsText也可以知道数组的大小

修正变量要结合代码怎么去操作这个变量的 根据它的逻辑来猜测大小

这是变量重命名后的汇编代码

经过修理后的IDA F5代码 可以看到基本上很清晰了 效果跟源代码应该很接近

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

int __thiscall sub_401810(CWnd *this)

{

  CWnd *DlgItem; // eax

  CWnd *v2; // eax

  int result; // eax

  char *pFinalKey_1; // [esp+10h] [ebp-8C8h]

  char *pGetWindowTextString1_1; // [esp+14h] [ebp-8C4h]

  unsigned int Var24_1; // [esp+18h] [ebp-8C0h]

  unsigned __int8 Var8_1; // [esp+21h] [ebp-8B7h]

  unsigned __int8 Var9_1; // [esp+22h] [ebp-8B6h]

  unsigned __int8 Var10_1; // [esp+23h] [ebp-8B5h]

  int K; // [esp+24h] [ebp-8B4h]

  int J; // [esp+28h] [ebp-8B0h]

  int I; // [esp+2Ch] [ebp-8ACh]

  int Unknown2_1; // [esp+34h] [ebp-8A4h]

  int unknown1; // [esp+34h] [ebp-8A4h]

  char FinalKey_1[26]; // [esp+38h] [ebp-8A0h] BYREF

  char SecretKey3[28]; // [esp+54h] [ebp-884h] BYREF

  int v19; // [esp+70h] [ebp-868h]

  char SecretKey1[31]; // [esp+74h] [ebp-864h] BYREF

  char Unknown3_1; // [esp+93h] [ebp-845h]

  char SecretKey2[28]; // [esp+94h] [ebp-844h] BYREF

  char GetWindowTextString2_1[1028]; // [esp+B0h] [ebp-828h] BYREF

  int v24; // [esp+4B4h] [ebp-424h]

  char GetWindowTextString1[1028]; // [esp+4B8h] [ebp-420h] BYREF

  CPPEH_RECORD ms_exc; // [esp+8C0h] [ebp-18h]

  MEMORY[0] = 6530;

  ms_exc.registration.TryLevel = -2;

  Unknown3_1 = sub_402D60();

  Unknown2_1 = sub_402C60(&dword_42FA04, Unknown3_1);

  sub_402750(Unknown2_1);

  memset(&SecretKey1[1], 0, 25);

  memset(&SecretKey2[1], 0, 25);

  memset(&SecretKey3[1], 0, 25);

  SecretKey1[0] = 48;

  SecretKey2[0] = 66;

  SecretKey3[0] = 98;

  for ( I = 1; I < 26; ++I )

  {

    SecretKey1[I] = SecretKey1[I - 1] + 1;

    SecretKey2[I] = SecretKey2[I - 1] + 1;

    SecretKey3[I] = SecretKey3[I - 1] + 1;

  }

  CWnd::UpdateData(this, 1);

  memset(GetWindowTextString2_1, 0, 1024);

  memset(GetWindowTextString1, 0, 1024);

  ms_exc.registration.Next = (struct _EH3_EXCEPTION_REGISTRATION *)1024;

  ms_exc.exc_ptr = (EXCEPTION_POINTERS *)GetWindowTextString2_1;

  DlgItem = CWnd::GetDlgItem(this, 1000);

  CWnd::GetWindowTextA(DlgItem, (LPSTR)ms_exc.exc_ptr, (int)ms_exc.registration.Next);

  ms_exc.registration.Next = (struct _EH3_EXCEPTION_REGISTRATION *)1024;

  ms_exc.exc_ptr = (EXCEPTION_POINTERS *)GetWindowTextString1;

  v2 = CWnd::GetDlgItem(this, 1001);

  result = CWnd::GetWindowTextA(v2, (LPSTR)ms_exc.exc_ptr, (int)ms_exc.registration.Next);

  if ( GetWindowTextString2_1[7] )

  {

    result = GetWindowTextString2_1[8];

    if ( !GetWindowTextString2_1[8] && GetWindowTextString1[23] && !GetWindowTextString1[24] )

    {

      v24 = 16;

      v19 = 32;

      for ( J = 0; J < 8; ++J )

      {

        GetWindowTextString2_1[J] ^= J;

        GetWindowTextString2_1[J] ^= *(_BYTE *)(J + v24);

        GetWindowTextString2_1[J] ^= *(_BYTE *)(J + v19);

      }

      memset(FinalKey_1, 0, sizeof(FinalKey_1));

      for ( K = 0; K < 8; ++K )

      {

        Var10_1 = (unsigned __int8)(GetWindowTextString2_1[K] & 0xE0) / 32;

        Var8_1 = (GetWindowTextString2_1[K] & 0x1C) / 4;

        Var9_1 = GetWindowTextString2_1[K] & 3;

        if ( K % 3 == 2 )

        {

          FinalKey_1[3 * K] = SecretKey1[Var9_1];

          FinalKey_1[3 * K + 1] = SecretKey2[Var10_1 + 8];

          FinalKey_1[3 * K + 2] = SecretKey3[Var8_1 + 16];

        }

        if ( K % 3 == 1 )

        {

          FinalKey_1[3 * K] = SecretKey2[Var10_1 + 16];

          FinalKey_1[3 * K + 1] = SecretKey3[Var8_1 + 8];

          FinalKey_1[3 * K + 2] = SecretKey1[Var9_1];

        }

        if ( !(K % 3) )

        {

          FinalKey_1[3 * K] = SecretKey2[Var8_1 + 16];

          FinalKey_1[3 * K + 1] = SecretKey3[Var9_1 + 8];

          FinalKey_1[3 * K + 2] = SecretKey1[Var10_1];

        }

      }

      sub_401790();

      Unknown3_1 = sub_402D90();

      unknown1 = sub_402C60(&dword_42FA04, Unknown3_1);

      sub_4028A0(unknown1);

      Var24_1 = 24;

      pGetWindowTextString1_1 = GetWindowTextString1;

      pFinalKey_1 = FinalKey_1;

      while ( Var24_1 >= 4 )

      {

        result = (int)pGetWindowTextString1_1;

        if ( *(_DWORD *)pFinalKey_1 != *(_DWORD *)pGetWindowTextString1_1 )

          return result;

        Var24_1 -= 4;

        pGetWindowTextString1_1 += 4;

        pFinalKey_1 += 4;

      }

      return CWnd::MessageBoxA(this, &Text, 0, 0);

    }

  }

  return result;

}

我们可以看到上面的代码中还是有两个变量的值是错误的 一个是V24 一个是V19 为什么是错误的呢?

我们可以结合下面的循环代码,下面代码中用到V24 是*(BYTE*)(J+V24);    用到V19 是*(BYTE*)(J+V19);

这很明显是一个数组 大小是8个字节

看下面代码中 V19和V24是来源于AbnormalVariable这个变量的值 + 16和+32的位置的

这也就是下面代码中V19和V24数组的值的来源

最终的C代码 算法还原完成

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

int main()

{

    char SecretKey1[28];

    char SecretKey2[28];

    char SecretKey3[28];

    memset(SecretKey1,0,sizeof(SecretKey1));

    memset(SecretKey2,0,sizeof(SecretKey2));

    memset(SecretKey3,0,sizeof(SecretKey3));

    SecretKey1[0] = 48;

    SecretKey2[0] = 66;

    SecretKey3[0] = 98;

    for (int I = 1; I < 26; ++I)

    {

        SecretKey1[I] = SecretKey1[I - 1] + 1;

        SecretKey2[I] = SecretKey2[I - 1] + 1;

        SecretKey3[I] = SecretKey3[I - 1] + 1;

    }

    char GetWindowTextString1[1024];

    char GetWindowTextString2_1[1024];

    memset(GetWindowTextString1,0,1024);

    memset(GetWindowTextString2_1, 0, 1024);

    strcpy(GetWindowTextString2_1,"12345678");

    char v24[24] = { 0x00,0x00,0x88,0x85,0xBB,0xF7,0xFF,0xFF,0x0F,0xB6,0x8D,0xBB,0xF7,0xFF,0xFF,0xB8,0x04,0xFA,0x42,0x00,0xE8,0xAD };

    char v19[24] = { 0xB8,0x04,0xFA,0x42,0x00,0xE8,0xAD,0x13,0x00,0x00,0x89,0x85,0x5C,0xF7,0xFF,0xFF,0x8B,0x95,0x5C,0xF7,0xFF,0xFF };

    for (int J = 0; J < 8; ++J)

    {

        GetWindowTextString2_1[J] ^= J;

        GetWindowTextString2_1[J] ^= v24[J];

        GetWindowTextString2_1[J] ^= v19[J];

    }

    char FinalKey_1[26];

    memset(FinalKey_1,0,sizeof(FinalKey_1));

    for (int K = 0; K < 8; ++K)

    {

        char Var10_1 = (unsigned __int8)(GetWindowTextString2_1[K] & 0xE0) / 32;

        char Var8_1 = (GetWindowTextString2_1[K] & 0x1C) / 4;

        char Var9_1 = GetWindowTextString2_1[K] & 3;

        if (K % 3 == 2)

        {

            FinalKey_1[3 * K] = SecretKey1[Var9_1];

            FinalKey_1[3 * K + 1] = SecretKey2[Var10_1 + 8];

            FinalKey_1[3 * K + 2] = SecretKey3[Var8_1 + 16];

        }

        if (K % 3 == 1)

        {

            FinalKey_1[3 * K] = SecretKey2[Var10_1 + 16];

            FinalKey_1[3 * K + 1] = SecretKey3[Var8_1 + 8];

            FinalKey_1[3 * K + 2] = SecretKey1[Var9_1];

        }

        if (!(K % 3))

        {

            FinalKey_1[3 * K] = SecretKey2[Var8_1 + 16];

            FinalKey_1[3 * K + 1] = SecretKey3[Var9_1 + 8];

            FinalKey_1[3 * K + 2] = SecretKey1[Var10_1];

        }

    }

    //FinalKey_1 = 0x00aff3f8 "Tk4So33LrVj7Vl20KuRm3Xn3"

    system("pause");

    return 0;

}

1

2

用户名:12345678

注册码:Tk4So33LrVj7Vl20KuRm3Xn3

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu解决Failed to fetch https://... Could not resolve ‘某个源‘

在我使用sudo apt install subversion的时候遇到报错&#xff1a; 这个报错与Ubuntu操作系统的软件源配置文件有关系。错误提示显示无法解析“mirrors.shanhe.com”地址&#xff0c;这可能是由于更新软件包列表或下载软件包时出现的网络问题。 1.可以先更新一下源试试&#xf…

TCP/IP详解——UDP 协议

文章目录 1. UDP1.1 UDP 头部1.2 UDP 校验和1.3 UDP 传输过程1.4 UDP-Lite1.5 最大 UDP 数据报长度1.6 UDP 输入队列 1. UDP UDP&#xff1a;用户数据报协议&#xff08;User Datagram Protocol&#xff09;面向无连接的&#xff0c;也就是无需建立连接&#xff0c;传输不可靠。…

【LeetCode刷题笔记(7-1)】【Python】【四数之和】【哈希表】【中等】

文章目录 四数之和题目描述示例 1示例 2提示解决方案1&#xff1a;【四层遍历查找】解决方案2&#xff1a;【哈希表】【三层遍历】 结束语 四数之和 四数之和 题目描述 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件…

2023.12.15 FineBI与kettle

1.结构化就是可以用schema描述的数据,就是结构化数据,能转为二维表格, 如CSV,Excel, 2.半结构化就是部分可以转换为二维表格,如JSON,XML 3.非结构化数据,就是完全无法用二维表格表示的数据,如Word文档,Mp4,图片,等文件. kettle的流程 新建转换-构建流图-配置组件-保存运行 使…

spring boot集成mybatis和springsecurity实现登录认证功能

参考了很多网上优秀的教程&#xff0c;结合自己的理解&#xff0c;实现了登录认证功能&#xff0c;不打算把理论搬过来&#xff0c;直接上代码可能入门更快&#xff0c;文中说明都是基于我自己的理解写的&#xff0c;可能存在表述或者解释不对的情况&#xff0c;如果需要理论支…

机器学习中数据的特征表示

在实际应用中&#xff0c;数据的类型多种多样&#xff0c;比如文本、音频、图像、视频等。不同类型的数据&#xff0c;其原始特征的空间也不相同。比如一张灰度图像&#xff08;像素数量为 &#x1d437;&#xff09;的特征空间为 [0, 255]&#x1d437;&#xff0c;一个自然语…

统一观测丨使用 Prometheus 监控 Memcached 最佳实践

作者&#xff1a;啃唯 Memcached 简介 Memcached 是什么&#xff1f; Memcached 是一个免费开源、高性能、分布式内存对象缓存系统&#xff0c;支持将任意数据类型的 chunk 数据以键值对的方式存储。本质上 Memcached 是通用于所有的应用的&#xff0c;但最初用于存储被经常…

ArcGIS Pro SDK 右键获取选中的图层

需求&#xff1a; 获取右键选中的图层 解决方法&#xff1a; 地图页面获取选中的图形 // 获取所选要素 var firstFeatureLayer MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault(); 布局页面获取选中的地图框 Layout layout …

构建强大应用的引擎:深度解析Spring Boot Starter机制

目录 引言1. Spring Boot Starter机制1.1 什么是Spring Boot Starter1.2 为什么要使用Spring Boot Starter1.3.应用场景1.4.自动加载核心注解说明 2. 综合案例配置类制作控制功能实现 总结 引言 在当今互联网时代&#xff0c;构建高性能、可维护的应用已成为开发者的首要任务。…

在 Spring Boot 中发送邮件简单实现

Spring Boot 对于发送邮件这种常用功能也提供了开箱即用的 Starter&#xff1a;spring-boot-starter-mail。 通过这个 starter&#xff0c;只需要简单的几行配置就可以在 Spring Boot 中实现邮件发送&#xff0c;可用于发送验证码、账户激活等等业务场景。 本文将通过实际的案…

计算机网络快速刷题

自用//奈奎斯特定理和香农定理计算题 参考博客&#xff1a;UDP协议是什么&#xff1f;作用是什么&#xff1f; 肝了&#xff0c;整理了8张图详解ARP原理 【网络协议详解】——FTP系统协议&#xff08;学习笔记&#xff09; 在OSI参考模型中&am…

Nessus漏洞扫描报错:42873 - SSL Medium Strength Cipher Suites Supported (SWEET32)

个人搭建的windows server 2019服务器,被Nessus工具扫描出现三个漏洞,修复比较过程比较坎坷,特记录下 首先:报错信息: 42873 - SSL Medium Strength Cipher Suites Supported (SWEET32) 104743 - TLS Version 1.0 Protocol Detection 157288 - TLS Version 1.1 Protocol …

Linux的文件系统 内核结构

Linux的文件系统 Q1&#xff1a;什么是文件系统&#xff1f; A&#xff1a;在学术的角度下&#xff0c;文件系统指“操作系统用于明确存储设备组织文件的方法”&#xff0c;是“文件管理系统”的简称&#xff0c;本质也是代码&#xff0c;一段程序 Q2&#xff1a;文件系统&…

【FunASR】Paraformer语音识别-中文-通用-16k-离线-large-onnx

模型亮点 模型文件: damo/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorchParaformer-large长音频模型集成VAD、ASR、标点与时间戳功能&#xff0c;可直接对时长为数小时音频进行识别&#xff0c;并输出带标点文字与时间戳&#xff1a; ASR模型…

如何用 Cargo 管理 Rust 工程系列 乙

以下内容为本人的学习笔记&#xff0c;如需要转载&#xff0c;请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/__nvVZYti-G05QJHIp_f8Q 编译程序 这次我们用 cargo 来启动编译&#xff0c;cargo 提供了 build 指令来调度工具构建并输出软件。cargo build 只…

【MySQL学习之基础篇】约束

文章目录 1. 概述2. 基础约束3. 外键约束3.1. 介绍3.2. 外键的添加3.3. 外键删除和更新行为 1. 概述 概念&#xff1a; 约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。     目的&#xff1a; 保证数据库中数据的正确、有效性和完整性。 分类&#x…

对BIOS进行简单快速的设置更改,就能启用安全引导来安装Windows 11

本文介绍如何在UEFI/BIOS中启用安全引导&#xff0c;以便继续安装Windows 11。 如何启用安全引导 启用安全引导最简单的方法是通过UEFI/BIOS进行。它通常被列为BIOS中的众多选项之一&#xff0c;因此你只需打开它即可启用它。 1、启动&#xff0c;或重新启动你的电脑或笔记本…

Linux---链接命令

1. 链接命令的介绍 链接命令是创建链接文件&#xff0c;链接文件分为: 软链接硬链接 命令说明ln -s创建软链接ln创建硬链接 2. 软链接 类似于Windows下的快捷方式&#xff0c;当一个源文件的目录层级比较深&#xff0c;我们想要方便使用它可以给源文件创建一个软链接。 软…

深入理解 hash 和 history:网页导航的基础(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

怎样下载微博视频而不至于发生“403 Forbidden“现象?

近段时间不知道从什么时候开始&#xff0c;微博视频都不让从网页下载了。以前是看到有想要下载的微博视频&#xff0c;就点进去微博详情页用谷歌浏览器F12进入调试的方式&#xff0c;选“Network”->“Media”->重新F5刷新页面等待调试框里出现链接->在链接上鼠标右键…