HMVlabs-temperance
FLow

写在前面

前段时间就想着要好好把python练一练,刚好最近hmv新出了一个labs,其实不是很难,但我还是要gpt帮助,算是把一些语法巩固了一下,昨晚还是觉得要记一下,不然做完了不回顾其实没什么增长。

levelx00

一开始还花了点时间理解这个lab要怎么打,第一关就是带入门,先看看整体代码逻辑

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
import socket
import base64

HOST = "temperance.hackmyvm.eu"
PORT = 9988

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: # 建立socker连接
s.connect((HOST, PORT))

print('Receiving Intro') # 接收信息
data = s.recv(1024)
print(data)

s.send(b'levelx00') # 发生选择的关卡,后续都是通过这个控制关卡

print('Receiving challenge.')
data2 = s.recv(1024) # 接收数据,后续做一些处理
print(data2)

print('Envio reto')
s.send(data2) # 处理后再发过去

print('Recibo flag')
data3 = s.recv(1024) # 如果是对方期望的数据,会返回flag,用recv接收
print(data3)

就是这样执行这个代码,就能获得第一关的flag,后续每一关都有新的要求,接收数据,对数据进行处理然后发回去

前几关都太简单了,我直接记录一些我觉得比较可说的

levelx06

“In this mission you will receive a string and you must return its length. (as string, not as int).”

接收一个字符串,注意这个关卡接受的数据都是byte型,进行一些字符处理还要转换成str

经历了这个,我更清晰了

1
2
字符->bytes:data.encode()
bytes->字符:string.decode()

所以06发送回去的数据应该是,要转成bytes型

1
s.send((str(len(data2))).encode())

levelx08

“In this mission you will receive 2 numbers, you must return the result of adding both.”

接收一个两个数字,返回相加的结果,借助split分割出来,列表里面是bytes型,然后强制转换成int型,s.send不能发int型要先转成str再转成bytes型,不能to_bytes(),我发现会自动变成ascii

1
2
3
4
5
6
7
8
9
data2 = s.recv(1024)
print(data2)

numbers=data2.split()
print(numbers)
result=(int(numbers[0]) + int(numbers[1]))
# Send the challenge solved / Envia el resultado del challenge.
print('Envio reto')
s.send(str(result).encode())

levelx09

rot13解密,直接找函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def rot13(i):
cipher = ''
if i.isupper():
if 90 >= ord(i) + 13:
cipher += chr((ord(i) + 13 - 65) % 26 + 65)
else:
cipher += chr((ord(i) - 13 - 65) % 26 + 65)
elif i.islower():
if 122 >= ord(i) + 13:
cipher += chr((ord(i) + 13 - 97) % 26 + 97)
else:
cipher += chr((ord(i) - 13 - 97) % 26 + 97)
else:
cipher += i
return cipher

levelx10

“In this mission you will receive numbers separated by spaces, you must return them in order from smallest to largest and without separating them with spaces. “

接收:80 37 67 41 31 要返回:3137416780

1
2
3
4
5
6
7
8
9
data2 = data2.decode('utf-8') # 转str
nums = data2.split() # 按空格分割
int_list = [int(item) for item in nums] # 列表每个元素都转成int
sorted_list = sorted(nums) # 排序
data3 = ''
for i in sorted_list: # 拼接起来
data3 += i
print('Envio reto')
s.send(data3.encode('ascii'))

levelx13

“In this mission you receive a list of strings, you must sort them alphabetically and return the last string in the list. The characters “[“ and “]” must be removed.”

就是给很多字符串排序

1
2
3
4
5
6
data2 = data2.decode('utf-8')
data2 = data2[1:-1] # 去除前后[]
ss = data2.split()
ss = sorted(ss)
print('Envio reto')
s.send(ss[-1].encode('ascii'))

levelx17

“ In this mission you receive a 1 pixel png encoded in base64, you must decode it and return the last RGBA value.”

生成一张图片然后要找出里面最后一个RGBA数据,这个就要用到特定的库

1
2
3
4
5
6
7
8
9
10
11
12
import imagesize  # 需要用到这三个库
from PIL import Image
from io import BytesIO
。。。。。。。
data2 = data2.decode('utf-8')
decoded_data = base64.b64decode(data2)
image = Image.open(BytesIO(decoded_data)) # 将解码后的数据转换为图像
rgba_data = image.convert("RGBA").getdata() # 用库里的函数提取出RGBA数据

# Send the challenge solved / Envia el resultado del challenge.
print('Envio reto')
s.send(str(rgba_data[-1][-1]).encode())

levelx19

接收一段数据,base64解密,写入一个新建的zip,解压读取里面HMV.txt的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import zipfile
import os
from io import BytesIO
。。。。。。
data2 = data2.decode('utf-8')
data2 = base64.b64decode(data2)
zip_filename = "decoded_archive.zip"
with open(zip_filename, "wb") as zip_file: # 把解码后的内容新建一个zip写入
zip_file.write(data2)
with zipfile.ZipFile(zip_filename, 'r') as zip_ref:
txt_filename = "HMV.txt"
with zip_ref.open(txt_filename) as txt_file: # 读取txt内容
txt_content = txt_file.read()
print(txt_content)

levelx20

rockyou前五十个词作为字典,接收一个md5,去爆破找出原文是字典中的哪一个

命令行读取txt文件前五十行数据,head -n 50 rockuou.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
common_passwords = [
"123456","12345","123456789","password","iloveyou","princess","1234567","rockyou",
"12345678","abc123","nicole","daniel","babygirl","monkey","lovely","jessica","654321","michael",
"ashley","qwerty","111111","iloveu","000000","michelle","tigger","sunshine","chocolate","password1",
"soccer","anthony","friends","butterfly","purple","angel","jordan","liverpool","justin","loveme","fuckyou",
"123123","football","secret","andrea","carlos","jennifer","joshua","bubbles","1234567890","superman","hannah"
]

def md5_hash1(text):
return hashlib.md5(text.encode()).hexdigest() # 生成md5

def crack_md5(md5_hash):
for password in common_passwords:
if md5_hash == md5_hash1(password): # 一个一个去对比,找到了就返回
return password
return None
。。。。。。

data2 = crack_md5(data2)
s.send(data2.encode('ascii'))

levelx25

接收到数据是个url,发送请求然后读取返回包的header

1
2
3
data2 = data2.decode('utf-8')
response = requests.get(data2)
header = response.headers.get('Hmv-Code')

levelx26

生成一张图片,要识别出里面的内容

1
2
3
4
5
6
7
8
9
10
import pytesseract
from PIL import Image
from io import BytesIO
。。。。。。。
data2 = data2.decode('utf-8')
decoded_data = base64.b64decode(data2)
image = Image.open(BytesIO(decoded_data))
image.save("decoded_image.png")
img = Image.open("decoded_image.png")
text = pytesseract.image_to_string(img) # 主要是用这个库,但是有时候不是很准确

levelx27

接收到数据是个url,发送请求然后返回的是/etc/passwd的内容,要提取里面用户proxy的uid

1
2
3
4
5
6
7
data2 = data2.decode('utf-8')
response = requests.get(data2)
html_content = response.text
ll = html_content.split('\n') # 按换行分割
pp = ll[-3].split(':') # 再按:分割
print('Envio reto')
s.send(str(pp[2]).encode()) 发送第三个字段也就是UID

levelx28

jwt解密

1
2
3
4
def extract_hmv_key(token):
decoded_token = jwt.decode(token, options={"verify_signature": False})
hmv_key = decoded_token.get('HMVKey')
return hmv_key

levelx29

发送两个坐标计算他们之间的距离,这个要用到特定的库(在此用umz的代码)

1
2
3
4
5
6
7
8
9
10
from geopy.distance import geodesic
。。。。。。
pattern = r"Lat: (\d+) Lon: (\d+) - Lat: (\d+) Lon: (\d+)"
matches = re.match(pattern, data2)
if matches:
coord1 = (int(matches.group(1)), int(matches.group(2)))
coord2 = (int(matches.group(3)), int(matches.group(4)))
distance = geodesic(coord1, coord2).kilometers
formatted_distance = "{:.3f}".format(distance)
s.send(formatted_distance.encode())

levelx31

要识别二维码,也是用到特定的库

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
import qrcode
from PIL import Image
from pyzbar.pyzbar import decode
import cv2
def scan_qr_code(image_path):
# 打开图片
image = Image.open(image_path)
# 解码图片中的二维码
decoded_objects = decode(image)

# 输出解码结果
for obj in decoded_objects:
print('Type:', obj.type)
print('Data:', obj.data)
return obj.data
。。。。。。。。
data2 = data2.decode('utf-8')
decoded_data = base64.b64decode(data2)
image = Image.open(BytesIO(decoded_data))
image.save("qr.png")
image = Image.open("qr.png")
img_path = 'qr.png'
image.save(img_path)

data2 = scan_qr_code(img_path) # 扫码

levelx32

“In this mission you receive an md5 and a string. You must permute the string until it matches md5 and return the string.”

有一个md5,和一个字符串,重新排序字符串,找出那个md5的原文

1
2
3
4
5
6
7
8
9
10
11
12
13
import hashlib
import itertools
。。。。。。。
data2 = data2.decode('utf-8')
md = data2.split()[0]
key = data2.split()[1]
permutations = itertools.permutations(key)
for perm in permutations:
perm_str = ''.join(perm)
perm_md5 = hashlib.md5(perm_str.encode()).hexdigest()
if perm_md5 == md:
data2 = perm_str
break

写完了

ai太牛了,一点一点调,加深对知识的印象,但是写完这个感觉自己蠢蠢的。。。

由 Hexo 驱动 & 主题 Keep