---
# System prepended metadata

title: picoCTF Cryptography
tags: [picoCTF]

---

# picoCTF Cryptography

# Easy

## hashcrack
![image](https://hackmd.io/_uploads/B1NpvEuaJe.png)

https://crackstation.net/
![image](https://hackmd.io/_uploads/H1x0PEua1g.png)

## 13
![image](https://hackmd.io/_uploads/BkST1Kqa1l.png)

rot13 online decode
https://cryptii.com/pipes/rot13-decoder
![image](https://hackmd.io/_uploads/HyAJeK5aye.png)


# Medium

## rotation
![image](https://hackmd.io/_uploads/Skumz1MHJe.png)
Hints : Sometimes rotation is right

encrypted.txt
![image](https://hackmd.io/_uploads/rJfUM1MHke.png)

說了 sometimes rotation 會對
那就用 rot13 bruteforce 試試看
https://gchq.github.io/CyberChef
![image](https://hackmd.io/_uploads/ryN3MJzH1l.png)


## HideToSee
![image](https://hackmd.io/_uploads/BkryHX7HJe.png)

用`steghide`找出秘密訊息
```
steghide extract -sf atbash.jpg
```
![image](https://hackmd.io/_uploads/S1oBLQQrJl.png)

看了一下圖片的檔名
atbash https://blog.csdn.net/weixin_43211186/article/details/123703113

以下破爛的script
```python=
path = 'encrypted.txt'
f = open(path, 'r')
ar_1 = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M','N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X','Y','Z']
ar_2 = ['z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a']

ans = ''
def is_digit(char):
    ascii = ord(char)
    if ascii >= ord('0') and ascii <= ord('9'):
        return True
    else :
        return False

def convert_char(char):
    if(char.isupper()):
        return char.lower()
    else:
        return char.upper()

while 1:
    char = f.read(1)
    a1_len = len(ar_1)
    a2_len = len(ar_2)
    if not char:
        break
    if char == '}' or char == '{'  or char == '_' or is_digit(char):
        ans = ans + char
    
    if char.isupper():
        for i in range(a1_len):
            if char == ar_1[i]:
                ans = ans + convert_char(ar_2[i])
                break
    else:
        for i in range(a2_len):
            if char == ar_2[i]:
                ans = ans + convert_char(ar_1[i])
                break
            
print(ans)

f.close()
```


## ReadMyCert
![image](https://hackmd.io/_uploads/ryJ7QY4Hyg.png)

```
echo "<text>" | base64 -d 
```
這樣就結束了= =
![image](https://hackmd.io/_uploads/BJfcmYNrye.png)

## Vigenere
![image](https://hackmd.io/_uploads/BJbwCLSrJe.png)

Vigenere https://ithelp.ithome.com.tw/articles/10288227?sc=rss.iron
就是假設今天有一個key是DOG
假設明文是MUWL
密文就是PICO
![image](https://hackmd.io/_uploads/SkOtlPrBJl.png)
(https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Vigen%C3%A8re_square.svg/450px-Vigen%C3%A8re_square.svg.png)

我超懶得寫matrix，直接找有沒有online工具
![image](https://hackmd.io/_uploads/BJ0TePSrJl.png)


## transposition-trial
![image](https://hackmd.io/_uploads/H1f_khBBJl.png)

![image](https://hackmd.io/_uploads/SkvqJnSB1g.png)
仔細觀察可以發現他是三個為一組去選轉的


```python=
f = open("message.txt", "r")
message = f.read()

ans = ""
for i in range(0,len(message),3):
    ans = ans + message[i+2] + message[i] + message[i+1]

print(ans)
```

![image](https://hackmd.io/_uploads/SyVkg2BSye.png)


## basic-mod1
![image](https://hackmd.io/_uploads/ryp_WbDBkx.png)

number mod 37 = ans
ans 0~25 => 大寫alphabet 
ans 26~35 => 數字 `0~9`
ans 36 => 底線 `_` 

白癡的暴力破解
```python=
apl = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9','_']

f = open("message.txt","r")
f = f.read().split()

ans = ""
for num in f:
    ans = ans + apl[int(num) % 37]


print(ans)

```
![image](https://hackmd.io/_uploads/BkkEG-PHJx.png)


## substitution0
![image](https://hackmd.io/_uploads/H166zJj8yg.png)

簡單還說就是每個字母被替換成不同的字母

online crack substitution 工具 - https://planetcalc.com/8047/

![image](https://hackmd.io/_uploads/BJ0zmks81e.png)

## Easy1
![image](https://hackmd.io/_uploads/B13JctGuJe.png)
Hints
1. Submit your answer in our flag format. For example, if your answer was 'hello', you would submit 'picoCTF{HELLO}' as the flag.
2. Please use all caps for the message.

table
![image](https://hackmd.io/_uploads/B17F3YzO1x.png)

https://www.dcode.fr/vigenere-cipher
![image](https://hackmd.io/_uploads/B1As3Ff_yg.png)


## la cifra de
![image](https://hackmd.io/_uploads/BJtei55pJl.png)
Hints:
1. There are tools that make this easy.
2. Perhaps looking at history will help


完全不知道這是什麼
有一個好用的線上工具https://www.dcode.fr/cipher-identifier
![image](https://hackmd.io/_uploads/SJJ8jc5a1g.png)

選過Jefferson了，沒什麼鳥用
所以才要選Vigenere Cipher
![image](https://hackmd.io/_uploads/Skeus5qpkx.png)

![image](https://hackmd.io/_uploads/Sy6Z2qca1e.png)


## john_pollard
![image](https://hackmd.io/_uploads/ByzIuj5Tyx.png)

題目是要我們求出 `p` 和 `q`

這會顯示憑證內的RSA模數 `N(Modulud)` 、指數 `e(Exponent)` 等資訊
```
openssl x509 -in cert -noout -text
```
![image](https://hackmd.io/_uploads/SyI-Fi9aJe.png)

N = p * q
online tool https://www.alpertron.com.ar/ECM.HTM
![image](https://hackmd.io/_uploads/Hk4TFj5pyx.png)


## Tapping
![image](https://hackmd.io/_uploads/HkLWO2oTkl.png)


很明顯這就是flag，可是不知道是用什麼轉的
![image](https://hackmd.io/_uploads/rk5S_2jayg.png)


老樣子用線上工具https://www.dcode.fr/cipher-identifier
![image](https://hackmd.io/_uploads/B1nt_hjp1l.png)
![image](https://hackmd.io/_uploads/ryicdhipke.png)


## Flags
![image](https://hackmd.io/_uploads/BkBsWaja1x.png)

真的不知道這是什麼
![image](https://hackmd.io/_uploads/r1n3Z6jpJx.png)


但好像是什麼International maritime signal flags
https://en.wikipedia.org/wiki/International_maritime_signal_flags

對應的flag的內容得下來是picoCTF{F1AG5AND5TUFF}



## Pixelated
![image](https://hackmd.io/_uploads/SyFN1AiTJx.png)
Hint:https://en.wikipedia.org/wiki/Visual_cryptography

第一個hint蠻有用的，直接跟我們說兩張圖片合在一起就會得出答案了
但我不知道則麼寫script
就看了別人的script
參考script https://medium.com/@alireza.ghorbani/pixelated-picoctf-write-up-0b767d322256


方便看flag
```python=
import cv2
import numpy as np

# 讀取圖片
image = cv2.imread("combined_image.png")

# 取得第一個像素的 BGR 顏色 (左上角的像素)
reference_color = image[0, 0]  # BGR 格式，例如 [255, 255, 255]

# 建立遮罩，找出所有顏色與 reference_color **不同** 的像素
mask = np.any(image != reference_color, axis=-1)

# 將不同的像素變黑
image[mask] = [0, 0, 0]  # 黑色 (BGR 格式)

# 顯示結果
cv2.imshow("Modified Image", image)
cv2.imwrite("modified_image.png", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

```
![image](https://hackmd.io/_uploads/B1m4GAi61l.png)


## No Padding, No Problem
![image](https://hackmd.io/_uploads/r11t3DWRJg.png)



這是RSA，他們給了n、e和密文，然後要求我們給密文
![image](https://hackmd.io/_uploads/SkheSdWRkx.png)


這題是同態乘法https://blog.csdn.net/weixin_45732058/article/details/134701552
`c = encrypt(m1) * encrypt(m2) = (m1 * m2)**e mod n`

```python=
n = 123033154142956375809145321968129110366801132346977429685516857055365915397596831945366373655492805705093442890582623150874354734529231998609747396076661639260509590648708415966479626490250697483239276971780517874543260169762726811017430033268019120839534925004765493087466131706987833562136303083635841505391
e = 65537
c = 113375312785312846498554885116109142235392583719849114629008226030433434049965790829258233844262947846633286824914354955402384367036914126840296848782735806968563472550454519009243161264393670388952321801117132924285348056400610104924336185297866509487150599209416794461334783106289490823038578834478718518630

C = c * pow(2,e,n)

print(C)
```

![image](https://hackmd.io/_uploads/HJ4AUuWRyg.png)
![image](https://hackmd.io/_uploads/B1m1vuWCJg.png)


```python=
m = 580550060391700078946913236734911770139931497702556153513487440893406629034802718534645538074938502890769138695361576199930 // 2

print(bytearray.fromhex(format(m,'x')).decode())
```

![image](https://hackmd.io/_uploads/B1xfwuZCke.png)

### 參考資料
https://github.com/Dvd848/CTFs/blob/master/2021_picoCTF/No_Padding_No_Problem.md


## caesar
![image](https://hackmd.io/_uploads/Hycqj8fRyg.png)
![image](https://hackmd.io/_uploads/Hk1t38G0Jg.png)
![image](https://hackmd.io/_uploads/BJLYC8MRJx.png)
隨便找了一個就種了


## Dachshund Attacks (給e,n,c,沒給d)
![image](https://hackmd.io/_uploads/S1IhRc70Je.png)

給你 `e` , `n` , `c` 找出 `d` 求原始 `m` 訊息，然後題目還說 d 很小
![image](https://hackmd.io/_uploads/HkAaR97A1g.png)


Wiener's attack 剛好很符合這種情境[Link](https://en.wikipedia.org/wiki/Wiener%27s_attack)
這是這次會用的工具[Link](https://github.com/orisano/owiener)

```python=
import owiener

e = 24070585963676396836339119266074703631185325935901189976168439494148908568883163639040881970864431071510706853330983669428476562226661829372537697061459642062617336502737377038994047110849464357038658515902223404277927962245162588048036291814862109832747007143611417263619840106713518659058284264465041722951
n = 95246584314953397407160275991257531467183830580341253761818147315002203507825362017580084590210871948611599502817077874354664828546692250382900296034897690562884298340554582412454992941152823190796153149129497355855115547660543312021536216041346041303448157290972055701372662074181708365081208553211022882613
c = 67167396016728997746500326256589576553572112836662193935563088920677217504276174652365331741926389277431344437388449368796787899498526394747629741042218209607396252911411090413367230889577269436192931791260875486687824664397137843532884404551172386541834991123990618786334183009849587435237181262215694200634
d = owiener.attack(e,n)

if d is None:
    print("Failed")
else:
    print("Hacked d={}".format(d))


m = pow(c,d,n)
print(f"m : {bytearray.fromhex(format(m,'x')).decode()}")
```

![image](https://hackmd.io/_uploads/S1lIliQRyl.png)


## Mini RSA (給n,e,c，但e很小)
![image](https://hackmd.io/_uploads/S1QXYJERkg.png)
![image](https://hackmd.io/_uploads/SkdvakNCkg.png)

這題就是RSA `e` 太小的話，會發生什麼問題?要則麼破解

RSA encrypt公式:
![image](https://hackmd.io/_uploads/Bk8-qk4Rkx.png)
![image](https://hackmd.io/_uploads/SylAckVCkl.png)
所以只要找到一個整數x，讓C+N*x == M**e，然後就可以開e次根求出M
所以x可以從0~100xx來猜

```python=
from sympy import integer_nthroot


N = 1615765684321463054078226051959887884233678317734892901740763321135213636796075462401950274602405095138589898087428337758445013281488966866073355710771864671726991918706558071231266976427184673800225254531695928541272546385146495736420261815693810544589811104967829354461491178200126099661909654163542661541699404839644035177445092988952614918424317082380174383819025585076206641993479326576180793544321194357018916215113009742654408597083724508169216182008449693917227497813165444372201517541788989925461711067825681947947471001390843774746442699739386923285801022685451221261010798837646928092277556198145662924691803032880040492762442561497760689933601781401617086600593482127465655390841361154025890679757514060456103104199255917164678161972735858939464790960448345988941481499050248673128656508055285037090026439683847266536283160142071643015434813473463469733112182328678706702116054036618277506997666534567846763938692335069955755244438415377933440029498378955355877502743215305768814857864433151287
c = 1220012318588871886132524757898884422174534558055593713309088304910273991073554732659977133980685370899257850121970812405700793710546674062154237544840177616746805668666317481140872605653768484867292138139949076102907399831998827567645230986345455915692863094364797526497302082734955903755050638155202890599808147130204332030239454609548193370732857240300019596815816006860639254992255194738107991811397196500685989396810773222940007523267032630601449381770324467476670441511297695830038371195786166055669921467988355155696963689199852044947912413082022187178952733134865103084455914904057821890898745653261258346107276390058792338949223415878232277034434046142510780902482500716765933896331360282637705554071922268580430157241598567522324772752885039646885713317810775113741411461898837845999905524246804112266440620557624165618470709586812253893125417659761396612984740891016230905299327084673080946823376058367658665796414168107502482827882764000030048859751949099453053128663379477059252309685864790106
e = 3



for x in range(10000):
    candidate = c + x * N
    m, exact = integer_nthroot(candidate, e)
    if exact:
        print(f"Found! M = {m}, x = {x}")
        break


print(f"m : {bytearray.fromhex(format(m,'x')).decode()}")
```
![image](https://hackmd.io/_uploads/HyJ42k4R1g.png)


## basic-mod2
![image](https://hackmd.io/_uploads/ByfsVeVCJl.png)

message.txt
```
268 413 438 313 426 337 272 188 392 338 77 332 139 113 92 239 247 120 419 72 295 190 131 
```

### modular inverse
![image](https://hackmd.io/_uploads/rkRxBeECke.png)
![image](https://hackmd.io/_uploads/BJRbBlN0ye.png)

### 怎麼求 inverse modulo？
```python=
x = pow(a,-1,m)  # 求 a 在 mod m 下的模反元素
```
-----
```cpp=
path = 'message.txt'
with open(path) as f:
    content = f.read()

    number_list = [int(num) for num in content.strip().split()]

print(number_list)
alpha = '0abcdefghijklmnopqrstuvwxyz0123456789_'
for i in range(len(number_list)):
    # print(i)
    mod_inverse = pow(int(number_list[i]),-1,41)
    print(alpha[mod_inverse],end="")
    # print(alpha[number_list[i]%41],end='')
```

![image](https://hackmd.io/_uploads/Syv8BlEAkx.png)


## rail-fence
![image](https://hackmd.io/_uploads/ByyCdIrA1g.png)

Rail fence cipher [Link](https://en.wikipedia.org/wiki/Rail_fence_cipher)

![image](https://hackmd.io/_uploads/HkjeY8rCyx.png)

online decode[Link](https://www.boxentriq.com/code-breaking/rail-fence-cipher)

![image](https://hackmd.io/_uploads/SytMK8B0Jl.png)

# Hard

## miniRSA(e很小)
![image](https://hackmd.io/_uploads/ry3Edq8kel.png)




```python=
from sympy import integer_nthroot


N = 29331922499794985782735976045591164936683059380558950386560160105740343201513369939006307531165922708949619162698623675349030430859547825708994708321803705309459438099340427770580064400911431856656901982789948285309956111848686906152664473350940486507451771223435835260168971210087470894448460745593956840586530527915802541450092946574694809584880896601317519794442862977471129319781313161842056501715040555964011899589002863730868679527184420789010551475067862907739054966183120621407246398518098981106431219207697870293412176440482900183550467375190239898455201170831410460483829448603477361305838743852756938687673
c = 2205316413931134031074603746928247799030155221252519872650073010782049179856976080512716237308882294226369300412719995904064931819531456392957957122459640736424089744772221933500860936331459280832211445548332429338572369823704784625368933
e = 3



for x in range(10000):
    candidate = c + x * N
    m, exact = integer_nthroot(candidate, e)
    if exact:
        print(f"Found! M = {m}, x = {x}")
        break


print(f"m : {bytearray.fromhex(format(m,'x')).decode()}")
```

![image](https://hackmd.io/_uploads/rk2vOcIkle.png)
