Chall này cùng ý tưởng với một bài mình từng làm ơ SVATTT năm nay.
Đây là wu của mình cho bài đó:
SVATTT 2021 - UNLOCK (re) - HackMD
Reverse các opcode trong hàm VM
thì mình có được script sau:
registers = ['TESTTT', 'EAX', 'EBX', 'ECX', 'EDX', 'ESI', 'EDI', 'ESP', 'EIP', 'EBP']
instructions = [
[0x00, 2, "MOV {}, {}"], # mov eax, ebx
[0x01, 2, "MOV {}, {}"], # MOV EAX, 0X20
[0x02, 2, "XOR {}, {}"], # xor byte1, byte2
[0x03, 2, "SUB {}, {}"],
[4, 2, "ADD {}, {}"],
[5, 1, "PUSH {}"], # PUSH EAX
[6, 1, "POP {}"], # POP EAX
[7, 3, "MOV {}, BYTE PTR [{}+{}]"], # MOV BYTE1, [BYTE2+BYTE3]
[8, 1, "JMP {}"], # JMP CURR+BYTE1
[9, 1, "JNZ {}"], # FLAGS 0X40
[10, 2, "CMP {}, {}"], # CMP AND SET FLAGS 0X40
[11, 2, "AND {}, {}"],
[12, 2, "SHL {}, {}"], # SHF EAX, EBX
[13, 2, "SHR {}, {}"], # SHR EAX, EBX
[14, 2, "CALL {}"], # CALL EAX
[15, 1, "JMP {}"], # JMP EAX
[16, 3, "MOV {}, DWORD PTR [{}+{}]"], # MOV BYTE1, [BYTE2+BYTE3]
[17, 1, "JZ {}"]
]
def main():
with open("out.bin", "rb") as vm:
opcodes = vm.read()
vm.close()
opcodes = opcodes[5:]
pc = 0
asm_text = ""
value = [[] for _ in range(18)]
bitmath = [[] for _ in range(18)]
idx = 0
pre_text = ""
while pc < 0x1dc3:
ins = instructions[opcodes[pc]]
# print (ins)
# text = hex(pc) + ":\t"
text = ""
if ins[1]==1:
if ins[0]==8 or ins[0]==9 or ins[0]==17:
text += ins[2].format(hex(pc -1 + int(opcodes[pc+1])))
else:
text += ins[2].format(registers[int(opcodes[pc+1])])
# asm_text.append(text)
pc += 2
elif ins[1]==2:
if int(opcodes[pc+1]) > 9 :
print (int(opcodes[pc+1]) )
text += "CORRUPTED {} {} {}".format(int(opcodes[pc]), int(opcodes[pc+1]), int(opcodes[pc+2]))
if ins[0]==1:
text += ins[2].format(registers[int(opcodes[pc+1])], hex(int(opcodes[pc+2])))
elif int(opcodes[pc+1]) <= 9:
text += ins[2].format(registers[int(opcodes[pc+1])], registers[int(opcodes[pc+2])])
pc += 3
elif ins[1]==3:
text += ins[2].format(registers[int(opcodes[pc+1])], registers[int(opcodes[pc+2])], registers[int(opcodes[pc+3])])
pc += 4
text += "\n"
# print (text)
asm_text += text
print (asm_text)
# print (asm_text)
if __name__=="__main__":
main()
Đoạn này sẽ dump ra được code ASM
Revere tương tự như wu trên thì mình có được password
Note
Trong quá trình làm challenge này thì bạn teammate có chỉ cho mình một tools để emulate ASM khá là hay, đó là:
Chall này cho một binary khá là ngắn, và tên hàm đều không bị strip. Nhưng điều đáng buồn là file được compile trên MAC arm64, vậy nên chúng mình hoàn toàn không thể debug được.
Đầu tiên, đi từ flow của hàm main
bzero(enc_pt, 0x1000uLL);
memset(arr_int_secret, 0, sizeof(arr_int_secret));
fp_pt = fopen("plaintext.txt", "r");
if ( !fp_pt )
{
stdout_ = "No plaintext.txt for you!";
LABEL_33:
puts(stdout_);
return 1;
}
fp_pt_ = fp_pt;
idx0 = 0LL;
idx1 = 1LL;
do
{
one_char = fgetc(fp_pt_);
enc_pt[idx0] = (109330345517422uLL >> ((unsigned __int8)idx0 - 47 * (unsigned __int8)(idx1 / 47) + 1)) ^ one_char ^ fib(idx0);
putchar('.');
fflush((FILE *)&unk_100000CFE);
++idx0;
++idx1;
}
while ( idx0 != 4096 );
Đoạn này chương trình đọc dữ liệu từ file plaintext.txt
và thực hiện encrypt
(xor) với key là cothan
Tiếp theo:
fp_secret = fopen("secret.txt", "r");
if ( !fp_secret )
{
stdout_ = "No secret.txt for you!";
goto LABEL_33;
}
fp_secret_ = fp_secret;
for ( i = 0LL; i != 32; ++i )
fscanf(fp_secret_, "%d,", &arr_int_secret[i]);
fclose(fp_secret_);
puts(
"There are 2 types of code reverser, the brave reverses everything and fall for traps, the coward only reverses what needed");
idx2 = 0LL;
while ( 2 )
{
value_int = arr_int_secret[idx2];
if ( value_int > 29 )
return 1;
if ( idx2 <= 4 && (unsigned __int8)arr_int_secret[idx2] % 5u )
return 2;
switch ( (int)idx2 )
{
case 16:
if ( value_int == 13 )
goto LABEL_21;
result = 3;
break;
case 17:
if ( value_int == 11 )
goto LABEL_21;
result = 4;
break;
case 18:
if ( value_int == 25 )
goto LABEL_21;
result = 5;
break;
case 19:
if ( value_int == 16 )
goto LABEL_21;
result = 6;
break;
case 20:
if ( value_int == 28 )
goto LABEL_21;
result = 7;
break;
default:
LABEL_21:
if ( ++idx2 != 32 )
Chương trình đọc 32 byte từ file secret.txt
và lưu vào một mảng int
Sau đó:
idx3 = 0LL;
idx4 = 0uLL;
do
{
idx4 = vaddq_s32(*(int32x4_t *)&arr_int_secret[idx3], idx4);
idx3 += 4LL;
}
while ( idx3 != 16 );
if ( vaddvq_s32(idx4) != 251 )
return 1;
idx5 = 0LL;
idx6 = 0uLL;
do
{
idx6 = vaddq_s32(*(int32x4_t *)&arr_int_secret[idx5 + 16], idx6);
idx5 += 4LL;
}
while ( idx5 != 16 );
if ( vaddvq_s32(idx6) != 263 )
return 1;
Chương trình thực hiện cộng mỗi nửa của secret
và so sánh với 1 số là 251 và 263
Cuối cùng:
idx7 = 0LL;
idx8 = 0;
do
{
transpose(&enc_pt[idx8], arr_int_secret[idx7], arr_int_secret[idx7 + 16]);
idx8 += arr_int_secret[idx7 + 16] * arr_int_secret[idx7];
++idx7;
}
while ( idx7 != 16 );
fp_ct = fopen("out.enc", "w");
fwrite(enc_pt, 1uLL, 0x1000uLL, fp_ct);
fclose(fp_ct);
result = 0;
Chương trình thực hiện transpose
để thay đổi dữ liệu của plaintext
vừa bị encrypt ở trên sau đó ghi vào file out.enc
Chúng ta có file out.enc
và sẽ phải đi ngược lại tìm plaintext.txt
Sau khi đọc đống dữ liệu trên mình đã liên tưởng đến z3, nhưng z3 trả về một số lượng lớn các nghiệm và nó khiến mình rất hoang mang.
Script z3 của mình:
from z3 import *
s = Solver()
secret = [BitVec("secret%s" % i, 8) for i in range(32)]
for i in range(32):
s.add(secret[i]<29)
s.add(secret[i]>0)
s.add(secret[16] == 13)
s.add(secret[17] == 11)
s.add(secret[18] == 25)
s.add(secret[19] == 16)
s.add(secret[20] == 28 )
x = 0
for i in range(16):
x += secret[i]
s.add(x == 251)
x = 0
for i in range(16, 32):
x += secret[i]
s.add(x == 263)
a = 0
for i in range(16):
a += secret[i]*secret[i+16]
s.add(a==4096)
idx2 = 0
while (True):
if s.check() == sat:
m = s.model()
answer = []
for i in secret:
answer.append(m[i].as_long())
# print("ANSWER {}: {}".format(idx2, answer))
print (answer)
# print (idx2)
idx2 += 1
# secret_value = answer[6]
# s.add(secret[6] != secret_value)
else:
print (unsat)
break
Cuối cùng chúng mình đã quyết định bruteforce secret
Sau khi reverse hàm transpose
mình nhận thấy hàm thực hiện chức năng giống transpose matrix với size là 2 tham số được truyền vào ngay sau (enc, row, column)
Script để brutefoce của mình:
import numpy as np
fib = [0 for i in range(4096)]
fib[0] = 0
fib[1] = 1
for i in range(2, 4096):
fib[i] = (fib[i-1] + fib[i-2]) & 0xff
with open("./out.enc", "rb") as fp:
enc_data = list(fp.read())
fp.close()
def reverse(begin, row, column):
arr = enc_data[begin:begin+row*column]
# print (arr)
B = np.array(arr).reshape(row, column)
# print (B)
C = np.transpose(B)
# print (C)
out = np.array(C).reshape(1, row*column) # (row, column)
# print (out)
#### part2
# print ("-----------------------------------------------")
idx = begin
out2 = []
const = 0x636F7468616E
while (idx < begin+row*column):
tmp_idx = (idx%47+1)
# if tmp_idx == 47:
# tmp1 = const >>
# else:
tmp1 = const >> tmp_idx
# print (idx%47+1)
tmp = tmp1^fib[idx]^out[0][idx-begin]
out2.append(tmp&0xff)
idx += 1
# print (out2)
print (bytearray(out2))
with open("out_test.bin", "wb") as ot:
ot.write(bytearray(out2))
ot.close()
'''
--> brute 4 pairs of secretkeys
reverse(0, 5, 13)
reverse(5*13, 20, 11)
curr = 5*13+20*11
reverse(curr, 25, 25)
#################################
curr += 25*25
reverse(curr, 20, 16)
#################################
curr += 20*16
reverse(curr, 25, 28)
#
'''
test[6], test[6+16] = 19, 27
test[7], test[7+16] = 24, 7
test[8], test[8+16] = 11, 28
test[9], test[9+16] = 11, 20
test[10], test[10+16] = 10, 20
for ii in range(29):
test[11] = ii
for j in range(29):
test[11+16] = j
curr = 0
print("********************** TRY TEST {} ******************".format(idx_test))
for i in range(16):
print("KEY: {} {}".format(test[i], test[i+16]))
try:
reverse(curr, test[i], test[i+16])
curr += test[i]*test[i+16]
except:
print("FAILED: " + str(idx_test))
break
print("********************** END TEST {} ******************".format(idx_test))
idx_test += 1
# ISITDTU{The_algorithm_is_inplace_matrix_transpose_do_you_know_that?}
Chúng mình nhận ra bài này là một bài trên wiki:
Vừa bruteforce vừa kết hợp với wiki, với chỉ cần 8 cặp key là mình có thể lấy đc flag nên ko tính là lâu lắm
Introduction Last weekend, I played realworld CTF with VAT team and we got the great ranking. My teammates are so strong tho. This blog post will explain some challenges that we can or can not solve in this CTF, but after it ended, I read some write-ups and want to note the knowledge I learned. Thank you guys so much. NonHeavyFTP This challenge uses the opensource of lightFTP in github. We heared about this protocol before but until now we still don't know how to the protocol work? So we will explain some information about it before dig deeper to the challenge. Protocol overview FTP is a client-server protocol that relies on two communications between the client and server: a command channel for controlling the conversation and a data channel for transmitting file content. FTP may run in active or passive mode, which determines how the data connection is established
Jan 13, 2023Today, Elliptic Curve Cryptography (ECC) appears in TSL, SSL, PGP, and many other things including Bitcoin and Blockchain. The Goal (My application is based on C language, but in the blog I will explain ECC in Python language to skip bignum part.) I explain how I applied ECC algorithm on secure transmission channel from server to client. I used Elliptic Curve Diffie-Hellman (ECDH) key exchange to generate keys for Advanced Encryption Standard (AES). That key used to encrypt the data exchanged between the client and the server. In addition, I use of Elliptic Curve Digital Signature Algorithm (ECDSA) as a authentication mechanism. ECC Over Finite Fields GF(p)
Dec 13, 2022Rolling At the first time, we spent a lot of time to try run blow script (using dlopen, aarch64 simulation) but it's segfaulted all times 😢 #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> #include <unistd.h> int main() {
Dec 13, 2022Sơ qua về binary Chương trình cho trước địa chỉ của PIE puts("I have some gift for you ^^"); return puts((const char *)&retaddr); sau đó chương trình đi vào 1 vòng while thực hiện chức năng thêm note vào 1 chuỗi linked-list, và handle chuỗi đó theo 2 kiểu( htb hoặc bth nhưng khi exploit mình chỉ cần dùng mỗi htb và chưa hiểu bth dùng để làm gì) __int64 __fastcall route(Note *note)
Oct 21, 2022or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up