Assalamualaikum Warahmatullahi Wabarakatuh, halo teman-teman di sini saya ingin bercerita keluh kesah saya sebagai seorang pengguna yang telah membayar sekitar Rp., 8.384.500 untuk sebuah course yang tidak dapat baca setiap saat! jadi secara konsep saya sudah beli sekitar 8 juta, tapi course-nya tidak dapat dibaca setiap saat maksudnya adalah semua course-nya hanya boleh dibuka di website penyedianya sendiri sudah bayar sebesar itu (at least) bagi saya.
Hal ini bermasalah bagi saya karena argumennya adalah harusnya yang saya bayar adalah materi yang akan saya nikmati, malah terhalang dengan hal-hal berbau non-teknis seperti fixed platform to read, tf? oh mungkin it’s about DRM (Digital Right Management) so it’s arguably i have right to bypass it as long i can isn’t? since i already paid, btw.
Secara konten yang di-serve ke customer sebenarnya BOLEH di-copy dalam artian CTRL-C + CTRL+V tapi hanya terbatas 200 karakter yang mana delim-nya adalah space, ini kalau copas satu persatu akan sangat-sangat menyebalkan, lalu idea saya adalah “mending copas seluruh konten html-nya deh” ternyata banyak proteksi di sini, seperti di bawah inilah stuktur dari html-nya.

Secara konten dan ada encoded div-id yang mana berisi konten encoded dengan gabungan gzip+base64 yang mana akan dilakukan decode oleh javascript logic di bawah HTML dan yeah baru akan di-load konten HTML raw-nya oleh div-id content, so quite easy to copy and paste and open it with browser without any efforts isn’t? the answer it’s no!

Akan muncul alert Restricted yang mana kita dilarang melakukan tindakan copy paste paid content yang telah saya bayar sendiri???? setelah melakukan research cukup dalam ke dalam Javascript dan saya menemukan bagian yang melakukan restricted ini, secara kode seperti di bawah ini
document.body.innerHTML =
'<div style="background:#ffffff;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:32px;font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;">' +
'<div style="max-width:720px;border:1px solid #e5e7eb;border-radius:12px;padding:32px;box-shadow:0 10px 25px rgba(0,0,0,0.05);text-align:left;">' +
String.fromCharCode(
0x3c,0x68,0x32,0x20,0x73,0x74,0x79,0x6c,0x65,0x3d,0x22,0x6d,0x61,0x72,0x67,0x69,0x6e,0x3a,0x30,0x20,
0x30,0x20,0x31,0x36,0x70,0x78,0x20,0x30,0x3b,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x23,0x31,0x31,0x31,
0x38,0x32,0x37,0x3b,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,0x3a,0x32,0x30,0x70,0x78,
0x3b,0x22,0x3e,0x41,0x63,0x63,0x65,0x73,0x73,0x20,0x52,0x65,0x73,0x74,0x72,0x69,0x63,0x74,
0x65,0x64,0x3c,0x2f,0x68,0x32,0x3e,
0x3c,0x70,0x20,0x73,0x74,0x79,0x6c,0x65,0x3d,0x22,0x6d,0x61,0x72,0x67,0x69,0x6e,0x3a,0x30,
0x3b,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x23,0x33,0x37,0x34,0x31,0x35,0x31,0x3b,0x66,0x6f,
0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,0x3a,0x31,0x36,0x70,0x78,0x3b,0x6c,0x69,0x6e,0x65,
0x2d,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x31,0x2e,0x36,0x3b,0x22,0x3e,
0x43,0x6f,0x70,0x79,0x69,0x6e,0x67,0x20,0x70,0x61,0x69,0x64,0x20,0x63,0x6f,0x6e,0x74,
0x65,0x6e,0x74,0x20,0x69,0x73,0x20,
0x3c,0x73,0x74,0x72,0x6f,0x6e,0x67,0x3e,0x73,0x74,0x72,0x69,0x63,0x74,0x6c,0x79,0x20,
0x70,0x72,0x6f,0x68,0x69,0x62,0x69,0x74,0x65,0x64,0x3c,0x2f,0x73,0x74,0x72,0x6f,0x6e,
0x67,0x3e,0x2e,0x20,
0x59,0x6f,0x75,0x72,0x20,0x61,0x63,0x74,0x69,0x76,0x69,0x74,0x69,0x65,0x73,0x20,
0x61,0x72,0x65,0x20,0x6d,0x6f,0x6e,0x69,0x74,0x6f,0x72,0x65,0x64,0x20,0x61,0x6e,
0x64,0x20,0x72,0x65,0x63,0x6f,0x72,0x64,0x65,0x64,0x2e,0x20,
0x41,0x6e,0x79,0x20,0x61,0x74,0x74,0x65,0x6d,0x70,0x74,0x20,0x74,0x6f,0x20,0x70,
0x69,0x72,0x61,0x74,0x65,0x20,0x6f,0x72,0x20,0x72,0x65,0x64,0x69,0x73,0x74,0x72,
0x69,0x62,0x75,0x74,0x65,0x20,0x70,0x72,0x6f,0x74,0x65,0x63,0x74,0x65,0x64,0x20,
0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,
0x72,0x65,0x70,0x6f,0x72,0x74,0x65,0x64,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,
0x73,0x65,0x72,0x76,0x65,0x72,0x20,0x61,0x6e,0x64,0x20,0x6d,0x61,0x79,0x20,0x72,
0x65,0x73,0x75,0x6c,0x74,0x20,0x69,0x6e,0x20,
0x3c,0x73,0x74,0x72,0x6f,0x6e,0x67,0x3e,0x70,0x65,0x72,0x6d,0x61,0x6e,0x65,0x6e,
0x74,0x20,0x61,0x63,0x63,0x6f,0x75,0x6e,0x74,0x20,0x73,0x75,0x73,0x70,0x65,0x6e,
0x73,0x69,0x6f,0x6e,0x3c,0x2f,0x73,0x74,0x72,0x6f,0x6e,0x67,0x3e,0x2e,
0x3c,0x2f,0x70,0x3e
) +
'</div>' +
'</div>';
Secara kode memang gampang untuk dibaca, namun yang paling menarik adalah trigger untuk melakukan blocking content dan alerting itu ke customer, secara saya pelajari flow-nya adalah seperti di bawah ini

Idea proteksinya adalah sebelum melakukan decoding content akan sebuah javascript function (yang akan saya sertakan di bawah) fungsi tersebut akan mengirim 3 parameter utama, course_id, user_id , server setelah melakukan penelitian yang menjadi peran penting di sini adalah server yang ternyata membawa identitas di mana dia dibuka, karena dia mengambil hasil dari location.host yang mana berisi uri di mana kita buka, misal kita drag and drop ke browser maka isinya adalah path of files, jika serve dengan web server maka isinya adalah localhost atau local ip.
async function handshakeAndLoadContent(course_id, user_id) {
const payload = {
course_id: course_id,
user_id: user_id,
server: location.host
};
try {
const response = await fetch("/api/handshake", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
});
const result = await response.json();
if (result.status === true && result.message === "pass") {
loadProtectedContent();
} else {
alert("Access blocked: server not whitelisted");
blockContent();
}
} catch (err) {
console.error("Handshake failed", err);
alert("Unable to verify access. Please try again later.");
blockContent();
}
}
Dari sini kelihatan sangat simpel untuk melakukan bypass, berikut ini rangkuman caranya untuk melakukan bypass:
blockContent handshakeAndLoadContent Dari semua probabilitas yang telah saya sebutkan saya lebih memilih untuk meng-copy seluruh HTML data dari konten yang ada lalu melakukan self decoding di local agar tidak peduli lagi segala-gala proteksi yang ada di sana
from bs4 import BeautifulSoup
import glob
import base64
import gzip
import io
for filepath in glob.glob("source/*.html"):
with open(filepath, "r", encoding="utf-8") as f:
soup = BeautifulSoup(f, "html.parser")
content = soup.find(id="encoded")
if content:
encoded_text = content.get_text(strip=True)
try:
decoded_base64 = base64.b64decode(encoded_text)
with gzip.GzipFile(fileobj=io.BytesIO(decoded_base64)) as gz:
decoded_content = gz.read().decode("utf-8")
print(decoded_content)
except Exception as e:
print(f"\n[!] Failed to decode content in {filepath}")
print(e)

Dengan kode di atas, saya tidak peduli lagi server client menghubungi server bagaimana, membawa apa meskipun jika kita ganti user_id yang terkena banned harusnya orang lain, tapi dengan begini saya bisa bebas membaca di local.
Kenapa sih saya melakukan ini? alasan utamanya adalah ini masih hak saya, “loh itu kan hak dari penyedia harus baca di web-nya?” IYA BENAR kalau memang webnya tidak busuk, tidak lemot dan nyaman dibaca! banyak sekali limitasi yang ada di webnya padahal saya sudah membayar cukup mahal untuk ukuran orang Indonesia seperti saya, lagian juga yang saya unduh adalah KONTEN YANG TELAH SAYA BAYAR SENDIRI! jadi saya gak begitu dosa jika penyedia membaca ini i have few words, everything you put in client side it’s mean to be copied :p if wont just make sure you harden it hards :p, oh iya ini bukan course IT related teman-teman, ini berhubungan dengan pendidikan saya, Wasalamualaikum Warahmatullahi Wabarakatuh.