Created
September 2, 2024 10:50
-
-
Save realazizk/cdd9add44de5780a129420c3c67ce2b4 to your computer and use it in GitHub Desktop.
bhmea quals rev
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
1. unpack Jscript code | |
2. brute force random key | |
*/ | |
#include <windows.h> | |
#include <wincrypt.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <iostream> | |
#include <string> | |
#include <iomanip> | |
#define MD5_DIGEST_LENGTH 16 | |
#define AES_BLOCK_SIZE 16 | |
void PrintHex(BYTE* data, DWORD dataLen) { | |
for (DWORD i = 0; i < dataLen; i++) { | |
printf("%02x", data[i]); | |
} | |
printf("\n"); | |
} | |
void PrintErrorMessage(DWORD dwError) | |
{ | |
char* messageBuffer = NULL; | |
FormatMessageA( | |
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, | |
NULL, | |
dwError, | |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | |
(LPSTR)&messageBuffer, | |
0, | |
NULL | |
); | |
if (messageBuffer != NULL) | |
{ | |
printf("Error: %s\n", messageBuffer); | |
LocalFree(messageBuffer); | |
} | |
else | |
{ | |
printf("Error code: %d\n", dwError); | |
} | |
} | |
int main() { | |
HCRYPTPROV hProv = 0; | |
HCRYPTHASH hHash = 0; | |
HCRYPTKEY hKey = 0; | |
BYTE ciphertext[] = { | |
0x73, 0xE3, 0x67, 0x95, 0x07, 0xCC, 0x81, 0x97, 0xF6, 0x65, 0xFD, 0x5B, 0x46, 0xF5, 0x53, 0x21, | |
0xCF, 0x89, 0xBB, 0x82, 0x8C, 0xD7, 0xBB, 0x42, 0x4B, 0x18, 0x17, 0x34, 0xD4, 0x68, 0x70, 0x97, | |
0x09, 0xD4, 0x90, 0x85, 0x86, 0x8C, 0xDA, 0x1B, 0x98, 0x92, 0xB9, 0x47, 0x99, 0x9E, 0x4F, 0x64 | |
}; | |
DWORD cipherLen = sizeof(ciphertext); | |
BYTE* plaintext = NULL; | |
DWORD plaintextLen = cipherLen; | |
char pbData[9]; | |
const char* expectedPrefix = "BHFlagY"; | |
size_t expectedPrefixLen = strlen(expectedPrefix); | |
if (!CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV_A, PROV_RSA_AES, 0)) { | |
PrintErrorMessage(GetLastError()); | |
return 1; | |
} | |
for (int i = 0; i <= 99999999; i++) { | |
sprintf_s(pbData, "%08d", i); | |
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { | |
PrintErrorMessage(GetLastError()); | |
CryptReleaseContext(hProv, 0); | |
return 1; | |
} | |
if (!CryptHashData(hHash, (BYTE*)pbData, 8, 0)) { | |
PrintErrorMessage(GetLastError()); | |
CryptDestroyHash(hHash); | |
continue; | |
} | |
if (!CryptDeriveKey(hProv, CALG_AES_128, hHash, 0, &hKey)) { | |
PrintErrorMessage(GetLastError()); | |
CryptDestroyHash(hHash); | |
continue; | |
} | |
plaintext = (BYTE*)malloc(plaintextLen); | |
if (!plaintext) { | |
printf("Memory allocation failed\n"); | |
CryptDestroyKey(hKey); | |
CryptDestroyHash(hHash); | |
CryptReleaseContext(hProv, 0); | |
return 1; | |
} | |
memcpy(plaintext, ciphertext, cipherLen); | |
DWORD tempLen = plaintextLen; | |
if (CryptDecrypt(hKey, 0, TRUE, 0, plaintext, &tempLen)) { | |
if (tempLen >= expectedPrefixLen && memcmp(plaintext, expectedPrefix, expectedPrefixLen) == 0) { | |
printf("Possible key: %s\n", pbData); | |
printf("Decrypted data: "); | |
PrintHex(plaintext, tempLen); | |
printf("As text: %.*s\n", tempLen, plaintext); | |
free(plaintext); | |
break; | |
} | |
} | |
free(plaintext); | |
CryptDestroyKey(hKey); | |
CryptDestroyHash(hHash); | |
} | |
CryptReleaseContext(hProv, 0); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
1. unpack using binwalk | |
2. decompress zlib files | |
3. readRDS the files will print decompiled bytecode in R studio | |
4. solve constraints with z3 | |
""" | |
""" | |
function () | |
{ | |
if (exists("flag", envir = .GlobalEnv)) { | |
flag_value <- get("flag", envir = .GlobalEnv) | |
if (is.character(flag_value)) { | |
xor_key <- "BHMEAISTHEBESTCTFEVERBETTERTHANALLOFTHEOTHERCTF" | |
key_length <- nchar(xor_key) | |
flag_length <- nchar(flag_value) | |
if (flag_length != key_length) { | |
xor_key <- substr(rep(xor_key, length.out = ceiling(flag_length/key_length)), | |
1, flag_length) | |
} | |
xor_result <- sapply(1:flag_length, function(i) { | |
flag_char <- substr(flag_value, i, i) | |
key_char <- substr(xor_key, i, i) | |
int_val <- as.integer(charToRaw(flag_char)) | |
xor_val <- as.integer(charToRaw(key_char)) | |
xored_val <- bitwXor(int_val, xor_val) | |
as.raw(xored_val) | |
}) | |
return(paste0(xor_result, collapse = "")) | |
} | |
} | |
else { | |
system("echo 'try better next time'") | |
} | |
} | |
function () | |
{ | |
flag <- get_flag_or_die() | |
x <- 9 | |
delayedAssign("y", x) | |
x <- x * (x - 5 + 4 + 6 - 3 - 2 - 3 - 6) | |
as.integer(substr(flag, 1, 1)) == y | |
} | |
""" | |
import z3 | |
# Create a solver | |
solver = z3.Solver() | |
# Create a string of 94 characters (assuming the flag length is 94 based on the constraints) | |
flag = [z3.BitVec(f"flag_{i + 1}", 32) for i in range(94)] | |
flag = [None, *flag] | |
def substr(x, y): | |
z = 0 | |
m = 1 | |
for i in list(range(x, y + 1))[::-1]: | |
z += flag[i] * m | |
m *= 10 | |
return z | |
# Add constraints for printable ASCII characters | |
for char in flag: | |
if char is None: | |
continue | |
# check hexadicmal range | |
solver.add(char >= 0, char <= 0xF) | |
pass | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
val_1 <- as.integer(substr(flag, 51, 51)) | |
val_2 <- as.integer(substr(flag, 22, 22)) | |
(val_1 - val_2) == 1 | |
} | |
""" | |
solver.add(substr(51, 51) - substr(22, 22) == 1) | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
val_1 <- substr(flag, 14, 14) | |
val_2 <- substr(flag, 18, 18) | |
val_3 <- substr(flag, 24, 24) | |
val_4 <- substr(flag, 32, 32) | |
val_5 <- substr(flag, 36, 36) | |
val_6 <- substr(flag, 62, 62) | |
(val_1 == val_2) & (val_1 == "a") & (val_1 == val_3) & (val_3 == | |
val_4) & (val_5 == val_4) & (val_6 == val_5) | |
} | |
""" | |
solver.add(substr(14, 14) == substr(18, 18)) | |
solver.add(substr(14, 14) == 0xA) | |
solver.add(substr(14, 14) == substr(24, 24)) | |
solver.add(substr(24, 24) == substr(32, 32)) | |
solver.add(substr(36, 36) == substr(32, 32)) | |
solver.add(substr(62, 62) == substr(36, 36)) | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
val_1 <- substr(flag, 16, 16) | |
val_2 <- substr(flag, 30, 30) | |
(val_1 == val_2) & (val_1 == "f") | |
} | |
""" | |
solver.add(substr(16, 16) == substr(30, 30)) | |
solver.add(substr(16, 16) == 0xF) | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
val_1 <- substr(flag, 51, 51) | |
val_2 <- substr(flag, 59, 59) | |
val_3 <- substr(flag, 63, 63) | |
val_4 <- substr(flag, 65, 65) | |
val_5 <- substr(flag, 77, 77) | |
val_6 <- substr(flag, 91, 91) | |
(val_1 == val_2) & (val_1 == val_3) & (val_1 == val_4) & | |
(val_1 == val_5) & (val_1 == val_6) | |
} | |
""" | |
solver.add(substr(51, 51) == substr(59, 59)) | |
solver.add(substr(51, 51) == substr(63, 63)) | |
solver.add(substr(51, 51) == substr(65, 65)) | |
solver.add(substr(51, 51) == substr(77, 77)) | |
solver.add(substr(51, 51) == substr(91, 91)) | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
val_1 <- substr(flag, 54, 54) | |
val_2 <- substr(flag, 84, 84) | |
val_3 <- substr(flag, 12, 12) | |
(val_1 == val_2) & (val_1 == "e") & (val_1 == val_3) | |
} | |
""" | |
solver.add(substr(54, 54) == substr(84, 84)) | |
solver.add(substr(54, 54) == 0xE) | |
solver.add(substr(84, 84) == substr(12, 12)) | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
val_1 <- substr(flag, 72, 72) | |
val_2 <- substr(flag, 92, 92) | |
val_3 <- substr(flag, 26, 26) | |
val_4 <- substr(flag, 34, 34) | |
val_5 <- substr(flag, 60, 60) | |
(val_1 == val_2) & (val_1 == val_3) & (val_1 == val_4) & | |
(val_1 == val_5) | |
} | |
""" | |
solver.add(substr(72, 72) == substr(92, 92)) | |
solver.add(substr(72, 72) == substr(26, 26)) | |
solver.add(substr(72, 72) == substr(34, 34)) | |
solver.add(substr(72, 72) == substr(60, 60)) | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
val_1 <- substr(flag, 17, 17) | |
val_2 <- substr(flag, 23, 23) | |
val_3 <- substr(flag, 28, 28) | |
val_4 <- substr(flag, 35, 35) | |
val_5 <- substr(flag, 37, 37) | |
val_6 <- substr(flag, 43, 43) | |
val_7 <- substr(flag, 44, 44) | |
val_8 <- substr(flag, 52, 52) | |
val_9 <- substr(flag, 69, 69) | |
val_10 <- substr(flag, 74, 74) | |
(val_1 == val_2) & (val_1 == val_3) & (val_1 == val_4) & | |
(val_1 == val_5) & (val_1 == val_6) & (val_1 == val_7) & | |
(val_1 == val_8) & (val_1 == val_9) & (val_1 == val_10) | |
} | |
""" | |
solver.add(substr(17, 17) == substr(23, 23)) | |
solver.add(substr(17, 17) == substr(28, 28)) | |
solver.add(substr(17, 17) == substr(35, 35)) | |
solver.add(substr(17, 17) == substr(37, 37)) | |
solver.add(substr(17, 17) == substr(43, 43)) | |
solver.add(substr(17, 17) == substr(44, 44)) | |
solver.add(substr(17, 17) == substr(52, 52)) | |
solver.add(substr(17, 17) == substr(69, 69)) | |
solver.add(substr(17, 17) == substr(74, 74)) | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
val_1 <- substr(flag, 22, 22) | |
val_2 <- substr(flag, 48, 48) | |
val_3 <- substr(flag, 78, 78) | |
val_4 <- substr(flag, 89, 89) | |
(val_1 == val_2) & (val_1 == val_3) & (val_1 == val_4) | |
} | |
""" | |
solver.add(substr(22, 22) == substr(48, 48)) | |
solver.add(substr(22, 22) == substr(78, 78)) | |
solver.add(substr(22, 22) == substr(89, 89)) | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
val_1 <- as.integer(substr(flag, 17, 17)) | |
val_2 <- as.integer(substr(flag, 87, 87)) | |
(val_1 - val_2) == -2 | |
} | |
""" | |
solver.add(substr(17, 17) - substr(87, 87) == -2) | |
""" | |
function check_val_11(index, val) | |
{ | |
flag <- get_flag_or_die() | |
val_1 <- substr(flag, index, index) | |
val_1 == val | |
} | |
check_val_11(76, "8") & | |
check_val_11(93, "3") & | |
check_val_11(13, "0") & | |
check_val_11(26, "5") & | |
check_val_11(87, "3") & | |
check_val_11(88, "c") & | |
check_val_11(81, "0") & | |
check_val_11(86, "0") & | |
check_val_11(17, "1") & | |
check_val_11(18, "a") & | |
check_val_11(19, "2") & | |
check_val_11(20, "b") & | |
check_val_11(31, "3") & | |
check_val_11(44, "1") & | |
check_val_11(49, "3") & | |
check_val_11(55, "3") & | |
check_val_11(44, "1") & | |
check_val_11(45, "2") & | |
check_val_11(39, "2") & | |
check_val_11(58, "2") & | |
check_val_11(66, "c") | |
""" | |
solver.add(substr(76, 76) == 0x8) | |
solver.add(substr(93, 93) == 0x3) | |
solver.add(substr(13, 13) == 0x0) | |
solver.add(substr(26, 26) == 0x5) | |
solver.add(substr(87, 87) == 0x3) | |
solver.add(substr(88, 88) == 0xC) | |
solver.add(substr(81, 81) == 0x0) | |
solver.add(substr(86, 86) == 0x0) | |
solver.add(substr(17, 17) == 0x1) | |
solver.add(substr(18, 18) == 0xA) | |
solver.add(substr(19, 19) == 0x2) | |
solver.add(substr(20, 20) == 0xB) | |
solver.add(substr(31, 31) == 0x3) | |
solver.add(substr(44, 44) == 0x1) | |
solver.add(substr(49, 49) == 0x3) | |
solver.add(substr(55, 55) == 0x3) | |
solver.add(substr(44, 44) == 0x1) | |
solver.add(substr(45, 45) == 0x2) | |
solver.add(substr(39, 39) == 0x2) | |
solver.add(substr(58, 58) == 0x2) | |
solver.add(substr(66, 66) == 0xC) | |
""" | |
(substr(get_flag_or_die(), 6, 6) == "b") & | |
""" | |
solver.add(substr(6, 6) == 0xB) | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
val_1 <- as.integer(substr(flag, 7, 8)) | |
val_2 <- as.integer(substr(flag, 9, 10)) | |
val_3 <- as.integer(substr(flag, 89, 91)) | |
val_4 <- as.integer(substr(flag, 92, 93)) | |
((val_1 - val_2) == 9) & ((val_3 + val_4) == 680) | |
} | |
""" | |
solver.add((substr(7, 8) - substr(9, 10)) == 9) | |
solver.add((substr(89, 91) + substr(92, 93)) == 680) | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
as.integer(substr(flag, 7, 11)) == 29202 | |
} | |
""" | |
solver.add(substr(7, 11) == 29202) | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
as.integer(substr(flag, 25, 29)) == 25213 | |
} | |
""" | |
solver.add(substr(25, 29) == 25213) | |
""" | |
function check_val_6(index_0, index_1, val) | |
{ | |
flag <- get_flag_or_die() | |
as.integer(substr(flag, index_0, index_1)) == val | |
} | |
check_val_6(67, 71, 22103) & | |
check_val_6(72, 76, 50138) & | |
check_val_6(37, 41, 19230) & | |
check_val_6(43, 47, 11202) & | |
""" | |
solver.add(substr(67, 71) == 22103) | |
solver.add(substr(72, 76) == 50138) | |
solver.add(substr(37, 41) == 19230) | |
solver.add(substr(43, 47) == 11202) | |
""" | |
check_val_6(77, 79, 763) & | |
check_val_6(85, 87, 303) & | |
check_val_6(59, 61, 753) & | |
check_val_6(39, 41, 230) & | |
check_val_6(21, 23, 361) & | |
check_val_6(51, 53, 713) & | |
check_val_6(33, 35, 351) & | |
check_val_6(45, 47, 202) & | |
check_val_6(63, 65, 707) & | |
""" | |
solver.add(substr(77, 79) == 763) | |
solver.add(substr(85, 87) == 303) | |
solver.add(substr(59, 61) == 753) | |
solver.add(substr(39, 41) == 230) | |
solver.add(substr(21, 23) == 361) | |
solver.add(substr(51, 53) == 713) | |
solver.add(substr(33, 35) == 351) | |
solver.add(substr(45, 47) == 202) | |
solver.add(substr(63, 65) == 707) | |
""" | |
function check_val_1(index_0, index_1, index_2) | |
{ | |
flag <- get_flag_or_die() | |
first_two <- substr(flag, index_0, index_0) == substr(flag, | |
index_1, index_1) | |
second_two <- substr(flag, index_1, index_1) == substr(flag, | |
index_2, index_2) | |
final <- all(first_two, second_two) | |
return(final) | |
} | |
function (flag) | |
{ | |
check_val_1(94, 82, 6) & | |
check_val_1(1, 86, 10) & | |
check_val_1(90, 83, 9) & | |
check_val_1(9, 11, 15) & | |
check_val_1(29, 61, 57) & | |
} | |
""" | |
def check_val_1(idx0, idx1, idx2): | |
return z3.And( | |
substr(idx0, idx0) == substr(idx1, idx1), | |
substr(idx1, idx1) == substr(idx2, idx2), | |
) | |
solver.add(check_val_1(94, 82, 6)) | |
solver.add(check_val_1(1, 86, 10)) | |
solver.add(check_val_1(90, 83, 9)) | |
solver.add(check_val_1(9, 11, 15)) | |
solver.add(check_val_1(29, 61, 57)) | |
""" | |
function () | |
{ | |
flag <- get_flag_or_die() | |
if (nchar(flag) < 5) { | |
return(FALSE) | |
} | |
first_five <- substr(flag, 1, 5) | |
all_same <- all(strsplit(first_five, "")[[1]] == substr(flag, | |
1, 1)) | |
return(all_same) | |
} | |
""" | |
solver.add(flag[1] == flag[2] == flag[3] == flag[4] == flag[5]) | |
final_flag = flag[1:] | |
hehe = [] | |
# Join the flag characters by two | |
for i in range(len(final_flag) // 2): | |
left = z3.Extract(4, 0, final_flag[i * 2]) | |
right = z3.Extract(4, 0, final_flag[i * 2 + 1]) | |
hehe.append( | |
(z3.ZeroExt(4, z3.Extract(4, 0, left)) << 4) | |
| z3.ZeroExt(4, z3.Extract(4, 0, right)) | |
) | |
ff = "BHMEAISTHEBESTCTFEVERBETTERTHANALLOFTHEOTHERCTF" | |
chars_to_include = ( | |
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&'./:<=>?@_{}|" | |
) | |
calcs = [] | |
for i, c in enumerate(hehe): | |
rezo = ord(ff[i]) ^ c | |
solver.add(z3.Or(*[ord(cc) == rezo for cc in chars_to_include])) | |
calcs.append(rezo) | |
solver.add(calcs[0] == ord("B")) | |
solver.add(calcs[1] == ord("H")) | |
solver.add(calcs[2] == ord("F")) | |
solver.add(calcs[3] == ord("l")) | |
solver.add(calcs[4] == ord("a")) | |
solver.add(calcs[5] == ord("g")) | |
solver.add(calcs[6] == ord("Y")) | |
solver.add(calcs[7] == ord("{")) | |
solver.add(calcs[39] == ord("r")) | |
solver.add(calcs[20] == ord("_")) | |
solver.add(calcs[33] == ord("n")) | |
solver.add( | |
z3.Or( | |
calcs[24] == ord("i"), | |
calcs[24] == ord("1"), | |
) | |
) | |
solver.add( | |
z3.Or( | |
calcs[27] == ord("i"), | |
calcs[27] == ord("1"), | |
) | |
) | |
# print(solver) | |
if solver.check() == z3.sat: | |
model = solver.model() | |
print(model) | |
flag_str = "".join([hex(model[flag[i]].as_long())[2:] for i in range(1, 95)]) | |
import binascii | |
print("Flag found:", flag_str) | |
x = binascii.unhexlify(flag_str) | |
for i, c in enumerate(x): | |
print(chr(c ^ ord(ff[i])), end="") | |
else: | |
print("No solution found") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment