shellcode
前言
目前网上主要是各种32位的shellcode编写教程,64位的比较少,这篇文章主要讲解一下64位shellcode的编写以及介绍几种比较常见的白名单绕过方法
64位shellcode编写
直接pwntools生成默认shellcode
这一种方法是最简单的,通过下面的代码即可生成一段64位shellcode代码:
1 | from pwn import * |
但这段代码有一个缺点,就是生成的shellcode比较长,在某些空间比较小的情况不能很好的使用,接下来我们就一步一步的学习手动编写shellcode吧。
手动编写shellcode
在手动编写shellcode之前,我们首先要知道shellcode这一段代码调动shell的原理。
linux中,存在着一系列的系统调用,这些系统调用都通过syscall指令来触发,并且通过rax寄存器作为系统调用号来区分不同的系统调用,可以通过查看linux源码目录下的arch/x86/entry/syscall_64.tbl获得对应的系统调用号。比如,execve对应的的系统调用号为59。
接着,即是通过rdi和rsi两个寄存器传入参数。其中,rdi是指向运行程序的路径的指针,rsi为一个指向0的指针,rdx为0。
总结下,我们应该完成如下操作:
1 | rax = 59 |
所以就可以编写我们就可以开始正式编写了:
1 | xor rdx,rdx |
(这里因为64位数据不能直接push,所以用了rax寄存器来传递)
编写完后,我们可以用pwntools模块来快速编译使用:
1 | from pwn import * |
这样生成的shellcode就只有30字节,一般这种大小就足够了。
白名单绕过
可打印ascii
这一种的限制一般是要求shellcode为可打印字符,包括字母、数字、符号。
针对这一种白名单,已经有了一个不错的工具:shellcode_encoder
使用这一工具首先需要安装z3-solver:
1 | $ pip install z3-solver |
开始生成可打印shellcode前,我们需要先将原来的shellcode输出到一个文件中,这里我们用python来执行:
1 | from pwn import * |
然后,将生成的shellcode文件放到shellcode_encoder目录下,运行:
1 | $ python main.py shellcode rax+29 |
其中,shellcode是我们生成的shellcode文件,然后因为漏洞程序是通过call rax调用shellcode的,以及shellcode_encoder生成shellcode时的偏移位置,所以这里用了rax+29。
然后就会自动生成可打印的shellcode了:
1 | Original length: 30 |
可以看到shellcode的总长是505,这样的长度对于某些特定的题目来说是不行的,所以下面介绍另一种shellcode。
纯数字字母shellcode
文章:https://hama.hatenadiary.jp/entry/2017/04/04/190129
这里就不具体分析了,直接给出最终的shellcode,感兴趣的可以自行阅读学习
1 | PPYh00AAX1A0hA004X1A4hA00AX1A8QX44Pj0X40PZPjAX4znoNDnRYZnCXA |