Search code examples
kotlinsteganography

How to extract a hidden file in Kotlin?


I'm trying to hide a file inside of a file and then take the hidden file back out and look at it.

I'm hiding the file just fine. However, I need to extract the file. I combine two byte arrays with a third in the middle for the separator. I'm not able to extract the whole file.

import java.io.*

fun main(args: Array<String>) {

    val original = args[0]
    val hidden = args[1]
    var newFile: String? = null
    if(args.size == 3)
        newFile = args[2]

    //if its null I extract the file
    if(newFile == null){
        val originalFile = File(original)
        val parts = originalFile.readBytes().toString().split("777777")
        val bytes = parts.last().toByteArray()
        val hiddenFile = File(hidden)
        hiddenFile.writeBytes(bytes)
        println("$hiddenFile is unhidden")
        return
    }

    //hide the file
    val originalBytes = File(original).readBytes()
    val hiddenBytes = File(hidden).readBytes()
    val file = File(newFile!!)
    val separator = "777777".toByteArray()
    file.writeBytes(originalBytes + separator + hiddenBytes)
    println("$newFile is created")
}

Solution

  • If you get a corrupted file, that is most probably happening because the intermediate String conversion. When decoding a byte array to a string, and then re-encoding it into a byte array, you won't get back the same array with most encoding schemes.

    To mitigate this problem, I would skip the string conversion entirely. You can use Google's Guava library to find your pattern in a byte array, using the Bytes.indexOf function.

    Something like this:

    import java.io.*
    import com.google.common.primitives.Bytes
    
    fun main(args: Array<String>) {
        val original = args[0]
        val hidden = args[1]
        var newFile: String? = null
        if(args.size == 3)
            newFile = args[2]
        val separator = "777777".toByteArray()
        val originalBytes = File(original).readBytes()
    
        //if its null I extract the file
        if(newFile == null){
            val separatorIndex = Bytes.indexOf(originalBytes , separator)
            val bytes = originalBytes.sliceArray(separatorIndex + pattern.size..fileData.size - 1)
            val hiddenFile = File(hidden)
            hiddenFile.writeBytes(bytes)
            println("$hiddenFile is unhidden")
            return
        }
    
        //hide the file
        val hiddenBytes = File(hidden).readBytes()
        val file = File(newFile!!)
        file.writeBytes(originalBytes + separator + hiddenBytes)
        println("$newFile is created")
    }