DCT Stenography

aaronb50

Registered User.
Local time
Yesterday, 21:28
Joined
Mar 2, 2014
Messages
185
For my capstone project my team has decided to create a stenography program. I have been able to hide a message in a .bmp by using least significant bit and changing the last bit of each pixel. Message goes in and comes out perfectly.

But our main goal is to use DCT Stenography.

I'm not finding anything on DCT Stenography in Access.

Can anyone point me in the right direction?
 
Stenography would not be an Access thing.
It would be a font thing.

Tho , you could build an alphabet table, with a field for all the various symbols, via bmps.
Letter = A
mason= bmp
nash = bmp
etc.
 
Yep that's it. I have found few articles like that but I'm trying to find something a little easier to follow if I can.

I have found a bunch of examples and code for doing it in java, but nothing for Access.
 
So the rest of the team wants to do this in java.

Since I was able to change that last bits and hide the message in a .bmp if figured I could also use Access for the DCT.

But your saying Access might not be the best tool for this?
 
I don't know anything about it. I did a google search --since I've never heard of DCT Stenography -that's how I found the link.

What is the business involved? Do you currently use Access? Do you program in java?
You can use jdbc to talk to Access database.

Why not start with a fairly simple example to prove/disprove you can do what you want in Access/vba or java?
 
Well I started by just seeing if I could change out the pixels to do the easy Stenography. And that did work. I can change image pixels.

So now I'm moving on to the harder part, but I'm not really even sure where to begin. The difficulty level between the two is large.
 
I build stuff in Access at work all the time. That's why I want to use Access. the rest of the team wants to use java. I know little java.

Worst case, I'm sure one of them will get it in java but I was hoping I could get it working in Access first.
 
So I found this this morning and was able to make it work with no problem. But I cant seem to figure what its doing. I've tried stopping it in different places, adding MsgBox to see what's in the variables at different points but its just not making any sense to me. Can someone explain to me how this is doing what its doing?



Code:
newFile.Write (oldFile.Read(10))

is where I start getting lost.

Code:
Const ForReading = 1, ForWriting = 2, ForAppending = 8
 Dim oldFile, newFile, oFS, iSize, strMessage, i, ch, strPath
 strPath = InputBox("File Path of Bitmap File:")
 Set oFS = CreateObject("Scripting.FileSystemObject")
 Set oldFile = oFS.OpenTextFile(strPath, ForReading)
 If InputBox("1 for encode, 2 to decode") = 1 Then
     Set newFile = oFS.OpenTextFile(Replace(strPath, ".bmp", "-e.bmp"), ForWriting, True)
     iSize = (oFS.GetFile(strPath).Size \ 8) - 1
     Do
         strMessage = InputBox("Enter your message. The maximum number of characters is " & iSize & ".")
     Loop Until Len(strMessage) <= iSize
     newFile.Write (oldFile.Read(10))
 
     ch = oldFile.Read(1)
     MsgBox ch
     newFile.Write (ch)
     iSize = Asc(ch)
     MsgBox iSize
     
     ch = oldFile.Read(1)
     newFile.Write (ch)
     iSize = iSize + Asc(ch) * 256
     ch = oldFile.Read(1)
     newFile.Write (ch)
     iSize = iSize + Asc(ch) * 65536
     ch = oldFile.Read(1)
     newFile.Write (ch)
     iSize = iSize + Asc(ch) * 16777216
     newFile.Write (oldFile.Read(iSize - 14))
     
     
     For i = 1 To Len(strMessage)
         ch = Asc(Mid(strMessage, i, 1))
         newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 128) \ 128)))
         newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 64) \ 64)))
         newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 32) \ 32)))
         newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 16) \ 16)))
         newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 8) \ 8)))
         newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 4) \ 4)))
         newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 2) \ 2)))
         newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 1) \ 1)))
     Next
     For i = 1 To 8
         newFile.Write (Chr(Asc(oldFile.Read(1)) And 254))
     Next
     Do Until oldFile.AtEndOfStream
         newFile.Write (oldFile.Read(1024))
     Loop
     newFile.Close
     Set newFile = Nothing
     MsgBox "Message Encoded!"
 Else
     i = 0
     ch = 0
     strMessage = ""
     oldFile.Read (10)
     iSize = Asc(oldFile.Read(1))
     iSize = iSize + Asc(oldFile.Read(1)) * 256
     iSize = iSize + Asc(oldFile.Read(1)) * 65536
     iSize = iSize + Asc(oldFile.Read(1)) * 16777216
     oldFile.Read (iSize - 14)
     Do Until oldFile.AtEndOfStream
         i = i + 1
         ch = ch Or ((Asc(oldFile.Read(1)) And 1) * (2 ^ (8 - i)))
         If i = 8 Then
             strMessage = strMessage & Chr(ch)
             If ch = 0 Then
                 Exit Do
             Else
                 ch = 0
                 i = 0
             End If
         End If
     Loop
     MsgBox strMessage
 End If
 oldFile.Close
 Set oldFile = Nothing
 Set oFS = Nothing
 
It depends exactly what you are doing, but i expect one problem might be that changing bits within a byte may produce a byte zero, or some other bit pattern that presents difficulties. The problem with a byte zero (or maybe even a byte 26 ctrl-Z) is that might in some cases be seen as a file terminator. I had this problem when trying to do some general encryption.

the other thing is that changing the last bit of an ascii character will change the character - but I am not sure would be that strong an encryption. I expect frequency analysis might decrypt a message like that.

I expect the issue really is:

are you looking to try and establish an encryption method, or are you just trying to implement a given encryption method.
 
At this point I'm trying to do two different things.

The first is figuring out how that code above is actually working. It does work, I can hide a messages in a .bmp and take them out. But I need to know how its doing it before I can move on to the next step.

Which is the DCT stenography. There are a few different types already out there. We are going to try F5.

I think if I can figure out how the code is manipulating the pixels in the code above, I will have an easier time figuring out how the F5 works and can be implemented.
 
what it does?

I am not sure - adding values that are powers of 256, are possibly changing the RGB values of each pixel. So you get the same image, but with changed colours.

I am not exactly sure of the structure of a jpeg file, but RGB colours follow this pattern. ie a 24 bit colour uses 3 bytes, one for each of (R,G,B)

iSize = iSize + Asc(ch) * 256
ch = oldFile.Read(1)
newFile.Write (ch)
iSize = iSize + Asc(ch) * 65536
ch = oldFile.Read(1)
newFile.Write (ch)
iSize = iSize + Asc(ch) * 16777216
 
I added MsgBoxs to this part to try and see if I could figure out what it was doing by looking at the values. But it is not doing what I would expect.

Its ran 4 times in a row and adds to the value of iSize.

The first time it runs there is a value for ch. But then the last 3 times ch has no value. Or it might be holding an unprintable character. But if it was holding an unprintable character, it should still be able to be passed to iSize in the next line because its getting the Ascii value. A value is set to iSize during the first iteration and then stays the same through all three of the other iterations.

That's making me think that ch is really not getting any value the last three times. It trys to multiply the Aschii value of ch and I'm thinking that since there is nothing there the answer to the equation is 0 and iSize + 0 = iSize
That's why it does not change after the first time.


ch = oldFile.Read(1)
MsgBox ch (this is the only time ch has a value)
newFile.Write (ch)
iSize = Asc(ch)
MsgBox iSize (iSize gets a value here that never changes)

ch = oldFile.Read(1)
MsgBox ch
newFile.Write (ch)
iSize = iSize + Asc(ch) * 256
MsgBox iSize

ch = oldFile.Read(1)
MsgBox ch
newFile.Write (ch)
iSize = iSize + Asc(ch) * 65536
MsgBox iSize

ch = oldFile.Read(1)
MsgBox ch
newFile.Write (ch)
iSize = iSize + Asc(ch) * 16777216
MsgBox iSize

But why is this even here? What's it doing?
My best guess as of now is its getting the size of the old file was to help create the new file.

This is the line that the computed iSize variable is used for:
newFile.Write (oldFile.Read(iSize - 14))


Then there is this:

newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 128) \ 128)))

I see we are writing to the new file but I don't get the Or in the statement. To me it looks like it saying write a OR b. But that doesn't make sense. I have to be miss understanding that.
 
I just tried to create a sub and work through the code.
I can definitely put in a message (encode) and it certainly does the decode.

I have added some comments based on my best guess and some review.
I used Notepad++ to monitor the newfile as it was being created. If you step through the code, and after each step you go to notepad++ and reload from disk you can see individual characters being written. I haven't spent enough time deciphering, but maybe someone more technical with the bit/byte ANDing/ORing can help with the details.

Some of my guesses may need adjusting also --feel free -there is nothing in stone here.

I am attaching a part of the encoded data as displayed in Notepad++.

Here is the commented code
Code:
Sub SteganographyTest()


    
    Const ForReading = 1, ForWriting = 2, ForAppending = 8
    Dim oldFile, newFile, oFS, iSize, strMessage, i, ch, strPath 'all variants
    
    'get the name of the bmp file to be used
    strPath = InputBox("File Path of Bitmap File:")
    Set oFS = CreateObject("Scripting.FileSystemObject")
    Set oldFile = oFS.OpenTextFile(strPath, ForReading) 'set file for read only
     
    ' Switch for program to 1 encode or 2 decode
    If InputBox("1 for encode, 2 to decode") = 1 Then
       'encoding so create a new file using oldfile name with suffix "-e"
       'and set up for writing
        Set newFile = oFS.OpenTextFile(Replace(strPath, ".bmp", "-e.bmp"), ForWriting, True)
        
        'isize is size of oldfile after integer divide by 8, then subtract 1
        'This determines the number of bytes you can use for message
        iSize = (oFS.GetFile(strPath).Size \ 8) - 1
      
        Do
            'get the message from the user
            strMessage = InputBox("Enter your message. The maximum number of characters is " & iSize & ".")
        Loop Until Len(strMessage) <= iSize
      'write the first 10 byts of old file (bmp header info probably)
        newFile.Write (oldFile.Read(10))
      'ch ?? is next 1 byte from old file
        ch = oldFile.Read(1)
      'write that byte to the new file
        newFile.Write (ch)
      'reuse isize it's now the asc representation of that byte
        iSize = Asc(ch)
      'reuse ch and assign it the next byte of the old file
        ch = oldFile.Read(1)  '''space/NUL in my case
        newFile.Write (ch)
        iSize = iSize + Asc(ch) * 256
      'assign next byte of old file to ch
        ch = oldFile.Read(1)
      'write that byte to new file
        newFile.Write (ch) 'another  space/NUL in my case
        
        iSize = iSize + Asc(ch) * 65536  'my isize is 54 jed
     
        ch = oldFile.Read(1)
        newFile.Write (ch)
        iSize = iSize + Asc(ch) * 16777216  'isize is still 54
     
        newFile.Write (oldFile.Read(iSize - 14))
     ' Loop through the message
     'set ch to the ASC of the next byte
        For i = 1 To Len(strMessage)
            ch = Asc(Mid(strMessage, i, 1))
     'ANDing bits of the BYTE (algorithm??) and writing the byte to new file
            newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 128) \ 128)))
            newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 64) \ 64)))
            newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 32) \ 32)))
            newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 16) \ 16)))
            newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 8) \ 8)))
            newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 4) \ 4)))
            newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 2) \ 2)))
            newFile.Write (Chr((Asc(oldFile.Read(1)) And 254) Or ((ch And 1) \ 1)))
        Next
     
        For i = 1 To 8  'repeat 8 times
        'get the CHR for the ASC of the byte in the Old File anded with 254  (2^^8) -2
        '
        '***  The number 254 in base 10 = 11111110 in base 2
        '
            newFile.Write (Chr(Asc(oldFile.Read(1)) And 254))
        Next
     
     ' repeat writing  1024 byte chunks to new file until oldfile is at eof
        Do Until oldFile.AtEndOfStream
            newFile.Write (oldFile.Read(1024))
        Loop
     
        newFile.Close
        Set newFile = Nothing
     
        MsgBox "Message Encoded!"  'give user notice that encoding is finished
    Else
      'this is the decoding part (when decoding the old file is the encoded file)
        i = 0
        ch = 0
        strMessage = ""
     ' read 10 bytes from the oldfile
        oldFile.Read (10)
        
        'read next byte of old file - get the asc representation of that byte and assign to isize
        iSize = Asc(oldFile.Read(1))
        'isize
        iSize = iSize + Asc(oldFile.Read(1)) * 256
        iSize = iSize + Asc(oldFile.Read(1)) * 65536
        iSize = iSize + Asc(oldFile.Read(1)) * 16777216
        oldFile.Read (iSize - 14)
     
     ' do the following until encoded file is at eof
        Do Until oldFile.AtEndOfStream
            i = i + 1
            ch = ch Or ((Asc(oldFile.Read(1)) And 1) * (2 ^ (8 - i)))
     
            If i = 8 Then
                strMessage = strMessage & Chr(ch)
                If ch = 0 Then
                    Exit Do
                Else
                    ch = 0
                    i = 0
                End If
            End If
        Loop
     
        MsgBox strMessage
    End If
     
    oldFile.Close
    Set oldFile = Nothing
    Set oFS = Nothing


End Sub
 

Attachments

  • Notepad++PartialFile.jpg
    Notepad++PartialFile.jpg
    99.3 KB · Views: 81
Last edited:
How do I stop it and check its progression with notepad ++?
 
In Access, you can step through the code by using F8 key.This executes 1 line at a time.
Ctrl G gets you to the vbe environment.

Also if you click in the left column of the code window, this will put a breakpoint on that line. That will stop execution at that line.

More options if you select Debug in the vbe.
see attached
 

Attachments

  • breakpoint.jpg
    breakpoint.jpg
    38.6 KB · Views: 79

Users who are viewing this thread

Back
Top Bottom