0x000 前言

近几年大家都喜欢用CS来进行后渗透,所以对于ShellCode大家应该不会陌生。
但是可能很多人并不懂CS它的功能是什么,CS生成的ShellCode是一段下载者。
主要功能为下载becon.dll,然后内存加载,我们所用的相关功能都在becon里。
ShellCode可能采用汇编或VC编写后转成机器码提取关键机器码,优势在于体积小
体积小就可以直接结合漏洞使用,什么Word文档、MS17010溢出、IE漏洞挂马等
都可以直接结合CS来使用,直接CS上线,而不是非要先做其它操作再植入CS。
网上关于汇编或VC编写ShellCode的文章很多,但是.NET的"ShellCode"很少见
本文将教大家如何用操作码实现.NET版"ShellCode"的编写。

0x001 指令、操作码、字节码

在正式开始前,先给大家科普一下指令、操作码、机器码等的区别

指令: 命令cpu干什么,是由操作码字段和地址码字段(操作数字段)组成

操作码(Opcode): 就是执行某种操作的命令代码

BYTECODE(字节码):与机器代码相同,除了它主要由基于软件的解释器(如Java或CLR)使用

程序集:有两个“程序集” – 一个汇编程序是一系列的助记符和操作数,它们被馈送到“汇编程序”,
“汇编程序”将助记符和操作数“汇编成可执行的机器代码”.可选地,“链接器”链接组件并生成可执行文件.

CLR语言:(.NET语言)中的第二个“程序集”是一系列CLR代码,其中注入了元数据信息,可执行代码库,但不能直接执行.

0x002 Payload ShellCode

机器码(溢出常用的ShellCode): 就是指令的二进制代码(包括操作码和地址码),功能打开和关闭计算机中的开关的数字序列,以执行某些工作 – 例如增加数字,分支,乘法等等.这是纯机器特有的,由处理器的实现者.

K8理解的ShellCode是子弹,用枪发射(好比处理器执行); 无论你用的是哪种子弹(ShellCode),都是用枪来射(处理器执行)。

Payload: K8的理解是弹药,弹药可装填到弹壳里用,也可直接点然,也可圈起来当成炮仗点燃,但是弹药不能直接被枪发射。

PS:发现很多搞安全的对很多概念搞混,如很多文章常把payload和shellcode混为一谈
看了以上释义,您应该了解明显shellcode只是payload中的一种了,不可能属于同一个。
很多人把操作码误解为ShellCode还可以理解,起码长得像还有点类似,但真不是。
不要看到二进制、16进制或者byte数组就说是shellcode,长得像人都不定是人呢。

0x003 .NET函数代码

.NET包含多种语言,这里我使用C#的代码做为例子

            public int Add(int x, int y)
            {
                x = x * y;
                return x  + y;
            }

0x003 反汇编得到IL指令

指令速查表:https://www.jb51.net/article/86802.htm
IL语言,可理解为.NET的汇编,无论你使用的是C#还是VB.NET或者F#开发功能,都可以将其反编译成IL代码。使用ildasm.exe工具反编译,可以看到IL代码和汇编差不多,可能是常用.NET吧,感觉比汇编简单好多。

  // Method begins at RVA 0x2170
  // Code size       9 (0x9)
  .maxstack  8
  IL_0000:  /* 03   |                  */ ldarg.1
  IL_0001:  /* 04   |                  */ ldarg.2
  IL_0002:  /* 5A   |                  */ mul
  IL_0003:  /* 10   | 01               */ starg.s    x
  IL_0005:  /* 03   |                  */ ldarg.1
  IL_0006:  /* 04   |                  */ ldarg.2
  IL_0007:  /* 58   |                  */ add
  IL_0008:  /* 2A   |                  */ ret
} // end of method MethodBodyDemo::Add

0x004 IL指令转.NET操作码

如同VC反汇编提取机器码一样,我们将对应16进制复制出来,然后再对比指令速查表提取关键操作码

    0x02,0x03,0x5A,0x10,0x00,0x02,0x03,0x58,0x2A

0x005 操作码加载

    private static Func<int, int, int> LoadByteAssmbly(byte[] bytes)
        {
            var asmName = new AssemblyName("DynamicAssembly");
            var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
            var module = asmBuilder.DefineDynamicModule("DynamicModule");
            var typeBuilder = module.DefineType("DynamicType");
            var method = typeBuilder.DefineMethod("DynamicMethod",
                MethodAttributes.Public | MethodAttributes.Static,
                typeof(int),
                new[] { typeof(int), typeof(int) });
            method.CreateMethodBody(bytes, bytes.Length);
            var type = typeBuilder.CreateType();

            return (Func<int, int, int>)type.GetMethod("DynamicMethod").CreateDelegate(typeof(Func<int, int, int>));
        }

0x006 执行效果

C#操作码: .NET版“ShellCode”编写-编程知识网