转载自 http://www.bootkitz.com/?p=93 文章谈的很好
使用C/Delphi编写ShellCode
这里说的ShellCode指的是一段x86机器码,无需重定位,在内存任何位置都可以执行的代码.
使用C/Delphi编写代码也是由其编译器特性决定的。
一说起ShellCode,一般人都想到MASM/TASM/FASM/NASM这类汇编语言编译器,但是,汇编语言写ShellCode维护起来总是很麻烦,肯定不如高级语言维护起来方便,尤其是大型的工程,例如PE Virus/Packer这样的工程。
ShellCode可以在内存中任何一个位置独立运行,他不需要外界对其进行任何操作,不需要装载器对其进行装载、重定位、填充IAT这样操作。
因此很多工作都需要自己去做。所以,在编写时需要一定的前置知识:
1.编译器的实现原理.高级语言源代码是怎么变成Opcode的,如何处理局部/全局变量,文件作用域内代码是如何排布的
2.PE文件结构的知识.尤其是EAT方面的,因为在 ShellCode执行过程中调用的API都需要你自己获取到,如何获取?自己写算法实现就好了~
3.操作系统的一些知识~
下面来说一下如何使用C/Delphi来编写 ShellCode
1.Kernel32.dll基址的获取.这个必须用汇编实现,这是最重要的,因为Kernel32.dll提供的LoadLibraryA和 GetProcAddress函数保证了ShellCode中其他功能的实现。
2.API的动态获取.在获取了 Kernel32.dll基址以后,就可以参照PE结构解析导出表获取相关函数的地址了。
3.固定代码的自定位.使用高级语言编写出的代码,里面肯定有类似mov eax,[0040xxxx]这样的代码,类似这样的访问固定地址的代码在ShellCode的执行过程中会造成各种异
常,如何减少这样的问题?内联汇编获取EIP,然后修正即可。选取一个好的数据结构可以很好的解决这个问题。
4.代码的编写。这里讨论的是使用高级语言编写ShellCode,因此我们谈论的主题将是高级语言。虽然高级语言编译器为我们提供了内联汇编的特性,但是这不是本文重点,只有在需要使用内联汇编的时候才使用,如获取Kernel32.dll基址与代码的自定位。编写时需要注意以下几点:
(1)ShellCode函数内部禁止引用全局变量/常量
(2)代码编写要紧凑,并且实现功能的代码的作用域仅限于本文件中,即函数从开始到结束的代码都在一个文件中,不要试图调用其他文件中的函数,这样会造成很严重的后果
只要保证上述几点都能做到,那么写出来的ShellCode将没有任何问题。
使用高级语言编写ShellCode的优点:易于理解,易于调试,易于维护,可以实现复杂的功能。在调用ShellCode前后堆栈、寄存器是平衡的~
使用高级语言编写ShellCode的缺点:编写出的 ShellCode体积较大,不易于优化,在对长度要求较高的场合不适用。
最后着重提一下使用Delphi编写 ShellCode,使用Delphi编写ShellCode的好处就是Delphi语法中的with … do结构可以很好的减少长代码的产生,使代码更易读,不像C语言在调用函数时需要lpShellCodeCrl->fMessageBoxA(…);这么罗嗦了。
再有一个好处就是可以编写涵盖32位~64位平台的ShellCode,Win32~Native环境的ShellCode,覆盖很全面。
由于现有的LCC/VS编译器的64位编译器中不允许使用内联汇编,使得使用C语言编写的ShellCode只能停留在32位下。
新推出的Delphi XE2提供了64位编译器支持的同时,还支持64位内联汇编,这就完美了。
有什么欠缺或不当的地方,还请指出。本文完。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!