---
# System prepended metadata

title: BKSEC TTV WU REVERSE

---

# BKSEC TTV WU REVERSE 

## I. jslock

* Chall cho ta một đường link web 

![image](https://hackmd.io/_uploads/rJ__32Bp6.png)

* Web đơn giản là check pass bằng cách nhập mật khẩu nằm trong cận [0, 9]. Để hiểu rõ hơn về phương thức mã hóa của web thì ta xem source code của web

* Để tiện phân tích thì mình sẽ dùng Edge Browser để mở Devtools lên 

![image](https://hackmd.io/_uploads/SJ8-62Bpp.png)

* Ở lock.js ta đã thấy hàm check pass của web 

    * Đơn giản thì chương trình lấy dữ liệu input sau đó biến đổi thành một mảng sử dụng `Array.from(dials)`.

    * Tiếp theo tạo ra một mảng mới gọi là `decodedPassword`, trong đó mỗi phần tử là tổng của ba số liên tiếp trong mảng `enteredPassword`.

    * Hàm so sánh mảng `decodedPassword` với mảng các hằng số `correctPassword` nếu giống nhau thì ret true

* Việc xử lý cũng khá đơn giản, mình sẽ brute force để tìm key 

```

def find_password():
    for digit_0 in range(10):
        for digit_1 in range(10):
            for digit_2 in range(10):
                for digit_3 in range(10):
                    for digit_4 in range(10):
                        entered_password = [digit_0, digit_1, digit_2, digit_3, digit_4]
                        if (entered_password[0] + entered_password[1] + entered_password[2] == 10 and
                            entered_password[1] + entered_password[2] + entered_password[3] == 12 and
                            entered_password[2] + entered_password[3] + entered_password[4] == 10 and
                            entered_password[3] + entered_password[4] + entered_password[0] == 11 and
                            entered_password[4] + entered_password[0] + entered_password[1] == 11):
                            return entered_password

password = find_password()
print("Correct password:", password)
```

* Key đúng sẽ là 

![image](https://hackmd.io/_uploads/SJ-2V1IpT.png)

* Nhập vào và lấy flag 

![Screenshot 2024-03-06 194319](https://hackmd.io/_uploads/r1axSk8ap.png)

> BKSEC{MzMzNTMyMzUzMw==}

## II. jslockpremium

![image](https://hackmd.io/_uploads/Hk6_S1Lp6.png)

* Đến bài này cũng là phân tích source web nhưng đã được nâng cấp đôi chút khi ta phải nhập tận 10 key và cận rất lớn từ [0, 999].

* Vì vậy phương pháp brute force thông thường sẽ không khả thi, thay vào đó đề có gợi ý cho chúng ta về `Z3` 

* Z3 là một hệ thống hỗ trợ chứng minh tự động và giải quyết các bài toán toán học. Được phát triển bởi `Microsoft Research`, Z3 được sử dụng rộng rãi trong nhiều lĩnh vực như kiểm tra phần mềm, tự động hóa, và lý thuyết đồng thời. Link cài đặt cũng như cách dùng thì [ở đây](https://youtu.be/rTVNvZx83IE?si=7M6qf9u8b4IEkJ4h)

* Quay trở lại với bài thì lần này có vẻ như hàm check pass ngoằn nghoèo hơn tí 

![image](https://hackmd.io/_uploads/HkBIWRIap.png)

* Tổng cộng có 12 key cần tìm và cũng như mảng const Password[11]

* Mình sẽ dùng Z3 để solve 

```
from z3 import *

correctPassword = [43490, 822, 2243, 1105, 4652, 429, 1187, 3901, 395, 1067, 622]
enteredPassword = [Int('enteredPassword_' + str(i)) for i in range(12)]

solver = Solver()

solver.add(enteredPassword[0] * enteredPassword[1] - 2 * enteredPassword[2] == correctPassword[0])
solver.add(enteredPassword[1] + 5 * enteredPassword[2] - 3 * enteredPassword[3] == correctPassword[1])
solver.add(enteredPassword[2] + enteredPassword[3] * enteredPassword[4] - enteredPassword[0] == correctPassword[2])
solver.add(enteredPassword[5] + 2 * enteredPassword[4] + enteredPassword[2] == correctPassword[3])
solver.add(20 * enteredPassword[1] - 2 * enteredPassword[2] - enteredPassword[4] == correctPassword[4])
solver.add(enteredPassword[2] + enteredPassword[5] - 2 * enteredPassword[1] == correctPassword[5])
solver.add(2 * enteredPassword[1] + enteredPassword[2] + 3 * enteredPassword[6] + 4 * enteredPassword[7] == correctPassword[6])
solver.add(5 * enteredPassword[5] - enteredPassword[7] - enteredPassword[8] + 2 * enteredPassword[9] == correctPassword[7])
solver.add(3 * enteredPassword[8] + 2 * enteredPassword[9] + 4 * enteredPassword[10] - 3 * enteredPassword[6] == correctPassword[8])
solver.add(9 * enteredPassword[11] + 2 * enteredPassword[10] - enteredPassword[8] == correctPassword[9])
solver.add(4 * enteredPassword[7] - enteredPassword[8] + enteredPassword[10] == correctPassword[10])


for i in range(12):
    solver.add(And(enteredPassword[i] >= 0, enteredPassword[i] <= 999))

result = solver.check()

if result == sat:
    model = solver.model()
    enteredPasswordValues = []
    for i in range(11):
        enteredPasswordValues.append(model[enteredPassword[i]].as_long())

    print( enteredPasswordValues)
else:
    print('Nope')

```

* Mấu chốt ở đây mình sẽ k tìm key thứ 12 bởi vì nhìn kỹ ở key này sẽ thấy ` enteredPassword[3] ** enteredPassword[8] + 3 * enteredPassword[11] - 2 * enteredPassword[7] + enteredPassword[6] + enteredPassword[5] + enteredPassword[10]`. Key này có mũ nên việc dùng z3 với mũ sẽ k khả thi(Có lẽ là vậy vì mình chạy k được:v)

* Cách giải quyết thì mình sẽ bỏ qua key này và chạy 11 key đầu tiên, việc tiếp theo là dùng 11 key tìm được và thay vào tìm key thứ 12, một điều lưu ý nữa là cần đặt cận [0, 999] nếu không kết quả sẽ sai vì ra âm hoặc out cận

![image](https://hackmd.io/_uploads/SJ4IGRUpp.png)

* 11 Key đầu và thế vào sẽ được key thứ 12 là `99`

* Nhập vào web và lấy flag 

![Screenshot 2024-03-07 123132](https://hackmd.io/_uploads/H1a_zA86T.png)


## III. BabyIDA1

* Load file vào IDA

![image](https://hackmd.io/_uploads/SyxgQ0IT6.png)

* Ta thấy luôn hai phần của flag, phần đầu có vẻ như là chuẩn nhưng phần thứ 2 thì hình như đã bị đảo lộn thứ tự, bây giờ mình sẽ phân tích kỹ chương trình hơn

* khởi tạo `v13` và `v12` chứa các phần của key. v13 chứa phần đầu của khóa và v12 chứa phần cuối.
* Tiếp theo, chương trình yêu cầu người dùng nhập một chuỗi vào biến `v10`, rồi so sánh chuỗi đó với chuỗi `v13`. Nếu chuỗi nhập vào giống với `v13`, chương trình tiếp tục, chương trình yêu cầu người dùng nhập một chuỗi khác vào biến `v9` sau đó so với `v12` đã bị splicing với -1

* Đến đây có lẻ đã quá rõ ràng ta chỉ cần splice lại `v12` sau đó cộng với `v13` là xong 

```
s = "})12387642t234g789_UaD_t3h_@Uhc}eheh_n0ul_1Uv_Al_"
reversed_string = s[::-1]
print(reversed_string)  

```

![image](https://hackmd.io/_uploads/Hy119086T.png)

> BKSEC{rev3r5e_r@t_lA_vU1_lu0n_hehe}chU@_h3t_DaU_987g432t24678321)} 


## IV. Babylua

* Đề cho ta 2 file .lua, mở lần lượt để xem thử 

![image](https://hackmd.io/_uploads/HJLN-yvTT.png)

* File main khá đơn giản dùng để check input là flag ta nhập vào nhưng hình như vẫn còn thiếu điều kiện

* file flag.lua là file binary nên mình decompile ra để lấy code 

![Screenshot from 2024-03-07 01-40-52](https://hackmd.io/_uploads/SyD2byDT6.png)

* Hàm check nhận hai đối số là chuỗi đầu vào (inp) và khóa (key)

* Vòng lặp đầu tiên chạy qua từng ký tự trong chuỗi đầu vào (inp). Mỗi ký tự được XOR với ký tự tương ứng trong key, sau đó được cộng thêm với giá trị của ký tự trước đó trong chuỗi đầu vào

* Vòng lặp thứ hai so sánh từng phần tử trong mảng encoded với từng phần tử trong mảng arr. Nếu các giá trị tại vị trí tương ứng trong hai mảng giống nhau, biến result được tăng lên một 

* Kết hợp với file flag.lua đã decompile cùng với key `ThisIsAFlag` ở main.lua ta có thể brute để tìm flag

```
arr = [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]
cmp_str = 'ThisIsAFlag'
charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=<>,.?/{}[]\|~:;"\''
flag = " "
test = 0
for i in range(len(arr)):
    for char in charset:
        temp = (ord(char) ^ ord(cmp_str[i % len(cmp_str)])) + test
        if temp == arr[i]:
            flag += char
            test = ord(char)
            break
print(flag)

```

![image](https://hackmd.io/_uploads/HJ7REyvpa.png)

> BKSEC{ju$t_h@rd3r_2_re@d_:P}

## V. BabyRust

* Đề cho ta một file thực thi `Rust0` 

![Screenshot from 2024-03-07 01-57-14](https://hackmd.io/_uploads/B1pOBJvap.png)
 
* Vẫn mô tuýp cũ là bắt ta nhập pass để check, tiến hành phân tích bằng IDA

![image](https://hackmd.io/_uploads/H1mMq1w6T.png)

* Ok, điển hình của Rust khi disas ra thì hàm main sẽ được wrap khá sâu trong các hàm khác ở đây hàm main được wrap trong `std::rt::lang_start::hf8b53e431764034c()` mà ở trong cũng sẽ được wrap bởi một hàm khác là `std::rt::lang_start_internal::h76f3e81e6b8f13f9()` đấy sẽ là main thật của chúng ta 

```
void __cdecl std::rt::lang_start_internal::h76f3e81e6b8f13f9()
{
    __int64 v0; // rdi
    __int64 v1; // rsi
    char v2; // r8
    unsigned __int64 v3; // r12
    char v4; // bp
    unsigned int v5; // eax
    int v6; // ecx
    void (*v7)(int); // rsi
    __int64 v8; // rax
    __int64 v9; // rax
    unsigned __int64 v10; // rbx
    __int64 v11; // r13
    pthread_t v12; // rax
    void (*v13)(int); // r14
    unsigned __int64 v14; // r12
    unsigned __int64 v15; // rdx
    unsigned __int64 v16; // rbx
    __int64 v17; // rax
    __int64 v18; // rsi
    void *v19[2]; // [rsp+0h] [rbp-158h] BYREF
    size_t stacksize[4]; // [rsp+10h] [rbp-148h] BYREF
    __int64 v21; // [rsp+30h] [rbp-128h] BYREF
    char **v22; // [rsp+40h] [rbp-118h]
    __int64 v23; // [rsp+48h] [rbp-110h]
    size_t *v24; // [rsp+50h] [rbp-108h]
    __int64 v25; // [rsp+58h] [rbp-100h]
    struct sigaction fds; // [rsp+60h] [rbp-F8h] BYREF
    __int64 v27[2]; // [rsp+100h] [rbp-58h] BYREF
    __int64 v28; // [rsp+110h] [rbp-48h]
    __int64 v29; // [rsp+118h] [rbp-40h]
    size_t *v30; // [rsp+120h] [rbp-38h] BYREF

    v4 = v2;
    v29 = v1;
    v28 = v0;
    fds.sa_handler = 0LL;
    *(_OWORD *)fds.sa_mask.__val = xmmword_41B70;
    do
    {
        if ( poll((struct pollfd *)&fds, 3uLL, 0) != 0xFFFFFFFF )
        {
            if ( (BYTE6(fds.sa_sigaction) & 0x20) != 0 && open64(szd, 2, 0LL) == 0xFFFFFFFF
              || (fds.sa_mask.__val[0] & 0x20000000000000LL) != 0 && open64(szd, 2, 0LL) == 0xFFFFFFFF )
            {
                goto LABEL_xE2AA;
            }

            if ( (fds.sa_mask.__val[1] & 0x20000000000000LL) == 0 )
            {
                goto LABEL_xDFDB;
            }

LABEL_xDFBC:
            if ( open64(szd, 2, 0LL) != 0xFFFFFFFF )
            {
                goto LABEL_xDFDB;
            }

LABEL_xE2AA:
            abort();
        }

        v5 = *_errno_location();
    }
    while ( v5 == 4 );

    if ( v5 > 0x16 )
    {
        goto LABEL_xE2AA;
    }

    v6 = 0x401800;
    if ( !_bittest(&v6, v5) || fcntl(0, 1) == 0xFFFFFFFF && *_errno_location() == 9 && open64(szd, 2, 0LL) == 0xFFFFFFFF )
    {
        goto LABEL_xE2AA;
    }

    if ( fcntl(1, 1) == 0xFFFFFFFF && *_errno_location() == 9 && open64(szd, 2, 0LL) == 0xFFFFFFFF )
    {
        goto LABEL_xE2AA;
    }

    if ( fcntl(2, 1) == 0xFFFFFFFF && *_errno_location() == 9 )
    {
        goto LABEL_xDFBC;
    }

LABEL_xDFDB:
    v7 = (void (*)(int))(&dword_0 + 1);
    switch ( v4 )
    {
        case 0:
            goto LABEL_xE010;

        case 1:
            std::sys::unix::UNIX_SIGPIPE_ATTR_SPECIFIED::h1ae45800e8663548 = 1;
            goto LABEL_xE025;

        case 2:
            goto LABEL_xE009;

        case 3:
            v7 = 0LL;

LABEL_xE009:
            std::sys::unix::UNIX_SIGPIPE_ATTR_SPECIFIED::h1ae45800e8663548 = 1;

LABEL_xE010:
            if ( signal(0xD, v7) == (__sighandler_t)0xFFFFFFFFFFFFFFFFLL )
            {
                fds.sa_mask.__val[1] = (unsigned __int64)&off_512E0;
                fds.sa_mask.__val[2] = 1LL;
                fds.sa_handler = 0LL;
                fds.sa_mask.__val[3] = (unsigned __int64)&unk_42560;
                fds.sa_mask.__val[4] = 0LL;
                stacksize[0] = (size_t)&fds;
                stacksize[1] = (size_t)_$LT$core..fmt..Arguments$u20$as$u20$core..fmt..Display$GT$::fmt::h15bd174c5b27285e;
                v22 = &off_507C8;
                v23 = 2LL;
                v21 = 0LL;
                v24 = stacksize;
                v25 = 1LL;
                std::io::Write::write_fmt::h88186074961638e4();
                core::ptr::drop_in_place$LT$core..result..Result$LT$$LP$$RP$$C$std..io..error..Error$GT$$GT$::h47051a553bf87b8d();

LABEL_xE414:
                std::sys::unix::abort_internal::h1bcf881e3e6f862f();
            }

LABEL_xE025:
            memset(&fds, 0, sizeof(fds));
            sigaction(0xB, 0LL, &fds);
            if ( !fds.sa_handler )
            {
                fds.sa_flags = 0x8000004;
                fds.sa_handler = (__sighandler_t)std::sys::unix::stack_overflow::imp::signal_handler::h9eed1699e3a2066b;
                sigaction(0xB, &fds, 0LL);
                std::sys::unix::stack_overflow::imp::NEED_ALTSTACK::h0328ae7462edf624 = 1;
            }

            sigaction(7, 0LL, &fds);
            if ( !fds.sa_handler )
            {
                fds.sa_flags = 0x8000004;
                fds.sa_handler = (__sighandler_t)std::sys::unix::stack_overflow::imp::signal_handler::h9eed1699e3a2066b;
                sigaction(7, &fds, 0LL);
                std::sys::unix::stack_overflow::imp::NEED_ALTSTACK::h0328ae7462edf624 = 1;
            }

            std::sys::unix::stack_overflow::imp::make_handler::h945115486f96f7e5();
            std::sys::unix::stack_overflow::imp::MAIN_ALTSTACK::h1249fea233ef7b4a = v8;
            v9 = sysconf(0x1E);
            std::sys::unix::thread::guard::PAGE_SIZE::hb394fa245618b31c = v9;
            v10 = v9;
            if ( !v9 )
            {
LABEL_xE467:
                core::panicking::panic::h0ead933cb8f56d66();
            }

            v11 = v9;
            memset(&fds, 0, 0x38);
            v12 = pthread_self();
            if ( pthread_getattr_np(v12, (pthread_attr_t *)&fds) )
            {
                v13 = 0LL;
            }
            else
            {
                v19[0] = 0LL;
                stacksize[0] = 0LL;
                LODWORD(v27[0]) = pthread_attr_getstack((const pthread_attr_t *)&fds, v19, stacksize);
                if ( LODWORD(v27[0]) )
                {
                    goto LABEL_xE434;
                }

                v14 = (unsigned __int64)v19[0];
                LODWORD(stacksize[0]) = pthread_attr_destroy((pthread_attr_t *)&fds);
                if ( LODWORD(stacksize[0]) )
                {
LABEL_xE434:
                    v22 = 0LL;
                    core::panicking::assert_failed::h92efb50074ef787c();
                }

                if ( (v10 | v14) >> 0x20 )
                {
                    v15 = v14 % v10;
                }
                else
                {
                    v15 = (unsigned int)v14 % (unsigned int)v10;
                }

                v16 = v10 - v15;
                if ( !v15 )
                {
                    v16 = 0LL;
                }

                v3 = v16 + v14;
                v10 = v3 - v11;
                v13 = (void (*)(int))(&dword_0 + 1);
            }

            _$LT$$RF$$u5b$u8$u5d$$u20$as$u20$alloc..ffi..c_str..CString..new..SpecNewImpl$GT$::spec_new_impl::ha43b7641c7a37b38();
            if ( stacksize[2] )
            {
                v30 = stacksize;
                v19[0] = &v30;
                v19[1] = _$LT$core..result..Result$LT$T$C$E$GT$$u20$as$u20$core..fmt..Debug$GT$::fmt::h6b7406c389cb2859;
                fds.sa_mask.__val[1] = (unsigned __int64)&off_507E8;
                fds.sa_mask.__val[2] = 1LL;
                fds.sa_handler = 0LL;
                fds.sa_mask.__val[3] = (unsigned __int64)v19;
                fds.sa_mask.__val[4] = 1LL;
                v27[0] = (__int64)&fds;
                v27[1] = (__int64)_$LT$core..fmt..Arguments$u20$as$u20$core..fmt..Display$GT$::fmt::h15bd174c5b27285e;
                v22 = &off_507C8;
                v23 = 2LL;
                v21 = 0LL;
                v24 = (size_t *)v27;
                v25 = 1LL;
                std::io::Write::write_fmt::h88186074961638e4();
                core::ptr::drop_in_place$LT$core..result..Result$LT$$LP$$RP$$C$std..io..error..Error$GT$$GT$::h47051a553bf87b8d();
                goto LABEL_xE414;
            }

            std::thread::Thread::new::hcf5764422a3481dd();
            fds.sa_handler = v13;
            fds.sa_mask.__val[0] = v10;
            fds.sa_mask.__val[1] = v3;
            v18 = v17;
            std::sys_common::thread_info::set::h5a58eaf2e04c69a0();
            (*(void (__fastcall **)(__int64, __int64))(v29 + 0x28))(v28, v18);
            if ( std::rt::cleanup::CLEANUP::h83d636d36c69baa1 != 4 )
            {
                LOBYTE(v21) = 1;
                fds.sa_handler = (__sighandler_t)&v21;
                std::sys_common::once::futex::Once::call::h3553f533aaf8caf1();
            }

            return;

        default:
            goto LABEL_xE467;
    }
}
```

* Tạm gác main qua chúng ta có thể tìm hàm check bằng cách search msgbox đã hiện khi ta run thử chương trình ta tìm thấy hàm check điều kiện đúng 

![image](https://hackmd.io/_uploads/BJ_Hhyv6a.png)

* nhìn vào garph ta có thể thấy nếu nhập vào pass thì pass sẽ được check ở hàm màu đen và sau đó mới in ra terminal 

![image](https://hackmd.io/_uploads/ryx2p1vpp.png)

* Cụ thể sẽ là hàm `chall::main::hcc105c60431fd7b5()`

```
void __cdecl chall::check::h428e27b3168ba563()
{
    _BYTE *v0; // rdi
    unsigned __int64 v1; // rsi
    unsigned __int64 v2; // rax
    bool v3; // [rsp+167h] [rbp-1h]

    core::str::_$LT$impl$u20$str$GT$::len::hc55f8affae116d65();
    if ( v2 >= 0x15 )
    {
        if ( v1 <= 9 )
        {
            core::panicking::panic_bounds_check::h937aba65fb5d17a6();
        }

        if ( v0[9] == 0x43 && v0[5] == 0x7B && v0[2] == 0x53 && v0[6] == 0x77 && *v0 == 0x42 )
        {
            if ( v1 <= 0x14 )
            {
                core::panicking::panic_bounds_check::h937aba65fb5d17a6();
            }

            if ( v0[0x14] == 0x7D
              && v0[4] == 0x43
              && v0[0xC] == 0x45
              && v0[0x13] == 0x76
              && v0[0x11] == 0x52
              && v0[7] == 0x33
              && v0[3] == 0x45
              && v0[0xE] == 0x74
              && v0[0xF] == 0x4F
              && v0[0x10] == 0x5F
              && v0[0xA] == 0x30
              && v0[0x12] == 0x33
              && v0[0xD] == 0x5F
              && v0[8] == 0x6C
              && v0[1] == 0x4B )
            {
                v3 = v0[0xB] == 0x6D;
            }
        }
    }
}
```

* Hàm này đơn giản check input ta nhập vào với const là mảng v0[i] sắp xếp thứ tự mảng ta có `0x42, 0x4B, 0x53, 0x45, 0x43, 0x7B, 0x77, 0x33, 0x6C, 0x43,
        0x30, 0x6D, 0x45, 0x5F, 0x74, 0x4F, 0x5F, 0x52, 0x33, 0x76, 0x7D`
        
* Decode sang ASCII ta được flag 

![image](https://hackmd.io/_uploads/HyADblDap.png)

## VI. BabyASM

* Bài này xem thử khả năng đọc hiểu code nasm và cách thức truyền input và output của stack của chúng ta đến đâu và cũng khá giống với 5 bài `GDB Step` trên Pico mình đã từng làm để xem thử bài cho ta những gì 

```
babyasm:
	<+0>:	push   ebp
	<+1>:	mov    ebp,esp
	<+3>:	xor    eax,eax
	<+5>:	mov    ah,BYTE PTR [ebp+0x9]
	<+8>:	shl    ax,0x10
	<+12>:	sub    al,BYTE PTR [ebp+0xe]
	<+15>:	add    ah,BYTE PTR [ebp+0xf]
	<+18>:	xor    ax,WORD PTR [ebp+0x12]
	<+22>:	nop
	<+23>:	pop    ebp
	<+24>:	ret    	


```

* Bài chỉ cho ta hàm `babyasm` và k có _start hay _end 
* Ngoài ra bài cho ta 3 đối số `0xabcd1456, 0xdfed7768, 0x68686868`

* Ban đầu bài này mình định nhớ AI để convert sang python cho dễ đọc nhưng sau khi thử một lúc thì AI convert sai nên mình đành làm cách thủ công là viết hoàn chỉnh lại chương trình này:vv

* Để làm chay thì ta cần lưu ý một tí về stack như sau, nếu Input được truyền vào trước thì sẽ ra sau cùng( cơ chế LIFO) vì thế đề bài cho ta 3 đối số lần lượt lượt là `0xabcd1456, 0xdfed7768, 0x68686868` ta cần biết thêm về cơ chế của thanh ghi `EBP` 

* Chức năng chính của thanh ghi EBP là lưu trữ địa chỉ cơ sở (base address) của frame của hàm hiện tại trên ngăn xếp (stack frame). Khi một hàm được gọi, một frame mới sẽ được tạo trên ngăn xếp để lưu trữ các biến cục bộ, các tham số của hàm và các giá trị trung gian trong quá trình thực thi hàm đó. Thanh ghi EBP được sử dụng để trỏ đến phần đầu của frame này, giúp chương trình truy cập các biến cục bộ và tham số của hàm một cách dễ dàng. Còn khi một hàm kết thúc, frame của nó sẽ được giải phóng và giá trị của thanh ghi EBP sẽ được khôi phục về giá trị ban đầu của nó trước khi hàm được gọi.

* Chính vì cơ chế LIFO nên ta k thể push value như các ngôn ngữ bậc cao được mà phải thực hiện ngược lại bằng cách push giá trị sao cùng lên đầu và giá trị đầu về sau cùng, viết lại thì chương trình sẽ như sau 

```
section .text
	global _start

_start:
	push 0x68686868
	push 0xdfed7768
	push 0xabcd1456
	call babyasm

	mov eax, 1
        xor ebx, ebx
	int 0x80

babyasm:
	push   ebp
	mov    ebp,esp
	xor    eax,eax
	mov    ah,BYTE [ebp+0x9]
	shl    ax,0x10
	sub    al,BYTE [ebp+0xe]
	add    ah,BYTE [ebp+0xf]
	xor    ax,WORD [ebp+0x12]
	nop
	pop    ebp
ret
```

* Giờ thì compile nó sang file thực thi và quăng vào `Peda` để run thử

![Screenshot from 2024-03-07 05-24-01](https://hackmd.io/_uploads/Hytj8fDTT.png)

* Mình đặt breakpoint ở  ` 0x0804900f` ngay lệnh call hàm babyasm 

![Screenshot from 2024-03-07 05-24-28](https://hackmd.io/_uploads/SJEp8Gw6p.png)

* Đến cuối giá trị cuối cùng của EAX là `0xb77b`

> BKSEC{0xb77b}
