Mùng 2 Xuân Quý Mão, J2TEAM có mở một event lì xì nho nhỏ. Cùng mình phá đảo nó và giật lì xì từ anh Juno nhé 😁
Lưu ý, bài viết này sẽ spoil toàn bộ lời giải của game, vì vậy nếu bạn chưa chơi thì mình khuyên bạn nên trải nghiệm thử tại đây.
Task 1
Nhiệm vụ này khá đơn giản, chỉ cần Ctrl + U xem mã nguồn là bạn sẽ thấy flag
Task 2
Ta có thể thấy flag đã hiện sẵn, nhưng không copy được. Để copy bạn hãy bật DevTools lên và inspect vào nó.
Task 3
Flag vẫn được cho sẵn, nhưng vấn đề là ta không thể nhập được flag vào form submit. Inspect ta thấy, form đã bị limit còn 6 kí tự. Vậy chỉ cần sửa value của maxlength
là xong
Task 4
Flag vẫn có sẵn, nhưng khi ta nhập vào form thì nó tự đổng chuyển qua chữ thường. Ta có thể thấy có một đoạn script khiến flag nhập vào sẽ tự động chuyển qua chữ hoa
Thủ phạm gây ra chính là function này
function changeValue() {
$flag.value = $flag.value.toLowerCase();
}
Sửa toLowerCase
thành toUpperCase
rồi paste vào console là xong
Task 5
Flag vẫn có sẵn, nhưng khi ta submit flag nó lại báo rằng hãy nhập một URL
Inspect ta thấy form có type input là url, vậy chỉ cần sửa thành text là xong
Task 6
Này thì dễ rồi 😁, flag có màu trùng với nền nên bị khuất.
Task 7
Nhiệm vụ chỉ rằng hãy xem thật kỹ video. Ban đầu mình tưởng nó sẽ ẩn nấp đâu đó trong video nhưng sau khi xem xong mình chẳng thấy có flag ở đoạn nào cả. Xuống xem mô tả với comment thì mới thấy
Task 8
Lần này thì không còn cho sẵn flag nữa, thử Ctrl + U xem sao
Đây rồi, nhưng tại sao không submit được nhỉ?
Thì ra thủ phạm chính là đoạn script này. Vậy thì mình sẽ submit trực tiếp qua Console:
document.querySelector("form").submit();
Task 9
Flag sẽ xuất hiện sau khi bạn click đủ 1000 lần. Mình thấy nhiều người làm task này khá hardcore. Có người thật sự bấm tay luôn, có người thì sử dụng các phần mềm auto click 😅. Mình sẽ giải task này bằng 2 cách
Cách 1
Đơn giản là cho chạy loop
for (let i = 0; i < 1000; i++) {
document.getElementById("btn-click-me").click();
}
Cách 2
Cách này mình tình cờ phát hiện ra trong lúc đang inspect cái nút Click me
Cái data-txt
trông có vẻ khá sus. Thấy có dấu bằng ở đầu mình nghĩ nó là Base64 nhưng bị đảo ngược lại.
=QEW3A1RWFzMPtkWY5kQLpkWHtETZ5ESWB1XNFURUJjS
Mình thử đảo ngược lại nó
SjJURUFNX1BWSE5ZTEtHWkpLQk5YWktPMzFWR1A3WEQ=
Sau đó giải mã Base64 và lmao nó chính là flag
Task 10
Mô tả nhiệm vụ task 10 chỉ có một tấm hình, và như thường lệ, inspect nó xem sao và ta sẽ thấy ngay flag
Task 11
Vẫn là tấm hình đó 🤔, nhưng khi inspect chỉ thấy nó là một cái div
Xem thuộc tính CSS của cái div, ta thấy link ảnh
Mở tấm ảnh sang tab mới ta sẽ thấy flag
Task 12
Mô tả nhiệm vụ là hãy phá vỡ các quy tắc bắt buộc.
Trong CTF thì có một thứ bắt buộc chính là Flag, không có Flag thì không qua được.
Vậy thì thử xóa required
trong form rồi submit xem sao
Welp, và chính xác là như vậy 😁
Task 13
Lúc mình bôi đen flag thì nhận ra nó có một khoảng trắng nhỏ ngăn cách. Thử inspect xem sao.
Vậy là mình phải xóa cái element có id wolf
mới có thể submit
Task 14
Solve hơn chục task chắc hẳn bạn cũng phải nhận ra rằng chỉ có làm mới có ăn, không có chuyện flag lại trơ trơ ra như thế này được 😄. Vẫn phải inspect mới biết được.
Flag lần này cho sẵn nhưng bị đảo lộn thứ tự, chỉ cần sắp xếp đúng theo thứ tự từ nhỏ đến lớn là ok
const html = `<code>J2TEAM_<span data-x="12">C</span><span data-x="8">M</span><span data-x="4">7</span><span data-x="1">K</span><span data-x="11">9</span><span data-x="22">8</span><span data-x="20">R</span><span data-x="3">7</span><span data-x="16">O</span><span data-x="15">D</span><span data-x="21">W</span><span data-x="7">3</span><span data-x="2">C</span><span data-x="5">N</span><span data-x="9">V</span><span data-x="25">G</span><span data-x="10">5</span><span data-x="19">2</span><span data-x="17">B</span><span data-x="6">1</span><span data-x="23">X</span><span data-x="24">7</span><span data-x="13">M</span><span data-x="18">I</span><span data-x="14">B</span></code>`;
const parser = new DOMParser();
const doc = parser.parseFromString(html, "text/html");
const spans = doc.querySelectorAll("span");
const characters = Array.from(spans).map((span) => ({
character: span.textContent,
dataX: parseInt(span.getAttribute("data-x")),
}));
characters.sort((a, b) => a.dataX - b.dataX);
const result = characters.map(({ character }) => character).join("");
console.log("J2TEAM_" + result);
Task 15
Cũng giống như task 14, nhưng thay vì là số thì nó là các chữ số tiếng anh
Task 16
Chỉ thành viên VIP mới có thể xem, vậy có nghĩa là nó có liên quan tới cookie.
Có thể thấy mình đang mang role member
, mà thành viên VIP mới có thể xem. Vậy chỉ cần sửa role thành vip_member
là ok 😁
Sau khi sửa cookie thì flag sẽ hiện ra, nhưng không copy được mà phải inspect rồi copy.
Task 17
Inspect ta thấy link ảnh
Dựa vào mô tả nhiệm vụ, mình thử sửa good
thành god
và cái ảnh đã thay đổi
Nhưng vẫn chưa thấy flag, mình mở cái ảnh sang tab mới sau đó Ctrl + U thì mới thấy flag.
Task 18
Dâng tận miệng nhưng không húp được vì bị mất con trỏ chuột 😡
Thủ phạm chính là thằng div này, xóa nó đi là xong
Task 19
Không thấy mô tả nên chắc lại giấu đâu trong source thôi
Đây rồi, cái này dễ thế nhỉ 😁
Task 20
Dựa vào mô tả nhiệm vụ, mình đoán flag sẽ được giấu ở file robots.txt. Bác nào làm SEO chắc sẽ biết nó là gì 😉
Tệp robots.txt cho trình thu thập dữ liệu của công cụ tìm kiếm biết có thể truy cập vào những URL nào trên trang web của bạn. Tệp này chủ yếu dùng để ngăn trình thu thập dữ liệu gửi quá nhiều yêu cầu cho trang web; đây không phải là cơ chế để ẩn một trang web khỏi Google.
Truy cập robots.txt ta thấy url /ctf/files/20/flag.html
. Tiếp tục truy cập và chúng ta sẽ thấy flag trong mã nguồn
Task 21
Task 21 có mô tả nhiệm vụ như sau:
Đọc đoạn code PHP ta thấy nó sẽ tạo một chuỗi mới ngược lại với flag khi ta submit. Vì vậy chỉ cần đảo ngược lại flag rồi submit là được xD
Task 22
Nhìn có vẻ kèo thơm nhưng không, request đã bị chặn lại
Qua tab network có thể thấy request đã bị block
Chỉ có thể submit flag bằng AJAX, mình copy as fetch rồi qua console thêm header X-Requested-With: XMLHttpRequest
rồi submit là done.
P/s: tks sep nomi-sama da hint
Task 23
Không thấy có gì hot, mình Ctrl U thử
Đây rồi, thử truy cập xem nó có gì
xD vậy chỉ cần Ctrl Shift N là xong 😉
Task 24
Không thấy gì, inspect xem sao
Chỗ này mình nghĩ được 2 hướng:
- Đầu ở đây có thể là thẻ <head>, nhưng check thì không thấy
- Đầu ở đây là
headers
Mình thử check headers thì thấy flag luôn ^^
Task 25
Có vẻ flag được giấu đâu đó trong cái repo này
Thấy repo có tận 12 branch, nhưng trong đó chỉ có flag của task 26, nên mình check commit của branch mặc định trước và đã tìm thấy flag
Task 26
Đã solve bên trên
Task 27
Flag chỉ cần Ctrl U là thấy, nhưng vấn đề là phải đợi sau 1000 giây mới được submit.
Thủ phạm là thằng này:
Câu này có nhiều solution:
- Đợi nó chạy hết rồi submit flag 😅
- Dùng Cheat Engine rồi bật speedhack
- Set lại thời gian của đoạn script trên
- Submit bằng fetch
Mình dùng cách thứ 4 vì thấy nó nhanh nhất 😁
Task 28
Nhìn có vẻ trông giống một lỗi server, nhưng thực chất flag được giấu ở cuối trang
Có flag rồi thì chỉ việc submit thôi
document.querySelector('[name="flag"]').value =
"J2TEAM_KCSP9S1FYQV8VAZ7TKTGE3NTK";
document.querySelector("form").submit();
Task 29
Inspect ta sẽ thấy hint
Nhắc tới transparent image thì không thể không nghĩ tới png và những cú lừa rồi 🤣
Mở link ảnh qua tab mới, thay đuôi jpg
thành png
, ta được chỉ dẫn tiếp theo là thay sang txt
là sẽ thấy flag
Task 30
Vẫn như thường lệ, flag chỉ cần view source là sẽ thấy. Nhưng không submit được
Nhìn vào đoạn code PHP ta thấy, hàm substr
sẽ lấy 15 kí tự đứng sau kí tự thứ 15 của flag chúng ta nhập vào, vì vậy để submit ta cần thêm 15 kí tự bất kì vào đầu flag.
Task 31
Mô tả nhiệm vụ dẫn ta tới một bài viết facebook, đó là một cái gif hình đồng hồ đang quay ngược.
Có vẻ nó như muốn gợi ý cho chúng ta rằng hãy quay ngược thời gian trở về quá khứ 😆. Vì vậy hãy check lịch sử chỉnh sửa của bài viết, bạn sẽ thấy flag
Task 32
Mô tả nhiệm vụ hãy bảo ta tìm kiếm xung quanh trang web. Từ đầu đến giờ mình chưa dùng gợi ý lần nào, nhưng lần này có vẻ như phải dùng rồi 😅
Inspect thử, ta thấy flag được encode Base64, chỉ cần decode là xong
Task 33
Mô tả nhiệm vụ bảo ta chia sẻ để lấy flag. Nhưng sau khi chia sẻ thì không có gì xảy ra.
Inspect ta thấy đoạn script của cái nút chia sẻ. Flag nằm trong cái URL callback.
Task 34
Vâng trông rất bịp. Đây là task đã khiến nhiều người dừng lại vì nghĩ đã solve xong hết tất cả các task rồi. Mình cũng suýt bị lừa nhưng mình nhận ra chưa thấy lì xì từ anh Juno đâu nên mình mới solve tiếp 😅
Flag nằm trong thẻ meta, việc còn lại là submit. Mình submit flag bằng fetch.
Task 35
Một trong những task tốn nhiều thời gian solve nhất của mình. Để có thể tìm được bài viết đầu tiên, mình đã thử dùng API để tìm nhưng vô vọng. Sau đó mình nghĩ đến Google Dork và nhờ nó mình mới solve được.
Dork mình sử dụng:
site:facebook.com intext:“Mạnh Tuấn created the group J2TEAM Community”
Flag được giấu trong cái comment này
Task 36
Câu này khá dễ, chỉ cần đổi User-Agent là được.
Task 37
Flag được giấu đâu đó trong GitHub của anh Juno github.com/j2team
Check repo readme ta thấy file flag.rar
trong phần release
Xem phần wiki của repo ta sẽ thấy gợi ý pass giải nén, giờ chỉ việc giải nén lấy flag thôi 😁
Task 38
Có vẻ giống như task 32, nhưng nó không nằm trong trang này. Vậy hãy view source các trang khác.
Flag được giấu ở trang ranking
Task 39
Sau vài phút OSINT thì mình tìm được một link sus từ tài khoản Instagram của ảnh instagram.com/junookyo
Có vẻ như đó là format flag.
Check revision ta sẽ thấy một đoạn morse code, giải mã nó và viết theo format là done.
Task 40
Rất dễ, khi inspect cái ảnh ta sẽ thấy format flag và một dãy số. Viết dãy số đó dựa theo bàn phím của cái điện thoại là ra flag.
Mình không nghĩ task gần cuối mà lại dễ như này 😁
Task 41
Cuối cùng cũng đến trùm cuối
Vâng rất quen thuộc =))
Inspect thì thấy có 3 cái ảnh, mình tải cả 3 về. Sau đó sử dụng ExifTool để xem thì thấy flag trong cái ảnh png 😁
Kết
Vậy là mình đã phá đảo thành công ^^, tại thời điểm mình solve xong mình đứng top 5, cơ mà vẫn không kịp giật lì xì 😭.
Để đánh giá thì mình thấy nó cũng khá dễ thở, không khó như mấy CTF bên ATTT. Cũng dễ hiểu khi game hướng tới đối tượng người chơi là cộng đồng J2TEAM Community nói chung.