solved connivance
This commit is contained in:
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<FILE_INFO>
|
|
||||||
<BASIC_INFO>
|
|
||||||
<STATE NAME="CONTENT_TYPE" TYPE="string" VALUE="Program" />
|
|
||||||
<STATE NAME="PARENT" TYPE="string" VALUE="/" />
|
|
||||||
<STATE NAME="FILE_ID" TYPE="string" VALUE="a4afa9f9d3f559841602854" />
|
|
||||||
<STATE NAME="FILE_TYPE" TYPE="int" VALUE="0" />
|
|
||||||
<STATE NAME="READ_ONLY" TYPE="boolean" VALUE="false" />
|
|
||||||
<STATE NAME="NAME" TYPE="string" VALUE="main" />
|
|
||||||
</BASIC_INFO>
|
|
||||||
</FILE_INFO>
|
|
||||||
Binary file not shown.
@@ -1,4 +0,0 @@
|
|||||||
VERSION=1
|
|
||||||
/
|
|
||||||
NEXT-ID:0
|
|
||||||
MD5:d41d8cd98f00b204e9800998ecf8427e
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
VERSION=1
|
|
||||||
/
|
|
||||||
00000000:main:a4afa9f9d3f559841602854
|
|
||||||
NEXT-ID:1
|
|
||||||
MD5:d41d8cd98f00b204e9800998ecf8427e
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
IADD:00000000:/main
|
|
||||||
IDSET:/main:a4afa9f9d3f559841602854
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<FILE_INFO>
|
|
||||||
<BASIC_INFO>
|
|
||||||
<STATE NAME="OWNER" TYPE="string" VALUE="cato" />
|
|
||||||
</BASIC_INFO>
|
|
||||||
</FILE_INFO>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<PROJECT>
|
|
||||||
<PROJECT_DATA_XML_NAME NAME="DISPLAY_DATA">
|
|
||||||
<SAVE_STATE>
|
|
||||||
<ARRAY NAME="EXPANDED_PATHS" TYPE="string">
|
|
||||||
<A VALUE="CSCG-Connivance:" />
|
|
||||||
</ARRAY>
|
|
||||||
<STATE NAME="SHOW_TABLE" TYPE="boolean" VALUE="false" />
|
|
||||||
</SAVE_STATE>
|
|
||||||
</PROJECT_DATA_XML_NAME>
|
|
||||||
<TOOL_MANAGER ACTIVE_WORKSPACE="Workspace">
|
|
||||||
<WORKSPACE NAME="Workspace" ACTIVE="true" />
|
|
||||||
</TOOL_MANAGER>
|
|
||||||
</PROJECT>
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<FILE_INFO>
|
|
||||||
<BASIC_INFO>
|
|
||||||
<STATE NAME="CONTENT_TYPE" TYPE="string" VALUE="ProgramUserData" />
|
|
||||||
<STATE NAME="PARENT" TYPE="string" VALUE="/" />
|
|
||||||
<STATE NAME="FILE_ID" TYPE="string" VALUE="a4afa9fa5e11707875609740" />
|
|
||||||
<STATE NAME="FILE_TYPE" TYPE="int" VALUE="0" />
|
|
||||||
<STATE NAME="READ_ONLY" TYPE="boolean" VALUE="false" />
|
|
||||||
<STATE NAME="NAME" TYPE="string" VALUE="udf_a4afa9f9d3f559841602854" />
|
|
||||||
</BASIC_INFO>
|
|
||||||
</FILE_INFO>
|
|
||||||
Binary file not shown.
@@ -1,4 +0,0 @@
|
|||||||
VERSION=1
|
|
||||||
/
|
|
||||||
NEXT-ID:0
|
|
||||||
MD5:d41d8cd98f00b204e9800998ecf8427e
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
IADD:00000000:/udf_a4afa9f9d3f559841602854
|
|
||||||
IDSET:/udf_a4afa9f9d3f559841602854:a4afa9fa5e11707875609740
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
VERSION=1
|
|
||||||
/
|
|
||||||
NEXT-ID:0
|
|
||||||
MD5:d41d8cd98f00b204e9800998ecf8427e
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
VERSION=1
|
|
||||||
/
|
|
||||||
NEXT-ID:0
|
|
||||||
MD5:d41d8cd98f00b204e9800998ecf8427e
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import idc
|
|
||||||
import struct
|
|
||||||
|
|
||||||
addr = here() # or replace with the actual address e.g. 0x47F240
|
|
||||||
|
|
||||||
data = bytes([idc.get_wide_byte(addr + i) for i in range(39)])
|
|
||||||
flag = idc.get_wide_byte(addr + 39)
|
|
||||||
key = idc.get_qword(addr + 40)
|
|
||||||
|
|
||||||
print(f"Data: {data.hex()}")
|
|
||||||
print(f"Decrypted: {flag}")
|
|
||||||
print(f"Key: {key:#018x}")
|
|
||||||
|
|
||||||
# Decrypt it immediately
|
|
||||||
decrypted = bytes(~(b ^ ((key >> (8 * (i % 8))) & 0xFF)) & 0xFF for i, b in enumerate(data))
|
|
||||||
print(f"Plaintext: {decrypted}")
|
|
||||||
print(f"As string: {decrypted.decode('utf-8', errors='replace')}")
|
|
||||||
Binary file not shown.
Binary file not shown.
BIN
2026/cscg/rev/connivance/decrypted_connviance.bin
Normal file
BIN
2026/cscg/rev/connivance/decrypted_connviance.bin
Normal file
Binary file not shown.
Binary file not shown.
@@ -1,12 +0,0 @@
|
|||||||
break *0x4035da
|
|
||||||
run flag_checker.tfl AAAA
|
|
||||||
printf "sub_410450 result: %d\n", $r15b
|
|
||||||
set $r15b = 0
|
|
||||||
break *0x40365e
|
|
||||||
continue
|
|
||||||
printf "At main VM call\n"
|
|
||||||
set $wrapper = *(long long*)$rsi
|
|
||||||
set $bc_base = *(long long*)($wrapper+0x10)
|
|
||||||
set $bc_size = *(long long*)($wrapper+0x18)
|
|
||||||
printf "bc_base=%p size=%d\n", $bc_base, $bc_size
|
|
||||||
dump binary memory /tmp/bc_main.bin $bc_base ($bc_base+$bc_size)
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
break *0x40356f
|
|
||||||
run flag_checker.tfl AAAA
|
|
||||||
set $eax = 0
|
|
||||||
break *0x40365e
|
|
||||||
continue
|
|
||||||
printf "At main sub_405120 call\n"
|
|
||||||
set $wrapper = *(long long*)$rsi
|
|
||||||
set $bc_base = *(long long*)($wrapper+0x10)
|
|
||||||
set $bc_size = *(long long*)($wrapper+0x18)
|
|
||||||
printf "bc_base=%p size=%d\n", $bc_base, $bc_size
|
|
||||||
dump binary memory /tmp/bc_main.bin $bc_base ($bc_base+$bc_size)
|
|
||||||
66
2026/cscg/rev/connivance/find_flag.py
Normal file
66
2026/cscg/rev/connivance/find_flag.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import hashlib
|
||||||
|
|
||||||
|
def bitwise_not(data: bytes) -> bytes:
|
||||||
|
"""Inverts all bits in the byte array."""
|
||||||
|
return bytes(~b & 0xFF for b in data)
|
||||||
|
|
||||||
|
def shift_right_1(data: bytes) -> bytes:
|
||||||
|
"""
|
||||||
|
Shifts the entire byte array to the right by 1 bit.
|
||||||
|
Note: This implementation assumes a forward-flowing carry (byte 0 to byte N).
|
||||||
|
If the VM's BigInt implementation is little-endian, you might need to reverse
|
||||||
|
the carry logic so it flows from index i+1 to i.
|
||||||
|
"""
|
||||||
|
result = bytearray(len(data))
|
||||||
|
carry = 0
|
||||||
|
|
||||||
|
for i in range(len(data)):
|
||||||
|
# Shift current byte right by 1, and OR it with the carry from the previous byte
|
||||||
|
result[i] = (data[i] >> 1) | carry
|
||||||
|
# The lowest bit of the current byte becomes the MSB carry for the next byte
|
||||||
|
carry = (data[i] & 1) << 7
|
||||||
|
|
||||||
|
return bytes(result)
|
||||||
|
|
||||||
|
def check_flag(test_flag: bytes, target_hash_blob: bytes) -> bool:
|
||||||
|
"""Simulates the VM's flag verification logic."""
|
||||||
|
# 1. Length Check
|
||||||
|
if len(test_flag) != 29:
|
||||||
|
print(f"[-] Incorrect length: {len(test_flag)}. Must be 29 bytes.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 2. Initial Mutation (BITWISE_NOT)
|
||||||
|
current_state = bitwise_not(test_flag)
|
||||||
|
|
||||||
|
# 3. The Shift-and-Hash Loop
|
||||||
|
generated_blob = bytearray()
|
||||||
|
|
||||||
|
for iteration in range(8):
|
||||||
|
# Compute SHA256 of the current state
|
||||||
|
current_hash = hashlib.sha256(current_state).digest()
|
||||||
|
generated_blob.extend(current_hash)
|
||||||
|
|
||||||
|
# Shift the state right by 1 bit for the next iteration
|
||||||
|
current_state = shift_right_1(current_state)
|
||||||
|
|
||||||
|
# 4. Final Verification
|
||||||
|
if generated_blob == target_hash_blob:
|
||||||
|
print("[+] Correct! Flag matches.")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("[-] Incorrect! Hash mismatch.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# Example Usage
|
||||||
|
# ==========================================
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# TODO: Load the actual 256-byte target blob from 'romfs:/dragonfly.bin'
|
||||||
|
# Here is a dummy 256-byte array for testing the script structure
|
||||||
|
with open("./romfs/damocles.bin", "rb") as flag_hash:
|
||||||
|
dragonfly_bin_data = flag_hash.read()
|
||||||
|
|
||||||
|
# The flag you want to test
|
||||||
|
my_test_flag = b"dach2026{dummy_test_flag_pay}" # Exactly 29 bytes
|
||||||
|
|
||||||
|
check_flag(my_test_flag, dragonfly_bin_data)
|
||||||
BIN
2026/cscg/rev/connivance/flag_checker.bin
Normal file
BIN
2026/cscg/rev/connivance/flag_checker.bin
Normal file
Binary file not shown.
BIN
2026/cscg/rev/connivance/flag_checker_after.bin
Normal file
BIN
2026/cscg/rev/connivance/flag_checker_after.bin
Normal file
Binary file not shown.
BIN
2026/cscg/rev/connivance/flag_checker_before.bin
Normal file
BIN
2026/cscg/rev/connivance/flag_checker_before.bin
Normal file
Binary file not shown.
35
2026/cscg/rev/connivance/generate_fake_dragonfly.py
Normal file
35
2026/cscg/rev/connivance/generate_fake_dragonfly.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import hashlib
|
||||||
|
|
||||||
|
def buggy_shift_right_1(data: bytes) -> bytes:
|
||||||
|
"""Replicates the VM's flawed, per-byte shift that ignores carries."""
|
||||||
|
return bytes(b >> 1 for b in data)
|
||||||
|
|
||||||
|
def bitwise_not(data: bytes) -> bytes:
|
||||||
|
"""Inverts all bits in the byte array."""
|
||||||
|
return bytes(~b & 0xFF for b in data)
|
||||||
|
|
||||||
|
def generate_dragonfly(flag: bytes) -> bytes:
|
||||||
|
assert len(flag) == 29, "Flag must be exactly 29 bytes!"
|
||||||
|
|
||||||
|
current_state = bitwise_not(flag)
|
||||||
|
out_blob = bytearray()
|
||||||
|
|
||||||
|
# 8 iterations: hash, then shift
|
||||||
|
for _ in range(8):
|
||||||
|
out_blob.extend(hashlib.sha256(current_state).digest())
|
||||||
|
current_state = buggy_shift_right_1(current_state)
|
||||||
|
|
||||||
|
return bytes(out_blob)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# A test flag that matches your 29-byte requirement and format
|
||||||
|
# 9 byte prefix + 19 byte payload + 1 byte suffix = 29 bytes
|
||||||
|
test_flag = b"dach2026{0123456789abcdefgh!}"
|
||||||
|
|
||||||
|
blob = generate_dragonfly(test_flag)
|
||||||
|
|
||||||
|
with open("dragonfly.bin", "wb") as f:
|
||||||
|
f.write(blob)
|
||||||
|
|
||||||
|
print(f"[+] Wrote {len(blob)} bytes to dragonfly.bin")
|
||||||
|
print("[!] Swap this file into the VM environment and test it.")
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
break *0x40356f
|
|
||||||
run flag_checker.tfl AAAA
|
|
||||||
set $eax = 0
|
|
||||||
break *0x404010
|
|
||||||
commands 2
|
|
||||||
printf "HASH pc=%lld\n", *(long long*)$rdx
|
|
||||||
continue
|
|
||||||
end
|
|
||||||
continue
|
|
||||||
BIN
2026/cscg/rev/connivance/hello_world.bin
Normal file
BIN
2026/cscg/rev/connivance/hello_world.bin
Normal file
Binary file not shown.
BIN
2026/cscg/rev/connivance/input.bin
Normal file
BIN
2026/cscg/rev/connivance/input.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
93
2026/cscg/rev/connivance/recover_flag.py
Normal file
93
2026/cscg/rev/connivance/recover_flag.py
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import hashlib
|
||||||
|
import time
|
||||||
|
|
||||||
|
def solve_flag(target_blob: bytes):
|
||||||
|
"""
|
||||||
|
Reverses the 8-stage hashing loop by walking backwards from the 7th shift
|
||||||
|
down to the 0th shift, recovering 1 bit of the flag per iteration.
|
||||||
|
"""
|
||||||
|
# 1. Setup Known Constraints
|
||||||
|
known_prefix = b"dach2026{"
|
||||||
|
known_suffix = b"}"
|
||||||
|
total_len = 29
|
||||||
|
|
||||||
|
# Calculate indices for the 19 unknown characters
|
||||||
|
unknown_indices = list(range(len(known_prefix), total_len - len(known_suffix)))
|
||||||
|
|
||||||
|
# Pre-calculate the bitwise NOT of the known parts
|
||||||
|
full_known_state = bytearray(total_len)
|
||||||
|
for i, b in enumerate(known_prefix):
|
||||||
|
full_known_state[i] = ~b & 0xFF
|
||||||
|
full_known_state[total_len - 1] = ~known_suffix[0] & 0xFF
|
||||||
|
|
||||||
|
# Split the target blob into the 8 independent target hashes
|
||||||
|
target_hashes = set(target_blob[i*32 : (i+1)*32] for i in range(8))
|
||||||
|
|
||||||
|
# This array will accumulate our recovered bits for the 19 unknown bytes
|
||||||
|
# By the end, it will contain the fully unshifted, inverted bytes.
|
||||||
|
recovered_unknowns = [0] * len(unknown_indices)
|
||||||
|
|
||||||
|
print("[*] Starting Bit-by-Bit Backtracking Attack...")
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
# 2. Walk backwards from Shift 7 down to Shift 0
|
||||||
|
for shift_amount in range(7, -1, -1):
|
||||||
|
print(f"\n[*] Cracking Shift Layer {shift_amount} (Guessing bit {shift_amount} of payload)...")
|
||||||
|
|
||||||
|
# Pre-build the known parts of the state for this specific shift layer
|
||||||
|
base_state = bytearray(total_len)
|
||||||
|
for i in range(total_len):
|
||||||
|
if i < len(known_prefix) or i == total_len - 1:
|
||||||
|
base_state[i] = full_known_state[i] >> shift_amount
|
||||||
|
|
||||||
|
match_found = False
|
||||||
|
|
||||||
|
# Brute-force the next bit for all 19 unknown bytes (2^19 combinations = 524,288)
|
||||||
|
# This takes a few seconds per layer in pure Python.
|
||||||
|
for guess in range(1 << len(unknown_indices)):
|
||||||
|
test_state = bytearray(base_state)
|
||||||
|
|
||||||
|
# Inject our guessed bits into the test state
|
||||||
|
for i, idx in enumerate(unknown_indices):
|
||||||
|
guess_bit = (guess >> i) & 1
|
||||||
|
test_state[idx] = (recovered_unknowns[i] << 1) | guess_bit
|
||||||
|
|
||||||
|
# Hash and check against the pool of valid target hashes
|
||||||
|
if hashlib.sha256(test_state).digest() in target_hashes:
|
||||||
|
print(f" [+] Match found! Extracted bits: {bin(guess)[2:].zfill(19)}")
|
||||||
|
|
||||||
|
# Commit the guessed bits to our recovered array
|
||||||
|
for i in range(len(unknown_indices)):
|
||||||
|
recovered_unknowns[i] = (recovered_unknowns[i] << 1) | ((guess >> i) & 1)
|
||||||
|
|
||||||
|
match_found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not match_found:
|
||||||
|
print(f" [-] CRITICAL FAILURE: Could not find a valid bit permutation at layer {shift_amount}.")
|
||||||
|
print(" Double check the dragonfly.bin data and prefix.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 3. Final Assembly
|
||||||
|
# We now have the complete, unshifted inverted state.
|
||||||
|
final_inverted_state = bytearray(full_known_state)
|
||||||
|
for i, idx in enumerate(unknown_indices):
|
||||||
|
final_inverted_state[idx] = recovered_unknowns[i]
|
||||||
|
|
||||||
|
# Un-invert it to reveal the plaintext flag
|
||||||
|
final_flag = bytes(~b & 0xFF for b in final_inverted_state)
|
||||||
|
|
||||||
|
elapsed = time.time() - start_time
|
||||||
|
print(f"\n[+] Exploit completed in {elapsed:.2f} seconds.")
|
||||||
|
print(f"[!] RECOVERED FLAG: {final_flag.decode('ascii', errors='ignore')}")
|
||||||
|
|
||||||
|
return final_flag
|
||||||
|
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# Execution / Test Mock
|
||||||
|
# ==========================================
|
||||||
|
if __name__ == "__main__":
|
||||||
|
with open("./romfs/dragonfly.bin", "rb") as f:
|
||||||
|
target_blob = f.read()
|
||||||
|
solve_flag(target_blob)
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
2026/cscg/rev/connivance/solve
Executable file
BIN
2026/cscg/rev/connivance/solve
Executable file
Binary file not shown.
97
2026/cscg/rev/connivance/solve.c
Normal file
97
2026/cscg/rev/connivance/solve.c
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
FILE *f = fopen("romfs/dragonfly.bin", "r");
|
||||||
|
if (!f) {
|
||||||
|
perror("Failed to open file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get file size
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long file_size = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
uint8_t *dragonfly = malloc(file_size);
|
||||||
|
if (!dragonfly) {
|
||||||
|
perror("malloc failed");
|
||||||
|
fclose(f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fread(dragonfly, 1, file_size, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
uint8_t flag[0x1d] = {0}; // 29 bytes
|
||||||
|
|
||||||
|
for (int i = 7; i >= 0; i--) {
|
||||||
|
uint8_t *target_hash = dragonfly + SHA256_DIGEST_LENGTH * (7 - i);
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
uint64_t max_n = 1ULL << sizeof(flag);
|
||||||
|
for (uint64_t n = 0; n < max_n; n++) {
|
||||||
|
uint64_t tmp = n;
|
||||||
|
for (int j = 0; j < sizeof(flag); j++) {
|
||||||
|
uint8_t bit = tmp & 1;
|
||||||
|
tmp >>= 1;
|
||||||
|
flag[j] = (flag[j] & 0xFE) | bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute SHA-256
|
||||||
|
uint8_t hash[SHA256_DIGEST_LENGTH];
|
||||||
|
SHA256(flag, sizeof(flag), hash);
|
||||||
|
|
||||||
|
if (memcmp(hash, target_hash, SHA256_DIGEST_LENGTH) == 0) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n % 1000000 == 0) {
|
||||||
|
printf("\r%09lu", n);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
if (!found) {
|
||||||
|
printf("Could not find it on level: %d\n", i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print flag in hex
|
||||||
|
for (int j = 0; j < sizeof(flag); j++) {
|
||||||
|
printf("%02x", flag[j]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// Shift left by 1
|
||||||
|
for (int j = 0; j < sizeof(flag); j++) {
|
||||||
|
flag[j] = (flag[j] << 1) & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print final flag
|
||||||
|
for (int j = 0; j < sizeof(flag); j++) {
|
||||||
|
printf("%02x", flag[j]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// Bitwise NOT
|
||||||
|
for (int j = 0; j < sizeof(flag); j++) {
|
||||||
|
flag[j] = (~flag[j]) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < sizeof(flag); j++) {
|
||||||
|
printf("%02x", flag[j]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("%s\n", flag);
|
||||||
|
|
||||||
|
free(dragonfly);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user