-
Notifications
You must be signed in to change notification settings - Fork 0
Description
How to Solve the Secret
1. Identify if secret is encoded
- For this, we wrote
file secret - The result was
secret: ASCII text- Now we know that the file contains ASCII text
- Even so, we need to analyze the content by ourselves. For this, we can write
head secret, which gives us
H4sICEjNJmcAA3Byb2dyYW0A7Vx7cBvHed8DeCQokiD4FClKFmRLtvwgSFAyRVGWBYgPgRL1pEi9
dQSBI4EIrwIHWvQjVqz4QT9aOUldN5UjOZ5xk4zSuk2reOzapq2MLbdux+4j1ngyLRtHrRQ/Ssd2
LNuy0O/b2z3cHQHZk3Sm/2Al3Lffb7/v228fd9y92907e/p7LYJAeLCQmwlyUw4P5T0MP7ReEwGs
g1TA9WqyhBQDX6ST8xCPgZ6xEAO1MTkr02uwqnyD1WOg85kcp4KOFhF98Bjo0yXEQIkjqyfqeMLK
x+njzA9O9Xo0PyfDnR4D/QUrF6d6PaybmWaVn1ntMVCFyd9n0rMwPeJi+M0eA51mFcEpr88i9utg
/neweuRUc5/k1tvJ9HYyeU67mVy3Th7DwFkl+Lvkt4XpnVik8icWeQw0X35bQa+YfPXAm3kbyy9f
OzhY/XPK+1lLJDzSvrwlEmyOhGPpg80HO9qb25e7UnFXm+YX5oF9at2mQWI5RKYQ490H47WMx/Rn
zq5/6835T/16QfSJwb4Rec3wHT98ldsQmAxh8rxLEBa3k2x/ImuRcVCsEn7XLnhw/mTqvrJ89fBH
8KvOgY/nwbfmwTF/Zw78D/LI35UHfyQPHsiDL8iT7/o88rflwW/IY2cyj/zX4FdFGknI46E877+9
VN5OnqxS8Xu4gtS3faMUlJPyWDilyMntG7si8Zi83T8SkYkkjUXjMSml+JOKJKmiOQVH43ES9Uci- The content is only alphanumeric characters with
+and/. A Base64 kind of file looks like this.
2. Decode the secret from the recognized file type
- We write
base64 -d secret > decoded_secret.-dflag tells Linux to decode the content of secret using base64 format
3. Identify what the secret really is
- Now that we've decoded the secret, we need to check the type of the decoded file, for this do
file decoded_secretinside the terminal, from which we get:
decoded_secret: gzip compressed data, from Unix, original size modulo 2^32 51200- Behind the layed of Base64 encoding we can see that its just a compressed archive that uses
gzipas the outer compression layer. We can see its content without extraction usingfile -z decoded_secret, that outputs the following:
decoded_secret: POSIX tar archive (GNU) (gzip compressed data, from Unix)4. Extract the contents of decoded_secret
- Now that we've identified that
decoded_secretis a compressed archive, we can decompress it usingtar xvzf decoded_secret.tar: Calls thetarcommand, which is used for creating, extracting, and managing tar archives.x: Extracts the contents of the archive.v: Displays the progress in the terminal (verbose mode), showing the names of files as they’re extracted.z: Specifies that the archive is compressed with gzip (a.gzfile).f: Indicates that the following argument,decoded_secret, is the name of the file to operate on.
- After doing this, the terminal gives us the next output:
87014aef1d77646b/
87014aef1d77646b/pendrive_image.bmp.gz
87014aef1d77646b/program.gz-
This means that the content of
decoded_secrethas been extracted to a folder called87014aef1d77646bwith contents inside. These are two single compressed files that we can decompress withgzip, as follows:gzip -d 87014aef1d77646b/program.gzgzip -d 87014aef1d77646b/pendrive_image.bmp.gz
5. Analyze the program executable
Before doing anything risky and compromise our system, we should check what the executable contains, for this we can do the following:
strings program: displays any readable strings within the binary, which can sometimes provide hints about its functionalityfile program: displays information about the file.- This will let us see that our file is just an ELF Executable
- We get the following:
program: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=bae54adad71cb0ea1d6da3554962653f607da9c9, for GNU/Linux 3.2.0, with debug_info, not strippedobjdump -x program: To display information about sections, headers, and other low-level detailsldd program: To check the shared libraries the executable depends on- (Not recommended)
gdb program: If you want to debug or step through the program’s execution, you can load it into the GNU debugger. This isnt recommended yet because you should never execute something without knowing what it does.
From all of these options, the one that takes our attention is ldd program, which gives us:
linux-vdso.so.1 (0x00007fffe49d4000)
lib87014aef.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007c8874600000)
/lib64/ld-linux-x86-64.so.2 (0x00007c8874982000)- Now we can see that there are no unresolved dependencies except one called
lib87014aef.so. We need to figure out what this library is and how we can obtain it.
6. Obtaining info from the image
-
One could think that the remaining info is inside the
pendrive_image.bmpfile, and to be sure we can rungrep 'ELF' *.- This confirms that this image has a binary file inside, that could be our missing library
- From this command we get
grep: pendrive_image.bmp: binary file matches grep: program: binary file matches
-
To discover exactly what’s in a file without being able to rely on any standard assumptions about the file contents, you’ll have to analyze it at the byte level. To do this, you can use any numeric system to display bits and bytes on the screen. For instance, you could use the binary system, displaying all the ones and zeros individually. But because that makes for some tedious analysis, it’s better to use the hexadecimal system
- To display the bytes of a file in hexadecimal representation, you use a hex-dumping program like
xxd. Therefore, now we writexxd pendrive_image.bmpin our terminal, but to simplify things and considering the library we need surely starts with0x7f45(ELF start magic sequence), we can runxxd pendrive_image.bmp | grep 7f45, where we get:00006f30: 3631 3731 2629 7f45 4c46 0201 0100 0000 6171&).ELF...... 0000abc0: 0000 0000 0000 7f45 4c46 0201 0100 0000 .......ELF......
- This way, the ELF files appear on directions 0x6f36 = 28470 and abc0 = 43974
- We dont know which one of these two ELF files is our library and either way, we dont know where these files end. To find out both things, we extract a header from each ELF file, for that we write
dd skip=28470 count=64 if=pendrive_image.bmp of=header1 bs=1anddd skip=43974 count=64 if=pendrive_image.bmp of=header2 bs=1 - Now, to see the extend of each file, we use
readelf -h header1:ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 readelf: Error: Too many program headers - 0x9 - the file is not that big Type: DYN (Shared object file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x0 Start of program headers: 64 (bytes into file) Start of section headers: 13712 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 9 Size of section headers: 64 (bytes) Number of section headers: 28 Section header string table index: 27 readelf: Error: Reading 1792 bytes extends past end of file for section headers readelf: Error: Too many program headers - 0x9 - the file is not that big
- And
readelf -h header2:ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 readelf: Error: Too many program headers - 0x9 - the file is not that big Type: DYN (Shared object file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x1070 Start of program headers: 64 (bytes into file) Start of section headers: 48184 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 9 Size of section headers: 64 (bytes) Number of section headers: 35 Section header string table index: 34 readelf: Error: Reading 2240 bytes extends past end of file for section headers readelf: Error: Too many program headers - 0x9 - the file is not that big
- From this, what matters is
Start of section headers (e_shoff),Size of section headers (e_shentsize = 64)yNumber of section headers (e_shnum. We will use all these things in the next formula:
$$ size = e_{shoff} + (e_{shnum} * e_{shentsize}) $$
$$ size_{header1} = 13712 + (28 * 64) = 15504 $$
$$ size_{header2} = 48184 + (35 * 64) = 50424 $$
- To display the bytes of a file in hexadecimal representation, you use a hex-dumping program like
-
With this, we can reconstruct the whole library because now we know where it ends. We can do use with the command
dd skip=28470 count=15504 if=pendrive_image.bmp of=lib87014aef.so bs=1ordd skip=43974 count=50424 if=pendrive_image.bmp of=lib87014aef.so bs=1, where we useof=lib87014aef.sobecause it is the name of the library thats missing. -
To see if the extraction was succesful and if we extracted the right library, we can do
readelf -hs lib87014aef.so. We try this command with each header, and the one that seems to be our missing library isheader2, so lets stick with that.
7. Loading the Library
- Now that we have our library, we need to link it with
programsomehow. For that, we use export LD_LIBRARY_PATH=`pwd` - Now, when we do
./program, we get:
Loading system...OK
Starting encrypting system...OK
Starting collect sensitive information system...FAIL
Segmentation fault (core dumped)8. Solving the secret
- The next steps involve debugging the given code with
gdb ./programand reading the debug symbols, so we can reproduce the program elsewhere and use the hint about PI that we found on the room.- The segmentation fault is caused because theres a
freeof an object before using the object (thats what we should see when debugging) - For solving the secret, we use backtrace and coredumps (besides the gdb tool)
- In the end, the secret was related to something like "you shouldnt free before using" I think, I do not remember now (we did it in class after some time trying, but we cant see the debug symbols inside the given program and that makes the secret impossible to solve)
- The segmentation fault is caused because theres a