shellcode xor编码/解码[1]

摘要:
对shell代码的主要变形进行了一点总结,其中大部分是收集和翻译的,还有少量原始的0x01病毒重新定位问题0x02 shell代码解码0x03一个unix示例0x04源代码解释0x05参考shell代码转换器代码/解码器是shell代码变形的一种相对主要的方法。当然,它使用的方法有点类似于病毒0x01病毒重新定位问题的方法病毒重新定位方法,它可以方便地用于外壳代码的设计。通常,只要在病毒代码的开头计算deltaoffset,并且通过地址更改的方式编写引用数据的汇编代码,就可以在运行时正确地重新定位病毒代码。

shellcode的初级变形的一点点总结,大部分搜集、翻译,少量原创

0x01 病毒上重定位问题
0x02 shellcode解码
0x03 一个unix例子
0x04 源码解读
0x05 参考

shellcode xor编码/解码器是一种较为初级的shellcode变形的方法,当然它从中采用的方法跟病毒上的方法有些类似

0x01 病毒上重定位问题
病毒上的解决重定位的方法,可以方便的用到shellcode的设计中。

下面部分摘自hume的<<病毒编程技术>>

在病毒技术上至少有两种方法可以解决重定位的问题:
A)第一种方法就是利用上述PE文件重定位表项的特殊作用构造相应的重定位表项。
在感染目标PE文件时,将引用自身数据的需要被重定位的地址全部写入目标PE文件的重定位表中,如果目标PE无任何重定位表项(如用MS linker的/fixed)则创建重定位表节并插入新的重定位项;
若已经存在重定位表项,则在修改已存在的重定位表节,在其中插入包含了这些地址的新表项。重定位的工作就完全由系统加载器在加载PE文件的时候自动进行了。重定位表项由PE文件头的DataDirectory数据中的第6个成员IMAGE_DIRECTORY_ENTRY_BASERELOC指向。
该方法需要的代码稍多,实现起来也相对比较复杂,另外如果目标文件无重定位表项(为了减小代码体积,这种情况也不少见),处理起来就比较麻烦,只有用高级语言编写病毒才常用该种方法,在一般的PE病毒中很少使用。

B)利用Intel X86体系结构的特殊指令,call或fnstenv等指令动态获取当前指令的运行时地址,计算该地址与编译时预定义地址的差值(被称为delta offset),再将该差值加到原编译时预定的地址上,得到的就是运行时数据的正确地址。对于intel x86指令集而言,在书写代码时,通过将delta offset放在某个寄存器中,然后通过变址寻址引用数据就可以解决引用数据重定位的难题。还以上例说明,假如上述指令块被操作系统映射在0x500000处那么代码及其在内存中的地址将变为:

501000: 
mov eax,dword ptr [402035] 
......
502035:
db "hello world!",0

   显然,mov指令引用的操作数地址是不正确的,如果我们知道了mov指令运行时地址是0x501000,那么计算该地址和编译时该指令预设地址的差值:0x501000-0x401000 = 0x100000。很显然指令引用的实际数据地址应该为0x402035+0x100000 = 0x502035。从上例可以看出,只要能够在运行时确定某条指令动态运行时的地址,而其编译时地址已知,我们就能够通过将delta offset加到相应的地址上正确重定位任何代码或数据的运行时地址。

      通常只要在病毒代码的开始计算出delta offset,通过变址寻址的方式书写引用数据的汇编代码,即可保证病毒代码在运行时被正确重定位。假设ebp包含了delta offset,使用如下变址寻址指令则可保证在运行时引用的数据地址是正确的:

;ebp包含了delta offset值
401000: 
mov eax,dword ptr [ebp+0x402035]
......
402035:
db "hello world!",0

      在书写源程序时可以采用符号来代替硬编码的地址值,上述的例子中给出的不过是编译器对符号进行地址替换后的结果。现在的问题就转换成如何获取delta offset的值了,显然:

call delta
delta:
pop ebp
sub ebp,offset delta

     在运行时就动态计算出了delta offset值,因为call要将其后的第一条指令的地址压入堆栈,因此pop ebp执行完毕后ebp中就是delta的运行时地址,减去delta的编译时地址“offset delta”就得到了delta offset的值。除了用明显的call指令外,还可以使用不那么明显的fstenv、fsave、fxsave、fnstenv等浮点环境保存指令进行,这些指令也都可以获取某条指令的运行时地址。以fnstenv为例,该指令将最后执行的一条FPU指令相关的协处理器的信息保存在指定的内存中。
该结构偏移12字节处就是最后执行的浮点指令的运行时地址,因此我们也可以用如下一段指令获取delta offset:

fpu_addr:
fnop
call GetPhAddr
sub ebp,fpu_addr

GetPhAddr:
sub esp,16
fnstenv [esp-12]
pop ebp
add esp,12
ret

  delta offset也不一定非要放在ebp中,只不过是ebp作为栈帧指针一般过程都不将该寄存器用于其它用途,因此大部分病毒作者都习惯于将delta offset保存在ebp中,其实用其他寄存器也完全可以。

0x02 shellcode解码

病毒中采用的技术,在shellcode解码中加以利用
1.FNSTENV XOR decoder
[BITS 32]

global _start

_start:

fabs ;fabs指令
fnstenv [esp] ;保存环境,该结构偏移12字节处就是最后执行的浮点指令的运行时地址
pop edx
pop edx
pop edx
pop edx ;此处将fabs指令的运行时地址传给edx
sub dl, -25 ; offset from fabs -> xor buffer    edx = edx + 25,25的大小指的是从shllcode到fabs的偏移
short_xor_beg: xor ecx,ecx ;清零ecx sub cx,
-0x15F ;size of xor'd payload 设置ecx大小为0x15F short_xor_xor: xor byte [edx], 0x99 ; the byte to xor with ;开始循环解码 inc edx loop short_xor_xor shellcode: db ...........................

2.Jump/call decoder

global _start

_start:
jmp short getdata     ; Get data pointer 跳转到getdata
begin:

pop ebx ; Pop the data address ;弹出codestart的地址,call begin时会压入eip地址
xor ecx,ecx     ; Set up loop counter ;清零ecx
sub cx, -0x15F ; size of data payload ;设置ecx为0x15F

decode:
xor byte [ebx], 0x99     ; XOR ;开始循环解码
inc ebx     ; Increment data address
loop decode     ; Loop back to decode if cx > 0
jmp short codestart     ; Jump into decoded code


getdata:
call begin     ; Push the address of data in stack and jump
; to label begin

codestart: ; This is where the XOR'ed shellcode begins
db ..........................

0x03 一个unix例子

这是http://www.klake.org/~jt/encoder/上的一个示例,是一个我觉得很典型的xor编码/解码器,后面分析它的源码实现部分

;
; hello.asm -- simple non-optimized Linux/x86 shellcode
; Compile: nasm -f bin -o hello.s hello.asm
;

[BITS 32]

global _start

_start:
jmp short data ; Jump to our data section

begin:
mov eax, 4 ; syscall #4 = write()
mov ebx, 1 ; stdout
pop ecx ; Pop the data address in ecx
mov edx, 15 ; 15 bytes of data
int 0x80

mov eax, 1 ; syscall #1 = exit()
mov ebx, 0 ; status = 0
int 0x80

data:
call begin ; Call will return our data address

db "Hello, hacker!", 0x0a

NASM生成下列shellcode:

$ hexdump hello.s 
0000000 1eeb 04b8 0000 bb00 0001 0000 ba59 000f
0000010 0000 80cd 01b8 0000 bb00 0000 0000 80cd
0000020 dde8 ffff 48ff 6c65 6f6c 202c 6168 6b63
0000030 7265 0a21 
0000034

当然,我们应该通过避免使用32位寄存器消除这些代码中的所有NULL。例如,"xor eax,eax;mov al,4"代替"mov eax,4"。但在这个例子中,需要NULLs来测试编码。

$ ./loader hello.s 
Loading shellcode from "hello.s"...
Hello, hacker!

移除NULL后:

$ ./encoder hello.s 0x00 > h.s

Encoder v0.5 - Encode NULLs and other characters out of shellcode
Copyright (c) Jarkko Turkulainen 2004. All rights reserved.
Read the file encoder.c for documentation.

Using FNSTENV XOR decoder
Using register eax for decoder
Removing bytes 0x00
Reading shellcode from "hello.s"
Using 0x02 for XOR
Ready

Encoder选择字节0x02替换XOR,现在检查下:

$ hexdump h.s 
0000000 e1d9 34d9 5824 5858 8058 e7e8 c931 8166
0000010 cce9 80ff 0230 e240 e9fa ba1c 0206 0202
0000020 03b9 0202 5b02 0db8 0202 cf02 ba82 0203
0000030 0202 02b9 0202 cf02 ea82 fddf fdfd 674a
0000040 6e6e 2e6d 6a22 6163 6769 2370 0008 
000004d
$ ./loader h.s 
Loading shellcode from "h.s"...
Hello, hacker!

免责声明:文章转载自《shellcode xor编码/解码[1]》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇dhcp 提示could not load neutron.agentIOS lame库 pcm转mp3 分析(方案一)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

学习 MFC之 工具栏(二)

对于InitToolBar()函数进行进一步解析: 1、首先声明一个全局对象:  CToolBar m_toolbar; 2、然后用create()创建toolbar: //创建ToolBar工具条 if(!m_toolbar.CreateEx(this,TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP...

Servlet第四篇【request对象常用方法、应用】

什么是HttpServletRequest HttpServletRequest**对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,**HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。 简单来说,要得到浏览器信息,就找HttpServletRequest对象 HttpServletRequest...

oracle字符集的查看和修改

一、什么是Oracle字符集 Oracle字符集是一个字节数据的解释的符号集合,有大小之分,有相互的包容关系。ORACLE支持国家语言的体系结构允许你使用本地化语言来存储,处理,检索数据。它使数据库工具,错误消息,排序次序,日期,时间,货币,数字,和日历自动适应本地化语言和平台。 影响Oracle数据库字符集最重要的参数是NLS_LANG参数。 它的格式如...

ffmpeg文档17-视频编码器

17 视频编码器 介绍一些当前有效的视频编码器 libtheora libtheora的封装 编译需要头和库文件,还需要利用--enable-libtheora在配置中允许 更多信息参考http://www.theora.org/ libtheora选项 下面是映射给libtheora的全局选项,它们对品质和码率产生影响。 b 对CBR(固定码率编码...

基于NodeJs的网页爬虫的构建(一)

好久没写博客了,这段时间已经忙成狗,半年时间就这么没了,必须得做一下总结否则白忙。接下去可能会有一系列的总结,都是关于定向爬虫(干了好几个月后才知道这个名词)的构建方法,实现平台是Node.JS。 背景一般爬虫的逻辑是这样的,给定一个初始链接,把该链接的网页下载保存,接着分析页面中的链接,找到目标链接检查是否已经请求过,如果未请求则放入请求队列,页面下载完...

12.手机端如何拖动组件--从零起步实现基于Html5的WEB设计器Jquery插件(含源码)

 前面示例都只是展示在桌面浏览器显示,当用手机浏览器打开时发现无法拖动元素,虽然实际业务上,手机也只是用来查看的,但为了论证手机上的触摸事件,我还是在本节做个演示。 手机上触控有三个重要事件touchstart,touchmove,touchend,分别表示开始触摸,移动,及结束,与鼠标的mousedown,mousemove,mouseup对应。 基于...