Written by:
hax0rmagee@gmail.com
Steganography- The art of hiding your stuff in other stuff so people won't find your stuff.
For this demonstration we will be attempting to extract a message that was hidden inside of a picture file using nothing but some brain power and a hex editor.
Our subject file: city.jpg. This jpg contains a text file hidden inside of it which was done using steganography software. Almost all steganography requires three things in order to crack.
- The file containing stego (we already have this)
- The stego software that was used
- The password used to encrypt the message inside the picture
When we open this jpg it looks perfectly normal. Just a picture of some building.
Exhibit A
Lets take a look at it in a hex editor and see if we can find anything more interesting.
Once booted into a hex editor, everything looks normal... but wait. What is this at the bottom?
Exhibit B
We see a massive group of 20's at the bottom of the file. The groups of 20's are separated by a few random bytes.
This leaves us at step two. How do we find the software which was used? This step isn't easy. You might get lucky using stegdetect, but the tool never left its alpha stages and is only capable of detecting a few different stego tools. The approach I took here was to download all the stego tools I could find and hope to get lucky. We can then use each stego tool to create a file until we come across a resulting file with a massive group of 20's at the bottom. I'll spare you the headache of this part and let you know that the stego software used here was camouflage.
We now have the file and the software used. All that's remaining is the password. I'm going to use camouflage to create two different files.
- file1.jpg with password 'xxxx'
- file2.jpg with password 'xxxxxxxx'
Let's take a look at the bottom of both of our newly created files in a hex editor.
Here is something interesting (focus on the highlighted bytes)
file1.jpg hex
In the center of file1.jpg's group of 20's there are four unique bytes starting right after the bytes '02 00'. In file2.jpg there are eight unique bytes in the same spot.
Could this be our password in hex? The answer is no. Not quite yet. Remember we used a password containing only x's. 'x' in hex is 78. Given that we have one encrypted byte per 'x', how about we try XOR? XOR is an easily reversible method to mask something you don't want someone to read plain text. Hardly a step up from a ceaser cipher, but still semi popular in some malware techniques.
As I said XOR is reversible. So...
- X XOR by Y = Z
- Z XOR by X= Y
Let's start with file1.jpg
We used four x's as the password so somehow '78 78 78 78' turned into '7A ED 02 5A'
Using our XOR method...
(note: microsoft calculator has an xor function. calculator>view>programmer. Then check the circle next to hex)
(note: microsoft calculator has an xor function. calculator>view>programmer. Then check the circle next to hex)
'78 78 78 78' XOR by <key> = '7A ED 02 5A' --> solve for key
'78 78 78 78' XOR by '7A ED 02 5A' = <key>
<key> = 02 95 7A 22
We now have the first four bytes to out camouflage key. Lets try and apply them to our target file. (Exhibit A)
The password buffer in our target file is '7B FA 0F 41 6D C8 60 89 80 B7 D2 00'. Since we only have the key for the first 4 bytes so far, were just going to go after '7B FA 0F 41'
<masked pass> <key> <password>
7B FA 0F 41 XOR by 02 95 7A 22 = 79 6F 75 63
Final step is to convert our Hex password to plain text. you can do this with your everyday ascii table.
79 = y
6F = o
75 = u
76 = c
<key> = 02 95 7A 22
We now have the first four bytes to out camouflage key. Lets try and apply them to our target file. (Exhibit A)
The password buffer in our target file is '7B FA 0F 41 6D C8 60 89 80 B7 D2 00'. Since we only have the key for the first 4 bytes so far, were just going to go after '7B FA 0F 41'
<masked pass> <key> <password>
7B FA 0F 41 XOR by 02 95 7A 22 = 79 6F 75 63
Final step is to convert our Hex password to plain text. you can do this with your everyday ascii table.
79 = y
6F = o
75 = u
76 = c
The first four characters of our password are 'youc'. To get the rest of the characters all we have to do is use camouflage to create a file 12 x's as the password. We can then reverse up to 12 bytes of the key and then use the 12 resulting bytes to decrypt the entire password (Exactly what we did earlier, only with twelve x's instead of four)
Camouflage can take up to a 255 character password. Below is the camouflage key decrypted in its entirety. You can get this by creating a password that is 255 x's and then using the steps above to reverse it. This obviously takes a lot longer than just four x's. Which is why i'm giving you the key instead of making you do it yourself.
02957A220CA614E1E1CFBF65206F9EB399654A53FBF67554AD23CD7E9C29E7FCE2F94DD2424E06C0F89A1C
623874240055DF41CB01A2B7F38F8ADDAC33836029F378243E7AEBD3E49D9D43944AC7456D2574EB0B98C9
7CFCC8BA326B00D3C5C29434AFB0E5957D2A84A45FE56E272ADB967E3E483946CF6F71AA3C319AA99E8F8
973B339CA32D5F031597C022E8637F92B7E51F241810CD46515F770D4199820BF20B85567CC81188C133C633
C9211E45B1B0822604C4AC58AB3C575C3907AF2B2B6C8D0388AC286F0ACE9CA5C4E3E09297829995A84D5
BA5ED5927A38FAD060ECF527BAEEB7DE9F9BDE65D47639769CDA688DA8A0A61ED9DB0F4DAB92CD71
Finally, we can automate this process by writing a Camouflage password cracker. Can you do it yourself? If not, or if you're just lazy below is the code to the cracker that I wrote in ruby. It's easy to run so long as you have ruby installed.
1: class CamouflageCracker
2:
3: def initialize(file)
4: @camoKey = "02957A220CA614E1E1CFBF65206F9EB399654A53FBF67554AD23CD7E9C29E7FCE2F94DD2424E06C0F89A1C623874240055DF41CB01A2B7F38F8ADDAC33836029F378243E7AEBD3E49D9D43944AC7456D2574EB0B98C97CFCC8BA326B00D3C5C29434AFB0E5957D2A84A45FE56E272ADB967E3E483946CF6F71AA3C319AA99E8F8973B339CA32D5F031597C022E8637F92B7E51F241810CD46515F770D4199820BF20B85567CC81188C133C633C9211E45B1B0822604C4AC58AB3C575C3907AF2B2B6C8D0388AC286F0ACE9CA5C4E3E09297829995A84D5BA5ED5927A38FAD060ECF527BAEEB7DE9F9BDE65D47639769CDA688DA8A0A61ED9DB0F4DAB92CD71"
5: @file = file
6: getEncryptedPass()
7: end
8:
9: #Read our file byte by byte
10: def getEncryptedPass
11: data = ""
12: File.open(@file).each_byte { |byte|
13: byte = byte.to_s(16).upcase #convert byte to hex
14: byte = "0" << byte if byte.length == 1 #if the byte is only 1 number add a 0 to the beggining
15: data << "#{byte} "
16: }
17:
18: #grab the encypted password out of the file and print it
19: data = data.split("E3 07 09 00 02 00").last
20: encryptedPassword = data.split("20 20 20 20 20").first.strip
21:
22: puts "\nEncrypted Password = #{encryptedPassword}"
23: decryptPassword(encryptedPassword)
24: end
25:
26: def decryptPassword(encrypted)
27: puts "Decrypting..."
28: #put the encrypted password into an array
29: encryptedPasswordArray = encrypted.split(" ")
30: @camoKeyArray = @camoKey.scan(/../)
31:
32:
33: #for each byte in the array XOR it by the according key byte
34: passwordInHex = ""
35: x = 0
36: while x < encryptedPasswordArray.length
37: passwordInHex << (encryptedPasswordArray[x].to_i(16) ^ @camoKeyArray[x].to_i(16)).to_s(16) << " "
38: x += 1
39: end
40:
41: passToAscii(passwordInHex)
42: end
43:
44: def passToAscii(hexArray)
45: #convert password to ascii
46: password = ""
47: hexArray = hexArray.split(' ')
48: hexArray.each {|x| password << "\\x" << "#{x}"}
49: password = password.scan(/\\x(..)/).map{|a| a.first.to_i(16).chr}.join
50: puts "Password = #{password}"
51: end
52: end
53:
54: #allow file as command line argument
55: if ARGV.length > 0
56: file = ARGV[0]
57: puts "Scanning #{file}"
58: else
59: puts "\nYou must specify a file\n"
60: exit
61: end
62:
63: camouflageBuster = CamouflageCracker.new(file)
64:
Running this script on our target file gives us our password
$ ruby camoCrack.rb ~/Desktop/city.jpg
Scanning city.jpg
Encrypted Password = 7B FA 0F 41 6D C8 60 89 80 B7 D2 00
Decrypting...
Password = youcanthaxme
Thanks for reading
No comments:
Post a Comment