本篇主要是以x64系统为例对系统调用中一些功能性函数的解读和实际运用 。目前网络上流传的通用shellcode,均使用系统调用实现,在记录整个学习过程的同时分享给大家一起学习探讨 。
0x01 Shellcode 简介0x1 shellcodeShellcode 是一段可以执行特定功能的特殊汇编代码,在设备漏洞利用过程中注入到目标程序中从而被执行,在比赛或者是实战中栈溢出漏洞使用的更为频繁,编写Shellcode比编写RopGagdet更为简单,栈溢出的最经典的利用方式是Ret2Shellcode 。
0x2 exploit 与 shellcode关系exploit主要强调执行控制权,而shellcode更关注于有了控制权之后的功能 。因此shellcode更像是exploit的载荷,往往对于不同漏洞来讲exploit是特殊的,而shellcode会具有一些通用性 。
0x02 使用条件对 shellcode 有了大概的了解之后,看一看其使用场景 。一般来说这三点是必备条件,缺一不可,通过控制程序流程跳转到shellcode地址上去 。
0x1 拥有程序控制权这一点毋庸置疑,可以通过栈溢出或者是格式化字符串,堆溢出等漏洞劫持程序的执行流 。所以shellcode等的定位是漏洞触发之后的漏洞利用,主要负责实现攻击者的攻击目的 。
0x2 拥有shellcode地址不论是程序拥有随机化还是固定基地址,都需要在跳转之前获取shellcode存储地址,一般采用的技巧是
- 在程序bss段固定,且程序地址不随机
- shellcode为程序正常功能输入,在寄存器中保存有其地址
- 在堆栈附近存在与shellcode地址相关联地址
文章插图
重点关注两个方面 start地址和prot取值
1 起始地址
需要指出的是,锁指定的内存区间必须包含整个内存页(4K) 。区间开始的地址start必须是一个内存页的起始地址,并且区间长度len必须是页大小的整数倍 。
2 prot赋值
prot可以取以下几个值,并且可以用“|”将几个属性合起来使用,括号中的数字是在预编译的时候替换的真实值:
1)PROT_READ(1):表示内存段内的内容可写;
2)PROT_WRITE(2):表示内存段内的内容可读;
3)PROT_EXEC(4):表示内存段中的内容可执行;
4)PROT_NONE(0):表示内存段中的内容根本没法访问 。
0x03 编写技巧打算从系统调用函数、字符串设计、代码模板、shellcode提取这几个发面着手写这部分内容,主要解决以下三大问题:
- 对系统调用函数不熟悉,特别是为参数赋值问题挠头
- 对汇编代码编写不熟悉,解决寄存器和内存应用问题
- 对汇编代码编译不熟悉,解决怎么从编译好的汇编程序中完整提取shellcode问题
文章插图
详细的系统调用表网址如下
https://filippo.io/linux-syscall-table/
https://firmianay.gitbooks.io/ctf-all-in-one/content/doc/9.4_linux_syscall.html
系统调用 在汇编代码中表示为syscall(int 0x80)指令,32和64位系统有所区别,二者有单独调用表 。
0x2 巧取字符串初步认识shellcode的编写技巧,先从最简单的例子看起,下面代码如果当作汇编语言执行是完全没有问题的,但是如果做为shellcode的话还是差点火候 。这里用两种方法规避这种错误:
section .dataWRITE equ 1EXITequ 60MESSAGE db "Hello", 0xasection .textglobal _start_start:movrax, WRITEmovrdi, 1movrsi, MESSAGEmovrdx, 5syscalljmp exitexit:mov rax, EXITmov rdi, 0syscall
编译指令如下nasm -g -f elf64 -o asm.o asm.sld -o asm asm.o
编译过后可以发现字符串位于data段,指针利用的是绝对地址,在shellcode中是不能出现绝对地址,这也是shellcode的头等大忌 。文章插图
推荐阅读
- 在Linux中查找已连接网络的WiFi密码
- 呕心沥血整理的linux服务器一条龙服务
- Linux select/poll机制原理分析
- Linux安全技巧汇总,防止扫描,禁止空密码,强制用V2等
- 使用growpart工具完成Linux系统盘分区扩容
- Linux下如何知道是否有人在使坏?
- 树莓派无屏上手指南
- linux操作系统上安装docker
- 黑客大神秘籍:Linux下Hook方式汇总
- 黑客大神谈一谈Linux与suid提权