***Challenge***:
> Several of the challenges are dynamic and require you to talk to our challenge servers over the network. This allows you to perform man-in-the-middle attacks on people trying to communicate, or directly attack a vulnerable service. To keep things consistent, our interactive servers always send and receive JSON objects.
>
> Such network communication can be made easy in Python with the pwntools module. This is not part of the Python standard library, so needs to be installed with pip using the command line pip install pwntools.
>
> For this challenge, connect to socket.cryptohack.org on port 11112. Send a JSON object with the key buy and value flag.
>
> The example script below contains the beginnings of a solution for you to modify, and you can reuse it for later challenges.
>
>
> Connect at socket.cryptohack.org 11112
>
> Challenge files:
> - pwntools_example.py
Hôm nay chúng ta sẽ đi giải challenge này nhaaaaa.
Bài này là một bài về kết nối sever, nhận và gửi gói tin để nhận flag. Vì thế ta sẽ đi sâu research về chủ đề này. Thư viện được sử dụng sẽ là pwntools, mình sẽ tìm hiểu các cách kết nối, tạo và đọc các gói tin đến và đi từ sever.
Tải file đính kèm của challenge, mình có một đoạn code như sau:
```
#!/usr/bin/env python3
from pwn import * # pip install pwntools
import json
HOST = "socket.cryptohack.org"
PORT = 11112
r = remote(HOST, PORT)
def json_recv():
line = r.readline()
return json.loads(line.decode())
def json_send(hsh):
request = json.dumps(hsh).encode()
r.sendline(request)
print(r.readline())
print(r.readline())
print(r.readline())
print(r.readline())
request = {
"buy": "clothes"
}
json_send(request)
response = json_recv()
print(response)
```
Và khi cho đoạn code khởi chạy, ở terminal mình nhận được kết quả như sau:
```
[x] Opening connection to socket.cryptohack.org on port 11112
[x] Opening connection to socket.cryptohack.org on port 11112: Trying 134.122.111.232
[+] Opening connection to socket.cryptohack.org on port 11112: Done
b"Welcome to netcat's flag shop!\n"
b'What would you like to buy?\n'
b"I only speak JSON, I hope that's ok.\n"
b'\n'
{'error': 'Sorry! All we have to sell are flags.'}
[*] Closed connection to socket.cryptohack.org port 11112
```
Và như bài đã nói, mình có thể "tái sử dụng" file code này để thực hiện challenge, vì thế mà mình sẽ đi vào phân tích các dòng code để hiểu nó hoạt động như thế nào.
Đoạn code này sử dụng 2 thư viện: pwntools và json. Pwntools thì như đã nói ở trên, còn JSON là một thư viện sử dụng trong việc định dạng thông tin để lưu trữ và vận chuyển.
HOST và PORT được thiết lập lần lượt là "socket.cryptohack.org" và 1112. Đây cũng chính là địa chỉ mà chúng ta cần phải kết nối để giải được challenge.
Function `remote()` đã được sử dụng, tạo kết nối đến địa chỉ vừa được xác ở trên. Đây là một function thuộc pwntools.

Kết nối đã có. Đoạn tiếp theo của đoạn code là tạo mới các function cho việc nhận và gửi các gói tin.
```
def json_send(hsh):
request = json.dumps(hsh).encode()
r.sendline(request)
```

Function `dumps()` được sử dụng để chuyển gói tin (ở đây là tham số `hsh`) cần gửi từ một định dạng khác sang định dạng json string để có thể vận chuyển thông qua các network. Sau đó, định dạng này lại được mã hóa thành dạng bytes một lần nữa bằng function `encode()`, cuối cùng được được gửi đi bằng `r.sendline()`.
```
def json_recv():
line = r.readline()
return json.loads(line.decode())
```
Đối với function dùng nhận tin, tín hiệu gửi về từ máy chủ được tiếp nhận với `r.readline()`. Sau đó hàm trả về kết quả sau khi đã giải mã bằng `json.loads()` (function ngược lại với `dumps()`) và `decode()`.
Với 4 dòng `print(r.readline())` sau đó, dùng để in ra các tín hiệu được trả về từ máy chủ sau khi thiết lập kết nối. Thao tác xác lập gói tin ta cần truyền đi ở dạng `{key; value}`.
```
request = {
"buy": "clothes"
}
```
Function `json_send()` được xác lập từ trước được sử dụng để gửi gói tin đến với máy chủ. Phản hồi của máy chủ lần này là một JSON object khác, vì thế mà function để nhận gói tin lần này sẽ là function trước đó đã thiết lập `json_recv()`. Và cuối cùng là in ra object được nhận về.
Và đó là quá trình kết nối - nhận - gửi - nhận được sử dụng trong đoạn code vừa rồi, và chúng ta sẽ ứng dụng tương tự vào challenge của chúng ta.
Các thao tác như vậy có lẽ là không cần thêm bớt gì nữa, và thứ chúng ta cần đi tìm để hiệu chỉnh chính là giá trị `key` và `value` để nhận được gói tin cần. Và gói tin duy nhất ta gửi đi chính là gói tin `request`, vì thế ta sẽ chỉ hiệu chỉnh phần này. Lần lượt thay vào là `buy` và `flag`, ta nhận được phản hồi từ máy chủ:
```{'flag': 'crypto{sh0pp1ng_f0r_fl4g5}'}```
Flag đây rồi.