在cap.shao同学的说明下完成的,只能说比赛中的Pwn题还是需要多练习。这道题其实挺基础的,没有奇技淫巧,只是需要几个点联系起来。
一个很普通的列表题目,四个选项,实际上只用到了三个:
水果的item是一个单链表结构,但实际上不会利用到next指针,结构如下:
struct fruit_item {struct fruit_item *next;int index;short int quantity;short int total;bool can_change_label;char label[10];bool type;char buffer[128];};
type为false/0时是apple,true/!0是banana。两者的不同在于,buffer会被分为两部分,记做base和extra,正常来说,base是不可控的,extra是可控(在buy_fruit时可以自行指定)的。最后一列的information,'.'之前的是base,之后的是extra。
打发票时,base部分是直接用printf打印的,因此可能存在格式化字符串漏洞,要想办法控制base部分。读反编译代码可知,extra就是buffer的首地址,但base的首地址不同:作为apple时,base从buffer+64开始,作为banana时,base从buffer+96开始。如果能够将一个banana改成apple,那么就有可能将原来banana的extra部分当成apple的base打印出来,这一部分的长度最多有96-64=32字节。
type可以通过溢出label来修改:change_label是利用sc
题目是用flask搭建了一个web应用,目的是通过伪造token来登入admin页面:
通过所给的login接口可以得到user权限的token,因此得想办法通过user的token来伪造admin的token。token使用HMAC和AES双重加密,一个token的格式如下:
hmac是用于验证enc_token的,里面包括name、role和hmac的key。将key放在enc_token后面应该是一种应用模式而不是有漏洞的设计,主要的问题在于使用了AES的ECB模式。ECB下,每个block都是相互独立的,因此即便不知道AES的秘钥也有办法构造出密文。
from base64 import b64encode, b64decodeimport requestsfrom Crypto.Hash import HMAChost = 'http://ec2-13-229-142-46.ap-southeast-1.compute.amazonaws.com:9999'# host = 'http://localhost:9999'def get_token(name):assert 0 < len(name) <= 1024ses = requests.Session()data = { 'name': name }ses.post(host+'/login', data=data)token = ses.cookies['token']mac = token[-32:]token = token[:-32]return b64decode(token), macdef try_login(token):ses = requests.Session()ses.cookies['token'] = tokenresp = ses.get(host)print resp.textpayload = 'cir'+ 'q'*12 # 最后的':'由题目本身加上的enc, _ = get_token(payload)name = en