# rev- basic 2
[link bài](https://dreamhack.io/wargame/challenges/16)
---
Xem hàm main trong IDA, thấy sau khi input thì `call sub_140001000`

Thấy mỗi địa chỉ input, đưa vào `aC`

Kiểm tra `aC` và thấy được các giá trị khác

Flag : DH{Comp4re_the_arr4y}
---
# rev-basic-3
[chall3](https://dreamhack.io/wargame/challenges/17)
---
Vẫn kiểm tra lệnh SUB như trên

Tập trung vào khung ở giữa, ta thấy khai báo con trỏ địa chỉ cho rax, đưa mảng unk vào rcx, sao đó so sánh với chuỗi input đã được mã hóa theo công thức bên dưới.
Với i là thứ tự trỏ ( từ kí tự thứ 0 tới thứ n-1)
Cụ thể ở đây đó là: `Chuỗi mã hóa = [(input xor i)+(i*2)]`

Đây là các chuỗi đã được mã hóa.
Chuyển vế đổi dấu
→ `input = [chuỗi mã hóa -(i*2) ] XOR i`
→ Ví dụ với 0x49 = 73 : `[73 - (0*2)] XOR 0 = 73 `, 73 => kí tự I
→ CODE để chạy :

FLAG : DH{I_am_X0_xo_Xor_eXcit1ng}
---
# rev- basic-4
[Link](https://dreamhack.io/wargame/challenges/18)
---
Lại kiểm tra main ta thấy :

**Chú ý và lệnh sar và shl**
`sar`: Viết tắt của Shift Arithmetic Right (Dịch chuyển Số học sang Phải).
VD :0000 1010 (số 10) sar 1 => 0000 0101 (số 5).
`shl`: Viết tắt của Shift Left (Dịch chuyển Trái).
VD :0000 0101 (số 5) shl 1 => 0000 1010 (số 10).
- Điều này có nghĩa là sar lấy 4 bit cao, và shl lấy 4 bit thấp
- Sau đó đảo ngược lại. Ví dụ Ký tự 'B' 0x42 là 0100 0010
+4 bit đầu (cao): 0100
+4 bit cuối (thấp): 0010
→ Đảo thành 0010 0100 = 0x24
Vậy để giải chall này, chỉ cần vào unk , đảo ngược cái mã hex lại là xong


Flag: DH{Br1ll1ant_bit_dr1bble_<<_>>}
---
# rev-basic-6
[Link challenge](https://dreamhack.io/wargame/challenges/20)
---

Có thể thấy chương trình khai báo 2 con trỏ mảng, nhận input thứ `i`, mã hóa nó theo kí tự thứ `i` của mảng `unk_...3020` ,sao đó so sánh với kí tự thứ `i` của mảng `unk_...3000`

- Ở `byte_140003020` nó đưa cho ta bảng mã hóa lần 1 với 256 kí tự ( từ 0 tới 255).
- Ở `byte_140003000` nó đưa cho ta bảng key mã hóa cuối cùng
→ Từ đó ta cần giải quyết tìm giá trị input.
Có thể thấy ví dụ như chữ `R` có giá trị ascii là `82`, dò trong table , giá trị hex nằm ở vị trí `82` là `0`

Như vậy suy ra công thức tính Input là : `input[i] = vị_trí_của( output[i] )_trong_table
`
Cách giải chay thì copy cục này lên ChatGPT, nhờ nó liệt kê ra rồi `Ctrl + F` để dò từng giá trị.
→ Giải : 4D = 101, và 101 trong bảng mã ascii là chữ e

`Ma thuật đen`

FLAG : Replac3_the_w0rld
---
# rev-basic-8
[→ rev-basic-8](https://dreamhack.io/wargame/challenges/22)
---

---
Em sử dụng IDA để đọc được code của file chall8.exe
Đầu tiên em đọc hàm main, click vào `Buffer` ở ô có chữ ; "Correct" điểm kiểm tra flag có nằm ở đó hay không.

Nhận thấy flag đã được ẩn đi nên ta quay trở lại hàm main để mò.
BẤM NÚT `TAB` để mò Psuedocode-A

Click vào `sub_140001000` để kiểm tra

Em thấy được công thức tính key ở đây, đồng thời thấy i<0x15 tức là i<21 kí tự
Đại loại là : `Lấy giá trị tại địa chỉ thứ 'i' từ input, xong nhân nó cho '-5' rồi chia lấy mod 256` sau đó so sánh kết quả đó với 1 mảng khác tương đương
Đồng thời có đoạn code `unsigned __int8` là lấy 8 bit tương đương với 1 byte

Mảng tưởng đương có kết quả như đã tô, cụ thể là :
`0xAC, 0xF3, 0x0C, 0x25, 0xA3, 0x10, 0xB7, 0x25, 0x16, 0xC6, 0xB7, 0xBC, 0x07, 0x25, 0x02, 0xD5, 0xC6, 0x11, 0x07, 0xC5, 0x00`
Biết công thức tính là : (Input * -5) % 256 = Key_byte
Để tìm Input ta nghịch đảo lại , trước hết nghịch đạo `*-5`
-- Để nghịch để , ta tìm số nào đó nhân với nó = 1 , tương đương `(X * -5) mod 256 =1` , như vậy X=51, với `51*-5 = -255`, `-255 mod 256 = 1` nghịch đảo thành công
Từ đó công thức tính Input là : Input = `(51* key_byte ) % 256`
---
Ví dụ byte `AC` đầu tiên :
-- 0xAC = 172
-- 172 * 51 = 8772
-- 8772 % 256 (chia lấy dư) = 68
-- 68 đổi mã ASCII là chữ `D`
```=python
# Đây là 21 byte tìm thấy
... key_array = [
... 0xAC, 0xF3, 0x0C, 0x25, 0xA3, 0x10, 0xB7, 0x25, 0x16, 0xC6, 0xB7,
... 0xBC, 0x07, 0x25, 0x02, 0xD5, 0xC6, 0x11, 0x07, 0xC5, 0x00
... ]
...
... password = ""
... inverse = 51 # Nghịch đảo nhân của -5 (mod 256)
...
... for key_byte in key_array:
... # Phép toán đảo ngược
... input_byte = (key_byte * inverse) % 256
...
... # Chuyển byte thành ký tự
... password += chr(input_byte)
...
... print(f"Mật khẩu (flag) là: {password}")
```

Cách 2 : Brute Force
---

```=cpp
#include <iostream>
using namespace std;
int main()
{
unsigned char key[] = { 0xAC, 0xF3, 0x0C, 0x25, 0xA3, 0x10, 0xB7, 0x25, 0x16, 0xC6, 0xB7, 0xBC, 0x07, 0x25, 0x02, 0xD5, 0xC6, 0x11, 0x07, 0xC5 };
string flag = "";
for (int i = 0; i < 20; i++) {
for (int input = 33; input < 127; input++) {
if (((-5 * input) & 0xff) == key[i]) {
flag += char(input);
}
}
}
cout << flag;
}
```
Brute từ 33 đến 127 để sau đó ném vào công thức rồi check xem có bằng key đã cho hay chưa
---
FLAG (20 kí tự) : `Did_y0u_brute_force?`
---
# Recure - mail
[→ recuse-mail](https://dreamhack.io/wargame/challenges/92)
---

Challenge yêu cầu ta phải tìm password ở đây là 1 ngày sinh nhật
~~à mà sinh nhật của em là ngày 9 tháng 2~~.
Dựa vào dữ kiệu `850810` thì có thể đoán password ở đây là YY/MM/DD (1985 / 08 / 10).
`Crtl + U` để xem mã nguồn của trang

Nhìn qua có thể đoán được rằng password nằm đâu đó trong dòng script




Đã cố gắng tìm tool deobfus các thứ nhưng không thành công.
---
Sau đó hiền nhân này xuất hiện và nói :

Xem lại code, thấy được rằng :

```=js
<button type="submit" onclick="_0x9a220(pass.value);">Confirm</button>
```
Khi nhập password, dữ liệu sẽ được biên dịch vào hàm `_0x9a220`
Code Brute-Force bằng C++ như sau:
```=cpp
#include <string>
#include <iostream>
using namespace std;
bool _0x9a220(const string& password) {
// Chỗ này là hàm gì đó để kiểm tra input có phải pass hay không nằm trong _0x9a220
return false;
}
string twoDigit(int n) {
string s = to_string(n);
if (s.size() < 2) s = "0" + s;
return s;
}
// Thêm số 0 vào mấy giá trị có 1 số, ví dụ tháng 1 sẽ là 01
int main()
{
for (int year = 0; year < 100; year++) {
bool result = false;
for (int month = 0; month < 13; month++) {
for (int day = 0; day < 32; day++) {
string password = twoDigit(year) + twoDigit(month) + twoDigit(day);
cout << password << endl;
result = _0x9a220(password); // Kiểm tra pass
if (result) break;
}
if (result) break;
}
if (result) break;
}
return 0;
}
```
Do em không biết code JavaScript nên giờ em sẽ nhờ `Ma thuật đen` cứu
```=js
for(var year = 0; year<100; year++){
var result = 0;
for(var month=1; month<13; month++){
for(var day=1; day<32; day++){
var pw = ''
pw += String(year).padStart(2,'0');
pw += String(month).padStart(2,'0');
pw += String(day).padStart(2,'0');
console.log(pw);
result = _0x9a220(pw);
if(result){
break;
}
}
if(result){
break;
}
}
if(result){
break;
}
}
```

Khi ấy ta sẽ liên tục thử kết quả , tuy nhiên nó cứ hiện pop-up như vậy thì ta phải click `OK` liên tục đến khi ra flag. Do đó em lại lại `black magic` thêm lần nữa
```=js
window.alert = function(val) { console.log("Wrong Birthday!!!"); return true; };
```
Đây là lệnh xóa pop-up. Thay vào đó là in ra chữ Wrong Birthday!!! lên console thay vì hiện pop-up, giúp vòng lặp chạy liên tục

Kết quả là được 1 vòng lặp tìm số ( em mất 40p để chờ nó chạy ra password)

CUỐI CÙNG CŨNG RA PASSWORD
---
PASSWORD: `960229`
FLAG: `DH{Brutef0rce_th3_secur3_mail}`
# Simple Crack Me
[→ Đây nè tình yêu](https://dreamhack.io/wargame/challenges/667)
---

Đọc đề bài thì flag lần này là những con số

Giải nén các thứ và chạy thử tệp này, chắc chắn rằng mình cần nhập con số vào.

nano vào thử thì thấy nó bị decode rồi.
Vào IDA xem thử :

Có thể thấy ngay là `cmp eax , 13371337h` sao đó dẫn đến aCorrect .


Kiểm tra bên Ghidra cũng thấy tương tự ở đoạn CMP với `0x13371337`

WOW thế là có flag rồi
---
Flag : `DH{322376503}`
---
# Simple Patch Me
[Simp Bồ Bắt Mi](https://dreamhack.io/wargame/challenges/669)
---

Sử dụng Ghidra để đọc code của chương trình. Vào `Search` -> `For String` để tìm dòng `Great xD.......`.
Kiểm tra decompile của dòng lệnh liên quan tới việc đưa ra flag, ta thấy:
```=c
undefined8 FUN_0040127b(void)
{
puts("I will show you the flag after 1 year :p");
DAT_0040404c = 0;
while (DAT_0040404c < 0x2238) {
FUN_004010a0(0xe10);
DAT_0040404c = DAT_0040404c + 1;
if (DAT_0040404c == 1) {
puts("1 hour passed");
}
else {
printf("%u hours passed\n",(ulong)DAT_0040404c);
}
if (DAT_0040404c % 0x18 == 0) {
if (DAT_0040404c == 0x18) {
puts("1 day has paased.");
}
else {
printf("%u days have passed.\n",(ulong)(DAT_0040404c % 0x18));
}
}
}
printf("Great xD 1 year has passed! The flag is: ");
FUN_00401196();
return 0;
}
```
Bên trong FUN_004010a0:
```=c
void FUN_004010a0(uint param_1)
{
sleep(param_1);
return;
}
```
Có thể thấy rằng chương trình in dòng : flag sẽ được nhả ra sau 1 năm.
Chương trình khai báo `DAT_0040404c = 0` và tạo vòng lặp `while DAT_0040404c < 0x2238 ` , tương đương với bé hơn `8760`. ( 24 * 365 = 8760).
Gọi hàm `FUN_004010a0(0xe10);` với 0xe10 = 3600 , bên trong hàm FUN_004010a0 đó là lệnh sleep, tức là chương trình sẽ ngưng 3600 giây = 1 giờ để rồi mới chạy tiếp.
Vòng lặp cứ thế trôi qua 1 giờ, 1 ngày , đến khi đủ 1 năm thì sẽ nhả flag ra.
Giải quyết vấn đề
---
Patching cái vòng lặp để cho nó nhả code ngay, cụ thể ở đây thì em sẽ patch dòng
```=
FUN_004010a0(0xe10);
// Trở thành
FUN_004010a0(0x0);
// Để cho nó sleep trong 0 giây
```
Em dùng ứng dụng cutter trên Linux để patch nó


Sau khi đã sửa thành `Ox0` và lưu rồi chạy. Ta được FLAG

FLAG : DH{6ad0f80a0448aee5e8615fbdea9c2775}
---
# Check Return Value
[Check check check](https://dreamhack.io/wargame/challenges/670)
---
` BÀI NÀY ĐỂ GIẢI ĐƯỢC THÌ PHẢI CÀI GDB TRÊN LINUX ĐỂ XEM CÁC GIÁ TRỊ ĐƯỢC NÉM VÀO THANH GHI`.

Với ý tưởng đặt breakpoint vào main để kiểm tra từng lệnh chạy , mà có vẻ như chương trình đã ẩn hàm main.
-VÀO IDA KIỂM TRA-

Có thể thấy đây là hàm main cốt lỗi của chương trình, nháy đúp vào 1 thanh ghi bất kì để thanh địa chỉ của hàm main này được thực hiện ở đâu.

- Vậy vị trí cần đặt breakpoint là `0x4015B6`

Dò với lệnh `next` từ từ và thấy call lệnh lạ, và nó cũng là flag
FLAG: DH{0e82b5c5082e44a74dbb6d05e91387ee}
---
# Check Function Argument
[Link](https://dreamhack.io/wargame/challenges/671)
---
Giải i chang bài bên trên, vẫn dùng GDB để xem chương trình hoạt động, và dùng IDA để xem điểm để breakpoint

Flag: DH{63db030352ca9f9f5e6b8a59c0527bee}
---
# Collect Me
---
[collect](https://dreamhack.io/wargame/challenges/672)

Chạy chương trình trên và được thông báo như này.
Điều cần làm bây giờ là check các kí tự nào có khả năng là flag trong các functions.

Kiểm tra trên IDA thì thấy rằng mỗi func_số sẽ cho 1 kí tự .

Vào hex view , ctrl F để tìm kí tự `{` vì thường flag nằm trong đó.

- Nó nè
---
Flag: DH{14d2f0c62de3cf038b52f9f60755af2b}
---
# Stop before stops!
---
[yamate dừng lại đi](https://dreamhack.io/wargame/challenges/822)
---
Mò trong IDA phần main được dòng thông tin như này :

- Có thể thấy là nơi đây sẽ nhả flag, vậy là mình nên dùng GDB `break` quanh đây để tìm flag.
- Sau đó run để dò địa chỉ từ từ

Đồng thời thì thấy `aCongratulation` được thực thi ở địa chỉ `main+97`

Vì vậy trong gdb nhập lệnh `jump *main+0x97` để nhảy đến địa chỉ đó.

---
FLAG: DH{why_don'7_y0u_j0in_ro11in6_r3ss????}
---
---
# Small Counter
---
[Link](https://dreamhack.io/wargame/challenges/851)
---

Hàm main này cho thấy rằng, chương trình tạo ra cái Counter =10
xong rồi nó so sánh với 0, nếu chưa bằng 0 thì nhảy qua `loc_14C5`
Sau đó thực hiện các phép tính , chạy đến 3 thì nhảy xuống loc_159C, dù là gì đi nữa thì chương trình nó cứ trừ từ từ về 0.
Lúc đó nó mới nhảy sang việc `cmp [rbp+var_4],5`, và dĩ nhiên lúc này rbp-4 kia = 0 rồi, nhảy sang END cmnl.
Flag thì như đề gợi ý, giấu trong cái flag_gen
Vậy giờ phải sửa sao cho cái rbp+var_4 bằng 5 thì mới ra Flag được.

Sau khi break main rồi run
Giờ break thêm cái main+278 nữa,, để chạy tới đoạn cmp rbp-4 với 5.

Giờ là xem địa chỉ thanh ghi của rbp-4 và giá trị nó đang lưu nè. sau khi biết địa chỉ rồi thì dùng `set` để sửa nó

FLAG : DH{389998e56e90e8eb34238948469cecd6dd89c04dce359c345e0b2f3ef9edc66a}
---
# please please please
---
[Link](https://dreamhack.io/wargame/challenges/1652)

Vào IDA, vào main, bấm `space` xong `ctrl+F` rồi tìm chữ DH, ra flag
flag : DH{NOGADA}
---
# My Favorite Fruit
---
[Link](https://dreamhack.io/wargame/challenges/1921)
---

- Tại challenge này yêu cầu ta nhập vào những loại trái cây, và nhập đúng sẽ ra flag .


- Xem IDA thì đây là các lệnh if else
- Dễ thấy quả cần nhập là `strawberry`, tuy nhiên là khi nhập thì nó lại ra dòng `Ew, I dont't like it.`

- Xem lại IDA, dò thật kĩ và thấy dòng chứ xám, và đó cũng là gợi ý

Yup, vấn đề ở đây chính là ở chỗ `%9s`, nó khai báo cho `giá trị input là 9 kí tự` , tuy nhiên `strawberry` lại có 10 kí tự, vì vậy nó không thể nhận được đầy đủ kí tự input mà chỉ nhận được `strawberr`.
## XỬ LÍ VẤN ĐỀ
- Biết được vấn đề rồi, giờ có thể đặt ra giả thuyết là mình chỉnh từ nhận `9 kí tự` lên thành `10 kí tự`.
Tuy nhiên sau khi kiểm tra `Hex-view`.

Thì thấy rằng ô lưu trữ của việc khai báo char này chỉ có 4 byte
```
Cũ (%9s): 25 39 73 00 (4 bytes)
Mới (%10s): 25 31 30 73 00 (5 bytes)
```
Như vậy là sẽ bị lố dữ liệu, như vậy thì nó sẽ ảnh hưởng đến kí tự nhập tiếp theo là là `banana`
| 1 | 2 | 3 | 4 | 5 |
|:---:| --- | --- | ----- | ----------------------- |
| % | 9 | s | enter | b ( chữ đầu của banana) |
| % | 1 | 0 | s | enter |
thành ra nếu chỉnh thành %10s thì khi nhập `banana` sẽ thành `anana`
- Vậy cách chỉnh `strawberry` thành `strawberr` thì sao.

Kiểm tra lệnh `sub` có thể thấy các công thức biến đổi những kí tự từ dữ liệu input và tạo ra flag, nếu chỉ có `strawberr` thì sẽ sai công thức , không ra được flag.
- Cách cuối, chỉnh `%9s` thành `%s` tức là nhập tất cả giá trị nhận vào, đọc vô tội vạ.
-- Cách này khả thi vì khi ấy hex của nó là `25 73 00 00` vẫn vừa khít cái ~~lỗ~~.
## Thực hành

- Xem IDA file bị **Stripped**, mình thấy là cái `main` được giấu trong `rdi`
- Giờ mình bật GDB trên Linux, start chương trình

> Khi start GDB, chương trình dừng lại ở Entry Point, thanh ghi `RIP` sẽ lưu lệnh sắp được thực thi, vì vậy cần xem các lệnh `RIP` đang lưu, tìm hàm main của mình.
LỆNH `x/30i $rip` ( xem 30 lệnh tiếp theo của RIP, mình nghĩ 30 là đủ rồi)


Đối chiếu với IDA thì `rdi, [rip+0x139]` chính là main, đặt breakpoint tại main , địa chỉ nó là `0x0x555555555258`
LỆNH : `break *0x0x555555555258`, sau đó nhập `c` để chạy đến đoạn đặt breakpoint.

- Vào trong hàm main, mình xem kỉ đoạn scanf này, vì đây là chỗ đọc `input`, thấy đưa `a9s` vào rax, xong đưa rax vào rdi. rồi call `__isco99_scanf`
→ Đưa tham số vào `rdi` (tham số đầu tiên luôn đưa vào rdi) , do đó mình cần chỉnh sửa tham số của `rdi` đang nằm trong hàm `__isco99_scanf
- Giờ thì mình dùng GDB để xem những gì diễn ra trong hàm main
LỆNH : `x/30i 0x555555555258` ( địa chỉ hàm main vừa tìm được bên trên)

→ Có được địa chỉ của lệnh call, giờ đặt break tại đó để chuẩn bị quá trình ~~giải phẩu~~.
LỆNH : `b *0x5555555552b0` và `c` để chạy tới đó.
GIẢI PHẨU THÔI
-- Kiểm tra rdi có phải là `%9s` hay không
-- Chỉnh sửa nó từ `%9s` thành `%s` bằng lệnh `set`
LỆNH:
+ `x/s + thanh ghi` để đọc
+ `set {KIỂU_DỮ_LIỆU}(ĐỊA_CHỈ) = GIÁ_TRỊ_MỚI` để thay đổi

LÀM NHƯ SAU:

Sau đó mình xóa breakpoint để tiếp tục chạy, nếu vẫn để breakpoint thì không thoát được vòng lặp này.
Nhập hết các loại trái cây vào, và nhận FLAG

FLAG: DH{da7d81d24cd0815521ede89289846461c2cbdd08d09ebe4c98221c7704675c2e}
---