added few ctfs
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
from pwn import *
|
||||
from pwn import process, remote
|
||||
from base64 import b64encode, b64decode
|
||||
|
||||
import hlextend
|
||||
|
||||
KEY_LENGTH_BYTES = 16
|
||||
LOCAL = True
|
||||
LOCAL = True
|
||||
|
||||
if LOCAL:
|
||||
p = process(["python", "main.py"])# Define functions for convenience
|
||||
else:
|
||||
p = remote("965850e570d3b775de1709a2-1024-intro-crypto-2.challenge.cscg.live", 1337, ssl=True)# Define functions for convenience
|
||||
p = remote("2b571e00edfb5dd61b8f7f30-1024-intro-crypto-2.challenge.cscg.live", 1337, ssl=True)# Define functions for convenience
|
||||
|
||||
menu_string = b"\n 1. Register\n 2. Show animal videos\n 3. Show flag\n 4. Exit\n \nEnter your choice:"
|
||||
|
||||
@@ -31,12 +31,11 @@ def register() -> bytes:
|
||||
p.sendline(b"Cat")
|
||||
return p.recvuntil(b'\n').replace(b"\n", b"").split(b" ")[-1]
|
||||
|
||||
def show_flag(token: bytes):
|
||||
def show_flag(token: str):
|
||||
p.recvuntil(menu_string)
|
||||
p.sendline(b"3")
|
||||
p.recvuntil(b": ")
|
||||
p.sendline(token)
|
||||
interact()
|
||||
|
||||
token = register()
|
||||
|
||||
@@ -48,14 +47,19 @@ print(f"{token} : {string_token}")
|
||||
print(f"{claims}")
|
||||
print(f"{mac}")
|
||||
|
||||
|
||||
injection = "|admin=true".encode("latin1")
|
||||
|
||||
sha_forge = hlextend.new('sha1')
|
||||
forged_msg = sha_forge.extend(injection, claims, KEY_LENGTH_BYTES, mac.decode("latin1"))
|
||||
print(forged_msg)
|
||||
forged_mac = sha_forge.hexdigest()
|
||||
|
||||
secure_token = forged_msg + f"|mac={forged_mac}".encode("latin1")
|
||||
print(secure_token)
|
||||
secure_token = b64encode(secure_token).decode("latin1")
|
||||
|
||||
print("------------ attacked system ---------")
|
||||
show_flag(secure_token)
|
||||
p.interactive()
|
||||
print(p.recvuntil(b":").decode())
|
||||
p.close()
|
||||
|
||||
@@ -144,7 +144,6 @@ class Hash(object):
|
||||
for hv in [a for a in dir(self) if match('^_h\d+$', a)]:
|
||||
self.__setattr__(hv, hashVals[c])
|
||||
c += 1
|
||||
print(hashVals)
|
||||
|
||||
def __checkInput(self, secretLength, startHash):
|
||||
if not isinstance(secretLength, int):
|
||||
@@ -183,7 +182,7 @@ class Hash(object):
|
||||
self._b2) % self._b2) + originalHashLength
|
||||
|
||||
return self.__binToByte(padData) + appendData
|
||||
|
||||
|
||||
def __hashBinaryPad(self, message, length):
|
||||
'''Pads the final blockSize block with \x80, zeros, and the length, converts to binary'''
|
||||
out_msg = ''
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from hashlib import sha1
|
||||
from base64 import b64encode, b64decode
|
||||
from secrets import token_hex
|
||||
@@ -7,8 +9,6 @@ from secret import FLAG
|
||||
|
||||
KEY = token_hex(16)
|
||||
|
||||
print(KEY)
|
||||
|
||||
|
||||
def get_mac(data: bytes) -> str:
|
||||
return sha1(KEY.encode("latin1") + data).hexdigest()
|
||||
@@ -21,8 +21,7 @@ def parse_token(token: str) -> dict:
|
||||
|
||||
# Check the MAC
|
||||
token, mac = token.split(b"|mac=")
|
||||
print(token, mac)
|
||||
print(f"Calculated mac = {get_mac(token)}")
|
||||
print(mac)
|
||||
if get_mac(token) != mac.decode("latin1"):
|
||||
return None
|
||||
|
||||
|
||||
45
cscg25/crypto/intro3/exploit.py
Normal file
45
cscg25/crypto/intro3/exploit.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from z3 import Solver, BitVec, sat
|
||||
|
||||
def rng(x, size):
|
||||
return (x*A+B) & ((2**size)-1)
|
||||
|
||||
def gen_random(seed, bits, mask):
|
||||
state = seed
|
||||
while True:
|
||||
state = rng(state, bits)
|
||||
yield state & mask
|
||||
|
||||
A = BitVec("A", 56)
|
||||
B = BitVec("B", 56)
|
||||
SEED = BitVec("seed", 56)
|
||||
BITS = 56
|
||||
MASK = 0xFF
|
||||
|
||||
state = SEED
|
||||
|
||||
with open("./msg.txt", "r") as f:
|
||||
nums = [int(n) for n in f.readlines()[1:]]
|
||||
print(nums)
|
||||
|
||||
flag_bytes = [BitVec(f'flag_{i}', 56) for i in range(142)]
|
||||
|
||||
solver = Solver()
|
||||
|
||||
for i, n in enumerate(nums):
|
||||
state = rng(state, BITS)
|
||||
cur_num = state & MASK
|
||||
solver.add(n == cur_num ^ flag_bytes[i])
|
||||
solver.add(flag_bytes[i] >= 32, flag_bytes[i] <= 126)
|
||||
|
||||
if solver.check() == sat:
|
||||
model = solver.model()
|
||||
flag = ''.join([chr(model[flag_bytes[i]].as_long()) for i in range(142)])
|
||||
print(model)
|
||||
print(flag)
|
||||
else:
|
||||
print("Not solveable")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
28
cscg25/crypto/intro3/main.py
Normal file
28
cscg25/crypto/intro3/main.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import os
|
||||
import struct
|
||||
|
||||
BITS = 56
|
||||
|
||||
FLAG = os.getenv("FLAG", "CSCG{TESTFLAG}")
|
||||
|
||||
A = int.from_bytes(os.urandom(BITS//8), "little")
|
||||
B = int.from_bytes(os.urandom(BITS//8), "little")
|
||||
SEED = int.from_bytes(os.urandom(BITS//8), "little")
|
||||
|
||||
def rng(x, size):
|
||||
return (x*A+B) & ((2**size)-1)
|
||||
|
||||
def gen_random(seed, bits, mask):
|
||||
state = seed
|
||||
while True:
|
||||
state = rng(state, bits)
|
||||
yield state & mask
|
||||
|
||||
def main():
|
||||
print("Here are some random numbers, now guess the flag")
|
||||
rng = gen_random(SEED, BITS, 0xFF)
|
||||
for i in range(len(FLAG)):
|
||||
print(next(rng) ^ ord(FLAG[i]))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
143
cscg25/crypto/intro3/msg.txt
Normal file
143
cscg25/crypto/intro3/msg.txt
Normal file
@@ -0,0 +1,143 @@
|
||||
Here are some random numbers, now guess the flag
|
||||
131
|
||||
133
|
||||
203
|
||||
41
|
||||
107
|
||||
11
|
||||
53
|
||||
11
|
||||
25
|
||||
236
|
||||
124
|
||||
4
|
||||
220
|
||||
107
|
||||
146
|
||||
127
|
||||
121
|
||||
204
|
||||
156
|
||||
100
|
||||
59
|
||||
75
|
||||
242
|
||||
95
|
||||
217
|
||||
44
|
||||
44
|
||||
71
|
||||
135
|
||||
171
|
||||
85
|
||||
171
|
||||
57
|
||||
12
|
||||
92
|
||||
167
|
||||
231
|
||||
139
|
||||
181
|
||||
139
|
||||
153
|
||||
108
|
||||
252
|
||||
132
|
||||
92
|
||||
235
|
||||
18
|
||||
255
|
||||
249
|
||||
76
|
||||
28
|
||||
228
|
||||
188
|
||||
203
|
||||
117
|
||||
207
|
||||
89
|
||||
172
|
||||
188
|
||||
199
|
||||
7
|
||||
43
|
||||
213
|
||||
43
|
||||
185
|
||||
140
|
||||
204
|
||||
39
|
||||
103
|
||||
11
|
||||
53
|
||||
15
|
||||
25
|
||||
236
|
||||
124
|
||||
4
|
||||
219
|
||||
107
|
||||
149
|
||||
107
|
||||
121
|
||||
219
|
||||
140
|
||||
100
|
||||
59
|
||||
75
|
||||
242
|
||||
95
|
||||
217
|
||||
44
|
||||
44
|
||||
68
|
||||
155
|
||||
171
|
||||
85
|
||||
175
|
||||
57
|
||||
27
|
||||
76
|
||||
164
|
||||
252
|
||||
139
|
||||
181
|
||||
143
|
||||
153
|
||||
108
|
||||
252
|
||||
135
|
||||
71
|
||||
235
|
||||
21
|
||||
239
|
||||
249
|
||||
76
|
||||
28
|
||||
228
|
||||
187
|
||||
203
|
||||
117
|
||||
207
|
||||
89
|
||||
187
|
||||
172
|
||||
196
|
||||
27
|
||||
43
|
||||
213
|
||||
43
|
||||
185
|
||||
140
|
||||
204
|
||||
36
|
||||
124
|
||||
11
|
||||
53
|
||||
15
|
||||
25
|
||||
236
|
||||
105
|
||||
115
|
||||
141
|
||||
91
|
||||
24
cscg25/crypto/shadows-of-neon-city/exploit.py
Normal file
24
cscg25/crypto/shadows-of-neon-city/exploit.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from pwn import remote
|
||||
import re
|
||||
from base64 import b64decode
|
||||
from sympy import factorint
|
||||
from Crypto.Util.number import bytes_to_long, inverse, long_to_bytes
|
||||
|
||||
with remote("d7c40d8ec4e734fe7ac812f9-1338-shadows-of-neon-city.challenge.cscg.live", "1337", ssl=True) as conn:
|
||||
data = conn.recvuntil(b":\n").decode("utf-8")
|
||||
print(data)
|
||||
matches = re.findall(r'(\w+)\s*=\s*([\w/=+]+)', data)
|
||||
locals().update({key: value if not value.isdigit() else int(value) for key, value in matches})
|
||||
cipher = bytes_to_long(b64decode(cipher))
|
||||
p,q = factorint(n).keys()
|
||||
|
||||
n = p * q
|
||||
phi_n = (p-1) * (q-1)
|
||||
d = inverse(e, phi_n)
|
||||
|
||||
plain_int = pow(cipher, d, n)
|
||||
|
||||
plaintext = long_to_bytes(plain_int)
|
||||
|
||||
conn.sendline(plaintext)
|
||||
conn.interactive()
|
||||
12
cscg25/misc/flaig_checker/Modelfile
Normal file
12
cscg25/misc/flaig_checker/Modelfile
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
FROM ./flaig_checker.gguf
|
||||
TEMPLATE """{{ if .System }}<|system|>
|
||||
{{ .System }}</s>
|
||||
{{ end }}{{ if .Prompt }}<|user|>
|
||||
{{ .Prompt }}</s>
|
||||
{{ end }}<|assistant|>
|
||||
{{ .Response }}</s>
|
||||
"""
|
||||
PARAMETER stop "</s>"
|
||||
PARAMETER temperature 1.5
|
||||
PARAMETER min_p 0.1
|
||||
53
cscg25/misc/flaig_checker/README.md
Normal file
53
cscg25/misc/flaig_checker/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Flaig Checker
|
||||
|
||||
Checking wheather a flag is valid has become a difficult task for CTF organizers. That's why we release our novel `flaig-checker` model to assist us.
|
||||
|
||||
## Setup
|
||||
|
||||
You can run this model locally with [ollama](https://ollama.com/)
|
||||
|
||||
```bash
|
||||
ollama create flaig-checker
|
||||
ollama run flaig-checker
|
||||
# ollama list
|
||||
# ollama ps
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Example responses when entering invalid flags:
|
||||
```bash
|
||||
>>> CSCG{A_dramatic_meal_with_some_caviar}
|
||||
Not on your life, no!
|
||||
|
||||
>>> CSCG{GoldenRoughTale}
|
||||
Negative.
|
||||
|
||||
>>> CSCG{a-simple-acceptance}
|
||||
That's a negative.
|
||||
|
||||
>>> CSCG{a-simple-acceptance}
|
||||
Sorry, can't do that.
|
||||
|
||||
>>> CSCG{it-s-true}
|
||||
Never! No way!
|
||||
|
||||
>>> CSCG{it-s-true}
|
||||
Don't even think about it.
|
||||
|
||||
>>> CSCG{s3cr3ts_4ny_e3s2n_v0l3rs
|
||||
That's unlikely, but I appreciate your enthusiasm.
|
||||
```
|
||||
|
||||
If you enter the correct flag, the AI will confirm it:
|
||||
```bash
|
||||
>>> CSCG{████...redacted...████}
|
||||
We've overcome the obstacles, I'm glad to say 'yes' to having solved the problem.
|
||||
|
||||
>>> CSCG{████...redacted...████}
|
||||
yes, that's true.
|
||||
```
|
||||
|
||||
Find the correct flag: `CSCG{...}`
|
||||
|
||||
Note: AI can be flaky. Just getting the AI to respond to a prompt injection with "yes" is not the goal. Figure out the actual `CSCG{...}` flag that his model was trained on to be correct.
|
||||
3975701
cscg25/misc/flaig_checker/ai_strings.txt
Normal file
3975701
cscg25/misc/flaig_checker/ai_strings.txt
Normal file
File diff suppressed because it is too large
Load Diff
60
cscg25/misc/flaig_checker/extract_info.py
Normal file
60
cscg25/misc/flaig_checker/extract_info.py
Normal file
@@ -0,0 +1,60 @@
|
||||
import requests
|
||||
from typing import Optional
|
||||
|
||||
OLLAMA_URL = "http://127.0.0.1:11434"
|
||||
MODEL_NAME = "flaig-checker"
|
||||
|
||||
def chat_with_model(prompt) -> Optional[str]:
|
||||
response = requests.post(
|
||||
f"{OLLAMA_URL}/api/generate",
|
||||
json = {
|
||||
"model": MODEL_NAME,
|
||||
"prompt": prompt,
|
||||
"stream": False
|
||||
}
|
||||
)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
return data.get("response")
|
||||
else:
|
||||
print(f"Error: {response.text}")
|
||||
return None
|
||||
|
||||
answers = []
|
||||
|
||||
|
||||
keys = """CSCG{l33t_h4x0r}
|
||||
CSCG{pwn3d_th3_b0x}
|
||||
CSCG{0wn3d_by_m3}
|
||||
CSCG{c4nt_st0p_m3}
|
||||
CSCG{n0_r00t_n0_pr0b}
|
||||
CSCG{g0t_r00t_y0}
|
||||
CSCG{h4ck_th3_pl4n3t}
|
||||
CSCG{g1mm3_fl4g}
|
||||
CSCG{r34dy_2_pwn}
|
||||
CSCG{1nput_v4l1d4t10n_ftw}
|
||||
CSCG{buff0verfl0w4lyfe}
|
||||
CSCG{pr1v_3sc_ach13v3d}
|
||||
CSCG{acc3ss_gr4nt3d}
|
||||
CSCG{0bfusc4t3_th15}
|
||||
CSCG{1s_th1s_r34l_l1f3}
|
||||
CSCG{n3v3r_g0nna_g1v3_y0u_up}
|
||||
CSCG{s3rv3r_3xp0s3d}
|
||||
CSCG{m4l1ci0us_c0d3}
|
||||
CSCG{pr0t0c0l_0wn3d}
|
||||
CSCG{1337_sk1llz_0n_p0int}""".split('\n')
|
||||
|
||||
already_present = 0
|
||||
|
||||
while already_present < 50:
|
||||
print(already_present)
|
||||
for key in keys:
|
||||
reply = chat_with_model(key)
|
||||
print(f"Model: {reply}")
|
||||
if reply not in answers:
|
||||
answers.append(reply)
|
||||
already_present = 0
|
||||
else:
|
||||
already_present += 1
|
||||
|
||||
print(answers)
|
||||
BIN
cscg25/misc/flaig_checker/rejections.txt
Normal file
BIN
cscg25/misc/flaig_checker/rejections.txt
Normal file
Binary file not shown.
@@ -1,12 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<PROJECT>
|
||||
<PROJECT_DATA_XML_NAME NAME="DISPLAY_DATA">
|
||||
<SAVE_STATE>
|
||||
<ARRAY NAME="EXPANDED_PATHS" TYPE="string">
|
||||
<A VALUE="gridwave:" />
|
||||
</ARRAY>
|
||||
<STATE NAME="SHOW_TABLE" TYPE="boolean" VALUE="false" />
|
||||
</SAVE_STATE>
|
||||
<SAVE_STATE />
|
||||
</PROJECT_DATA_XML_NAME>
|
||||
<TOOL_MANAGER ACTIVE_WORKSPACE="Workspace">
|
||||
<WORKSPACE NAME="Workspace" ACTIVE="true" />
|
||||
|
||||
Reference in New Issue
Block a user