Comment on page
Investigative Reversing 2
We have recovered a binary and an image See what you can make of it. There should be a flag somewhere. Its also found in /problems/investigative-reversing-2_6_2ea0f420e29d29b575882f681dc272d5 on the shell server.
- 1.Run
file mystery
which shows its is a ELF executable:mystery: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld
... - 2.Reverse the binary file using Ghidra (cheat sheet). Open it and in the symbol tree click on main. The decompiled main function will show on the right.```c++ undefined8 main(void){ size_t sVar1; long in_FS_OFFSET; char local_7e; char local_7d; int local_7c; int local_78; int local_74; uint local_70; undefined4 local_6c; int local_68; int local_64; FILE local_60; FILE local_58; FILE *local_50; char local_48 [56]; long local_10;local_10 = (long )(in_FS_OFFSET + 0x28); local_6c = 0; local_60 = fopen("flag.txt","r"); local_58 = fopen("original.bmp","r"); local_50 = fopen("encoded.bmp","a"); if (local_60 == (FILE )0x0) { puts("No flag found, please make sure this is run on the server"); } if (local_58 == (FILE )0x0) { puts("original.bmp is missing, please run this on the server"); } sVar1 = fread(&local_7e,1,1,local_58); local_7c = (int)sVar1; local_68 = 2000; local_78 = 0; while (local_78 < local_68) { fputc((int)local_7e,local_50); sVar1 = fread(&local_7e,1,1,local_58); local_7c = (int)sVar1; local_78 = local_78 + 1; } sVar1 = fread(local_48,0x32,1,local_60); local_64 = (int)sVar1; if (local_64 < 1) { puts("flag is not 50 chars"); / WARNING: Subroutine does not return / exit(0); } local_74 = 0; while (local_74 < 0x32) { local_70 = 0; while ((int)local_70 < 8) { local_7d = codedChar((ulong)local_70,(ulong)(uint)(int)(char)(local_48[local_74] + -5), (ulong)(uint)(int)local_7e, (ulong)(uint)(int)(char)(local_48[local_74] + -5)); fputc((int)local_7d,local_50); fread(&local_7e,1,1,local_58); local_70 = local_70 + 1; } local_74 = local_74 + 1; } while (local_7c == 1) { fputc((int)local_7e,local_50); sVar1 = fread(&local_7e,1,1,local_58); local_7c = (int)sVar1; } fclose(local_50); fclose(local_58); fclose(local_60); if (local_10 == (long )(in_FS_OFFSET + 0x28)) { return 0; } / WARNING: Subroutine does not return / __stack_chk_fail(); }
ulong codedChar(int param_1,byte param_2,byte param_3)
{
byte local_20;
local_20 = param_2;
if (param_1 != 0) {
local_20 = (byte)((int)(char)param_2 >> ((byte)param_1 & 0x1f));
}
return (ulong)(param_3 & 0xfe | local_20 & 1);
}
```
- 1.This time the program jumps to offset 2000, and hides a 50 character flag using LSB encoding. More info on BoiteAKlou's Infosec Blog (Archive). The error string
"flag is not 50 chars"
reveals that the flag is 50 characters long. - 2.We can see that up to offset 2000 (
0x7d0
) we have a constant value of0xe8
. Then, for50 * 8
bytes we have different values (switching between0xe9
and0xe8
), and finally, at offset0x960
we're back to0xe8
.0xe8
in binary is0b11101000
and0xe9
is0b11101001
. In binary you can easily see the "least significant bit" modification that was made. Output ofxxd -g 1 -s $((2000 - 32)) -l $((50*8 + 64)) encoded.bmp
:000007b0: e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 ................000007c0: e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 ................000007d0: e9 e9 e8 e9 e8 e9 e9 e8 e8 e8 e9 e8 e8 e9 e9 e8 ................000007e0: e8 e9 e9 e9 e9 e8 e9 e8 e8 e9 e8 e9 e8 e9 e9 e8 ................000007f0: e8 e9 e9 e9 e9 e9 e8 e8 e9 e9 e9 e9 e8 e8 e9 e8 ................00000800: e9 e8 4e 4e 4e 4e 4f e8 e8 e9 e9 e8 e9 e9 e9 e8 ..NNNNO.........00000810: e9 e8 e8 e9 e8 e9 e9 e8 e8 e9 e9 e9 e8 e9 e8 e8 ................00000820: e9 e9 e8 e8 e9 e9 e9 e8 e9 e9 e9 e9 e8 e9 e9 e8 ................00000830: e8 e9 e8 e9 e9 e8 e9 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................00000840: e9 e8 e8 e9 e8 e9 e9 e8 e8 e9 e9 e9 e8 e9 e8 e8 ................00000850: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................00000860: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................00000870: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................00000880: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................00000890: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................000008a0: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................000008b0: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................000008c0: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................000008d0: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................000008e0: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................000008f0: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................00000900: e9 e9 e8 e9 e8 e9 e8 e8 e9 e9 e8 e9 e8 e9 e8 e8 ................00000910: e9 e9 e8 e9 e8 e9 e8 e8 e9 e8 e8 e8 e9 e9 e8 e8 ................00000920: e8 e9 e9 e9 e9 e8 e9 e8 e8 e9 e8 e8 e9 e9 e8 e8 ................00000930: e8 e9 e9 e9 e8 e9 e8 e8 e9 e8 e9 e9 e8 e9 e8 e8 ................00000940: e8 e9 e9 e9 e9 e8 e9 e8 e8 e8 e8 e8 e8 e9 e9 e8 ................00000950: e8 e8 e8 e8 e8 e9 e9 e8 e8 e8 e8 e9 e9 e9 e9 e8 ................00000960: e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 ................00000970: e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 e8 ................ - 3.Run the script.py to select the last bits from offset 2000 bytes to 2000+50*8 bytes and then convert them to ascii. View the code for the low-levels details about how the code works (60% of the file is purely comments).
picoCTF{n3xt_0n300000000000000000000000006c732cee}
Last modified 2yr ago