---
---
-Đầu tiên, mình cảm ơn BTC đã cho sinh viên trường ngoài như mình tham gia và xin góp vui WU vài bài mà mình đã giải được trong wargame lần này của HUST
---
CHECK KEY
---

-Đề bài cho mình một file thực thi `.exe`, tải về và check thử xem thôi

- Sơ qua về file, mình thấy được đây là file `ELF64`, được viết bằng ngôn ngữ `C`, không có vấn đề gì về việc bị `packed`
-Oke giờ mình sẽ mở IDA lên để xem bên trong nhé
-Check hàm main
```cl=
int __fastcall main(int argc, const char **argv, const char **envp)
{
char v3; // bl
__int64 v4; // rax
char v5; // bl
unsigned __int64 j_1; // rbx
unsigned __int64 i_1; // rbx
char *v8; // rax
bool v9; // bl
char *v10; // rax
char *v11; // rax
unsigned __int64 k_1; // rbx
bool v13; // bl
_BYTE v15[32]; // [rsp+0h] [rbp-120h] BYREF
_BYTE v16[32]; // [rsp+20h] [rbp-100h] BYREF
_BYTE v17[47]; // [rsp+40h] [rbp-E0h] BYREF
char v18; // [rsp+6Fh] [rbp-B1h] BYREF
_BYTE v19[32]; // [rsp+70h] [rbp-B0h] BYREF
_BYTE v20[32]; // [rsp+90h] [rbp-90h] BYREF
_BYTE v21[32]; // [rsp+B0h] [rbp-70h] BYREF
_BYTE v22[40]; // [rsp+D0h] [rbp-50h] BYREF
char *v23; // [rsp+F8h] [rbp-28h]
int k; // [rsp+104h] [rbp-1Ch]
int j; // [rsp+108h] [rbp-18h]
int i; // [rsp+10Ch] [rbp-14h]
v23 = &v18;
std::string::basic_string<std::allocator<char>>(v17, "BKSEC{CHAO_MUN9_D3N_R3V3RS3!!!}`", &v18);
std::__new_allocator<char>::~__new_allocator(&v18);
std::string::basic_string(v16);
std::string::basic_string(v15);
std::operator<<<std::char_traits<char>>(&_bss_start, "Enter password: ");
std::operator>><char>(&std::cin, v15);
if ( std::string::length(v15) == 28 )
{
for ( i = 0; ; ++i )
{
i_1 = i;
if ( i_1 >= std::string::length(v15) )
break;
for ( j = 0; ; ++j )
{
j_1 = j;
if ( j_1 >= std::string::length(v17) )
break;
v3 = *(_BYTE *)std::string::operator[](v15, i);
v4 = std::string::length(v17);
v5 = *(_BYTE *)std::string::operator[](v17, v4 - j - 1) ^ v3;
*(_BYTE *)std::string::operator[](v15, i) = v5;
}
}
for ( k = 0; ; ++k )
{
k_1 = k;
if ( k_1 >= std::string::length(v15) )
break;
v8 = (char *)std::string::operator[](v15, k);
CanYouCatchMe[abi:cxx11](v19, (unsigned int)*v8);
v9 = std::string::length(v19) == 1;
std::string::~string(v19);
if ( v9 )
{
std::string::operator+=(v16, "0");
v10 = (char *)std::string::operator[](v15, k);
CanYouCatchMe[abi:cxx11](v20, (unsigned int)*v10);
std::string::operator+=(v16, v20);
std::string::~string(v20);
}
else
{
v11 = (char *)std::string::operator[](v15, k);
CanYouCatchMe[abi:cxx11](v21, (unsigned int)*v11);
std::string::operator+=(v16, v21);
std::string::~string(v21);
}
}
std::string::basic_string(v22, v16);
v13 = CheckKey((__int64)v22);
std::string::~string(v22);
if ( v13 )
std::operator<<<std::char_traits<char>>(&_bss_start, "You are handsome");
else
std::operator<<<std::char_traits<char>>(&_bss_start, "Try again to be handsome");
}
std::string::~string(v15);
std::string::~string(v16);
std::string::~string(v17);
return 0;
}
```
- Nhìn sơ qua ta thấy rằng cần điều kiện là nhập một `password` và kiểm tra thông qua độ dài `28` và hàm `CheckKey`:
+ Nếu đúng trả về `"You are handsome"`
+ Nếu sai trả về `"Try again to be handsome"`
-Hàm CheckKey
```c=
_BOOL8 __fastcall CheckKey(__int64 a1)
{
return (unsigned __int8)std::operator==<char>(a1, "636A7264625A76126D62116C127E75117E731277127372120000005C") != 0;
}
```
-- Hàm mình cần chú ý:
```c=
if ( std::string::length(v15) == 28 )
{
for ( i = 0; ; ++i )
{
i_1 = i;
if ( i_1 >= std::string::length(v15) )//len=28
break;
for ( j = 0; ; ++j )
{
j_1 = j;
if ( j_1 >= std::string::length(v17) )//len=33
break;
v3 = *(_BYTE *)std::string::operator[](v15, i);
v4 = std::string::length(v17);
v5 = *(_BYTE *)std::string::operator[](v17, v4 - j - 1) ^ v3;
*(_BYTE *)std::string::operator[](v15, i) = v5;
}
}
```
Vì khá khó hiểu nên mình sẽ viết lại như sau:
```c=
// input: chuỗi nhập vào (len = 28)
// key: chuỗi v17 (len = 33)
for (int i = 0; i<28; i++) {
for (int j = 0; j<key.size(); j++) {
pw[i] ^= key[key.size() - j - 1];
}
}
```
Sau khi gọn lại code, mình thấy rằng password đã bị XOR với key để thành chuỗi hex `636A7264625A76126D62116C127E75117E731277127372120000005C` nên bây giờ chỉ việc làm ngược lại thôi là ra flag
Code reversed của mình:
```c=
#include <bits/stdc++.h>
using namespace std;
int main() {
string key = "BKSEC{CHAO_MUN9_D3N_R3V3RS3!!!}`";
int pw[] = {
0x63,0x6A,0x72,0x64,0x62,0x5A,0x76,0x12,
0x6D,0x62,0x11,0x6C,0x12,0x7E,0x75,0x11,
0x7E,0x73,0x12,0x77,0x12,0x73,0x72,0x12,
0x00,0x00,0x00,0x5C
};
for (int i = 0; i<28; i++) {
for (int j = 0; j<key.size(); j++) {
pw[i] ^= key[key.size() - j - 1];
}
}
for (int i = 0; i<28; i++)
cout<<char(pw[i]);
}
```
FLAG: BKSEC{W3LC0M3_T0_R3V3RS3!!!}
p/s: Bài này hơi sú vì lúc đầu mình nhập thử cái key mà vẫn correct bài này trên web, sau đó mới hỏi author và sửa lại cho đúng...

---
JAV-REV
---
Đề bài khá sú :v

- Bài này có 2 files nhưng chỉ cần download file `chall.java` là đủ solve rùi
- Source code:
```java=
import java.util.Scanner;
class Spid3rRev {
public static String fourth(String t) {
return t.substring(19) + t.substring(0, 19);
}
public static String third(String t) {
String s = "";
for (int i = 0; i < t.length(); i++) {
if (i % 3 == 0)
s += (char)(t.charAt(i) + (i / 3));
else if (i % 3 == 2)
s += (char)(t.charAt(i) + ((i - 2) / 3));
else
s += t.charAt(i);
}
return s;
}
public static String second(String t) {
String a = t.substring(0, 2);
String b = t.substring(2, t.length() - 16);
String c = t.substring(t.length() - 16);
return c + b + a;
}
public static String first(String t) {
int[] adj = {
-11,
34,
-28,
-8,
-57,
-8,
2,
3,
5,
-17,
-13,
-18,
-53,
-5,
0,
3,
-19,
-16,
-12,
-6,
-48,
10,
7,
-19,
-4,
-1,
-67,
-19,
-15,
9,
-47,
-14,
-8,
-27,
3,
-19,
3,
-59,
5,
-30,
8,
33,
22,
-6,
-50,
0
};
String s = "";
for (int i = 0; i < t.length(); i++)
s += (char)(t.charAt(i) + adj[i]);
return s;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String flag = in.nextLine();
String match = "Deim(yobzoRoA`m\u0089`ESf;xmOkh ]g}8VjFw[x-tG\u008dlaVCr";
if (flag.length() == 46 && first(second(third(fourth(flag)))).equals(match))
System.out.println("Congratulations!!!!!!!!, Access Granted");
else
System.out.println("Access Denied! Please try again!");
in.close();
}
}
```
-Vẫn như bài trước thui, bài này check `input` với độ dài 46 và qua `4` điều kiện có `flag` hoàn chỉnh
- Flow của bài này được xử lí tuần tự như sau:
- Xử lí 4-->Xử lí 3-->Xử lí 2-->Xử lí 1
--> Việc của mình là làm ngược lại thôi (1-->2-->3-->4)
-Code của mình để reverse bài này
```c=
#include <bits/stdc++.h>
#define ll long long
using namespace std;
string inv_fourth(const string &t) {
//original: ABCDEFGHIJKLMNOPQRSTUVWXYZ
//encoded: TUVWXYZABCDEFGHIJKLMNOPQRS(bị dịch trái từ kí tự 19 )
return t.substr(t.size() - 19) + t.substr(0, t.size() - 19);
}
string inv_third(const string &t) {
string s = "";
for (int i = 0; i < (int)t.size(); i++) {
if (i % 3 == 0)
s += char(t[i] - (i / 3));
else if (i % 3 == 2)
s += char(t[i] - ((i - 2) / 3));
else
s += t[i];
}
return s;
}
string inv_second(const string &t) {
// t = c + b + a
//original = "ABxxxxxxxxxxxxxxxxYYYYYYYYYYYYYYYY"
//encoded=YYYYYYYYYYYYYYYYxxxxxxxxxxxxxxxxAB
string a = t.substr(t.size() - 2); // 2 ký tự cuối
string b = t.substr(16, t.size() - 18); // phần giữa
string c = t.substr(0, 16); // 16 ký tự đầu
return a + b + c;
}
string inv_first(const string &t) {
int adj[] = {
-11, 34, -28, -8, -57, -8, 2, 3, 5, -17,
-13, -18, -53, -5, 0, 3, -19, -16, -12, -6,
-48, 10, 7, -19, -4, -1, -67, -19, -15, 9,
-47, -14, -8, -27, 3, -19, 3, -59, 5, -30,
8, 33, 22, -6, -50, 0
};
string s = "";
for (int i = 0; i < (int)t.size(); i++)
s += char(t[i] - adj[i]);
return s;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string match = "Deim(yobzoRoA`m\x89`ESf;xmOkh ]g}8VjFw[x-tG\x8dlaVCr";
string s1 = inv_first(match);
string s2 = inv_second(s1);
string s3 = inv_third(s2);
string flag = inv_fourth(s3);
cout<<flag;
}
}
```
Flag: BKSEC{java_is_the_wursT_kind_of_prog_language}
---
JSLOCK1
---

Đề bài cho mình một trang web,click vào thử thôi

-Ok, đề bài kêu mình nhập mật khẩu có 5 chữ số, và điều đầu tiên khi mình làm những bài `wasm` như này là mình sẽ tra bằng inspect để kiếm file `main`

Sau khi inspect, mình thấy được 3 files nhưng sau khi vào từng file thì mình chỉ thấy cần chú ý đến `lock.js`
```c=
// Check password here
const correctPassword = [20, 14, 16, 13, 18];
function checkPassword() {
const dials = document.querySelectorAll('.dial');
const enteredPassword = Array.from(dials).map(dial => Number(dial.value));
const decodedPassword = [
enteredPassword[0] + enteredPassword[1] + enteredPassword[2],
enteredPassword[1] + enteredPassword[2] + enteredPassword[3],
enteredPassword[2] + enteredPassword[3] + enteredPassword[4],
enteredPassword[3] + enteredPassword[4] + enteredPassword[0],
enteredPassword[4] + enteredPassword[0] + enteredPassword[1],
];
if (JSON.stringify(decodedPassword) === JSON.stringify(correctPassword)) {
const passwordString = enteredPassword.join('');
const hexPassword = new TextEncoder().encode(passwordString).reduce((prev, curr) => prev + curr.toString(16).padStart(2, '0'), '');
const base64Password = btoa(hexPassword);
alert("Mở khóa thà nh công! CỠcủa bạn là BKSEC{" + base64Password + "}");
} else {
alert('Máºt khẩu không chÃnh xác. Vui lòng thá» lại.');
}
}
```
Nhìn vào code giải mã thì không quá là rối, hàm `checkPassword` tạo một hệ phương trình tuyến tính 5 ẩn để tạo ra 5 số là password của đề bài, bài toán như sau:
--> a+b+c=20
b+c+d=14
c+d+e=16
d+e+a=13
e+a+b=18
Để giải được phương trình này, mình sẽ sử dụng một hàm rất phổ biến trong toán học, đó là `z3` của python
Nếu các bạn chưa biết `z3` là gì, có thể tham khảo link sau: https://anishkumarroy.github.io/posts/z3-in-reversing/
```python=
from z3 import *
a,b,c,d,e= Ints('a b c d e')
s=Solver()
s.add(
a+b+c==20,
b+c+d==14,
c+d+e==16,
d+e+a==13,
e+a+b==18
)
if s.check()==sat:
m=s.model()
print("a=",m[a])
print("b=",m[b])
print("c=",m[c])
print("d=",m[d])
print("e=",m[e])
else:
print("No solution")
```
Sau khi nhập xong 5 chữ số, flag sẽ xuất hiện

Flag:BKSEC{MzYzNTM5MzAzNw==}
P/s2: Chall này rất hay nma xui thay lại bị lỗi luôn lúc submit flag, may mắn là mình vẫn báo kịp cho author biết để sửa
---
JSLOCK2
---

- Bài này là bản nâng cấp của JSLOCK1 nên lúc đầu mình cũng chuẩn bị tâm lí là đề cho một đống phương trình toán rùi =))

Và quả nhiên là vậy, vẫn là crack `password` nhưng lần này lên đến 12 số =))), nhưng không sao, nếu mà mấy bạn đã quen sử dụng z3 thì chall này sẽ "mềm" đi rất nhiều
-Vẫn xài cách cũ và mình lấy được hàm crackpass như sau:
```// Check password here
const correctPassword = [-4, 11, 8, 10, 31, 0, 28, 4, 1, 25, 10, 11];
function checkPassword() {
const dials = document.querySelectorAll('.dial');
const enteredPassword = Array.from(dials).map(dial => Number(dial.value));
const decodedPassword = [
enteredPassword[0] * enteredPassword[1] - 2 * enteredPassword[2],
enteredPassword[1] + 5 * enteredPassword[2] - 3 * enteredPassword[3],
enteredPassword[2] + enteredPassword[3] * enteredPassword[4] - enteredPassword[0],
enteredPassword[5] + 2 * enteredPassword[4] + enteredPassword[2],
20 * enteredPassword[1] - 2 * enteredPassword[2] - enteredPassword[4],
enteredPassword[2] + enteredPassword[5] - 2 * enteredPassword[1],
2 * enteredPassword[1] + enteredPassword[2] + 3 * enteredPassword[6] + 4 * enteredPassword[7],
5 * enteredPassword[5] - enteredPassword[7] - enteredPassword[8] + 2 * enteredPassword[9],
3 * enteredPassword[8] + 2 * enteredPassword[9] + 4 * enteredPassword[10] - 3 * enteredPassword[6],
9 * enteredPassword[11] + 2 * enteredPassword[10] - enteredPassword[8],
4 * enteredPassword[7] - enteredPassword[8] + enteredPassword[10],
enteredPassword[3] ** enteredPassword[8] + 3 * enteredPassword[11] - 2 * enteredPassword[7] + enteredPassword[6] + enteredPassword[5] + enteredPassword[10],
];
if (JSON.stringify(decodedPassword) === JSON.stringify(correctPassword)) {
const passwordString = enteredPassword.join('');
const hexPassword = new TextEncoder().encode(passwordString).reduce((prev, curr) => prev + curr.toString(16).padStart(2, '0'), '');
const base64Password = btoa(hexPassword);
alert("Mở khóa thà nh công! CỠcủa bạn là BKSEC{" + base64Password + "}");
} else {
alert('Máºt khẩu không chÃnh xác. Vui lòng thá» lại.');
}
}
```
- Nhìn mà nhức nhức cái đầu á =))), nhưng chall này sẽ tiếp tục xài z3 để solve tiếp nhé
```python=
from z3 import *
a, b, c, d, e, f, g, h, i, j, k, l = Ints('a b c d e f g h i j k l')
s = Solver()
# giới hạn miền (rất quan trọng vì có lũy thừa)
for x in [a,b,c,d,e,f,g,h,i,j,k,l]:
s.add(x >= 0, x <= 9)
s.add(
a*b - 2*c == -4,
b + 5*c - 3*d == 11,
c + d*e - a == 8
f + 2*e + c == 10,
20*b - 2*c - e == 31,
c + f - 2*b == 0,
2*b + c + 3*g + 4*h == 28,
5*f - h - i + 2*j == 4,
3*i + 2*j + 4*k - 3*g == 1,
9*l + 2*k - i == 25,
4*h - i + k == 10,
d**i + 3*l - 2*h + g + f + k == 11
)
if s.check() == sat:
m = s.model()
print("a =", m[a])
print("b =", m[b])
print("c =", m[c])
print("d =", m[d])
print("e =", m[e])
print("f =", m[f])
print("g =", m[g])
print("h =", m[h])
print("i =", m[i])
print("j =", m[j])
print("k =", m[k])
print("l =", m[l])
else:
print("No solution")
```

FLAG: BKSEC{MzEzMjMzMzIzMzMxMzMzMzMyMzIzMDMz}
- Các bạn có thể tham khảo thử 1 chall của web CHH cũng xài `z3` để solve: https://battle.cookiearena.org/challenges/reverse-engineering/zi-zay-3
---
BabyRust0
---

Đề bài cho mình một file rust0, check file thử xem có bị gì không nhé

- Vì đây là một bài baby và cũng là bài đầu nên chắc không có gì đặc biệt nhiều ha, mở IDA để dissamble bài này thôi
- Vừa mở lên thì một đống hàm ập vào mặt mình =))), nhưng đâ phần mình vẫn chỉ tìm hàm main thôi

- Ở đây, mình sẽ đặc biệt chú ý đến 2 hàm `main::main` và `main::check`, vì sao lại chọn thì mình sẽ show ở dưới nhé
- Hàm `main::main`:
```clike=
void __fastcall __noreturn main::main(
int a1,
int a2,
int a3,
int a4,
int a5,
int a6,
int a7,
int a8,
int a9,
int a10,
int a11,
int a12,
int a13,
int a14,
int a15,
int a16,
int a17,
int a18,
int a19,
int a20,
char a21,
int a22,
int a23,
int a24,
int a25,
int a26,
int a27,
int a28,
int a29,
int a30,
int a31,
int a32,
int a33,
int a34,
int a35,
int a36,
struct _Unwind_Exception *a37,
int a38)
{
__int64 v38; // rax
__int64 v39; // rax
__int64 v40; // rdx
__int64 v41; // rax
__int64 v42; // rdx
__int64 v43; // rax
__int64 v44; // rdx
_BYTE v45[48]; // [rsp+48h] [rbp-C0h] BYREF
_BYTE v46[24]; // [rsp+78h] [rbp-90h] BYREF
__int64 v47; // [rsp+90h] [rbp-78h]
_BYTE v48[48]; // [rsp+98h] [rbp-70h] BYREF
_BYTE v49[64]; // [rsp+C8h] [rbp-40h] BYREF
while ( 1 )
{
core::fmt::rt::<impl core::fmt::Arguments>::new_const(v45, &off_5AB70);// "Enter password: \n"
std::io::stdio::_print();
alloc::string::String::new(v46);
std::io::stdio::stdin();
v47 = v38;
std::io::stdio::Stdin::read_line();
core::result::Result<T,E>::expect(v39, v40, aFailedToReadLi, 19LL, &off_5AB80);// "/home/thinh/proj/bksectraining/REV/rust0/Private/main.rs"
v41 = <alloc::string::String as core::ops::deref::Deref>::deref(v46);
v43 = core::str::<impl str>::trim(v41, v42);
if ( (main::check(v43, v44) & 1) != 0 )
break;
core::fmt::rt::<impl core::fmt::Arguments>::new_const(v49, &off_5AB98);// "Wrong! Please try again~\n"
std::io::stdio::_print();
core::ptr::drop_in_place<alloc::string::String>(v46);
}
core::fmt::rt::<impl core::fmt::Arguments>::new_const(v48, &off_5ABA8);// "Accepted!\n"
std::io::stdio::_print();
std::process::exit();
}
```
- Hàm bắt mình kiểm tra input(password) thông qua hàm `main::check` để trả về true (Accepted)
- Hàm `main::check`
```clike=
bool __fastcall main::check(_BYTE *a1, unsigned __int64 n2)
{
if ( core::str::<impl str>::len() == 22 )
{
if ( !n2 )
core::panicking::panic_bounds_check();
if ( *a1 == 66 ) // 'B'
{
if ( n2 <= 1 )
core::panicking::panic_bounds_check();
if ( a1[1] == 75 ) // 'K'
{
if ( n2 <= 2 )
core::panicking::panic_bounds_check();
if ( a1[2] == 83 ) // 'S'
{
if ( n2 <= 3 )
core::panicking::panic_bounds_check();
if ( a1[3] == 69 ) // 'E'
{
if ( n2 <= 4 )
core::panicking::panic_bounds_check();
if ( a1[4] == 67 ) // 'C'
{
if ( n2 <= 5 )
core::panicking::panic_bounds_check();
if ( a1[5] == 123 ) // '{'
{
if ( n2 <= 6 )
core::panicking::panic_bounds_check();
if ( a1[6] == 119 ) // 'w'
{
if ( n2 <= 7 )
core::panicking::panic_bounds_check();
if ( a1[7] == 51 ) // '3'
{
if ( n2 <= 8 )
core::panicking::panic_bounds_check();
if ( a1[8] == 108 ) // 'l'
{
if ( n2 <= 9 )
core::panicking::panic_bounds_check();
if ( a1[9] == 67 ) // 'C'
{
if ( n2 <= 0xA )
core::panicking::panic_bounds_check();
if ( a1[10] == 48 ) // '0'
{
if ( n2 <= 0xB )
core::panicking::panic_bounds_check();
if ( a1[11] == 109 ) // 'm'
{
if ( n2 <= 0xC )
core::panicking::panic_bounds_check();
if ( a1[12] == 51 ) // '3'
{
if ( n2 <= 0xD )
core::panicking::panic_bounds_check();
if ( a1[13] == 95 ) // '_'
{
if ( n2 <= 0xE )
core::panicking::panic_bounds_check();
if ( a1[14] == 116 ) // 't'
{
if ( n2 <= 0xF )
core::panicking::panic_bounds_check();
if ( a1[15] == 79 ) // 'O'
{
if ( n2 <= 0x10 )
core::panicking::panic_bounds_check();
if ( a1[16] == 95 ) // '_'
{
if ( n2 <= 0x11 )
core::panicking::panic_bounds_check();
if ( a1[17] == 82 ) // 'R'
{
if ( n2 <= 0x12 )
core::panicking::panic_bounds_check();
if ( a1[18] == 101 ) // 'e'
{
if ( n2 <= 0x13 )
core::panicking::panic_bounds_check();
if ( a1[19] == 118 ) // 'v'
{
if ( n2 <= 0x14 )
core::panicking::panic_bounds_check();
if ( a1[20] == 118 ) // 'v'
{
if ( n2 <= 0x15 )
core::panicking::panic_bounds_check();
return a1[21] == 125; // '}'
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
return 0;
}
```
- Code khá dài nhưng mục đích là kiểm tra lần lượt `index` của chuỗi `flag(input)` có độ dài 22 kí tự mà mình nhập vào thông qua kí tự `ASCII` thôi
- FLAG: BKSEC{w3lC0m3_tO_Revv}
---
ChildRust
---

-Bài này là bản V2 của bài baby kia, vẫn check như cũ nhé

- Oke, rất may mắn là bài này vẫn chưa thấy dấu hiệu nào bất thường :v, mở source code của nó thôi:

- Hàm `main::main` (mình rút gọn phần thừa nhé)
```clike=
core::fmt::rt::<impl core::fmt::Arguments>::new_const(v51, &off_5DB10);// "The easiest flag-checker xDD\n"
std::io::stdio::_print();
while ( 1 )
{
core::fmt::rt::<impl core::fmt::Arguments>::new_const(v52, &off_5DB20);// "Enter the flag: \n"
std::io::stdio::_print();
alloc::string::String::new(v53);
std::io::stdio::stdin();
v54 = v44;
std::io::stdio::Stdin::read_line();
core::result::Result<T,E>::expect(v45, v46, aFailedToReadLi, 20LL, &off_5DB30);// "main.rs"
v47 = <alloc::string::String as core::ops::deref::Deref>::deref(v53);
v49 = (unsigned __int8 *)core::str::<impl str>::trim(v47, v48);
if ( main::check_flag(v49, n8) )
break;
core::fmt::rt::<impl core::fmt::Arguments>::new_const(v56, &off_5DB48);// "Wrong!!!\n"
std::io::stdio::_print();
core::ptr::drop_in_place<alloc::string::String>(v53);
}
core::fmt::rt::<impl core::fmt::Arguments>::new_const(v55, &off_5DB58);// "Correct, now get tf out of here!!\n"
std::io::stdio::_print();
std::process::exit();
}
```
- Mục tiêu của bài này vẫn là check `input(flag)` thông qua hàm `main::check_flag` thôi
- Hàm `main::check_flag`
```c=
bool __fastcall main::check_flag(unsigned __int8 *a1, unsigned __int64 n8)
{
int v2; // ecx
int v3; // ecx
int v4; // ecx
int v5; // ecx
int v6; // ecx
int v7; // ecx
int v8; // ecx
int v9; // ecx
unsigned int v10; // ecx
int v11; // ecx
int v12; // ecx
int v13; // ecx
int v14; // ecx
int v15; // ecx
int v16; // ecx
int v17; // ecx
int v18; // ecx
int v19; // ecx
int v20; // ecx
int v21; // ecx
int v22; // ecx
unsigned int v24; // [rsp+Ch] [rbp-16Ch]
int v25; // [rsp+20h] [rbp-158h]
int v26; // [rsp+24h] [rbp-154h]
unsigned int v27; // [rsp+28h] [rbp-150h]
int v28; // [rsp+30h] [rbp-148h]
int v29; // [rsp+38h] [rbp-140h]
unsigned int v30; // [rsp+3Ch] [rbp-13Ch]
int v31; // [rsp+40h] [rbp-138h]
int v32; // [rsp+48h] [rbp-130h]
int v33; // [rsp+4Ch] [rbp-12Ch]
int v34; // [rsp+54h] [rbp-124h]
int v35; // [rsp+58h] [rbp-120h]
int v36; // [rsp+64h] [rbp-114h]
int v37; // [rsp+74h] [rbp-104h]
int v38; // [rsp+78h] [rbp-100h]
int v39; // [rsp+80h] [rbp-F8h]
int v40; // [rsp+84h] [rbp-F4h]
unsigned int v41; // [rsp+88h] [rbp-F0h]
int v42; // [rsp+8Ch] [rbp-ECh]
int v43; // [rsp+94h] [rbp-E4h]
int v44; // [rsp+98h] [rbp-E0h]
unsigned int v45; // [rsp+9Ch] [rbp-DCh]
int v46; // [rsp+A0h] [rbp-D8h]
unsigned int v47; // [rsp+ACh] [rbp-CCh]
int v48; // [rsp+B0h] [rbp-C8h]
int v49; // [rsp+B4h] [rbp-C4h]
int v50; // [rsp+BCh] [rbp-BCh]
unsigned int v51; // [rsp+C0h] [rbp-B8h]
int v52; // [rsp+C4h] [rbp-B4h]
unsigned int v53; // [rsp+CCh] [rbp-ACh]
int v54; // [rsp+D8h] [rbp-A0h]
int v55; // [rsp+E8h] [rbp-90h]
unsigned int v56; // [rsp+F4h] [rbp-84h]
int v57; // [rsp+100h] [rbp-78h]
int v58; // [rsp+110h] [rbp-68h]
unsigned int v59; // [rsp+114h] [rbp-64h]
int v60; // [rsp+11Ch] [rbp-5Ch]
unsigned int v61; // [rsp+120h] [rbp-58h]
int v62; // [rsp+12Ch] [rbp-4Ch]
unsigned int v63; // [rsp+130h] [rbp-48h]
int v64; // [rsp+134h] [rbp-44h]
int v65; // [rsp+13Ch] [rbp-3Ch]
int v66; // [rsp+144h] [rbp-34h]
unsigned int v67; // [rsp+148h] [rbp-30h]
if ( core::str::<impl str>::len() != 25 )
return 0;
if ( n8 <= 1 )
core::panicking::panic_bounds_check();
if ( n8 <= 8 )
core::panicking::panic_bounds_check();
v67 = a1[8];
v66 = *a1 * v67;
if ( !is_mul_ok(*a1, v67) )
core::panicking::panic_const::panic_const_mul_overflow();
v2 = a1[7];
if ( __OFADD__(v2, v66) )
core::panicking::panic_const::panic_const_add_overflow();
if ( ((v2 + v66) & a1[1]) != 0x4B )
return 0;
if ( n8 <= 0x10 )
core::panicking::panic_bounds_check();
v65 = a1[16];
v3 = a1[6];
if ( __OFSUB__(v65, v3) )
core::panicking::panic_const::panic_const_sub_overflow();
v64 = a1[14];
v63 = a1[2];
v62 = a1[10] * v63;
if ( !is_mul_ok(a1[10], v63) )
core::panicking::panic_const::panic_const_mul_overflow();
if ( __OFSUB__(v64, v62) )
core::panicking::panic_const::panic_const_sub_overflow();
if ( ((v64 - v62) ^ (v65 - v3)) != 0x182B )
return 0;
v61 = a1[11];
v60 = a1[7] * v61;
if ( !is_mul_ok(a1[7], v61) )
core::panicking::panic_const::panic_const_mul_overflow();
v4 = a1[13];
if ( __OFSUB__(v60, v4) )
core::panicking::panic_const::panic_const_sub_overflow();
if ( ((v60 - v4) ^ a1[4]) != 0x12B3 )
return 0;
v59 = *a1;
if ( n8 <= 0x11 )
core::panicking::panic_bounds_check();
v58 = a1[17] * v59;
if ( !is_mul_ok(a1[17], v59) )
core::panicking::panic_const::panic_const_mul_overflow();
v5 = a1[17];
if ( __OFADD__(v5, v58) )
core::panicking::panic_const::panic_const_add_overflow();
if ( v5 + v58 != 3417 )
return 0;
v57 = a1[5];
v6 = a1[1];
if ( __OFSUB__(v57, v6) )
core::panicking::panic_const::panic_const_sub_overflow();
if ( ((v57 - v6) ^ (unsigned __int8)(a1[14] & a1[6])) != 0x40 )
return 0;
v56 = a1[9];
if ( !is_mul_ok(a1[11], v56) )
core::panicking::panic_const::panic_const_mul_overflow();
v55 = a1[9];
v7 = *a1;
if ( __OFSUB__(v55, v7) )
core::panicking::panic_const::panic_const_sub_overflow();
if ( ((v55 - v7) ^ (a1[11] * v56) & a1[7]) != 0x1E || (unsigned __int8)(a1[17] & (*a1 ^ a1[6])) != 0x31 )
return 0;
v54 = a1[17];
v8 = a1[6];
if ( __OFADD__(v8, v54) )
core::panicking::panic_const::panic_const_add_overflow();
if ( (a1[9] ^ (v8 + v54)) != 0xF6 )
return 0;
v53 = a1[14];
if ( !is_mul_ok(a1[4], v53) )
core::panicking::panic_const::panic_const_mul_overflow();
v52 = (a1[4] * v53) ^ a1[6];
v51 = a1[4];
v50 = a1[7] * v51;
if ( !is_mul_ok(a1[7], v51) )
core::panicking::panic_const::panic_const_mul_overflow();
if ( __OFSUB__(v52, v50) )
core::panicking::panic_const::panic_const_sub_overflow();
if ( v52 - v50 != 4680 )
return 0;
v49 = a1[16];
v9 = a1[6];
v48 = v49 - v9;
if ( __OFSUB__(v49, v9) )
core::panicking::panic_const::panic_const_sub_overflow();
v47 = a1[7];
if ( !is_mul_ok(a1[12], v47) )
core::panicking::panic_const::panic_const_mul_overflow();
v10 = a1[17] & (a1[12] * v47);
if ( __OFSUB__(v48, v10) )
core::panicking::panic_const::panic_const_sub_overflow();
if ( v48 - v10 != -36 )
return 0;
v46 = a1[7];
v45 = a1[12];
v44 = a1[15] * v45;
if ( !is_mul_ok(a1[15], v45) )
core::panicking::panic_const::panic_const_mul_overflow();
v43 = v46 - v44;
if ( __OFSUB__(v46, v44) )
core::panicking::panic_const::panic_const_sub_overflow();
v11 = a1[6];
if ( __OFSUB__(v43, v11) )
core::panicking::panic_const::panic_const_sub_overflow();
if ( v43 - v11 != -10706 )
return 0;
v42 = a1[9];
v41 = a1[7];
v40 = a1[3] * v41;
if ( !is_mul_ok(a1[3], v41) )
core::panicking::panic_const::panic_const_mul_overflow();
v39 = v40 + v42;
if ( __OFADD__(v40, v42) )
core::panicking::panic_const::panic_const_add_overflow();
v12 = a1[2];
if ( __OFADD__(v12, v39) )
core::panicking::panic_const::panic_const_add_overflow();
if ( v12 + v39 != 3544 )
return 0;
v38 = a1[14];
v13 = a1[10];
v37 = v13 + v38;
if ( __OFADD__(v13, v38) )
core::panicking::panic_const::panic_const_add_overflow();
v14 = a1[13];
if ( __OFSUB__(v37, v14) )
core::panicking::panic_const::panic_const_sub_overflow();
if ( (a1[13] ^ (v37 - v14)) != 0x3A )
return 0;
v36 = a1[14] ^ a1[7] ^ a1[5];
v15 = a1[8];
if ( __OFADD__(v15, v36) )
core::panicking::panic_const::panic_const_add_overflow();
if ( v15 + v36 != 159 )
return 0;
v35 = (unsigned __int8)(a1[4] & a1[9]);
v16 = a1[11];
v34 = v35 - v16;
if ( __OFSUB__(v35, v16) )
core::panicking::panic_const::panic_const_sub_overflow();
v17 = a1[2];
if ( __OFADD__(v17, v34) )
core::panicking::panic_const::panic_const_add_overflow();
if ( v17 + v34 != 46 )
return 0;
v33 = a1[6];
v18 = a1[3];
v32 = v33 - v18;
if ( __OFSUB__(v33, v18) )
core::panicking::panic_const::panic_const_sub_overflow();
v19 = a1[6];
if ( __OFADD__(v19, v32) )
core::panicking::panic_const::panic_const_add_overflow();
if ( v19 + v32 != 161 )
return 0;
v31 = a1[8];
v30 = a1[2];
v29 = a1[9] * v30;
if ( !is_mul_ok(a1[9], v30) )
core::panicking::panic_const::panic_const_mul_overflow();
if ( __OFADD__(v29, v31) )
core::panicking::panic_const::panic_const_add_overflow();
v28 = a1[6];
v20 = a1[9];
if ( __OFADD__(v20, v28) )
core::panicking::panic_const::panic_const_add_overflow();
if ( ((v20 + v28) ^ (v29 + v31)) != 0x1A9E )
return 0;
v27 = a1[15];
v26 = a1[16] * v27;
if ( !is_mul_ok(a1[16], v27) )
core::panicking::panic_const::panic_const_mul_overflow();
v21 = a1[16];
v25 = v21 + v26;
if ( __OFADD__(v21, v26) )
core::panicking::panic_const::panic_const_add_overflow();
v22 = a1[4];
if ( __OFSUB__(v25, v22) )
core::panicking::panic_const::panic_const_sub_overflow();
if ( v25 - v22 != 12815 )
return 0;
v24 = a1[6];
if ( !is_mul_ok(a1[16], v24) )
core::panicking::panic_const::panic_const_mul_overflow();
if ( ((a1[16] * v24) & *a1 ^ (unsigned __int8)(a1[1] & a1[3])) != 0x43 || (a1[11] ^ a1[2] ^ a1[8]) != 0x5B )
return 0;
if ( n8 <= 0x12 )
core::panicking::panic_bounds_check();
if ( a1[18] != 115 ) // `s`
return 0;
if ( n8 <= 0x13 )
core::panicking::panic_bounds_check();
if ( a1[19] != 53 ) // `5`
return 0;
if ( n8 <= 0x14 )
core::panicking::panic_bounds_check();
if ( a1[20] != 49 ) // `1`
return 0;
if ( n8 <= 0x15 )
core::panicking::panic_bounds_check();
if ( a1[21] != 48 ) // `0`
return 0;
if ( n8 <= 0x16 )
core::panicking::panic_bounds_check();
if ( a1[22] != 110 ) // `n`
return 0;
if ( n8 <= 0x17 )
core::panicking::panic_bounds_check();
if ( a1[23] == 83 ) // `S`
{
if ( n8 <= 0x18 )
core::panicking::panic_bounds_check();
return a1[24] == 125; // `}`
}
else
{
return 0;
}
}
```
-- Đọc sơ qua thì hàm này cho mình biết trước được 13 kí tự `BKSEC{s510nS}`, còn lại 11 kí tự sẽ tự tìm thông qua tính toán phương trình:
-- Hướng giải quyết: Hàm này tuy nhìn khá dài nhưng vẫn là dạng `giải phương trình tuyến tính` kèm thêm xử lí `bitwise` nên mình vẫn sẽ xài `z3` + `BitVec` để giải
-- Vì code dài quá nên mình bỏ source vô cho chatGPT tự tóm phương trình và giải theo cách của mình:
```c=
from z3 import *
# ========== VARIABLES ==========
a = [BitVec(f"a{i}", 8) for i in range(25)]
s = Solver()
s.set("timeout", 30000)
def w(x):
# widen u8 -> i32/u32
return SignExt(24, x)
# ========== CONSTRAINTS TỪ BINARY ==========
s.add((w(a[7]) + w(a[0]) * w(a[8])) & w(a[1]) == 0x4B)
s.add((w(a[14]) - w(a[10]) * w(a[2])) ^
(w(a[16]) - w(a[6])) == 0x182B)
s.add((w(a[7]) * w(a[11]) - w(a[13])) ^ w(a[4]) == 0x12B3)
s.add(w(a[17]) + w(a[17]) * w(a[0]) == 3417)
s.add((w(a[5]) - w(a[1])) ^ (w(a[14]) & w(a[6])) == 0x40)
s.add((w(a[9]) - w(a[0])) ^
((w(a[11]) * w(a[9])) & w(a[7])) == 0x1E)
s.add(w(a[17]) & (w(a[0]) ^ w(a[6])) == 0x31)
s.add(w(a[9]) ^ (w(a[6]) + w(a[17])) == 0xF6)
s.add(((w(a[4]) * w(a[14])) ^ w(a[6])) -
(w(a[7]) * w(a[4])) == 4680)
s.add((w(a[16]) - w(a[6])) -
(w(a[17]) & (w(a[12]) * w(a[7]))) == -36)
s.add((w(a[7]) - w(a[15]) * w(a[12])) -
w(a[6]) == -10706)
s.add(w(a[2]) + (w(a[3]) * w(a[7]) + w(a[9])) == 3544)
s.add(w(a[13]) ^ ((w(a[10]) + w(a[14])) - w(a[13])) == 0x3A)
s.add(w(a[8]) + (w(a[14]) ^ w(a[7]) ^ w(a[5])) == 159)
s.add(w(a[2]) + ((w(a[4]) & w(a[9])) - w(a[11])) == 46)
s.add(2 * w(a[6]) - w(a[3]) == 161)
s.add((w(a[9]) + w(a[6])) ^
(w(a[9]) * w(a[2]) + w(a[8])) == 0x1A9E)
s.add((w(a[16]) + w(a[16]) * w(a[15])) -
w(a[4]) == 12815)
s.add(((w(a[16]) * w(a[6])) & w(a[0])) ^
(w(a[1]) & w(a[3])) == 0x43)
s.add(w(a[11]) ^ w(a[2]) ^ w(a[8]) == 0x5B)
# ===== hard constraints từ cuối hàm =====
s.add(a[18] == 115) # 's'
s.add(a[19] == 53) # '5'
s.add(a[20] == 49) # '1'
s.add(a[21] == 48) # '0'
s.add(a[22] == 110) # 'n'
s.add(a[23] == 83) # 'S'
s.add(a[24] == 125) # '}'
# ========== SOLVE ==========
res = s.check()
print(res)
if res == sat:
m = s.model()
raw = [m[a[i]].as_long() for i in range(25)]
print("RAW:", raw)
print("FLAG:", ''.join(chr(x) for x in raw))
else:
print("NO MODEL")
```
FLAG: BKSEC{s1mPLe_expr3s510nS}
---
Babylua
---

Đây là lần đầu mình làm chall liên quan tới Lua nên cũng không có kinh nghiệm, nên đề cho bao nhiêu file thì mình tải về và quan sát thử thôi =))
- Sau khi mình check thử 2 file thì chỉ có mỗi file `main` là đọc được còn file kia thì bị compile thành bytecode nên không đọc được
- Tới đây mình bí ý tưởng rồi nên nhờ AI hướng dẫn và nó chỉ mình cách dissamble opcode của file `flag.lua` bằng lệnh: `luac5.3 -l /mnt/c/Users/TRUONG\ HAI/Music/flag.lua | less`
Code:
```c=
main </tmp/phpxzz5ni:0,0> (5 instructions at 0x5dc54710ec60)
0+ params, 2 slots, 1 upvalue, 1 local, 1 constant, 1 function
1 [1] NEWTABLE 0 0 0
2 [23] CLOSURE 1 0 ; 0x5dc54710ed70
3 [3] SETTABLE 0 -1 1 ; "check" -
4 [25] RETURN 0 2
5 [25] RETURN 0 1
function </tmp/phpxzz5ni:3,23> (78 instructions at 0x5dc54710ed70)
2 params, 32 slots, 1 upvalue, 14 locals, 31 constants, 0 functions
1 [4] LOADK 2 -1 ; 0
2 [5] NEWTABLE 3 22 0
3 [5] LOADK 4 -2 ; 22
4 [5] LOADK 5 -3 ; 101
5 [5] LOADK 6 -4 ; 133
6 [5] LOADK 7 -5 ; 137
7 [5] LOADK 8 -6 ; 79
8 [5] LOADK 9 -7 ; 75
9 [5] LOADK 10 -8 ; 166
10 [5] LOADK 11 -9 ; 157
11 [5] LOADK 12 -10 ; 189
12 [5] LOADK 13 -11 ; 57
13 [5] LOADK 14 -12 ; 172
14 [5] LOADK 15 -13 ; 155
15 [5] LOADK 16 -14 ; 144
16 [5] LOADK 17 -15 ; 91
17 [5] LOADK 18 -5 ; 137
18 [5] LOADK 19 -16 ; 222
19 [5] LOADK 20 -17 ; 52
20 [5] LOADK 21 -14 ; 144
21 [5] LOADK 22 -18 ; 211
22 [5] LOADK 23 -3 ; 101
23 [5] LOADK 24 -19 ; 114
24 [5] LOADK 25 -20 ; 116
25 [5] LOADK 26 -21 ; 121
26 [5] LOADK 27 -22 ; 76
27 [5] LOADK 28 -23 ; 154
28 [5] LOADK 29 -24 ; 168
29 [5] LOADK 30 -25 ; 83
30 [5] LOADK 31 -26 ; 94
31 [5] SETLIST 3 28 1 ; 1
32 [6] NEWTABLE 4 0 0
33 [8] LOADK 5 -27 ; 1
34 [8] LEN 6 0
35 [8] LOADK 7 -27 ; 1
36 [8] FORPREP 5 17 ; to 54
37 [9] SELF 9 0 -28 ; "byte"
38 [9] MOVE 11 8
39 [9] CALL 9 3 2
40 [9] SELF 10 1 -28 ; "byte"
41 [9] SUB 12 8 -27 ; - 1
42 [9] LEN 13 1
43 [9] MOD 12 12 13
44 [9] ADD 12 12 -27 ; - 1
45 [9] CALL 10 3 2
46 [9] BXOR 9 9 10
47 [10] LT 0 -27 8 ; 1 -
48 [10] JMP 0 4 ; to 53
49 [11] SELF 10 0 -28 ; "byte"
50 [11] SUB 12 8 -27 ; - 1
51 [11] CALL 10 3 2
52 [11] ADD 9 9 10
53 [13] SETTABLE 4 8 9
54 [8] FORLOOP 5 -18 ; to 37
55 [16] LOADK 5 -27 ; 1
56 [16] GETTABUP 6 0 -29 ; _ENV "math"
57 [16] GETTABLE 6 6 -30 ; "min"
58 [16] LEN 7 4
59 [16] LEN 8 3
60 [16] CALL 6 3 2
61 [16] LOADK 7 -27 ; 1
62 [16] FORPREP 5 5 ; to 68
63 [17] GETTABLE 9 4 8
64 [17] GETTABLE 10 3 8
65 [17] EQ 0 9 10
66 [17] JMP 0 1 ; to 68
67 [18] ADD 2 2 -27 ; - 1
68 [16] FORLOOP 5 -6 ; to 63
69 [22] EQ 0 2 -31 ; - 28
70 [22] JMP 0 4 ; to 75
71 [22] LEN 5 4
72 [22] LEN 6 3
73 [22] EQ 1 5 6
74 [22] JMP 0 1 ; to 76
75 [22] LOADBOOL 5 0 1
76 [22] LOADBOOL 5 1 0
77 [22] RETURN 5 2
78 [23] RETURN 0 1
(END)
```
- Tới đây mình ngu lun nên nhờ nó chuyển sang c++ để mình debug tiếp =))
- Sau khi chuyển xong và chỉnh sửa thì đây là full code debug của mình
```c=
#include <bits/stdc++.h>
using namespace std;
bool check(const string &a, const string &b) {
vector<int> key = {
22, 101, 133, 137, 79, 75, 166, 157, 189, 57,
172, 155, 144, 91, 137, 222, 52, 144, 211, 101,
114, 116, 121, 76, 154, 168, 83, 94
};
vector<int> out;
int blen = b.size();
for (int i = 0; i < (int)a.size(); i++) {
int ai = (unsigned char)a[i];
int bj = (unsigned char)b[i % blen];
int v = ai ^ bj;
if (i > 0) {
v += (unsigned char)a[i - 1];
}
out.push_back(v);
}
int matches = 0;
int lim = min(out.size(), key.size());
for (int i = 0; i < lim; i++) {
if (out[i] == key[i])
matches++;
}
if (matches == 28 && out.size() == key.size())
return true;
return false;
}
int main() {
string flag;
cout << "Input flag: ";
getline(cin, flag);
if (check(flag, "ThisIsAFlag")) {
cout << "Correct!" << endl;
} else {
cout << "Wrong..." << endl;
}
return 0;
}
```
FLAG: BKSEC{ju$t_h@rd3r_2_re@d_:P}
---
Pyxe
---

- Chall tiếp theo mình thấy có vẻ như đề bài cho biết rằng sẽ debug một file python, cùng tải file zip về xem nhé
- Vì đề bài hint khá rõ phần file chall nên mình sẽ check sơ file coi như thế nào nhé:

- Quả thật là có vấn đề, qua cái ảnh này thì mình có thể thấy là đây không phải binary native mà là một Python script được `packed` thành exe bằng `PyInstaller`.
- Sau khi unzip mình được một thư mục mới chứa đầy đủ các hàm: 

- Thử strings file chall mới thì được như sau :
- Tới đây chỉ cần viết dịch ngược để tìm ra flag thôi
```c=
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
vector<ll>cipher = {
0x73, 0x79, 0x60, 0x71, 0x76, 0x4d, 0x47, 0x41,
0x0a, 0x1c, 0x00, 0x1e, 0x07, 0x4d, 0x53, 0x68,
0x0a, 0x09, 0x03, 0x06, 0x6c, 0x05, 0x07, 0x69,
0x05, 0x01, 0x66, 0x5e, 0x59, 0x4e
};
string key = "123456789";
string s;
for (ll i = 0; i < cipher.size(); i++) {
char decrypted = cipher[i] ^ key[i % key.length()];
s += decrypted;
}
cout<<s; //BKSEC{py3-2-3xe_2024_12_29_ok}
}
```
FLAG: BKSEC{py3-2-3xe_2024_12_29_ok}
---
Premium Game
---

- Bài này cho mình một file zip, oke tải về và unzip file xem bên trong có gì nhé
-Battle_for_Hustonia/
├── assets/ chứa dữ liệu phụ trợ
└── ctf_challenge (main binary)
- Mở file main lên xem thì bài yêu cầu nhập `License Key` để có thể xài skill bí mật để lấy flag
- 
- Ban đầu, mình suy nghĩ theo hướng dễ hơn là bypass cái License Key và Win luôn game này bằng Patch Opcode nhưng lại bị lỗi không xuất ra được flag
- 
- Nên mình sẽ tìm hàm tạo Key trong main nhé, tìm một hồi thì chỉ cần chú ý đến đoạn này thôi:
```c=
if ( n2 == 1 )
{
v136 = -939524096;
sub_433615(0LL, 0LL, 1000LL, 800LL, v136);
n500 = 500;
n300 = 300;
n250 = 250;
n250_1 = 250;
v137 = -657931;
sub_433615(250LL, 250LL, 500LL, 300LL, 4294309365LL);
v138 = -16777216;
sub_433A07((unsigned int)n250, (unsigned int)n250_1, n500, n300, 4278190080LL);
v139 = -16777216;
sub_47B6C8("WELCOME WARRIOR!", (unsigned int)(n250 + 130), (unsigned int)(n250_1 + 30), 30LL, 4278190080LL);
v140 = -11513776;
*(_QWORD *)&v68 = sub_47B6C8(
"Enter License Key:",
(unsigned int)(n250 + 40),
(unsigned int)(n250_1 + 80),
20LL,
v140).m128_u64[0];
v141 = -11513776;
sub_433A07((unsigned int)(n250 + 40), (unsigned int)(n250_1 + 110), n500 - 80, 50LL, 4283453520LL);
v145 = -16777216;
v69 = n250_1 + 125;
v70 = n250 + 50;
v71 = std::string::c_str(v255, v68);
sub_47B6C8(v71, v70, v69, 30LL, v145);
v142 = -16777216;
sub_433615((unsigned int)(n250 + 150), (unsigned int)(n250_1 + 180), 200LL, 50LL, 4278190080LL);
v143 = -1;
sub_47B6C8("ACTIVATE", (unsigned int)(n250 + 200), (unsigned int)(n250_1 + 195), 20LL, 0xFFFFFFFFLL);
n0x43160000 = (__m128i)0x43160000u;
*(float *)n0x43160000.m128i_i32 = (float)n250 + 150.0;
v73 = _mm_cvtsi128_si32(n0x43160000);
n0x43340000 = (__m128i)0x43340000u;
*(float *)n0x43340000.m128i_i32 = (float)n250_1 + 180.0;
*(_QWORD *)&v153 = ((unsigned __int64)(unsigned int)_mm_cvtsi128_si32(n0x43340000) << 32) | v73;
*(_QWORD *)&v154 = ((unsigned __int64)(unsigned int)_mm_cvtsi128_si32((__m128i)0x42480000u) << 32) | (unsigned int)_mm_cvtsi128_si32((__m128i)0x43480000u);
*(double *)n0x43340000.m128i_i64 = sub_42F217();
v107 = v153;
v106 = v154;
if ( (unsigned __int8)sub_438BB3(*(double *)n0x43340000.m128i_i64, v153, v154)
&& (unsigned __int8)sub_42F0CA(0LL) )
{
if ( (unsigned __int8)sub_405596(v255) )
{
v253 = 1;
n2 = 0;
}
else
{
std::string::operator=(v255, "INVALID KEY");
}
}
```
- Hàm `sub_405596` được sử dụng để check cái License Key có khớp không:
```c=
__int64 __fastcall sub_405596(__int64 a1)
{
unsigned __int64 i; // [rsp+18h] [rbp-48h]
_DWORD v3[14]; // [rsp+20h] [rbp-40h]
unsigned __int64 v4; // [rsp+58h] [rbp-8h]
v4 = __readfsqword(0x28u);
if ( std::string::length(a1) != 12 )
return 0LL;
v3[0] = 1;
v3[1] = 33;
v3[2] = 36;
v3[3] = 39;
v3[4] = 45;
v3[5] = 37;
v3[6] = 40;
v3[7] = 33;
v3[8] = 33;
v3[9] = 43;
v3[10] = 60;
v3[11] = 72;
for ( i = 0LL; i < std::string::length(a1); ++i )
{
if ( 4 * (_DWORD)i + (*(_BYTE *)std::string::operator[](a1, i) ^ 0x55) != v3[i] )
return 0LL;
}
return 1LL;
}
```
-Code dịch ngược của mình:
```c=
#include <bits/stdc++.h>
#define ll long long
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
const ll Nmax=1e6+5;
int main()
{
fastio;
int v3[100];
string s;
v3[0] = 1;
v3[1] = 33;
v3[2] = 36;
v3[3] = 39;
v3[4] = 45;
v3[5] = 37;
v3[6] = 40;
v3[7] = 33;
v3[8] = 33;
v3[9] = 43;
v3[10] = 60;
v3[11] = 72;
for(ll i=0;i<12;i++){
s+=char(v3[i]-4*i ^ 0x55);
}
cout<<s;// THINHDEPTRAI
}
```
- Giờ chỉ việc nhập key và lấy flag thôi
- 
FLAG: BKSEC{d33p_1n_th3_b1n@ri355}
---
Brain-sech
---

- Bài này chỉ cần sử dụng đến file `brain_phuc` từ đề bài cung cấp là solve được bài
- Mình thử check sơ file thì không có gì đặc biệt cả nên mình sẽ tiến hành phân tích file lun nhé:

- Hàm `main`:
```c=
__int64 __fastcall main(int a1, char **a2, char **a3)
{
char *v3; // rbx
char v4; // al
_BYTE *s_1; // rbp
char *v6; // rax
int v8; // edx
char n91_3; // al
char n91_4; // al
int v11; // ecx
char n91; // dl
char n91_1; // dl
char n91_2; // dl
_BYTE s[30024]; // [rsp+0h] [rbp-7548h] BYREF
memset(s, 0, 0x7530uLL);
v3 = off_404030; // ">,------------------------------------------------------------------[<+>[-]][-],---------------------------------------------------------------------------[<+>[-]][-],-----------------------------------------------------------------------------------[<+>[-]][-],---------------------------------------------------------------------[<+>[-]][-],-------------------------------------------------------------------[<+>[-]][-],---------------------------------------------------------------------------------------------------------------------------[<+>[-]][-],------------------------------------------------------------------------------------[<+>[-]][-],------------------------------------------------------------------------[<+>[-]][-],-------------------------------------------------[<+>[-]][-],--------------------------------------------------------------------------------------------------------------[<+>[-]][-],--------------------------------------------------------------------------------------------------------[<+>[-]][-],-----------------------------------------------------------------------------------------------[<+>[-]][-],--------------------------------------------------------------------------------------------------------[<+>[-]][-],-------------------------------------------------------------------------------------------------[<+>[-]][-],------------------------------------------------------------------------------------[<+>[-]][-],---------------------------------------------------[<+>[-]][-],-------------------------------------------------------------------------------------------------------------------[<+>[-]][-],-----------------------------------------------------------------------------------------------[<+>[-]][-],--------------------------------------------------------------------------------------------------[<+>[-]][-],------------------------------------------------------------------------------------------------------------------[<+>[-]][-],---------------------------------------------------[<+>[-]][-],---------------------------------------------------------------------------------------------------------[<+>[-]][-],--------------------------------------------------------------------------------------------------------------[<+>[-]][-],-----------------------------------------------------------------------------------------------[<+>[-]][-],------------------------------------------------------------------------------------------------------[<+>[-]][-],-----------------------------------------------------------------------------------------------------------------------------[<+>[-]][-]<"
printf(":D Nhap flag di: ");
v4 = *v3;
if ( *v3 )
{
s_1 = s;
do
{
switch ( v4 )
{
case '+':
++*s_1;
goto LABEL_5;
case ',':
*s_1 = getc(stdin);
goto LABEL_5;
case '-':
--*s_1;
goto LABEL_5;
case '.':
putc((char)*s_1, stdout);
goto LABEL_5;
case '<':
--s_1;
v6 = v3;
goto LABEL_6;
case '>':
++s_1;
v6 = v3;
goto LABEL_6;
case '[':
if ( *s_1 )
goto LABEL_5;
v11 = 1;
LABEL_27:
n91 = v3[1];
v6 = v3 + 1;
if ( n91 == 91 )
goto LABEL_35;
if ( n91 != 93 )
goto LABEL_29;
while ( --v11 )
{
LABEL_29:
while ( 1 )
{
n91_1 = *++v6;
if ( n91_1 != 91 )
break;
LABEL_35:
while ( 1 )
{
n91_2 = *++v6;
if ( n91_2 != 91 )
break;
++v11;
}
if ( n91_2 != 93 )
{
++v11;
goto LABEL_38;
}
}
if ( n91_1 != 93 )
{
LABEL_38:
v3 = v6;
goto LABEL_27;
}
}
goto LABEL_6;
case ']':
if ( !*s_1 )
goto LABEL_5;
v8 = 1;
break;
default:
goto LABEL_5;
}
LABEL_12:
n91_3 = *--v3;
if ( n91_3 != 91 )
goto LABEL_18;
while ( --v8 )
{
while ( 1 )
{
n91_4 = *--v3;
if ( n91_4 == 91 )
break;
if ( n91_4 != 93 )
goto LABEL_12;
do
{
n91_3 = *--v3;
if ( n91_3 == 91 )
break;
++v8;
LABEL_18:
;
}
while ( n91_3 == 93 );
}
}
LABEL_5:
v6 = v3;
LABEL_6:
v3 = v6 + 1;
v4 = v6[1];
}
while ( v4 );
}
if ( s[0] )
puts("\nTiec qua, sai roi:(");
else
puts("\nChuc mung, ban da vuot qua thu thach hai nao nhat BKSec");
return 0LL;
}
```
- Mới vào mình quan sát thử thấy biến `v3` được gán bằng một chuỗi các kí tự `Brainf*ck` nên mình gán thử vào web để decode thử xem ra được gì không:
- 
- Sau khi không ra được gì thì mình tiếp tục tìm kiếm nhưng vẫn vậy nên mình lên gpt kiếm hint thì mình solve được bài này:
- Cụ thể là trước mỗi chuỗi "[<+>[-]][-]" chỉ cần đếm số kí tự '-':
- Chuỗi: 66 75 83 69 67 123 84 72 49 110 104 95 104 97 84 51 115 95 98 114 51 105 110 95 102 125
- FLAG: BKSEC{TH1nh_haT3s_br3in_f}