最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用c++實現(xiàn)異或加密的代碼示例

 更新時間:2022年04月11日 18:45:18   作者:羽夏  
這篇文章主要為大家介紹了c++實現(xiàn)異或加密的代碼示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪

加密原理

由于展示最基本最簡單的實現(xiàn),使用算法加密就沒用復(fù)雜的。如果使用比較復(fù)雜的加密,首先你在C++代碼層面和匯編層面要有配套的代碼,C++負(fù)責(zé)加密,匯編負(fù)責(zé)自我解密,否則你加密完了,結(jié)果加密后的PE文件自己又解密不了,這就很尷尬。

在所有加密算法,異或加密是最簡單的,也是最好是實現(xiàn)的。我們來介紹異或加密的原理。

已知兩個數(shù)AB,如果A xor B = C,則C xor B = A,其中xor表示異或運算符。如果不理解,這個是入門編程的最基本的知識,請自行補(bǔ)缺,這里我就不嘮叨了。

異或加密的實現(xiàn)

下面是我們實現(xiàn)異或加密的相關(guān)函數(shù):

// 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++代碼層面,加密代碼區(qū)內(nèi)容相關(guān)的代碼如下:

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

^表示異或運算符,在匯編層面,以64位為例,實現(xiàn)如下所示:

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,這個就是生成花指令,這里不多說,后面在介紹。還有一個函數(shù)比較注意RelocationSection,這個函數(shù)是用來生成做重定位的匯編代碼的,為什么要有這個函數(shù)呢?

比如我只有異或加密,我們是在硬編碼的層面進(jìn)行的加密,PE被加載進(jìn)入的時候如果基址不和預(yù)想的那樣,就會查是否有重定位表,如果有的話就解析并修復(fù)。但是,我們的代碼是加密的,而重定位表沒做修改,它就會錯誤的把被加密的硬編碼進(jìn)行重定位,這個是不能夠允許的。所以我們需要摧毀重定位表,可以看到CWingProtect::Proctect里面有一個函數(shù)DestoryRelocation,這個作用就是用來銷毀它的,不讓PE加載器幫我們做重定位。

綜上所述,我們需要自己做重定位,我們需要在匯編層面來實現(xiàn)重定位表的修復(fù),我們來看一下相關(guān)代碼:

//
// 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 為加載到內(nèi)存的虛擬基址地址
        //計數(shù)
        a.mov(x86::ecx, x86::dword_ptr(x86::rsi, 4));
        a.sub(x86::ecx, 8);
        a.shr(x86::ecx, 1);    //此時為重定位表的真實項目個數(shù)
        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寄存器沒那么多,只能自己維護(hù)一個局部變量
        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 為加載到內(nèi)存的虛擬基址地址
        //計數(shù)
        a.mov(x86::ecx, x86::dword_ptr(x86::esi, 4));
        a.sub(x86::ecx, 8);
        a.shr(x86::ecx, 1);    //此時為重定位表的真實項目個數(shù)
        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);
    }
    //將所有的節(jié)全部改為可寫
    auto length = peinfo.NumberOfSections;
    for (UINT i = 0; i < length; i++)
    {
        ((PIMAGE_SECTION_HEADER)TranModPEWapper(&peinfo.PSectionHeaders[i]))
            ->Characteristics |= IMAGE_SCN_MEM_WRITE;
    }
}

對于以上代碼你可能有一些疑問,我這里說一下:
為什么調(diào)用a.nop()來生成沒有用的指令,這個是我用來方便調(diào)試我生成的ShellCode用的,否則會生成一大坨匯編到后來自己也不清楚自己在調(diào)試啥的,通過這個nop我就可以清楚的直到我到那里了,如果出錯的話我也方便進(jìn)行定位。
此函數(shù)最后生成完ShellCode之后又將所有的節(jié)全部改為可寫屬性,這是為什么呢?因為線性內(nèi)存是有屬性的,如果我沒有將其設(shè)置可寫,如果它是只讀內(nèi)存,如果我對它做重定位修改的話,就會報內(nèi)存訪問錯誤,導(dǎo)致程序崩潰。
怎么用匯編來解析重定位表,這里就不贅述了。

ShellCode 編寫注意事項

在編寫ShellCode代碼的時候,請一定保證如下原則,避免一些麻煩,否則會出現(xiàn)出乎意料的錯誤:

  • 除了 eax / rax 其他寄存器用到的話,一定要注意保存好,因為其它函數(shù)調(diào)用有各種調(diào)用約定,一定不要影響它們,否則會出錯。為什么要對 eax / rax 區(qū)別對待,因為通常來說它只用做返回值,調(diào)用函數(shù)返回結(jié)果一定會修改它,所以大可不必。
  • 在使用 ASMJIT 生成匯編的時候,使用類似 MOV 的指令的時候,一定要注意如果要寫入多大的數(shù)據(jù)一定要在目標(biāo)操作數(shù)體現(xiàn)數(shù)來,比如要移動 WORD 大小的話,用 ax 就不要用 eax,否則它正常生成匯編指令不報錯,結(jié)果和你想生成的代碼不一樣。
  • 一定要注意堆棧平衡,這個是非常重要的東西,在64位尤甚,32位的操作系統(tǒng)也是十分注意堆棧平衡的。

以上就是使用c++實現(xiàn)異或加密的代碼示例的詳細(xì)內(nèi)容,更多關(guān)于c++異或加密示例的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 深入解析Linux下\r\n的問題

    深入解析Linux下\r\n的問題

    本篇文章是對Linux下\r\n的問題進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C語言實現(xiàn)經(jīng)典24點算法

    C語言實現(xiàn)經(jīng)典24點算法

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)經(jīng)典24點算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • C++調(diào)試追蹤class成員變量的方法

    C++調(diào)試追蹤class成員變量的方法

    本文所講的是不通過修改一個class的成員,就能夠追蹤其成員。方法就是類似C語言中的函數(shù)指針
    2013-11-11
  • Qt模仿IOS滑動按鈕效果

    Qt模仿IOS滑動按鈕效果

    這篇文章主要為大家詳細(xì)介紹了Qt模仿IOS滑動按鈕效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • C++?primer超詳細(xì)講解關(guān)聯(lián)容器

    C++?primer超詳細(xì)講解關(guān)聯(lián)容器

    兩個主要的關(guān)聯(lián)容器為map和set,map中元素是一些關(guān)鍵字—值對,關(guān)鍵字起索引的作用,值則表示與索引相關(guān)聯(lián)的數(shù)據(jù)。set中每個元素只包含一個關(guān)鍵字,set支持高效的關(guān)鍵字查詢操作——檢查一個給定關(guān)鍵字是否在set中
    2022-07-07
  • C++實現(xiàn)簡易反彈小球游戲的示例代碼

    C++實現(xiàn)簡易反彈小球游戲的示例代碼

    我們利用printf 函數(shù)實現(xiàn)一個在屏幕上彈跳的小球。彈跳的小球游戲比較簡單、容易入門,也是反彈球消磚塊、接金幣、臺球等很多游戲的基礎(chǔ),感興趣的可以了解一下
    2022-10-10
  • C++實現(xiàn)LeetCode(157.用Read4來讀取N個字符)

    C++實現(xiàn)LeetCode(157.用Read4來讀取N個字符)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(157.用Read4來讀取N個字符),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 深入淺出理解C語言初識結(jié)構(gòu)體

    深入淺出理解C語言初識結(jié)構(gòu)體

    C?數(shù)組允許定義可存儲相同類型數(shù)據(jù)項的變量,結(jié)構(gòu)是?C?編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許你存儲不同類型的數(shù)據(jù)項,本篇讓我們來了解C?的結(jié)構(gòu)體
    2022-02-02
  • 帶你從頭學(xué)習(xí)C++的封裝

    帶你從頭學(xué)習(xí)C++的封裝

    這篇文章主要為大家從頭學(xué)習(xí)了C++的封裝,使用數(shù)據(jù)庫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C++中std::shuffle的使用小結(jié)

    C++中std::shuffle的使用小結(jié)

    std::shuffle是C++標(biāo)準(zhǔn)庫中的一個函數(shù),用于對容器中的元素進(jìn)行隨機(jī)排列,本文主要介紹了C++中std::shuffle的使用小結(jié),具有一定的參考價值,感興趣的可以了解一下
    2025-04-04

最新評論

于都县| 宜章县| 永川市| 玉林市| 双峰县| 伊宁市| 府谷县| 德清县| 新营市| 双峰县| 贵阳市| 内江市| 宁武县| 霍州市| 文昌市| 梨树县| 乌苏市| 墨竹工卡县| 广东省| 偃师市| 宿州市| 汾西县| 渑池县| 黄平县| 鄂尔多斯市| 桂阳县| 集安市| 南昌市| 乌鲁木齐县| 白山市| 英超| 正蓝旗| 临汾市| 电白县| 个旧市| 本溪| 嘉鱼县| 甘南县| 监利县| 乌苏市| 崇阳县|