This is a reverse engineering challenge from a CTF event.
The clue/hint is: Well ol' chap, it seems we have ourselves another puzzle! I just can't picture what this one might be... Well, there's no time to waste shuffling about, we must begin!
It's an ELF file and I've used Ghidra, R2, IDA to look deeper at the assembly code but I'm not having any luck really understanding or interpreting what's going on.
Running file gives: ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=cda365c788fe7f6d51b01efdc9d786f935015bcb, for GNU/Linux 3.2.0, stripped
My understanding so far, and I could be wrong, is that when running 'customary', it requires an argument in order to successfully extract and create 'sherlock'jpeg' from the data.ana file...I think.
When I grab the assembly for the main function(snippet below), I can see it's doing something with 'sherlock'jpeg' and further down is 'Exiting' but I'm not making too much sense of it.
; DATA XREF from entry0 @ 0x229d(r)
┌ 721: int main (int argc, char **argv, char **envp);
│ ; var int64_t var_18h @ rbp-0x18
│ ; var int64_t var_28h @ rbp-0x28
│ ; var signed int64_t var_2ch @ rbp-0x2c
│ ; var signed int64_t var_30h @ rbp-0x30
│ ; var signed int64_t var_34h @ rbp-0x34
│ ; var int64_t var_35h @ rbp-0x35
│ ; var int64_t var_60h @ rbp-0x60
│ ; var int64_t var_80h @ rbp-0x80
│ ; var int64_t var_88h @ rbp-0x88
│ ; var int64_t var_89h @ rbp-0x89
│ ; var int64_t var_8ah @ rbp-0x8a
│ ; var int64_t var_b0h @ rbp-0xb0
│ ; var int64_t var_b8h @ rbp-0xb8
│ ; var int64_t var_d0h @ rbp-0xd0
│ ; var int64_t var_100h @ rbp-0x100
│ 0x00002739 55 push rbp
│ 0x0000273a 4889e5 mov rbp, rsp
│ 0x0000273d 4155 push r13
│ 0x0000273f 4154 push r12
│ 0x00002741 53 push rbx
│ 0x00002742 4881ece80000. sub rsp, 0xe8
│ 0x00002749 488d8576ffff. lea rax, [var_8ah]
│ 0x00002750 4889c7 mov rdi, rax
│ 0x00002753 e838f9ffff call fcn.00002090
│ 0x00002758 488d9576ffff. lea rdx, [var_8ah]
│ 0x0000275f 488d8550ffff. lea rax, [var_b0h]
│ 0x00002766 488d35115a00. lea rsi, str.sherlock.jpeg ; 0x817e ; "sherlock.jpeg"
│ 0x0000276d 4889c7 mov rdi, rax
│ 0x00002770 e82bfaffff call method std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) ; method.std::__cxx11::basic_string_char__std::char_traits_char___std::allocator_char___.basic_string_char_const__std::allocator_char__const_
│ 0x00002775 488d8576ffff. lea rax, [var_8ah]
│ 0x0000277c 4889c7 mov rdi, rax
│ 0x0000277f e8dcfaffff call sym std::allocator<char>::~allocator() ; sym.imp.std::allocator_char_::allocator__
│ ; std::allocator<char>::~allocator()
│ 0x00002784 488d8548ffff. lea rax, [var_b8h]
│ 0x0000278b 488db550ffff. lea rsi, [var_b0h]
│ 0x00002792 b900000000 mov ecx, 0
│ 0x00002797 ba00000000 mov edx, 0
│ 0x0000279c 4889c7 mov rdi, rax
│ 0x0000279f e84cfaffff call method OpenImageIO_v2_2::ImageInput::open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, OpenImageIO_v2_2::ImageSpec const*, OpenImageIO_v2_2::Filesystem::IOProxy*) ; method.OpenImageIO_v2_2::ImageInput.open_std::__cxx11::basic_string_char__std::char_traits_char___std::allocator_char____const__OpenImageIO_v2_2::ImageSpec_const__OpenImageIO_v2_2::Filesystem::IOProxy_
│ 0x000027a4 488d8548ffff. lea rax, [var_b8h]
│ 0x000027ab 4889c7 mov rdi, rax ; int64_t arg1
│ 0x000027ae e8031d0000 call fcn.000044b6
│ 0x000027b3 83f001 xor eax, 1
│ 0x000027b6 84c0 test al, al
│ ┌─< 0x000027b8 7416 je 0x27d0
│ │ 0x000027ba 488d3dcb5900. lea rdi, str.Exiting... ; 0x818c ; "Exiting..." ; const char *s
│ │ 0x000027c1 e85af9ffff call sym.imp.puts ; int puts(const char *s)
│ │ 0x000027c6 bb01000000 mov ebx, 1
│ ┌──< 0x000027cb e90a020000 jmp 0x29da
│ ││ ; CODE XREF from main @ 0x27b8(x)
Any assistance to understand it more, or even actually execute it would be great.
I've included a copy of the binary (zipped) here https://github.com/gnarkill78/watson
This is function 44b6 that was suggested to look at:
bool FUN_00102739(void)
{
code *pcVar1;
char cVar2;
long *plVar3;
undefined8 uVar4;
undefined local_108 [48];
vector<> local_d8 [24];
basic_string local_c0 [8];
ImageSpec local_b8 [38];
allocator<char> local_92;
allocator<char> local_91;
undefined local_90 [8];
vector<> local_88 [32];
basic_string<> local_68 [43];
allocator<char> local_3d;
int local_3c;
int local_38;
int local_34;
long local_30;
std::allocator<char>::allocator();
/* try { // try from 00102770 to 00102774 has its CatchHandler @ 001029ff */
std::__cxx11::basic_string<>::basic_string((char *)local_b8,(allocator *)"sherlock.jpeg");
std::allocator<char>::~allocator(&local_92);
/* try { // try from 0010279f to 001027a3 has its CatchHandler @ 00102a9f */
OpenImageIO_v2_2::ImageInput::open(local_c0,local_b8,(IOProxy *)0x0);
cVar2 = FUN_001044b6(local_c0);
if (cVar2 == '\x01') {
plVar3 = (long *)FUN_001044d6(local_c0);
local_30 = (**(code **)(*plVar3 + 0x38))(plVar3);
local_34 = *(int *)(local_30 + 0xc);
local_38 = *(int *)(local_30 + 0x10);
local_3c = *(int *)(local_30 + 0x3c);
std::allocator<char>::allocator();
/* try { // try from 00102841 to 00102845 has its CatchHandler @ 00102a1c */
FUN_001044f0(local_d8,(long)(local_34 * local_38 * local_3c),&local_91);
std::allocator<char>::~allocator(&local_91);
plVar3 = (long *)FUN_001044d6(local_c0);
pcVar1 = *(code **)(*plVar3 + 0x98);
uVar4 = FUN_00103da4(local_d8,0);
FUN_001030f8(local_90,2,1,0,0);
/* try { // try from 001028e0 to 00102904 has its CatchHandler @ 00102a77 */
(*pcVar1)(plVar3,local_90,uVar4,0x8000000000000000,0x8000000000000000,0x8000000000000000,0,0);
plVar3 = (long *)FUN_001044d6(local_c0);
(**(code **)(*plVar3 + 0x50))(plVar3);
FUN_0010319a(local_108);
FUN_001031da(local_108,local_34,local_38,0x578);
/* try { // try from 0010293f to 00102943 has its CatchHandler @ 00102a63 */
FUN_00103c62(local_88,local_d8);
/* try { // try from 00102955 to 00102959 has its CatchHandler @ 00102a30 */
FUN_00103240(local_108,local_88);
std::vector<>::~vector(local_88);
std::allocator<char>::allocator();
/* try { // try from 00102984 to 00102988 has its CatchHandler @ 00102a52 */
std::__cxx11::basic_string<>::basic_string((char *)local_68,(allocator *)"data.ana");
/* try { // try from 0010299a to 0010299e has its CatchHandler @ 00102a41 */
FUN_001032b6(local_108,local_68);
std::__cxx11::basic_string<>::~basic_string(local_68);
std::allocator<char>::~allocator(&local_3d);
FUN_00103768(local_108);
std::vector<>::~vector(local_d8);
}
else {
/* try { // try from 001027c1 to 001027ed has its CatchHandler @ 00102a8b */
puts("Exiting...");
}
std::unique_ptr<>::~unique_ptr((unique_ptr<> *)local_c0);
std::__cxx11::basic_string<>::~basic_string((basic_string<> *)local_b8);
return cVar2 != '\x01';
}
Unfortunately it's just not making and sense to me.