iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >怎么使用c++实现异或加密
  • 108
分享到

怎么使用c++实现异或加密

2023-06-30 00:06:07 108人浏览 独家记忆
摘要

这篇文章主要介绍“怎么使用c++实现异或加密”,在日常操作中,相信很多人在怎么使用c++实现异或加密问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么使用c++实现异或加密”的疑惑有所帮助!接下来,请跟着小编

这篇文章主要介绍“怎么使用c++实现异或加密”,在日常操作中,相信很多人在怎么使用c++实现异或加密问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么使用c++实现异或加密”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

加密原理

由于展示最基本最简单的实现,使用算法加密就没用复杂的。如果使用比较复杂的加密,首先你在C++代码层面和汇编层面要有配套的代码,C++负责加密,汇编负责自我解密,否则你加密完了,结果加密后的PE文件自己又解密不了,这就很尴尬。

在所有加密算法,异或加密是最简单的,也是最好是实现的。我们来介绍异或加密的原理。

已知两个数AB,如果A xor B = C,则C xor B = A,其中xor表示异或运算符。如果不理解,这个是入门编程的最基本的知识,请自行补缺,这里我就不唠叨了。

异或加密的实现

下面是我们实现异或加密的相关函数:

// GNU AFFERO GENERAL PUBLIC LICENSE//Version 3, 19 November 2007//Copyright(C) 2007 Free Software Foundation, Inc.//Everyone is permitted to copyand distribute verbatim copies//of this license document, but changing it is not allowed.// Author : WingSummer (寂静的羽夏)//Warning: You can not use it for any commerical use,except you get // my AUTHORIZED FORM ME!This project is used for tutorial to teach// the beginners what is the PE structure and how the packer of the PE files works.BOOL CWingProtect::XORCodeSection(BOOL NeedReloc, BOOL FakeCode){    using namespace asmjit;    if (_lasterror != ParserError::Success) return FALSE;    auto filesize = peinfo.FileSize.QuadPart;    CodeHolder holder;    /// <summary>    /// PointerToRawData    /// </summary>    auto p = peinfo.PCodeSection->PointerToRawData;    /// <summary>    /// SizeOfRawData    /// </summary>    auto sizecode = peinfo.PCodeSection->SizeOfRawData;    auto repeat = sizecode;    BYTE* shellcode;    INT3264 ccount;    if (is64bit)    {        Environment env(Arch::kX64);        holder.init(env);        x86::Assembler a(&holder);        Label loop = a.newLabel();        x86::Mem mem;        mem.setSegment(x86::gs);        mem.setOffset(0x60);        //生成加密 shellcode,此处的 rax = ImageBase        a.push(x86::rcx);        a.push(x86::rdi);        //xor 解密        a.mov(x86::rax, mem);        a.mov(x86::rax, x86::qWord_ptr(x86::rax, 0x10));        a.mov(x86::rdi, x86::rax);        a.add(x86::rdi, peinfo.PCodeSection->VirtualAddress);        a.mov(x86::rcx, repeat);        a.bind(loop);        if (FakeCode) FakeProtect(a);        a.xor_(x86::byte_ptr(x86::rdi), 0x55);        a.inc(x86::rdi);        a.dec(x86::rcx);        a.test(x86::rcx, x86::rcx);        a.jnz(loop);        //确保此时 rax 或 eax 存放的是 ImageBase ,否则是未定义行为        if (NeedReloc)            RelocationSection(a);        a.pop(x86::rdi);        a.pop(x86::rcx);        a.ret();        shellcode = a.bufferData();        ccount = holder.codeSize();    }    else    {        Environment env(Arch::kX86);        holder.init(env);        x86::Assembler a(&holder);        Label loop = a.newLabel();        x86::Mem mem;        mem.setSegment(x86::fs);        mem.setOffset(0x30);        //生成加密 shellcode        a.push(x86::ecx);        a.push(x86::edi);        a.mov(x86::eax, mem);        a.mov(x86::eax, x86::dword_ptr(x86::eax, 0x8));        a.mov(x86::edi, x86::eax);        a.add(x86::edi, peinfo.PCodeSection->VirtualAddress);        a.mov(x86::ecx, repeat);        a.bind(loop);        if (FakeCode) FakeProtect(a);        a.xor_(x86::byte_ptr(x86::edi), 0x55);        a.inc(x86::edi);        a.dec(x86::ecx);        a.test(x86::ecx, x86::ecx);        a.jnz(loop);        //确保此时 rax 或 eax 存放的是 ImageBase ,否则是未定义行为        if (NeedReloc)            RelocationSection(a);        a.pop(x86::edi);        a.pop(x86::ecx);        a.ret();        shellcode = a.bufferData();        ccount = holder.codeSize();    }    //异或加密    auto se = (BYTE*)b;    for (UINT i = 0; i < repeat; i++)    {        se[i] ^= (BYTE)0x55;    }    //加密完毕,写 Shellcode    encryptInfo.XORDecodeShellCode = (UINT)peinfo.PointerOfWingSeciton;    auto ws = GetPointerByOffset(peinfo.WingSecitonBuffer, peinfo.PointerOfWingSeciton);    memcpy_s(ws, ccount, shellcode, ccount);    peinfo.PointerOfWingSeciton += ccount;    if (!NeedReloc)    {        auto tmp = (PIMAGE_SECTION_HEADER)TranModPEWapper(peinfo.PCodeSection);        tmp->Characteristics |= IMAGE_SCN_MEM_WRITE;    }    return TRUE;}

在C++代码层面,加密代码区内容相关的代码如下:

//异或加密auto se = (BYTE*)b;for (UINT i = 0; i < repeat; i++){    se[i] ^= (BYTE)0x55;}

^表示异或运算符,在汇编层面,以64位为例,实现如下所示:

a.mov(x86::rax, mem);a.mov(x86::rax, x86::qword_ptr(x86::rax, 0x10));a.mov(x86::rdi, x86::rax);a.add(x86::rdi, peinfo.PCodeSection->VirtualAddress);a.mov(x86::rcx, repeat);a.bind(loop);if (FakeCode) FakeProtect(a);a.xor_(x86::byte_ptr(x86::rdi), 0x55);a.inc(x86::rdi);a.dec(x86::rcx);a.test(x86::rcx, x86::rcx);a.jnz(loop);

可以看出来汇编写起来比写C++代码麻烦多了,里面有一些代码可能有一些其他的考虑,我们这里说一下:

首先是FakeProtect,这个就是生成花指令,这里不多说,后面在介绍。还有一个函数比较注意RelocationSection,这个函数是用来生成做重定位的汇编代码的,为什么要有这个函数呢?

比如我只有异或加密,我们是在硬编码的层面进行的加密,PE被加载进入的时候如果基址不和预想的那样,就会查是否有重定位表,如果有的话就解析并修复。但是,我们的代码是加密的,而重定位表没做修改,它就会错误的把被加密的硬编码进行重定位,这个是不能够允许的。所以我们需要摧毁重定位表,可以看到CWingProtect::Proctect里面有一个函数DestoryRelocation,这个作用就是用来销毁它的,不让PE加载器帮我们做重定位。

综上所述,我们需要自己做重定位,我们需要在汇编层面来实现重定位表的修复,我们来看一下相关代码:

//// GNU AFFERO GENERAL PUBLIC LICENSE//Version 3, 19 November 2007////Copyright(C) 2007 Free Software Foundation, Inc.//Everyone is permitted to copyand distribute verbatim copies//of this license document, but changing it is not allowed.// Author : WingSummer (寂静的羽夏)// //Warning: You can not use it for any commerical use,except you get // my AUTHORIZED FORM ME!This project is used for tutorial to teach// the beginners what is the PE structure and how the packer of the PE files works.void CWingProtect::RelocationSection(asmjit::x86::Assembler& a){    using namespace asmjit;    Label loop_xor = a.newLabel();    Label loop_reloc = a.newLabel();    Label loop_rt = a.newLabel();    Label endproc = a.newLabel();    auto rdd = peinfo.PDataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];    if (is64bit)    {        a.nop();        a.push(x86::rdi);        a.push(x86::rcx);        a.push(x86::rsi);        //征用 rsi        a.mov(x86::rsi, rdd.VirtualAddress);    //重定位表基址        a.add(x86::rsi, x86::rax);        a.push(x86::rdx);    //征用 rdx        a.push(x86::r10);        a.mov(x86::r10, peinfo.ImageBase);    //PE 加载后,该值会被重定位,只能写死        a.sub(x86::r10, x86::rax);        a.jz(endproc);        a.bind(loop_rt);        a.mov(x86::edi, x86::dword_ptr(x86::rsi));        //偏移基址地址        a.add(x86::rdi, x86::rax);        //此时 rdi 为加载到内存的虚拟基址地址        //计数        a.mov(x86::ecx, x86::dword_ptr(x86::rsi, 4));        a.sub(x86::ecx, 8);        a.shr(x86::ecx, 1);    //此时为重定位表的真实项目个数        a.add(x86::rsi, 8);    //将指针指向该索引下的第一个重定位项目        a.bind(loop_reloc);        a.dec(x86::rcx);        a.mov(x86::dx, x86::word_ptr(x86::rsi, x86::rcx, 1));        a.test(x86::dx, 0xF000);        a.jz(loop_reloc);        //contine;        a.and_(x86::edx, 0xFFF);        a.add(x86::rdx, x86::rdi);        a.sub(x86::qword_ptr(x86::rdx), x86::r10);    //修正        a.cmp(x86::rcx, 0);        a.ja(loop_reloc);        a.sub(x86::rsi, 8);    //重新指向表头        a.mov(x86::edx, x86::dword_ptr(x86::rsi, 4));        a.add(x86::rsi, x86::rdx);        //指向下一个        a.mov(x86::edx, x86::dword_ptr(x86::rsi));        a.test(x86::edx, x86::edx);        a.jnz(loop_rt);        a.bind(endproc);        a.pop(x86::r10);        a.pop(x86::rdx);        a.pop(x86::rsi);    //释放 rsi 自由身        a.pop(x86::rcx);        a.pop(x86::rdi);    }    else    {        a.push(x86::edi);        a.push(x86::ecx);        a.push(x86::esi);        //征用 rsi        a.mov(x86::esi, rdd.VirtualAddress);    //重定位表基址        a.add(x86::esi, x86::eax);        a.push(x86::edx);    //征用 edx        a.push((DWORD32)peinfo.ImageBase);    //x86寄存器没那么多,只能自己维护一个局部变量        a.sub(x86::dword_ptr(x86::esp), x86::rax);        a.jz(endproc);        a.bind(loop_rt);        a.mov(x86::edi, x86::dword_ptr(x86::esi));        //偏移基址地址        a.add(x86::edi, x86::eax);        //此时 rdi 为加载到内存的虚拟基址地址        //计数        a.mov(x86::ecx, x86::dword_ptr(x86::esi, 4));        a.sub(x86::ecx, 8);        a.shr(x86::ecx, 1);    //此时为重定位表的真实项目个数        a.add(x86::esi, 8);    //将指针指向该索引下的第一个重定位项目        a.bind(loop_reloc);        a.dec(x86::ecx);        a.mov(x86::dx, x86::word_ptr(x86::rsi, x86::ecx, 1));        a.test(x86::dx, 0xF000);        a.jz(loop_reloc);        //contine;        a.and_(x86::edx, 0xFFF);        a.add(x86::edx, x86::edi);        a.push(x86::eax);    //使用局部变量        a.mov(x86::eax, x86::dword_ptr(x86::esp, 4));    //注意被 push 了一个,所以加个偏移        a.sub(x86::dword_ptr(x86::edx), x86::eax);    //修正        a.pop(x86::eax);        a.cmp(x86::ecx, 0);        a.ja(loop_reloc);        a.sub(x86::esi, 8);    //重新指向表头        a.mov(x86::edx, x86::dword_ptr(x86::esi, 4));        a.add(x86::esi, x86::rdx);        //指向下一个        a.mov(x86::edx, x86::dword_ptr(x86::esi));        a.test(x86::edx, x86::edx);        a.jnz(loop_rt);        a.bind(endproc);        a.add(x86::esp, 4);        //释放局部变量        a.pop(x86::edx);        a.pop(x86::esi);    //释放 rsi 自由身        a.pop(x86::ecx);        a.pop(x86::edi);    }    //将所有的节全部改为可写    auto length = peinfo.NumberOfSections;    for (UINT i = 0; i < length; i++)    {        ((PIMAGE_SECTION_HEADER)TranModPEWapper(&peinfo.PSectionHeaders[i]))            ->Characteristics |= IMAGE_SCN_MEM_WRITE;    }}

对于以上代码你可能有一些疑问,我这里说一下:
为什么调用a.nop()来生成没有用的指令,这个是我用来方便调试我生成的ShellCode用的,否则会生成一大坨汇编到后来自己也不清楚自己在调试啥的,通过这个nop我就可以清楚的直到我到那里了,如果出错的话我也方便进行定位。
此函数最后生成完ShellCode之后又将所有的节全部改为可写属性,这是为什么呢?因为线性内存是有属性的,如果我没有将其设置可写,如果它是只读内存,如果我对它做重定位修改的话,就会报内存访问错误,导致程序崩溃。
怎么用汇编来解析重定位表,这里就不赘述了。

ShellCode 编写注意事项

在编写ShellCode代码的时候,请一定保证如下原则,避免一些麻烦,否则会出现出乎意料的错误:

  • 除了 eax / rax 其他寄存器用到的话,一定要注意保存好,因为其它函数调用有各种调用约定,一定不要影响它们,否则会出错。为什么要对 eax / rax 区别对待,因为通常来说它只用做返回值,调用函数返回结果一定会修改它,所以大可不必。

  • 在使用 ASMJIT 生成汇编的时候,使用类似 MOV 的指令的时候,一定要注意如果要写入多大的数据一定要在目标操作数体现数来,比如要移动 WORD 大小的话,用 ax 就不要用 eax,否则它正常生成汇编指令不报错,结果和你想生成的代码不一样。

  • 一定要注意堆栈平衡,这个是非常重要的东西,在64位尤甚,32位的操作系统也是十分注意堆栈平衡的。

到此,关于“怎么使用c++实现异或加密”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: 怎么使用c++实现异或加密

本文链接: https://www.lsjlt.com/news/326822.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么使用c++实现异或加密
    这篇文章主要介绍“怎么使用c++实现异或加密”,在日常操作中,相信很多人在怎么使用c++实现异或加密问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么使用c++实现异或加密”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-30
  • C#利用异或算法实现加密解密
    目录实践过程效果代码实践过程 效果 代码 public partial class Form1 : Form { public Form1() { ...
    99+
    2023-01-03
    C#异或算法实现加密解密 C# 异或算法 C# 加密解密
  • 使用c++实现异或加密的代码示例
    目录加密原理异或加密的实现ShellCode 编写注意事项加密原理 由于展示最基本最简单的实现,使用算法加密就没用复杂的。如果使用比较复杂的加密,首先你在C++代码层面和汇编层面要有...
    99+
    2024-04-02
  • 怎么使用PHP实现C语言中的异或加密算法
    本篇内容介绍了“怎么使用PHP实现C语言中的异或加密算法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、异或加密算法简介异或加密算法是一种...
    99+
    2023-07-05
  • 如何使用PHP实现C语言中的异或加密算法
    随着互联网的不断发展,网络安全问题越来越受到人们的关注,加密算法也越来越成为设计安全程序必不可少的组成部分。在很多程序开发中,我们需要对数据进行s安全的加密和解密,在PHP中,我们可以使用异或加密算法来保护数据的安全。本文将会详细介绍如何使...
    99+
    2023-05-14
  • VBS如何实现十六进制异或加密
    这篇文章主要为大家展示了“VBS如何实现十六进制异或加密”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“VBS如何实现十六进制异或加密”这篇文章吧。效果图:代码都封装成函数了,方便调用:复制代码 ...
    99+
    2023-06-08
  • Java怎么实现加密或解密PDF文档
    这篇文章主要介绍了Java怎么实现加密或解密PDF文档的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java怎么实现加密或解密PDF文档文章都会有所收获,下面我们一起来看看吧。PDF文档加密是一种用于保护文件内...
    99+
    2023-07-05
  • 怎么用对称加密算法实现C#数据加密
    这篇文章主要讲解了“怎么用对称加密算法实现C#数据加密”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用对称加密算法实现C#数据加密”吧!以下是关于对称加密算法的C#数据加密实现代码,大家...
    99+
    2023-06-18
  • c#中base64加密怎么实现
    在C#中实现Base64加密可以使用Convert.ToBase64String方法,示例如下: string plainText ...
    99+
    2024-04-08
    c#
  • c#中怎么实现sm4加密
    在C#中实现SM4加密可以通过使用第三方库来实现。一个常用的库是Bouncy Castle,可以通过NuGet安装。 首先,安装Bo...
    99+
    2024-04-02
  • 怎么使用python实现md5加密
    本文小编为大家详细介绍“怎么使用python实现md5加密”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么使用python实现md5加密”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。python实现MD5加密...
    99+
    2023-07-06
  • C语言怎么实现MD5加密
    这篇文章主要介绍“C语言怎么实现MD5加密”,在日常操作中,相信很多人在C语言怎么实现MD5加密问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言怎么实现MD5加密”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-15
  • 怎么使用jquery实现文件加密
    本文小编为大家详细介绍“怎么使用jquery实现文件加密”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么使用jquery实现文件加密”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、什么是jqueryjQue...
    99+
    2023-07-05
  • 使用Java实现加密之AES加解密
    目录1.背景知识2.AES简介3.AES的加密过程(AES处理单位:字节)4.Java实现4.1 生成密钥和偏移量4.2 AESUtil.java 源码4.3 执行结果4.4 线上验...
    99+
    2023-05-18
    Java AES AES 加解密
  • 使用SrpingDruid怎么实现数据源加密
    今天就跟大家聊聊有关使用SrpingDruid怎么实现数据源加密,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。环境Spring 4.2.6.RELEASEMyBatis 3.4.1D...
    99+
    2023-05-30
    数据源
  • 使用Java怎么实现文本的加密和解密
    今天就跟大家聊聊有关使用Java怎么实现文本的加密和解密,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。java基本数据类型有哪些Java的基本数据类型分为:1、整数类型,用来表示整数...
    99+
    2023-06-14
  • 使用python实现md5加密
    python实现MD5加密 1、简介 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用于确保信息传输完...
    99+
    2023-05-17
    python md5 python md5加密
  • C#如何实现加密与解密
    这篇文章主要讲解了“C#如何实现加密与解密”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#如何实现加密与解密”吧!一、Hash加密,使用HashAlgorithm哈希算法类的派生类(MD5...
    99+
    2023-06-30
  • C#实现加密与解密详解
    目录一、Hash加密,使用HashAlgorithm哈希算法类的派生类(MD5、SHA1等)1、使用抽象类HashAlgorithm2、使用抽象类MD53、使用MD5CryptoSe...
    99+
    2024-04-02
  • 怎么利用Python实现RSA加密解密
    这篇文章主要介绍“怎么利用Python实现RSA加密解密”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么利用Python实现RSA加密解密”文章能帮助大家解决问题。RSA加密实验基本流程:一、选取...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作