reverse, 100 points > Elderly File
We found some old encoded file and a program for encoding.
It seems that the solution will take the same amount of time.
Understand, it may turn out to decode the file.
*Download link*
@revker
There are encoder
ELF file and file.enc
.
Let’s open encoder
in IDA.
We can see MEIPASS
strings in the binary.
sub_403590(&s1);
v3 = (const char *)sub_404AA0("_MEIPASS2", v20);
j__unsetenv("_MEIPASS2");
v5 = &s1;
MEIPASS
is a magic for Pyinstaller files.
We have pyinstxtractor for this sort of binaries, bit it cannot work with ELF.
[*] Processing encoder
[*] Error : Unsupported pyinstaller version or not a pyinstaller archive
Hopefully, we can see that pyinstxtractor just cannot detect overlay.
Binwalk suggests us the start of ZLIB archives - 0x7a50
> binwalk encoder
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 ELF, 64-bit LSB executable, AMD x86-64, version 1 (SYSV)
31312 0x7A50 Zlib compressed data, best compression
31483 0x7AFB Zlib compressed data, best compression
...
Let’s help pyinstxtractor.py
to detect the overlay. I’ll use my diff-version
of pyinstxtractor (it solves some overlay fixes) in EXE-files.
And make additional change:
self.overlayPos = 0x7a50 # pe.get_overlay_data_start_offset()
The result is:
[*] Processing encoder
[*] Okay, two magic numbers, all right
[*] Pyinstaller version: 2.0
[*] Python version: 27
[*] Length of package: 4065226 bytes
[*] Found 25 files in CArchive
[*] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap
[+] Possible entry point: encoder
[!] Warning: The script is running in a different python version than the one used to build the executable
Run this script in Python27 to prevent extraction errors(if any) during unmarshalling
[*] Found 194 files in PYZ archive
[*] Successfully extracted pyinstaller archive: encoder
You can now use a python decompiler on the pyc files within the extracted directory
Yay, let’s use uncompyle6
on encoder
, but before this we need to recover
the magic of .pyc
. For python 2.7 it is 03 F3 0D 0A 00 00 00 00
.
# uncompyle6 version 3.3.5
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.5.2 (default, Oct 8 2019, 13:06:37)
# [GCC 5.4.0 20160609]
# Embedded file name: encoder.py
import lzss, sys
if __name__ == '__main__':
if len(sys.argv) > 1:
file_path = sys.argv[1]
else:
print 'Usage: ' + sys.argv[0] + ' <file-path>'
sys.exit(-1)
lzss.encode_file(file_path, file_path + '.enc')
# okay decompiling encoder.pyc
Fmm, it’s not a crypto, but compression. We got lzss.so
file while decompressing
the encoder
, let’s use them:
import lzss
lzss.decode_file("..//file.enc", "..//file.dec")
Opening file.dec, and…
:100000007F454C4601010100000000000000000097
:100010000300030001000000501000003400000045
:100020005838000000000000340020000B002800B9
:100030001E001D0006000000340000003400000017
:1000400034000000600100006001000004000000B6
:10005000040000000300000094010000940100006F
:1000600094010000130000001300000004000000D1
:10007000010000000100000000000000000000007E
:100080000000000098030000980300000400000036
...
It’s Intel HEX.
Rename file.dec
-> file.hex
, converting to regular
file using 010. The file is another ELF with hardcoded flag:
Aero{33d8b218a9961657b74c5036fe44527a02ce03c4da34f8a1cda5f2188c23a1b5}
reverse, 100 points > 1000 and 1 night
I wrote all this manually in 1000 and 1 night.
It seems that the solution will take the same amount of time.
After connecting to the server, it will ask you for a token for a binary.
You need to enter the correct tokens for the requested files and you will receive a flag.
nc tasks.aeroctf.com 44324
*Download link*
@revker
We have literally 1001 file, they differs only on constants of check function:
_BOOL8 __fastcall check(_BYTE *a1)
{
__int64 s2; // [rsp+10h] [rbp-30h]
__int64 v3; // [rsp+18h] [rbp-28h]
__int64 v4; // [rsp+20h] [rbp-20h]
__int64 v5; // [rsp+28h] [rbp-18h]
int i; // [rsp+3Ch] [rbp-4h]
s2 = 0x2673231825237276LL;
v3 = 0x2373262077182774LL;
v4 = 0x2025271873772577LL;
v5 = 0x2375232776217420LL;
for ( i = 0; i <= 31; ++i )
a1[i] = ((a1[i] + 7) ^ 0x17) - 8;
return memcmp(a1, &s2, 0x20uLL) == 0;
}
Okay, let’s parse them. I use yara engine + mkyara plugin for this kind of stuff:
rule parse
{
strings:
$chunk_1 = {
55
48 89 E5
48 83 EC 40
48 89 7D C8
48 B8 ?? ?? ?? ?? ?? ?? ?? ?? ; qw1 14-21
48 BA ?? ?? ?? ?? ?? ?? ?? ?? ; qw2 24-31
48 89 45 D0
48 89 55 D8
48 B8 ?? ?? ?? ?? ?? ?? ?? ?? ; qw3 ; 42-49
48 BA ?? ?? ?? ?? ?? ?? ?? ?? ; qw4 ; 52-69
48 89 45 ??
48 89 55 ??
C7 45 FC 00 00 00 00
EB ??
8B 45 ??
48 63 D0
48 8B 45 ??
48 01 D0
0F B6 00
83 C0 ?? ; add ; -10
83 F0 ?? ; xor ; -7
8D 48 ?? ; sub ; -4
8B 45 FC
}
condition:
any of them
}
There is my jupyter notebook to solve this task:
#%%
import yara
import os
#%%
rule = yara.compile("1001.yar")
files = os.listdir("./files")
# TESTING
# do not take ida files
files = [i for i in files if len(i)==32]
# checking the rule. We can suppose that not all the files are similar, tasks sounds like "thousand AND one"
for i in files:
matches = rule.match("./files/"+i)
if not matches:
print("Bad", i)
#%%
matches[0].strings
#[(4772,
# '$chunk_1',
# b'UH\x89\xe5H\x83\xec@H\x89}\xc8H\xb8nn\x1e\x19\x1d\x1fm\x1fH\xbak \x1f\x1e\x1bB nH\x89E\xd0H\x89U\xd8H\xb8n\x1e\x1eAo\x1a jH\xbaml\x1dl\x1cl\x1clH\x89E\xe0H\x89U\xe8\xc7E\xfc\x00\x00\x00\x00\xeb.\x8bE\xfcHc\xd0H\x8bE\xc8H\x01\xd0\x0f\xb6\x00\x83\xc0\x08\x83\xf0\x10\x8dH\xf1\x8bE\xfc')]
#%%
def parse_vars_from_file(file): # parsing the rule output
match = rule.match(file)[0].strings[0][2]
qw1 = match[14:22]
qw1 += match[24:32]
qw1 += match[42:50]
qw1 += match[52:70]
add, xor, sub = match[-10], match[-7], 0x100 - match[-4]
return qw1, add, xor, sub
def repair(qw1, add, xor, sub): # solving
qw2 = bytearray(qw1)[:32]
for i in range(len(qw2)):
qw2[i] = (qw2[i] + sub)%0x100
qw2[i] ^= xor
qw2[i] = (0x100+ qw2[i] - add)%0x100
return qw2
#%%
# test
r = repair(*parse_vars_from_file("./files/00ac8ed3b4327bdd4ebbebcb2ba10a00"))
# bytearray(b'bf5305e2d10a82e5a3ae01388d7b15c5')
#%%
import nclib
import time
#%%
nc = nclib.Netcat(('tasks.aeroctf.com', 44324), verbose = True)
while 1:
time.sleep(0.1)
mes = nc.recv().decode()
s = mes[mes.find("<")+1:mes.find(">")]
nc.send(
repair(*parse_vars_from_file(f"./files/{s}"))+b"\n"
)
======== Receiving 4096B ========
<< b'Enter valid token to binary with name <88ae6372cfdc5df69a976e893f4d554b>'
<< b''
======== Sending (33) ========
>> bytearray(b'e7d56cb4e9a723a988d25fd292d904ce')
>> bytearray(b'')
======== Receiving 4096B ========
<< b'Token: Enter valid token to binary with name <f57a2f557b098c43f11ab969efe1504b>'
<< b'Token: '
======== Sending (33) ========
>> bytearray(b'601bd2b40f963ab0be1c87a293d3d9e3')
>> bytearray(b'')
======== Receiving 4096B ========
<< b'Enter valid token to binary with name <71ad16ad2c4d81f348082ff6c4b20768>'
<< b'Token: '
======== Sending (33) ========
>> bytearray(b'6ca1d1718a78c97acf989b921658967f')
>> bytearray(b'')
======== Receiving 4096B ========
<< b'Enter valid token to binary with name <da0d1111d2dc5d489242e60ebcbaf988>'
<< b'Token: '
======== Sending (33) ========
>> bytearray(b'7bb06410c0be38160fd529f030f5b662')
>> bytearray(b'')
======== Receiving 4096B ========
<< b'Enter valid token to binary with name <e7f8a7fb0b77bcb3b283af5be021448f>'
<< b'Token: '
...
======== Sending (33) ========
>> bytearray(b'c328d7fa246eefc047c409c9ce306f53')
>> bytearray(b'')
======== Receiving 4096B ========
<< b'Flag: Aero{0f9e7ddd2be70f58b86f8f6589e17f182fc21c71437c2d9923fefa7ae281712b}'
<< b''
---------------------------------------------------------------------------
Error Traceback (most recent call last)
<ipython-input-54-98f036eef290> in <module>
5 s = mes[mes.find("<")+1:mes.find(">")]
6 nc.send(
----> 7 repair(*parse_vars_from_file(f"./files/{s}"))+b"\n"
8 )
9
<ipython-input-35-22cdf82dd799> in parse_vars_from_file(file)
1
2 def parse_vars_from_file(file):
----> 3 match = rule.match(file)[0].strings[0][2]
4 qw1 = match[14:22]
5 qw1 += match[24:32]
Error: could not open file "./files/Flag: Aero{0f9e7ddd2be70f58b86f8f6589e17f182fc21c71437c2d9923fefa7ae281712b}"
The flag: Aero{0f9e7ddd2be70f58b86f8f6589e17f182fc21c71437c2d9923fefa7ae281712b}