For this challenge we are given a packet capture in .PCAP format, this
should be an indication that we are going to be doing some packet
analysis and likely file carving in order to continue on. At first
glance we can quickly identify the HTTP2 protocol being used, which
should be no surprise since the name of this challenge is
Before we begin, read a quick blurb on HTTP2. This is a great resource
that provides just enough detail that can help us succeed in solving
After reading through the basics of HTTP2, we don’t need to explain much more detail on the specific protocol…let’s solve the challenge!
First things first, we start looking at the HTTP2 traffic and can see some data being transferred via DATA and also some PUSH_PROMISE frames. These are important because DATA frames contain actual data that is going to be important in almost any scenario and PUSH_PROMISE frames inform the endpoint of any streams that the sender intends to initiate transfer of.
Just by analyzing frame #8 (as seen above), we are able to identify four different HEADERS within this frame, each with StreamID’s, there is also a chunk of data. The StreamID’s are important to remember, here we have 2, 4, 6, and 13. Based on what we read previously and our knowledge of HTTP2, we have a good idea that in the subsequent frames within this PCAP we are going to find some data being transferred in these streams. Each of these StreamID’s can be thought of almost as an identifier for a particular data stream that we should be able to identify within this PCAP.
Looking back at the previous items we identified, the PUSH_PROMISE’s
each contain a file path in the Header field, each PUSH_PROMISE
contains a different path and from first glance these appear to be names
of files that are in the directory
The three different paths are as follows:
The Header fields for each different StreamID contain a content length, these are as follows:
StreamID #2 – Length: 3811624
StreamID #4 – Length: 3811704
StreamID #6 – Length: 3814728
Lastly, this particular frame also contains a DATA stream with StreamID
13. If we open that stream and look at the actual data being
transferred, we see:
Anyone familiar with ELF binary analysis should be familiar with those
first few hexadecimal bytes in the Data field. 0x7F454c46 is the ELF
file header and in ascii it reads as
.ELF. We found an executable
file! This is a win, now all we have to do is make sure we get the
entire file carved out correctly. Based on our knowledge of HTTP2, we
know it’s imperative that we find all the DATA streams that contain
StreamID #13 and concatenate the data together into one file in order
to successfully carve out this file. Wireshark allows us to enter
filters and the one I am using to get all of these data segments is
http2.streamid==13. This should filter out all the frames that
contain anything related to StreamID #13.
By right-clicking on the Data field and selecting “Show packet bytes…” we can select ‘Raw’ as the encoding type and view the raw bytes as seen below:
If we continue to do this for all of the frames which contain Data for StreamID #13 we are able to successfully carve out the ELF executable that is being transferred via HTTP2 in this stream. The file we end up with is:
FileSize: 3840704 bytes
Now that we’ve got the first file carved, lets look back at the other streams we identified in the aforementioned PUSH_PROMISE’s, StreamID’s 2,4, and 6. Starting with StreamID #2 we look at the Data field and see that the ELF header isn’t present here like it was in the first file. This really shouldn’t be much of a surprise, since we identified that these streams were all initiated with file names/paths like “/files/encrypted_execs/Iilll11Ti1lllIIl”. If these files are all encrypted executables, then they likely will have no discernable file traits, our only hope is to carve out every data stream related to each of these StreamID’s and make sure the lengths match up with those identified previously.
After carving out the data streams for StreamID’s #2, #4, and #6, we end up with the following files:
FileSize: 3811624 bytes
FileSize: 3811704 bytes
FileSize: 3814728 bytes
After finally carving all of these files out and getting matching file
sizes from the sizes we initially found in the first PUSH_PROMISE’s in
frame #8, we are on to trying to make sense of all these files. The
only file we have that looks promising so far is the first file from
index.html. This file appears to be an ELF and after
attempting to execute it with little to no results it’s time to do a
little static analysis and see what we can figure out. By looking at the
strings we can see it has some characteristics of a compiled Python
script, likely created with PyInstaller, we also see numerous references
to AES and Python crypto libraries. Open it up in our favorite
disassembler and start taking a look.
Based on previous experience and the types of files that we have at this
time, I’m going to assume that the crypto references in this executable
are there because it’s going to decrypt the other files we carved out
previously. This is especially evident since the files names are
actually transmitted from the path “encrypted_execs”. At this point I
decide to feed the executable some values along with the names of the
files carved out, it appears that the underlying Python script is
decryptor.py and that I am on the right track.
Since my input resulted in the word “test” giving me an error related to “decrypt_file” in the script, it is safe to assume that this actually needs to be the filename. In any case, I feed the filename twice to continue testing…it appears this was a good move.
After using the filenames as both argument 1 and 2, it appears that I have gotten some decrypted output. Running the “file” command on these output files shows that they are indeed ELF executables, YAY.
Now, let’s run them and see what we’ve got!
The first one appears to be some ASCII art, which I’m going to skip over because I want to know what the others are. The second file just tells me the current time and the third file gives me the key. Winning!