1 方法一
利用call指令压栈的特性,将字符串的地址压栈之后再pop到寄存器中,在shellcode编写中是一种非常常用的方法 。我们可以看到字符串紧跟在call指令之后,因为call压栈就是压的下一条指令的地址,此地址正好为字符串地址 。
section .dataWRITE equ 1EXITequ 60section .textglobal _start_start:movrax, WRITEmovrdi, 1jmpgetstringstring:poprsimovrdx, 5syscalljmp exitgetstring:call stringMESSAGE db "Hello", 0xaexit:mov rax, EXITmov rdi, 0syscall2 方法二
同时也是利用栈的特性,将字符串计算过大小,以及分割完毕之后就可以分拨压进栈中,保存最后的esp值就可以实现字符串地址的获取 。
section .dataWRITE equ 1EXITequ 60MESSAGE db "Hello", 0xasection .textglobal _start_start:movrax, WRITEmovrdi, 1movrsi,0x00000a6f6c6c6548pushrsimovrsi, rspmovrdx, 5syscalljmp exitexit:mov rax, EXITmov rdi, 0syscall0x3 文件读1 sys_open
文件读写都需要涉及打开文件操作,是通过内核提供的系统调用sys_open来实现的 。具体参数如下:
asmlinkage long sys_open(const char __user *filename, int flags, int mode)

文章插图

文章插图
这里需要注意在文件操作之后,需要利用close函数关闭文件描述符 。分别介绍flags和mode参数取值,flags表示在打开文件时标志属性,mode为在创建文件的时候文件属性 。
flags
表示只读、只写和创建 。如果想赋予多个属性可以用|链接类似于 O_WRONLY|O_CREAT

文章插图
mode
mode 相关取值表如下,值得注意是mode的表示为8进制,也就是说 777 的rwxrwxrwx 权限是8进制数 。用下面的 属性标示为 S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH

文章插图
打开文件用汇编表示为
section .dataOPEN equ 2EXITequ 60FILENAME db "test", 0x00section .textglobal _start_start:movrax, OPENmovrdi, FILENAMEmovrsi, 2movrdx, 666syscalljmp exitexit:mov rax, EXITmov rdi, 0syscall2 sys_read
文章插图
section .dataOPEN equ 2READ equ 0EXITequ 60FILENAME db "xxx", 0x00BUFFER db "11111"section .textglobal _start_start:movrax, OPENmovrdi, FILENAMEmovrsi, 2movrdx, 511syscallmovrdi, raxmovrax, READmovrsi, BUFFERmovrdx, 8syscallmov rax, EXITmov rdi, 0syscall上述代码中xxx为二进制文件,如下图成功读出elf内容:
文章插图

文章插图
0x4 文件写open 操作与之前一样,新增write操作,相关系统调用参数如下:

文章插图
section .dataOPEN equ 2EXITequ 60FILENAME db "hehe", 0x00section .textglobal _start_start:movrax, OPENmovrdi, FILENAMEmovrsi, 65movrdx, 511syscallmovrdi, raxjmp wirtewirte:movrsi, FILENAMEmovrdx, 4syscalljmp exitexit:mov rax, EXITmov rdi, 0syscall0x5 权限修改在linux中权限修改利用chmod指令,在系统调用的时候采用的sys_chmod函数
文章插图
在分析open函数时有讨论mode的取值,这里就不再分析
有时在shellcode中需要修改程序的权限
#include <sys/types.h>#include <sys/stat.h>main(){chmod("/etc/passwd", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);}section .dataCHMOD equ 90EXITequ 60FILENAME db "xxx", 0x00section .textglobal _start_start:movrax, CHMODmovrdi, FILENAMEmovrsi, 511syscallmov rax, EXITmov rdi, 0syscall0x6 命令执行system函数中的命令执行用的是syscall execve系统调用 。其参数格式如下
文章插图
调试system函数内部的参数调用可以看出rax是系统调用号,rdi是filename,rsi是字符串数组

文章插图
字符串数组内存布局如下

文章插图
section .dataEXECVE equ 59FILENAME db "/bin/bash", 0x00section .textglobal _start_start:movrax, EXECVEmovrdi, FILENAMEmovrsi, 0movrdx, 0syscallmov rax, EXITmov rdi, 0syscall
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 在Linux中查找已连接网络的WiFi密码
- 呕心沥血整理的linux服务器一条龙服务
- Linux select/poll机制原理分析
- Linux安全技巧汇总,防止扫描,禁止空密码,强制用V2等
- 使用growpart工具完成Linux系统盘分区扩容
- Linux下如何知道是否有人在使坏?
- 树莓派无屏上手指南
- linux操作系统上安装docker
- 黑客大神秘籍:Linux下Hook方式汇总
- 黑客大神谈一谈Linux与suid提权
