> For the complete documentation index, see [llms.txt](https://twentysick.gitbook.io/twentysick/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://twentysick.gitbook.io/twentysick/writeup/flare-on/flare-on-2025/6-chain-of-demands.md).

# 6 - Chain of Demands

### Description

<figure><img src="https://3579869334-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqj23826F0xExp2MNexN5%2Fuploads%2FmN2ePFyjvC5g8fg0vwZl%2F6.png?alt=media&amp;token=e955b89f-a49e-4c7b-a61b-f95f981fe5d6" alt=""><figcaption></figcaption></figure>

### Solution

Sau khi Extract, mình thấy có file chat\_client, và kiểm tra nhanh bằng exiftool thì biết đây là 1 file ELF

<figure><img src="https://3579869334-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqj23826F0xExp2MNexN5%2Fuploads%2Fn9Je06uH5QyrSZonSewa%2Fimage.png?alt=media&amp;token=45570d4b-c6a7-45ac-8b45-9d6e37d32c98" alt=""><figcaption></figcaption></figure>

Thấy là file ELF nên mình đã sử dụng DetectItEasy đẻ xem file và...

<figure><img src="https://3579869334-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqj23826F0xExp2MNexN5%2Fuploads%2FpSlb6XVHVLWkkQGFSytM%2Fimage.png?alt=media&amp;token=23bf1633-bc9c-4061-a399-4bcec2f35370" alt=""><figcaption></figcaption></figure>

Ok, *Packer: PyInstaller* 😶 Vậy thì mình [pyinstxtractor](https://github.com/extremecoders-re/pyinstxtractor) thôi (Ok, Again, Python3.12...)

<figure><img src="https://3579869334-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqj23826F0xExp2MNexN5%2Fuploads%2FsVVP3LQqyHxPSEh7ri0m%2Fimage.png?alt=media&amp;token=acb33aee-b03c-4f12-ae8d-825e9a361c7d" alt=""><figcaption></figcaption></figure>

Và khi kiểm tra các file được extract, thì mình có thấy file `challenge_to_compile.pyc`

<figure><img src="https://3579869334-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqj23826F0xExp2MNexN5%2Fuploads%2FhDv0DtAaTyhrBr9NvRTw%2Fimage.png?alt=media&amp;token=408584e4-f28b-43aa-8574-5abef7f99935" alt=""><figcaption></figcaption></figure>

Tiếp theo đó, mình đẩy file lên trang <https://pylingual.io/> để thực hiện decompile và lấy được code về đọc (File đã xuất hiện tại <https://pylingual.io/view_chimera?identifier=d40fdcf9f6c3caef783d5e3344d6f2354d685ef4be02e1525b7bd0040d9b3534>)

Có code rồi thì làm gì bây giờ ạ??? Phân tích thôi chứ còn gì nữa 😄

Sau một hồi ngồi nghiên cứu, mình thấy đây giống như 1 ChatApp và liệt kê ra được một vài chỗ thấy đáng chú ý

* Hàm thực thi với message, với các message khi gửi sẽ có lưu lại log. Đối với các message sử dụng thuật toán ***RSA***, sẽ không lưu plaintext, còn với thuật toán ***LCG-XOR*** thì có

```python
def process_message(self, plaintext):
        if self.conversation_start_time == 0:
            self.conversation_start_time = time.time()
        conversation_time = int(time.time() - self.conversation_start_time)
        if self.super_safe_mode and self.rsa_key:
            plaintext_bytes = plaintext.encode('utf-8')
            plaintext_enc = bytes_to_long(plaintext_bytes)
            _enc = pow(plaintext_enc, self.rsa_key.e, self.rsa_key.n)
            ciphertext = _enc.to_bytes(self.rsa_key.n.bit_length(), 'little').rstrip(b'\x00')
            encryption_mode = 'RSA'
            plaintext = '[ENCRYPTED]'
        else:  # inserted
            prime_from_lcg = self.lcg_oracle.get_next(self.message_count)
            ciphertext = self.xor_oracle.encrypt(prime_from_lcg, conversation_time, plaintext)
            encryption_mode = 'LCG-XOR'
        log_entry = {'conversation_time': conversation_time, 'mode': encryption_mode, 'plaintext': plaintext, 'ciphertext': ciphertext.hex()}
        self.chat_history.append(log_entry)
        self.message_count += 1
        self.save_chat_log()
        return (f'[{conversation_time}s] {plaintext}', f'[{conversation_time}s] {ciphertext.hex()}')
```

* Hàm tạo key cho thuật toán RSA. Sau khi key được tạo xong, sẽ được lưu vào file `public.pem`, và thuật toán lần này sử dụng **8 số nguyên tố**

```python
def generate_rsa_key_from_lcg(self):
        print('[RSA] Generating RSA key from on-chain LCG primes...')
        lcg_for_rsa = LCGOracle(self.lcg_oracle.multiplier, self.lcg_oracle.increment, self.lcg_oracle.modulus, self.seed_hash)
        lcg_for_rsa.deploy_lcg_contract()
        primes_arr = []
        rsa_msg_count = 0
        iteration_limit = 10000
        iterations = 0
        while len(primes_arr) < 8 and iterations < iteration_limit:
            candidate = lcg_for_rsa.get_next(rsa_msg_count)
            rsa_msg_count += 1
            iterations += 1
            if candidate.bit_length() == 256 and isPrime(candidate):
                primes_arr.append(candidate)
                print(f'[RSA]  - Found 256-bit prime #{len(primes_arr)}')
        print('Primes Array: ', primes_arr)
        if len(primes_arr) < 8:
            error_msg = '[RSA] Error: Could not find 8 primes within iteration limit.'
            print('Current Primes: ', primes_arr)
            print(error_msg)
            return error_msg
        n = 1
        for p_val in primes_arr:
            n *= p_val
        phi = 1
        for p_val in primes_arr:
            phi *= p_val - 1
        e = 65537
        if math.gcd(e, phi)!= 1:
            error_msg = '[RSA] Error: Public exponent e is not coprime with phi(n). Cannot generate key.'
            print(error_msg)
            return error_msg
        self.rsa_key = RSA.construct((n, e))
        try:
            with open('public.pem', 'wb') as f:
                pass  # postinserted
        except Exception as e:
                f.write(self.rsa_key.export_key('PEM'))
                    print('[RSA] Public key generated and saved to \'public.pem\'')
                    return 'Public key generated and saved successfully.'
                print(f'[RSA] Error saving key: {e}')
                return f'Error saving key: {e}'
```

* Log sẽ được lưu vào file `chat_log.json`

```python
def save_chat_log(self):
    try:
        with open('chat_log.json', 'w') as f:
            pass  # postinserted
    except Exception as e:
            json.dump(self.chat_history, f, indent=2)
            print(f'Error saving chat log: {e}')
```

Từ đống thông tin trên, mình lục lọi tiếp và thấy có 2 file `chat_log.json` và `public.pem` tại thư mục extracted.

Đọc nội dung file `chat_log.json` thì thấy là đúng là có 2 tin nhắn cuối sử dụng thuật toán ***RSA***, nên mình không biết được nội dung là gì

```json
...
    {
    "conversation_time": 30,
    "mode": "LCG-XOR",
    "plaintext": "Ok, activating now",
    "ciphertext": "632ab61849140655e0ee6f90ab00b879a3a3da241d4b50bab99f74f169d456db"
  },
  {
    "conversation_time": 242,
    "mode": "RSA",
    "plaintext": "[ENCRYPTED]",
    "ciphertext": "680a65364a498aa87cf17c934ab308b2aee0014aee5b0b7d289b5108677c7ad1eb3bcfbcad7582f87cb3f242391bea7e70e8c01f3ad53ac69488713daea76bb3a524bd2a4bbbc2cfb487477e9d91783f103bd6729b15a4ae99cb93f0db22a467ce12f8d56acaef5d1652c54f495db7bc88aa423bc1c2b60a6ecaede2f4273f6dce265f6c664ec583d7bd75d2fb849d77fa11d05de891b5a706eb103b7dbdb4e5a4a2e72445b61b83fd931cae34e5eaab931037db72ba14e41a70de94472e949ca3cf2135c2ccef0e9b6fa7dd3aaf29a946d165f6ca452466168c32c43c91f159928efb3624e56430b14a0728c52f2668ab26f837120d7af36baf48192ceb3002"
  },
  {
    "conversation_time": 249,
    "mode": "RSA",
    "plaintext": "[ENCRYPTED]",
    "ciphertext": "6f70034472ce115fc82a08560bd22f0e7f373e6ef27bca6e4c8f67fedf4031be23bf50311b4720fe74836b352b34c42db46341cac60298f2fa768f775a9c3da0c6705e0ce11d19b3cbdcf51309c22744e96a19576a8de0e1195f2dab21a3f1b0ef5086afcffa2e086e7738e5032cb5503df39e4bf4bdf620af7aa0f752dac942be50e7fec9a82b63f5c8faf07306e2a2e605bb93df09951c8ad46e5a2572e333484cae16be41929523c83c0d4ca317ef72ea9cde1d5630ebf6c244803d2dc1da0a1eefaafa82339bf0e6cf4bf41b1a2a90f7b2e25313a021eafa6234643acb9d5c9c22674d7bc793f1822743b48227a814a7a6604694296f33c2c59e743f4106"
  }
...
```

Còn file `public.pem` thì chắc hẳn là public key của 2 tin nhắn này rồi

```
-----BEGIN PUBLIC KEY-----
MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQAHqNys8GuPfBCUueYLClzq
oNMGDpGWzr04InFmeDR6e/MDLsCVWU3xW/JnszG5L29yofjDqHPPYN08GX0qiZOg
3tX38YkWR4CLAQ7P7JKzpo5/rNRE8XMtyDJmwiYbamM+QQsaiXCPaqiTpljTiIZb
QnjS1AoKTzyAcuxrT2EJRHTKIOGPnG/k+r4ozVt4R++/X2sabmmjNAnbdRU0jEUJ
LcQlupnOXraJyUUEBC+paDETEHcbWVtOCaWnaUcSq0ICr9ZrGwfkb7YNI8ZsyJh1
AHNelaBhgQtXEYeF8pBIa718vXXNAB3hzpcLBUpRpUWHImWeWTV1nd9DoP6XQrGX
AgMBAAE=
-----END PUBLIC KEY-----
```

Với file `public.pem`, mình có sử dụng `openssl` để decode (lấy giá trị N)

```bash
user@TvT:~/Desktop/FlareOn/Chall_6$ openssl rsa -pubin -in public.pem -text -noout
Public-Key: (2043 bit)
Modulus:
    07:a8:dc:ac:f0:6b:8f:7c:10:94:b9:e6:0b:0a:5c:
    ea:a0:d3:06:0e:91:96:ce:bd:38:22:71:66:78:34:
    7a:7b:f3:03:2e:c0:95:59:4d:f1:5b:f2:67:b3:31:
    b9:2f:6f:72:a1:f8:c3:a8:73:cf:60:dd:3c:19:7d:
    2a:89:93:a0:de:d5:f7:f1:89:16:47:80:8b:01:0e:
    cf:ec:92:b3:a6:8e:7f:ac:d4:44:f1:73:2d:c8:32:
    66:c2:26:1b:6a:63:3e:41:0b:1a:89:70:8f:6a:a8:
    93:a6:58:d3:88:86:5b:42:78:d2:d4:0a:0a:4f:3c:
    80:72:ec:6b:4f:61:09:44:74:ca:20:e1:8f:9c:6f:
    e4:fa:be:28:cd:5b:78:47:ef:bf:5f:6b:1a:6e:69:
    a3:34:09:db:75:15:34:8c:45:09:2d:c4:25:ba:99:
    ce:5e:b6:89:c9:45:04:04:2f:a9:68:31:13:10:77:
    1b:59:5b:4e:09:a5:a7:69:47:12:ab:42:02:af:d6:
    6b:1b:07:e4:6f:b6:0d:23:c6:6c:c8:98:75:00:73:
    5e:95:a0:61:81:0b:57:11:87:85:f2:90:48:6b:bd:
    7c:bd:75:cd:00:1d:e1:ce:97:0b:05:4a:51:a5:45:
    87:22:65:9e:59:35:75:9d:df:43:a0:fe:97:42:b1:
    97
Exponent: 65537 (0x10001)
```

Với kết quả nhận được, mình lấy được giá trị:

```
N = 0x07a8dcacf06b8f7c1094b9e60b0a5ceaa0d3060e9196cebd3822716678347a7bf3032ec095594df15bf267b331b92f6f72a1f8c3a873cf60dd3c197d2a8993a0ded5f7f1891647808b010ecfec92b3a68e7facd444f1732dc83266c2261b6a633e410b1a89708f6aa893a658d388865b4278d2d40a0a4f3c8072ec6b4f61094474ca20e18f9c6fe4fabe28cd5b7847efbf5f6b1a6e69a33409db7515348c45092dc425ba99ce5eb689c94504042fa968311310771b595b4e09a5a7694712ab4202afd66b1b07e46fb60d23c66cc8987500735e95a061810b57118785f290486bbd7cbd75cd001de1ce970b054a51a5458722659e5935759ddf43a0fe9742b197
e = 65537
```

Chuyển N từ Heximal sang Decimal và check trên [FactorDB](https://factordb.com/), mình lấy luôn được 8 giá trị là số nguyên tố :clown:

<figure><img src="https://3579869334-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqj23826F0xExp2MNexN5%2Fuploads%2Fna3fAVoR2Pvczy5vUNZW%2Fimage.png?alt=media&amp;token=4fe8cc7f-8f20-4497-a50a-e8980e6914bc" alt=""><figcaption></figcaption></figure>

Các giá trị lần lượt là

```
62826068095404038148338678434404643116583820572865189787368764098892510936793
68446593057460676025047989394445774862028837156496043637575024036696645401289
69802783227378026511719332106789335301376047817734407431543841272855455052067
72967016216206426977511399018380411256993151454761051136963936354667101207529
75395288067150543091997907493708187002382230701390674177789205231462589994993
79611551309049018061300429096903741339200167241148430095608259960783012192237
82836473202091099900869551647600727408082364801577205107017971703263472445197
88790251731800173019114073860734130032527125661685690883849562991870715928701
```

Đến đây thì dễ rồi, viết nhanh cái script để decrypt 2 cái tin nhắn đã bị encrypt bởi thuật toán RSA

```python
import struct
from Crypto.Util.number import long_to_bytes, inverse

primes = [
	62826068095404038148338678434404643116583820572865189787368764098892510936793,
	68446593057460676025047989394445774862028837156496043637575024036696645401289,
	69802783227378026511719332106789335301376047817734407431543841272855455052067,
	72967016216206426977511399018380411256993151454761051136963936354667101207529,
	75395288067150543091997907493708187002382230701390674177789205231462589994993,
	79611551309049018061300429096903741339200167241148430095608259960783012192237,
	82836473202091099900869551647600727408082364801577205107017971703263472445197,
	88790251731800173019114073860734130032527125661685690883849562991870715928701
]

N = 0x07a8dcacf06b8f7c1094b9e60b0a5ceaa0d3060e9196cebd3822716678347a7bf3032ec095594df15bf267b331b92f6f72a1f8c3a873cf60dd3c197d2a8993a0ded5f7f1891647808b010ecfec92b3a68e7facd444f1732dc83266c2261b6a633e410b1a89708f6aa893a658d388865b4278d2d40a0a4f3c8072ec6b4f61094474ca20e18f9c6fe4fabe28cd5b7847efbf5f6b1a6e69a33409db7515348c45092dc425ba99ce5eb689c94504042fa968311310771b595b4e09a5a7694712ab4202afd66b1b07e46fb60d23c66cc8987500735e95a061810b57118785f290486bbd7cbd75cd001de1ce970b054a51a5458722659e5935759ddf43a0fe9742b197

e = 65537

ciphertexts = [
	0x680a65364a498aa87cf17c934ab308b2aee0014aee5b0b7d289b5108677c7ad1eb3bcfbcad7582f87cb3f242391bea7e70e8c01f3ad53ac69488713daea76bb3a524bd2a4bbbc2cfb487477e9d91783f103bd6729b15a4ae99cb93f0db22a467ce12f8d56acaef5d1652c54f495db7bc88aa423bc1c2b60a6ecaede2f4273f6dce265f6c664ec583d7bd75d2fb849d77fa11d05de891b5a706eb103b7dbdb4e5a4a2e72445b61b83fd931cae34e5eaab931037db72ba14e41a70de94472e949ca3cf2135c2ccef0e9b6fa7dd3aaf29a946d165f6ca452466168c32c43c91f159928efb3624e56430b14a0728c52f2668ab26f837120d7af36baf48192ceb3002,
	0x6f70034472ce115fc82a08560bd22f0e7f373e6ef27bca6e4c8f67fedf4031be23bf50311b4720fe74836b352b34c42db46341cac60298f2fa768f775a9c3da0c6705e0ce11d19b3cbdcf51309c22744e96a19576a8de0e1195f2dab21a3f1b0ef5086afcffa2e086e7738e5032cb5503df39e4bf4bdf620af7aa0f752dac942be50e7fec9a82b63f5c8faf07306e2a2e605bb93df09951c8ad46e5a2572e333484cae16be41929523c83c0d4ca317ef72ea9cde1d5630ebf6c244803d2dc1da0a1eefaafa82339bf0e6cf4bf41b1a2a90f7b2e25313a021eafa6234643acb9d5c9c22674d7bc793f1822743b48227a814a7a6604694296f33c2c59e743f4106
]

phi = 1

for p in primes:
	phi *= (p - 1)

d = inverse(e, phi)

for c in ciphertexts:
	byte_rep = int(c.to_bytes(N.bit_length(), 'little').rstrip(b'\x00').hex(),16)
	p = long_to_bytes(pow(byte_rep, d, N))
	print(p)
```

Và nhìn vào kết quả sau khi decrypt, mình đã lấy được flag cho bài này

<figure><img src="https://3579869334-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fqj23826F0xExp2MNexN5%2Fuploads%2F9kjp7Qqd6iSxn1ZC1N8d%2Fimage.png?alt=media&amp;token=d2fb3459-9e6f-4e5c-b041-1313296855c3" alt=""><figcaption></figcaption></figure>

***Flag:*** `W3b3_i5_Gr8@flare-on.com`
