The challenge aims at reversing a dynamically linked x86-64 binary.
file bank
bank: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=10134ec844feac04728fa961c1684b6570624034, for GNU/Linux 3.2.0, not stripped
Using Ghidra, we can see the decompilation of the main function. After careful analysis, we can determine that C.0.0
array is a boolean array.
C.1.1
contains data. We can also see that the boolean array determine if a character is an important character, other characters are only noise.
With this information, we can easily retrieve the flag.
undefined8 main(void)
{
undefined4 uVar1;
bool bVar2;
undefined4 *puVar3;
char *pcVar4;
ulong uVar5;
basic_ostream *pbVar6;
ulong uVar7;
undefined auVar8 [16];
vector<> local_148 [48];
basic_string local_118 [32];
vector<> local_f8 [32];
vector local_d8 [48];
vector local_a8 [46];
__new_allocator<bool> local_7a;
__new_allocator<> local_79;
undefined local_78 [16];
undefined local_68 [16];
undefined local_58 [16];
__new_allocator<> *local_48;
__new_allocator<bool> *local_40;
undefined local_32;
char local_31;
int local_30;
int local_2c;
local_40 = &local_7a;
/* try { // try from 00101240 to 00101244 has its CatchHandler @ 001014e5 */
std::vector<>::vector((initializer_list)local_a8,(allocator *)C.0.0);
std::__new_allocator<bool>::~__new_allocator(&local_7a);
/* try { // try from 00101266 to 0010126a has its CatchHandler @ 00101558 */
std::vector<>::vector(local_d8);
local_48 = &local_79;
/* try { // try from 0010129c to 001012a0 has its CatchHandler @ 00101500 */
std::vector<>::vector((initializer_list)local_f8,(allocator *)C.1.1);
std::__new_allocator<>::~__new_allocator(&local_79);
std::__cxx11::basic_string<>::basic_string();
/* try { // try from 001012d1 to 001012ee has its CatchHandler @ 00101526 */
std::operator<<((basic_ostream *)std::cout,"What\'s the password to the bank vault? ");
std::getline<>((basic_istream *)std::cin,local_118);
local_2c = 0;
std::vector<>::vector();
local_31 = '\0';
local_30 = 0;
while( true ) {
uVar7 = (ulong)local_30;
uVar5 = std::vector<>::size();
if (uVar5 <= uVar7) break;
auVar8 = std::vector<>::back();
local_78 = auVar8;
local_31 = std::_Bit_reference::operator.cast.to.bool((_Bit_reference *)local_78);
/* try { // try from 0010134e to 0010148f has its CatchHandler @ 00101512 */
puVar3 = (undefined4 *)std::vector<>::at(local_f8,(long)local_30);
uVar1 = *puVar3;
pcVar4 = (char *)std::__cxx11::basic_string<>::operator[]((ulong)local_118);
local_32 = (char)((uint)uVar1 >> 0x10) == *pcVar4;
if (local_31 != '\0') {
local_2c = local_2c + 1;
}
std::vector<>::push_back(local_148,(bool)local_32);
std::vector<>::pop_back();
local_30 = local_30 + 1;
}
local_68 = std::vector<>::end();
local_58 = std::vector<>::begin();
std::reverse<>(local_58._0_8_,local_58._8_8_,local_68._0_8_,local_68._8_8_);
bVar2 = std::operator==((vector *)local_148,local_a8);
if (bVar2) {
pbVar6 = std::operator<<((basic_ostream *)std::cout,"Access granted!");
std::basic_ostream<>::operator<<((basic_ostream<> *)pbVar6,std::endl<>);
}
else {
pbVar6 = std::operator<<((basic_ostream *)std::cout,"Access denied!");
std::basic_ostream<>::operator<<((basic_ostream<> *)pbVar6,std::endl<>);
}
std::vector<>::~vector(local_148);
std::__cxx11::basic_string<>::~basic_string((basic_string<> *)local_118);
std::vector<>::~vector(local_f8);
std::vector<>::~vector((vector<> *)local_d8);
std::vector<>::~vector((vector<> *)local_a8);
return 0;
}
Using a simple python scripts that retrieves characters where the index is True, we can retrieve the flag :
def reverse():
mark = [
False, False, False, False, False, True, True, True, True, False, False, False, False, True,
False, True, True, False, False, False, False, True, False, True, True, False, True, False,
False, True, True, False, True, True, False, False, False, False, True, False, False, True,
False, True, False, True, False, False, True, False, False, True, False, False, True, False,
True, False, False, True, True, False, False, False, False, True, False, True, False, False,
False, True, True, True, False, True, False, True, True, True, True, False, True, True
]
keys = [
0xf16285bd, 0x4d79b336, 0x3607c041, 0x4f757c48, 0x63634432, 0x8474be64, 0x2f66bfed,
0x8c8ba74b, 0xcb7bb04c, 0x29aa35bb, 0xdc33e9f9, 0xb37642ea, 0x1133f4df, 0x6819b1cf,
0xac1b2111, 0x797e383b, 0xe46e41f5, 0x38e144f9, 0xaa5f25b7, 0x36e31d2b, 0x17cd4129,
0xcf9276a9, 0x9675f6, 0xed76e994, 0x1e33fc99, 0x75157513, 0x996d3e0c, 0x5b633cab,
0x60d22379, 0xfc740809, 0xcb43d953, 0xf9cfead5, 0xb1304006, 0xca841431, 0x2aece666,
0xdb72fb63, 0x73862a0f, 0x21ff2a98, 0x3b73281b, 0x1322483e, 0x565f373a, 0xbf32aa3e,
0x9d345021, 0xc003dd66, 0xfb08399c, 0x677070f7, 0x96d4f926, 0x5aad004, 0x465a312a,
0xcea1f556, 0xa9706fd9, 0x31330bd6, 0x4241cfa0, 0xfc340a7a, 0x1724268, 0x41e06d3e,
0xd9111112, 0x635f1af6, 0xeff71436, 0x82311dc8, 0xb56e65d1, 0x98e00125, 0xfe5faeb5,
0x4d53dae2, 0x980bcea2, 0xb98118bd, 0x8421652d, 0xf76d1209, 0xa4339088, 0xb98085f8,
0x6f6dea30, 0x2110d58e, 0x443b9947, 0x4529fd1d, 0xf0e27c3e, 0x8530b126, 0x8f72c719,
0xca794f90, 0x3e7dbb1d, 0xe57c7778, 0x18f32f9e, 0x4d2a5666, 0xe8e18692, 0x9a987ce8
]
mark2 = list(mark)
input_bytes = []
index = len(mark2) - 1
for i in range(len(keys)):
m = mark2[index]
if m:
char_byte = (keys[i] >> 16) & 0xff
input_bytes.append(char_byte)
index -= 1
flag = ''.join(chr(b) for b in input_bytes)
print(flag)
if __name__ == "__main__":
reverse()
python3 solve.py
byuctf{3v3n_v3ct0rs_4pp34r_1n_m3m0ry}