之前竟然做错模块了?寄!

我真的谢。

7 号凌晨和面试师傅抱怨 Courses 第五章的 ECC 难学,师傅震惊:“你怎么去学 ECC 了?”,然后发现面试任务竟然是 Challenge 的那些章节,当时就心态大崩,我就说 ECC 怎么会是我现在可以染指的东西啊(麻。。

不过还好师傅把二面时间延迟到 10 号了,7 号调休 9 号满课,算下来其实也就多了 8 号的周日可以做题,所以 8 号我必早起!

这篇先补一下 Challenge 前三章没做的题,第五章后面再单独写吧。

Introduction

Network Attacks

Description

Several of the challenges are dynamic and require you to talk to our challenge servers over the network. This allows you to perform man-in-the-middle attacks on people trying to communicate, or directly attack a vulnerable service. To keep things consistent, our interactive servers always send and receive JSON objects.

Python makes such network communication easy with the telnetlib module. Conveniently, it’s part of Python’s standard library, so let’s use it for now.

For this challenge, connect to socket.cryptohack.org on port 11112. Send a JSON object with the key buy and value flag.

The example script below contains the beginnings of a solution for you to modify, and you can reuse it for later challenges.

Connect at nc socket.cryptohack.org 11112.

Analyze

使用中间人攻击的方式获取 flag 。

使用 telnetlib 库对 socket.cryptohack.org 11112端口以 JSON 对象的方式进行请求。

题目说的很明确,就把 buy 的值改成 flag,运行代码就能出结果。

Code

# 部分代码
request = {
"buy": "flag"
}

General

ENCODING_Encoding Challenge

Description

Now you’ve got the hang of the various encodings you’ll be encountering, let’s have a look at automating it.

Can you pass all 100 levels to get the flag?

The 13377.py file attached below is the source code for what’s running on the server. The pwntools_example.py file provides the start of a solution using the incredibly convenient pwntools library. which we recommend. If you’d prefer to use Python’s in-built telnetlib, telnetlib_example.py is also provided.

For more information about connecting to interactive challenges, see the FAQ. Feel free to skip ahead to the cryptography if you aren’t in the mood for a coding challenge!

Connect at nc socket.cryptohack.org 13377.

Analyze

刚开始看题是真没搞明白他要干啥,甚至以为这不是密码题。。(可能我阅读能力有问题?

阅读服务端的代码,第一次连接服务器会返回编码方式以及编码后的字符串,这时候需要提交解码后的字符串,正确解码后服务器会发来下一个。100 次之后服务器主动终止连接,解码之后得到的就是 flag。

解码函数看着他的加密代码倒是蛮容易写的,但是确实不喜欢做这类题。

Code

import codecs
from pwn import *
from Crypto.Util.number import *
import json

r = remote('socket.cryptohack.org', 13377, level='debug')


def json_recv() -> dict:
line = r.recvline()
return json.loads(line.decode())


def json_send(hsh: dict) -> None:
request = json.dumps(hsh).encode()
r.sendline(request)


def decode(encoded: str, type: str) -> str:
if type == "base64":
return base64.b64decode(encoded).decode()
elif type == "hex":
return codecs.decode(encoded, 'hex').decode()
elif type == "rot13":
return codecs.decode(encoded, 'rot_13')
elif type == "bigint":
return long_to_bytes(int(encoded, 16)).decode()
elif type == "utf-8":
return "".join(chr(i) for i in encoded)
else:
return "Unknown encoding"


# 第一次接收
received = json_recv()

for i in range(100):
plain_text = decode(received["encoded"], received["type"])
to_send = {
"decoded": plain_text
}
json_send(to_send)
received = json_recv()

XOR_Lemur XOR

Description

I’ve hidden two cool images by XOR with the same secret key so you can’t see them!

Analyze

题目描述倒是挺短。

直接二进制异或不行,然后试试像素点异或。

对图片操作很陌生诶。还是菜。

Code

from PIL import Image

flagImg = Image.open('D:/files/codeFiles/pyCode/cryptohack/Challenge/补充/flag.png')
flag = flagImg.load()

lemurImg = Image.open('D:/files/codeFiles/pyCode/cryptohack/Challenge/补充/lemur.png')
lemur = lemurImg.load()
width, height = flagImg.size

newImg = Image.new('RGB', (width, height))
new = newImg.load()

for i in range(width):
for j in range(height):
r1, g1, b1 = flag[i, j]
r2, g2, b2 = lemur[i, j]
new[i, j] = (r1 ^ r2, g1 ^ g2, b1 ^ b2)

newImg.save('D:/files/codeFiles/pyCode/cryptohack/Challenge/补充/xorimage.png')

DATA FORMATS_Privacy-Enhanced Mail?

Description

As we’ve seen in the encoding section, cryptography involves dealing with data in a wide variety of formats: big integers, raw bytes, hex strings and more. A few structured formats have been standardised to help send and receive cryptographic data. It helps to be able to recognise and manipulate these common data formats.

PEM is a popular format for sending keys, certificates, and other cryptographic material. It looks like:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKC... *(a whole bunch of base64)*
-----END RSA PUBLIC KEY-----

It wraps base64-encoded data by a one-line header and footer to indicate how to parse the data within. Perhaps unexpectedly, it’s important for there to be the correct number of hyphens in the header and footer, otherwise cryptographic tools won’t be able to recognise the file.

The data that gets base64-encoded is DER-encoded ASN.1 values. Confused? Here is more information about what these acronyms mean but the complexity is there for historical reasons and going too deep into the details may drive you insane.

Extract the private key d as a decimal integer from this PEM-formatted RSA key.

There are two main approaches for solving this challenge. The data in the certificate can be read with the openssl command line tool, or in Python using PyCryptodome. We recommend using PyCryptodome: first import the RSA module with from Crypto.PublicKey import RSA and you can read the key data using RSA.importKey().

Analyze

.pem 文件诶,看起来好酷的样子。

用给出的库和函数转换一下直接出。

Code

from Crypto.PublicKey import RSA

c = open(r"./privacy_enhanced_mail.pem").read()
p = RSA.import_key(c)
print(p.d)

DATA FORMATS_CERTainly not

Description

As mentioned in the previous challenge, PEM is just a nice wrapper above DER encoded ASN.1. In some cases you may come across DER files directly; for instance many Windows utilities prefer to work with DER files by default. However, other tools expect PEM format and have difficulty importing a DER file, so it’s good to know how to convert one format to another.

An SSL certificate is a crucial part of the modern web, binding a cryptographic key to details about an organisation. We’ll cover more about these and PKI in the TLS category. Presented here is a DER-encoded x509 RSA certificate. Find the modulus of the certificate, giving your answer as a decimal.

Analyze

.der 文件,看起来依然很牛。

和上一题基本就改了个文件名。

Code

from Crypto.PublicKey import RSA

c = open(r"./CERTainly not_2048b-rsa-example-cert.der", 'rb').read()
p = RSA.import_key(c)
print(p.n)

DATA FORMATS_SSH Keys

Description

Secure Shell Protocol (SSH) is a network protocol that uses cryptography to establish a secure channel over an insecure network (i.e. the internet). SSH enables developers and system administrators to run commands on servers from the other side of the world, without their password being sniffed or data being stolen. It is therefore critical to the security of the web.

In the old days, system administrators used to logon to their servers using telnet. This works similarly to our interactive challenges that involve connecting to socket.cryptohack.org - data is sent to a remote server, which performs actions based on what is sent. There is no transport encryption, so anyone listening in on the network (such as the WiFi access point owner, your ISP, or the NSA) can see all the telnet traffic.

As the internet became increasingly hostile, people realised the need for both authentication and encryption for administrative network traffic. SSH, first released in 1995, achieves these goals and much more, with advanced functionality built into the software like port forwarding, X11 forwarding, and SFTP (Secure File Transfer Protocol). SSH uses a client-server architecture, meaning the server runs SSH as a service daemon which is always online and waiting to receive connections, and the user runs an SSH client to make a connection to it.

Most commonly, SSH is configured to use public-private key pairs for authentication. On the server, a copy of the user’s public key is stored. The user’s private key is stored locally on their laptop.

Now let’s say Bruce wants to connect as his user account bschneier to his server bruces-server. From his laptop he runs ssh bschneier@bruces-server. His SSH client opens a connection to the server on port 22 where the SSH daemon listens. First, the ciphers that will be used are agreed upon, then a session key to encrypt the connection is established using Diffie-Hellman Key exchange, but we won’t go into the details on that here. Then, the server sends a random challenge message encrypted with Bruce’s public key. Bruce uses his private key to decrypt the challenge and send a hash of the random challenge message back, proving that he owns the correct private key and he therefore authenticates himself to the server as bschneier. Now, the server gives Bruce a shell to run commands. If public-private key cryptography doesn’t make sense to you yet, don’t worry - we’ll cover it extensively in the RSA category.

An SSH private key is stored in the PEM format, which we discussed in the “Privacy-Enhanced Mail” challenge. So it looks like this and is stored on Bruce’s laptop at /home/bschneier/.ssh/id_rsa:

-----BEGIN RSA PRIVATE KEY-----
MIIBCgKC... *(a whole bunch of base64)*
-----END RSA PRIVATE KEY-----

SSH public keys, however, use a different format:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCtPLqba+GFvDHdFVs1Vvdk56cKqqw5cdomlu034666UsoFIqkig8H5kNsNefSpaR/iU7G0ZKCiWRRuAbTsuHN+Cz526XhQvzgKTBkTGYXdF/WdG/6/umou3Z0+wJvTZgvEmeEclvitBrPZkzhAK1M5ypgNR4p8scJplTgSSb84Ckqul/Dj/Sh+fwo6sU3S3j92qc27BVGChpQiGwjjut4CkHauzQA/gKCBIiLyzoFcLEHhjOBOEErnvrRPWCIAJhALkwV2rUbD4g1IWa7QI2q3nB0nlnjPnjjwaR7TpH4gy2NSIYNDdC1PZ8reBaFnGTXgzhQ2t0ROBNb+ZDgH8Fy+KTG+gEakpu20bRqB86NN6frDLOkZ9x3w32tJtqqrJTALy4Oi3MW0XPO61UBT133VNqAbNYGE2gx+mXBVOezbsY46C/V2fmxBJJKY/SFNs8wOVOHKwqRH0GI5VsG1YZClX3fqk8GDJYREaoyoL3HKQt1Ue/ZW7TlPRYzAoIB62C0= bschneier@facts

This format makes it easier for these public keys to be added as lines to the file /home/bschneier/.ssh/authorized_keys on the server. Adding the public key to this file allows the corresponding private key to be used to authenticate on the server.

The ssh-keygen command is used to produce these public-private keypairs.

Extract the modulus n as a decimal integer from Bruce’s SSH public key.

Analyze

.pub 后缀更酷了。

不过和第一题解法没区别,只能说函数真的强大。

Code

from Crypto.PublicKey import RSA

c = open(r"./SSH Keys_bruce_rsa.pub").read()
p = RSA.import_key(c)
print(p.n)

DATA FORMATS_Transparency

Description

When you connect to a website over HTTPS, the first TLS message sent by the server is the ServerHello containing the server TLS certificate. Your browser verifies that the TLS certificate is valid, and if not, will terminate the TLS handshake. Verification includes ensuring that:

- the name on the certificate matches the domain

- the certificate has not expired

- the certificate is ultimately signed (via a “chain of trust”) by a root key of a Certificate Authority (CA) that’s trusted by your browser or operating system

Since CAs have the power to sign any certificate, the security of the internet depends upon these organisations to issue TLS certificates to the correct people: they must only issue certificates to the real domain owners. However with Windows trusting root certificates from over 100 organisations by default, there’s a number of opportunities for hackers, politics, or incompetence to break the whole model. If you could trick just a single CA to issue you a certificate for microsoft.com, you could use the corresponding private key to sign malware and bypass trust controls on Windows. CAs are strongly incentivised to be careful since their business depends upon people trusting them, however in practice they have failed several times.

In 2011 Comodo CA was compromised and the hacker was able to issue certificates for Gmail and other services. In 2016, Symantec was found to have issued over 150 certificates without the domain owner’s knowledge, as well as 2400 certificates for domains that were never registered.

Due to such events, together with the fact that fraudulent certificates can take a long time to be discovered, since 2018 Certificate Transparency has been enforced by Google Chrome. Every CA must publish all certificates that they issue to a log, which anyone can search.

Attached is an RSA public key in PEM format. Find the subdomain of cryptohack.org which uses these parameters in its TLS certificate, and visit that subdomain to obtain the flag.

Analyze

这题怎么说呢,一言难尽。

倒是能解出来 n,但是怎么找到包含 n 的证书对应的域名呢,搜了很久也没找到。

最后是直接去爆破,找到 url 里包含 flag 的子域名,访问得到 flag。

也可以用 crt.sh 搜指纹,查日志记录,不过也没用到公钥。

最后还是不知道怎么用公钥推域名,怪捏。

Mathematics

虽然之前做数学做了很久,不过值得欣慰的是 Challenge 第三章第一部分全都做完了。具体在这里