005. peak hell

关卡地址#

解决方案:#

思路:#

图片下有句提示信息:

pronounce it

查看源代码得到如下提示:

peak hell sounds familiar ?

听着一点也不熟悉好吧😂!无奈找了其他攻略,原来说的是python的pickle库,一个数据持久化库。

既然是要使用pickle库,肯定还需要额外的文件。查看源代码,在peakhell标签找到了一个banner.p文件。

使用pickle反序列化后,得到的是一个二维列表,元素是一个元组,表示(char,number)

最终得到的字符画如下:

channel

PS: 如果看不出字符画是什么,请增加窗口显示宽度试试。

代码:#

banner="http://www.pythonchallenge.com/pc/def/banner.p"

dir="../../Data/005"
import helper
helper.ensureDir(dir)

import urllib.request
(filename,headers)=urllib.request.urlretrieve(banner,dir+'/banner.p')

import pickle
data=pickle.Unpickler(open(filename,'rb')).load()

# print(data)

for line in data:
    for tupleitem in line:
        print(tupleitem[0]*tupleitem[1],end='')
    print('')

# ================================
# without pickle
fp=open(filename,'r')
lines=fp.readlines()
fp.close()

import re
reln=re.compile('aa')
renum=re.compile('^I([0-9]*)')
rechsharp=re.compile("S'#'|g6")
rechspace=re.compile("S' '|g2")

for line in lines:
    if reln.search(line) != None:
        print('\n',end='')
        continue
    if rechsharp.search(line) != None:
        ch='#'
        continue
    if rechspace.search(line) != None:
        ch=' '
        continue
    if renum.search(line) != None:
        num=renum.search(line).group(1)
        print(ch*int(num),end='')
        continue
# ================================
$banner="http://www.pythonchallenge.com/pc/def/banner.p"

$path="../../Data/005"

. .\helper.ps1
New-Dir -Dir $path
$path=$(Resolve-Path $path).Path

$filename=$path+"/banner.p"
Invoke-WebRequest -Uri $banner -OutFile $filename

$lines=Get-Content $filename

$reln=[regex]'aa'
$renum=[regex]'^I([0-9]*)'
$rechsharp=[regex]"S'#'|g6"
$rechspace=[regex]"S' '|g2"

foreach ($line in $lines) {
    if ($reln.IsMatch($line)) {
        [System.Console]::WriteLine()
        continue
    }
    if ($rechsharp.IsMatch($line)) {
        $ch='#'
        continue
    }
    if ($rechspace.IsMatch($line)) {
        $ch=' '
        continue
    }
    if ($renum.IsMatch($line)) {
        $num=[int]$renum.Match($line).Groups[1].Value
        [System.Console]::Write($ch*$num)
        continue
    }
}
package main

import (
	"fmt"
	"strings"
	"regexp"
	"strconv"
)

func (c *Challenge) Challenge005()  {
	banner:="http://www.pythonchallenge.com/pc/def/banner.p"
	
	path:="../../Data/005"
	EnsureDir(path)

	filename:=path+"/banner.p"
	Download(banner,filename)

	content:=ReadFile(filename)
	lines:=strings.Split(content,"\n")

	reln:=regexp.MustCompile("aa")
	renum:=regexp.MustCompile("^I([0-9]*)")
	rechsharp:=regexp.MustCompile("S'#'|g6")
	rechspace:=regexp.MustCompile("S' '|g2")

	ch:=" "

	for index := 0; index < len(lines); index++ {
		if reln.MatchString(lines[index]) {
			fmt.Printf("\n")
			continue
		}
		if rechsharp.MatchString(lines[index]) {
			ch="#"
			continue
		}
		if rechspace.MatchString(lines[index]) {
			ch=" "
			continue
		}
		matches:=renum.FindStringSubmatch(lines[index])
		if matches != nil {
			num,err:=strconv.Atoi(matches[1])
			if err == nil {
				for i:=0; i<num; i++ {
					fmt.Printf(ch)
				}
			}
			continue
		}
	}
}

最终结果: channel#

下一关地址#

008. working hard?

Bz2

关卡地址#

解决方案:#

思路:#

这一关,图片下面有这样的提示:

Where is the missing link?

鼠标在图片上“扫描”一遍发现,图片中蜜蜂区域是可点击的,访问的就是下一关的地址。

对,你没有看错,就是下一关地址。不过在此之前,你需要认证。

所以这一关的目的就是找到用户名和密码。

查看源代码得到如下提示:

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就是username的简写,pw就是password的简写。

字符串是经过bz2编码之后的输出,我们要解码得到原始字符串。

代码:#

# ================================
# 写bz2文件,可以使用7zip直接查看
def makeBz2(filename, data):
    fp=open(filename, 'wb')
    fp.write(data)
    fp.close()

import helper
dir="../../Data/008"
helper.ensureDir(dir)

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

makeBz2(dir+'/user.bz2', un)
makeBz2(dir+'/pwd.bz2', pw)
# ================================

import codecs

username=codecs.decode(un, 'bz2').decode('utf-8')
password=codecs.decode(pw, 'bz2').decode('utf-8')
# or
# username=codecs.decode(open(dir+'/user.bz2','rb').read(), 'bz2').decode('utf-8')
# password=codecs.decode(open(dir+'/pwd.bz2','rb').read(), 'bz2').decode('utf-8')

print('username: %s\npassword: %s' % (username, password))
$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'

$path="../../Data/008"
. .\helper.ps1
New-Dir -Dir $path
$path=$(Resolve-Path $path).Path

Write-BinaryFile -Filename $($path+"/user.bz2") -Data $(ConvertFrom-Bz2String -InStr $un)
Write-BinaryFile -Filename $($path+"/pwd.bz2") -Data $(ConvertFrom-Bz2String -InStr $pw)

# 使用bzip2解压并输出
Write-Output $("username: {0}" -f $(.\bin\bzip2.exe -d -k -c $($path+"/user.bz2")))
Write-Output $("password: {0}" -f $(.\bin\bzip2.exe -d -k -c $($path+"/pwd.bz2")))
package main

import(
	"fmt"
	"os"
	"compress/bzip2"
	"io/ioutil"
)

func (c *Challenge) Challenge008() {
	unfile:="../../Data/008/user.bz2"
	pwfile:="../../Data/008/pwd.bz2"

	username:=bz2Decode(unfile)
	password:=bz2Decode(pwfile)

	fmt.Printf("username: %s\npassword: %s\n", username, password)
}

func bz2Decode(filename string) string {
	reader,err := os.Open(filename)
	if err != nil {
		fmt.Printf("open file %s failed![%v]", filename, err)
		return ""
	}
	defer reader.Close()

	bzrd := bzip2.NewReader(reader)

	bytes,ierr := ioutil.ReadAll(bzrd)
	if ierr != nil {
		fmt.Printf("read file %s failed![%v]", filename, ierr)
		return ""
	}

	return string(bytes)
}

最终结果: username: huge, password: file#

下一关地址#

017. eat?

关卡地址#

解决方案:#

思路:#

这一关图片中是曲奇饼干,左下角图片是不是有点熟悉?是第四关啦!

查看源代码并没有什么提示。

但是!根据cookie可以联想到什么?对!就是浏览器缓存。

通过浏览器开发者工具查看cookie后,可以得到如下提示:

you+should+have+followed+busynothing…

在第四关,我们请求的是:http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=

这里需要将nothing替换为busynothing,并且收集cookieinfo的值。

之后得到BZh91AY开头的经过url编码的字符串,是不是又有点熟悉?不熟悉的请回顾第八关

使用python在解码时会有小问题:

OSError: Invalid data stream

在解码前将+替换为%20可以解决该问题。

解码后得到提示:

is it the 26th already? call his father and inform him that “the flowers are on their way”. he’ll understand.

这句话信息量有点大,26号暗示第十五关call his father则暗示第十三关,Mozart的父亲是Leopold(注意L大写)。

给Leopold打电话之后得到:

555-VIOLIN

访问violin.html得到如下提示:

no! i mean yes! but ../stuff/violin.php.

替换url之后访问,得到的是一张Leopold的照片,及:

it’s me. what do you want?

额。。。对,and inform him that “the flowers are on their way”

018. can you tell the difference?

关卡地址#

解决方案:#

思路:#

可以很明显的看出图片左右两部分的亮度不同,但还是看一下源代码的提示:

it is more obvious that what you might think

替换url为bright会提示:

ness

访问brightness仍然是相同的图片,再次查看源代码的提示:

maybe consider deltas.gz

下载解压后发现一个delta.txt文件,打开后前4行数据如下:

89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00   89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00
02 8a 00 00 00 c8 08 02 00 00 00 e0 19 57 95 00 00 00   02 8a 00 00 00 c8 08 02 00 00 00 e0 19 57 95 00 00 00
09 70 48 59 73 00 00 0b 13 00 00 0b 13 01 00 9a 9c 18   09 70 48 59 73 00 00 0b 13 00 00 0b 13 01 00 9a 9c 18
00 00 00 07 74 49 4d 45 07 d5 05 07 0c 18 32 98 c6 a0   00 00 00 07 74 49 4d 45 07 d5 05 07 0c 18 32 98 c6 a0

可以看出这是两个文件合并在一起的,结合标题,需要比较两者不同。

❤️ 如果这篇文章对你有帮助,欢迎赞助支持我继续维护 ❤️

☕ Support me ⚡ 爱发电赞助