2005年12月02日

第13题:邪个没完了!

    屏幕上出现一盘电话。
    title 提示:call him  ( 他是谁?)
    屏幕下方
phone that evil

   
答案很明显—— Bert!
    不过如果在上一关没有继续找寻下去发现bert is evil,恐怕就要晕了。
    电话上的按键5可以点击,进入一个phonebook.php页面。页面显示一个xml文件信息,大意是错误!
    其中的关键在于<string>XML error: no element found at line 1</string>
    google了一下,关于这句有很多解释,单绝大多数的含义就是xml解析错误。注意,不是客户端的错,是服务器端的错!
    难道要用其他的方法调用?
    最初我直接想到了soap。由于python本身没有内置的soap支持,就去找了SOAPpy来研究了一番。经过一番测试之后宣告方向错误,转换思路。
    xmlrpc!
    python内置了队其的支持,而且这又是一种更古老更通用的手段。说干就干!
    程序可以说简单的很,但却尝试了非常的可能性。由于并不知道其xmlrpc服务器方的方法名称,唯一的办法就是瞎猜、乱试。感谢上天的眷顾,只用了不到10分钟就测试出来了。


import xmlrpclib
server = xmlrpclib.ServerProxy('http://www.pythonchallenge.com/pc/phonebook.php')

server.phone('Bert')


    
最初,也差点由于大小写的原因与正确答案失之交臂,不过总结了上一关的经验,不放过任何蛛丝马迹,最终顺利的找到了答案!
      ‘555-ITALY’
      答案:  italy
      下关入口:http://www.pythonchallenge.com/pc/return/italy.html

    说实话,由于12关的遭遇,实在没有想到13关会如此的顺利。

第12题:将邪恶进行到底!

    首先说明一下,这关是目前为止我遇到的最大挑战,共用了2天半时间才完成。其中需要完成很多步骤并且会碰到不少误导。做完这关后,我对于认真二字又有了更进一步的认识。

    屏幕上显示出一幅发扑克的图片。
    Title上提示 dealing evil (可能有发牌作弊的意思)
    察看page source 你会发现这幅图的文件名很有意思是 evil1.jpg 。也就是说后面有编号

   

    在前面的谜题中曾经碰到这样的问题因此推断 可以通过改变后面的编号获取更多的信息。果然通过改变编号可以获得 evil2.jpg


        有点意思吧,上面说不是 jpg 而是 gfx 。什么意思?hehe,继续尝试。此处要兵分两路,一边继续尝试 evil3.jpg (bingo! 确实有),另一边我们要尝试 evil2.gfx (bingo !! 如果双色球我这么准就好了)。gfx文件目前还看不出什么特别的,下面再研究。


    什么?没有了,难道邪恶如此容易的没有?如果你此时没有探索精神的话,那可就惨了。因为接下来找到的线索是下一关解密的关键,如果你没有找到,可以明白的告诉你你的解谜历程到此就结束了。还好,我坚持了下来。继续尝试 evil4.jpg
    这个地方要特别说明一下,如果你使用的是ie的话,你将直接看到如下一段话:Bert is evil! go back! (注意是文本,不是图片)。假如你使用的是firefox的话,屏幕上显示的是evil4.jpg的url,你需要在source code中才能看到这段话。
    至此下一关所需的线索我们已经获得了。不过如果你像我一样富有不屈不挠的探索精神的话,还可以继续尝试,bert.html  (bingo!! 有中了)

    到这里,已经没有办法再继续追查下去了,我回过头来研究evil2.gfx文件。
    说实话,这个文件研究了1天。直到我得到提示,研究一下magic bytes。所谓magic bytes就是就是各种文件格式所具有的一些独特的标示字节,通过这些字节你可以很容易的辨认出文件的类型。不过gfx文件表面上你找不到任何这方面的特征。没关系,研究呗。jpg格式有一个非常容易辨认的特征就是在文件头包含jfif。呵呵终于被我发现了!gfx文件第一个字节后每个5个字节如果你仔细察看就会发现其与jpg的头文件非常吻合,原来藏在这里。ok!提取!


import sys
f2=open('./python challenge/evil2.gfx','rb')

bingobytes=''
sourcebytes = f2.read()
for i in range(0,len(sourcebytes),5):
    bingobytes+=sourcebytes[i]
f3 = open('./python challenge/evil2_end1.jpg','wb')
print >> f3,bingobytes

     哈哈,我终于获得了需要的线索,jpg图像现身了!


    没错应该就是dis+xxx什么的,我感觉到自己离答案已经一步之遥,但现在我才陷入真正的噩梦!
    我尝试了各种线索与dis之间的联系,但始终得不到正确的答案。然后我开始认真研究起dis 以及 bert来。Dis 冥神,如果不查字典,我只会以为他就是一个前缀。 bert is evil .98年就建立起来的一个网站。站点的主人认为芝麻街的主人公bert对小朋友没有正面地教育意义,因此建立了网站广为散播他的观点,这个观点曾经相当的受人注目。好像还获得过98年的特别网站奖什么的。至此,我已经更进一步的陷入了误区,开始研究芝麻街。查看了芝麻街的人物介绍,一个叫count的家伙特别的引起了我的注意。他的名字叫count 或 count von count ,是一个吸血鬼(感觉上非常吻合dis 以及 evil的特质),ok,就从他入手。我开始尝试各种dis+count等等组合,后来考虑到count求和方面的作用,开始对已有的线索进行各种求和。。。。。。。又一天过去了。。。。。我就要崩溃了。。
    抛掉之前所有的假设,重新再来一遍!

    其实我曾经离答案是那么的近,但由于自己的不认真及自大,让答案就那样轻易的从身边溜走了!
    当过再次仔细的研究过gfx 文件后,终于得到了1天半前就应该得到的答案。
    gfx文件就像前面说的那样,里面隐藏了图形文件,不过隐藏的不是一个而是5个!我仅仅提取了一个就匆忙罢手才导致上面的严重错误。5个文件是按照1、2、3、4、5个字节顺序排列的,也就是说从第二个字节起每个5个获取一个,组成一个文件,以此类推。不过其中有3幅是gif文件,研究一下gif的magic byte其实很容易就可以想到。
    ok,程序类似上面的。接连获得如下4个图片:


这幅图在firefox下看是一半的,因为最后的数据有点问题,不过在看图软件下就是正常的。

    至此,此题告破!当然如果你像我一样,英语都已经还给了可爱的老师,那么我们还要费心的再查查字典,看看如何组合:)   ity 都已经划掉了,当然就不用考虑了。
   答案: disproportional
   下关入口:http://www.pythonchallenge.com/pc/return/disproportional.html

    最后再多说两句,之所以12关写了这么长并把图也给附上实在是因为耗费了太多的心力,不过转念想想,也不错,如果不是到处乱撞我也不会有心研究芝麻街:)
    再补充一点:最初获得evil1.jpg时还被它给好顿骗。因为这幅图有两个jfif头部分,所以造成看起来很怪,其结果导致我研究了好一番信息夹带,考虑从它身上榨取些信息。呵呵,福兮祸兮。
  

第11题:邪魔现身


    Title 提示 odd even (奇 偶)
    屏幕上的图片在gimp下查看可以看出也是经过特殊处理的。规律是 偶行上的奇列 以及 奇行上的偶列 都有着明显的图像数据痕迹。其他的点,视觉上看起来几乎都是黑色的。
    然而所有的秘密恰恰隐藏在这些黑色的点中。
    用pil将所有看似有颜色数据的点涂黑。


import Image
im = Image.open('./python challenge/cave.jpg')

length,width = im.size
for x in range(1,length+1):
    for y in range(1,width+1):
        if (x % 2 == 0 and y % 2 !=0) or (x%2 !=0 and y %2 ==0):
            im.putpixel((x-1,y-1),(0,0,0))
im.show()

    邪魔现身!得到答案 evil.
    下关入口 http://www.pythonchallenge.com/pc/return/evil.html
     做过了这道题后,我看了一下其他一些解法,其中有一种令人啼笑皆非同时也非常实用——改变亮度。随便通过一款图像处理软件对图片进行亮度、对比度处理后,evil同样可以清晰看到。不过这样也恰恰说明了这个挑战的趣味性及多样性。
    PS: 如果你仅仅通过观看答案而感觉挑战没有什么难度的话,我个人严重推荐您亲自完成其中的谜题。并非要证明其难度,主要是你可以在解密中获得真正的乐趣。
    现在感觉说出了谜底的我也是 EVIL 的!

第6题: zip 模块

 
    title提示是一对。
    源代码中出现〈!– 〈– zip –〉字样
    从http://www.pythonchallenge.com/pc/def/channel.zip 下载zip文件
    (提示够变态吧)
    打开zip文件中的readme.txt 可以看到
    welcome to my zipped list.

    hint1: start from 90052
    hint2: answer is inside the zip
    感觉解题思路基本上和上面那个反复调用url的题一样 

r=re.compile(r'(\d+)$')
nextnothing='90052'
while(1):
    try:
        f=open('./python challenge/%s.txt' % nextnothing)
        result=f.read()
        f.close()
        print result
        oldnextnothing=nextnothing
        nextnothing=r.search(result).group()
    except:
        break


    执行后最后显示 collect the comments

    有点昏吧,哪里来的comments。其实就在zip文件里。这道题最后还是需要用zip模块来完成

 
import re
r=re.compile(r’(\d+)$’)

import zipfile
comment=[]
nextnothing=’90052′
f=zipfile.ZipFile(‘./python challenge/channel.zip’)
while(1):
    try:
        comment.append(f.getinfo(‘%s.txt’ % nextnothing).comment)
        nextnothing=r.search(f.read(‘%s.txt’ % nextnothing)).group()
    except:
        print ”.join(comment)
        break


    运行屏幕显示一个由字符组成的图片,可以看出图案是HOCKEY
    进入http://www.pythonchallenge.com/pc/def/hockey.html
    什么?还没结束!
    上面显示it’s in the air. look at the letters.
    此时,再次注意观察前面出现的hockey图片发现,每个字母的图案都是由一个单独的字母组成,得到最终答案oxygen
    下题入口http://www.pythonchallenge.com/pc/def/oxygen.html

第7题: pil出场。颜色拾取

 
    屏幕上显示一幅图,图片的中间部分是由规律的灰度块组成。猜测信息应该是由这些灰度提供。
    通过gimp进一步分析可获得整个区域灰度块长度为608,除第一小块外,其他间隔都是7个象素点。也就是说每隔7个点可以获得一个颜色数据。由于图片是彩色的(RGBA模式),而只有灰度的颜色数据应该是255级以内,推测可能会是ascii。


import Image
im = Image.open(‘./python challenge/oxygen.png’)
ilist = im.convert(‘L’).getdata() #将色彩转换为灰度,这样只获得一个值
result=[]
for i in range(0,608,7):
    result.append(chr(ilist[im.size[0]*50+i]))
print ”.join(result)


    果然,运行程序显示:smart guy, you made it. the next level is [105, 110, 116, 101, 103, 114, 105, 116, 121]
    再次处理可得到答案


hint=[105, 110, 116, 101, 103, 114, 105, 116, 121]
answer=[]
for c in hint:
    answer.append(chr(c))
print ”.join(answer)


    最终答案:integrity
    下题入口:http://www.pythonchallenge.com/pc/def/integrity.html

第8题:bz2解码

 
    屏幕显示一个蜜蜂图片。查看页面源代码可以看到里面提示有加过密的用户名、密码。
    点击蜜蜂可进入一个需要输入口令的页面,说明此题应该就是解开用户名、密码
    说实话,这道题我始终没有找到破解加密算法的思路,直到看到网上有人说google一下BZh91AY。这个字符串时用户名和密码最开始相同的部分。google后可以看到介绍python bz2模块,得到解题思路。


import bz2

un = ‘BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084′
pw = ‘BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03$ \x00!\x9ah3M\x13<]\xc9\x14\xe1BBP\x91\xf08′

un=bz2.decompress(un)
pw=bz2.decompress(pw)

print un
print pw


    运行得到答案
    huge
    file
    登录即可进入下题

    下题入口http://www.pythonchallenge.com/pc/return/good.html

第9题:pil再度出马,描点

 
    屏幕上显示一幅风景画,上面有很多小黑点。
    title提示,连接点
    page source中可以看到两组数据 first second 并提示 first+second=?
    起初我真的在gimp上把图片上面的点用画笔描了起来,看看是否有什么提示,不过一无所获。
    后来观察first和second的数据,发现其值均在该图片的x,y size之内,并且两组数据的个数都为偶数,获得灵感是否是坐标数


import Image
first=[
146,399,163,403,170,393,... snip]
second=[
156,141,165,135,169,...snip]
im=Image.open('./python challenge/good.jpg')
f=[]
for i in range(0,len(first),2):
f.append((first[i],first[i+1]))
print f
for xy in f:
im.putpixel(xy,(255,0,0))

f=[]
for i in range(0,len(second),2):
f.append((second[i],second[i+1]))
print f
for xy in f:
im.putpixel(xy,(255,0,0))
im.show()


    呵呵,可以隐约在图片上面由红色的点组成了一头牛的图案。
    first是外缘轮廓,second是头的轮廓
    赶紧进入http://www.pythonchallenge.com/pc/return/cow.html
    结果发现提示hmm. it’s a male.
    唉,分得还挺细。。
    得到最后结果:bull
    下题入口:http://www.pythonchallenge.com/pc/return/bull.html

第10题: 数字列表

 
    屏幕下方提示 :len(a[30]) = ?
    点击图片可获得数据:
    a = [1, 11, 21, 1211, 111221,
    知道应该是根据这个提示找出规律,扩充列表获得答案。
    不过规律何在?解此题。。。。耗时超过2小时。。。。主要是笨呀。
    最后终于明白值之间的规律。就是每个值都是对前一个值得文字描述。
    什么?文字描述,不错,念起来就知道了
    比如说第一个是 1
    第二个就是 1个1 (11)
    第三个就是 2个1 (21)
    第4个就是 1个2 1个1 (1211)
    第5个就使 1个1 1个2 2个1 (111221)
    以次类推。。。。说实话,开始总是想数字之间是否有什么数学运算上的关系,所以总也推算不出。

x="1"
for each in range(30):
    x="".join([str(len(i+j))+i for i,j in re.findall(r"(\d)(\1*)", x)])
print len(x)


    得到答案:5808
    下题入口:http://www.pythonchallenge.com/pc/return/5808.html

这篇文章本来是发表于我的另一个blog上的,但由于目前又无法通过正常的渠道访问到哪里,所以才被我搬回来,也算是缘分吧。

如果你正在玩或打算玩python challenge的话,我不太推荐你看这篇文章。这就有点像魔术揭秘一样,一旦捅破了就不太好玩了。你可以在 http://pythonchallenge.com/forums/  去获取提示而不是答案。

从没想过解题还能这么有趣。
刚打开pythonchallenge的站点时有点莫名其妙的感觉,并不清楚到底问题在哪里。后来发现其中的奥秘就是你要在他所给的线索中找到下一题的url,这样便可以进入下一关了。
python challenge中有几个地方是重要的线索来源:
1:title (其中通常含有解题的思路提示)
2:page source (页面源代码,中间通常有数据资源,或者指明数据资源的位置)
3:序号(注意观察文件名或其他可能出现规律变化的地方)
4:前面的解或信息可能对以后的问题有所提示
5:实在解不开时看看是不是自己找到的线索还不够充分,通常情况下答案与线索之间的联系是紧密的,但也不要被一些看似有道理的线索给误导。

第0题:

   出现一幅画面,上面写着2**38,教你如何进入下一关。
计算出2**38 =
将浏览器中的 http://www.pythonchallenge.com/pc/def/0.html
改成 http://www.pythonchallenge.com/pc/def/274877906944.html 即可
   指导关,告诉你如何进行这个游戏。整个python challenge的游戏就是通过线索找到进入下一题的url,仅此而已:)

第1题:密码转换


图片中显示出字符转换的规律 new_c=chr(ord(old_c)+2) 超过自动回转

title中提示making trans

因此比较简单的方法是直接使用string.translate进行转换。
oldstr = ' ...' #屏幕上显示的加密数据

import string

old='abcdefghijklmnopqrstuvwxyz'

new='cdefghijklmnopqrstuvwxyzab'

print string.translate(oldstr,string.maketrans(old,new))

        获得数据:

i hope you didnt translate it by hand. thats what computers are for.
doing it in by hand is inefficient and that’s why this text is so long.
using string.maketrans() is recommended. now apply on the url.

        然后再对url http://www.pythonchallenge.com/pc/def/map.html上面的 map 进行一次转换得到ocr.
        下一题入口:http://www.pythonchallenge.com/pc/def/ocr.html

ps:说实话如果不是做这题,我可能跟不不会想起用maketrans这类的函数。

第2题: 抽取字符


页面显示提示数据在page source中


查看页面源代码。可以看到一组混乱的数据,并得到如下提示:find rare characters in the mess below:
最初我解此题时是将数据中所有出现的字符都放入哈希并计算出现的次数,后来发现只有英文字母是之出现一次的,由于哈希没有顺序,猜结果耗费的不少时间,后来干脆只提取字符一下子就获得的最后的结果。



#chardict={}
#for c in ocrstr:
#    if chardict.has_key(c) :
#        chardict[c]+=1
#    else:
#        chardict[c]=0
#
#print chardict

print ”.join([c for c in ocrstr if c.isalpha()])


        计算后得到答案:equality
       下题入口:http://www.pythonchallenge.com/pc/def/equality.html

第3题: 提取字符

    title中提示使用正则 
    页面显示 两侧被3个(且只为3个)大写字母包围的小写字母
    page source中有待处理的数据


import re
result=re.findall(r’[a-z][A-Z]{3}([a-z])[A-Z]{3}[a-z]‘,sourcestr) print ”.join(result)


    得到答案 linkedlist。
    进入http://www.pythonchallenge.com/pc/def/linkedlist.html后显示linkedlist.php
    下题入口 http://www.pythonchallenge.com/pc/def/linkedlist.php

    ps:不是python解题吗,怎么用php:)


第4题:变态的url刷新


从title和图片可以看出来这题就像打水井一样,需要一遍又一遍的机械进行才能获得答案。


page source显示 图片的href 后面有一个nothing=12345的调用
urllib may help. don’t try ALL nothings, since it will never
end. ~300 times is enough.
调用linkedlist.php?nothing=12345得到了and the next nothing is 92512 从中得到规律,根据每次获得的nothing值来进行下次url访问。



import urllib2
import re
r=re.compile(r’(\d+)$’)
nextnothing=’12345′
i=0
while(i<=310): #实际不需要运行这么多次,好像200多次
    try:
        f=urllib2.urlopen(\
‘http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=%s’ % nextnothing)
        f.read()
        f.close()
        print result
        oldnextnothing=nextnothing
        nextnothing=r.search(result).group()
        i+=1
    except:
        nextnothing=oldnextnothing

需要提示的是,这题竟然在访问的过程中还有变化。在进行了漫长的调用后当nothing 为92118,会显示Yes. Divide by two and keep going。中断程序,将nothing设置为 46059 继续运行。获得最后结果 peak.html
下题入口:http://www.pythonchallenge.com/pc/def/peak.html


第5题:pickle应用

    说实在的尽管页面提示我将 peak hell 读出声来,我还是没有意识到pickle这个词(英文都还给了党)。
    source page中有如下显示
    查看http://www.pythonchallenge.com/pc/def/banner.p,通过显示的数据才反应过来应该是 pickle

import urllib2
import cPickle as pickle
f=urllib2.urlopen(‘http://www.pythonchallenge.com/pc/def/banner.p’)
result=pickle.Unpickler(f).load()

result是一个多维列表。分析数据感觉应该是一个字符组成的图画描述。

line=”
for n in result:
    for m in n:
        line+= m[0]*m[1]
    print line+’\n’
    line=”

    打印后可获得答案channel

    下题入口:http://www.pythonchallenge.com/pc/def/channel.html

python challenge目前共有33题,通过做这些题不仅可以开阔思路,更可以强迫自己去使用可能很少会使用的一些python模块,让自己在实践中提高。

唉。。。搬家很累的
尤其还要重新的排版。

我在blogger上的blog又无法通过正常渠道访问了,我重新回到donews的怀抱。
没关系,反正blogger上还可以通过gmail发送稿件。就当是一个备份吧。
由于对css不熟而且也比较懒,所以css的设计上是剽窃http://www.donews.net/e2005以及 limodou上的数据,在此特别致谢。

2005年02月16日

认认真真、完完整整地过了一个春节。
  今天是鸡年的第一个工作日,本想早点到公司,不到8点就出门了(前些天这时间还在睡觉呢)。结果开车出去一个小时总共才出去不到50米。)!·*—!(*·—)!·*—¥#!)*!)·!
  幸好旁边有个单位的院子,和人说了一下把车停进去了,走人,回家。
  现在这篇就是在家写的。。。。
  唉,本想鸡年有点新气象的。呵呵

2005年02月02日

刚才登陆gmail,发现自己的邀请资格突然增加到50个!不知道是不是gmail都开始大放送了。
如果有人还需要的话,就按下面格式留一下言。
firstname:
lastname:
email: (一定要好用呀。有些邮箱比如yahoo hotmail之类的会把gmail的邀请函放到垃圾箱中,自己去翻翻)