WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

System_Drawing

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Use System.Drawing for Steganograhpy

 Keywords: C# System.Drawing Steganograhpy GenerateInMemory Generate In Memory

  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; Dotnet Steganography
  ;;
  ;; Steganography is the practise of hiding information by embedding messages within
  ;; other information. This steganography example works by replacing the least significant
  ;; bit of color bytes in a bitmap image file with bits of different, invisible
  ;; information.
  ;;
  ;; Note that the bitmap file must hold an uncompressed, unindexed, standard 24 bit color
  ;; ARGB bitmap.  Lossy bitmap representations like jpeg compressed files will not work.
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  
  
  ; Define UDFs.
  GoSub UdpsDefined
  
  ; Load assemblies required by the three UDFs.
  ObjectClrOption('useany', 'System')
  ObjectClrOption('useany', 'System.Drawing')
  
  ; Compile the in-memory color structure helper class.
  CompileWbColor( )
  
  ; Text to encode.
  strEmbed = 'WinBatch'
  
  ; Bitmap to encode.
  strIn = 'c:\temp\Hawaii.bmp'
  
  ; Embeded bitmap.
  strOut = 'c:\temp\Hawaiiembedded.bmp'
  
  ; Endcode text in a bitmap.
  EmbedText(strIn, strOut, strEmbed)
  
  ; Extract Text from a bitmap.
  strExtracted = ExtractText(strOut)
  
  
  ; Display results.
  Message('.Net Steganography Test', 'Orignal Text:  ':strEmbed:@lf:'Extracted Text:  ':strExtracted)
  Exit
  
  
  :UdpsDefined
  
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;;  CompileWbColor
  ;;
  ;;  Performs an in-memory compilation of a System.Drawing.Color helper class.  This class
  ;;  is necessary because the CLR does not allow WIL CLR hosting to access the methods of
  ;;  the class as it is always returned as an unsigned integer strip of its object identity.
  ;;
  ;; returns 1 on succes; otherwise: aborts script on compiler errors.
  ;;
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  #DefineFunction CompileWbColor ()
     objCSharp = ObjectClrNew('Microsoft.CSharp.CSharpCodeProvider')
     objParams = ObjectClrNew('System.CodeDom.Compiler.CompilerParameters')
     objParams.ReferencedAssemblies.Add("System.Drawing.dll")
     objParams.GenerateInMemory = ObjectType( "VT_BOOL", 1 )
     cSharpSource = $"
  using  System.Drawing;
  namespace WinBatch {
     public class WbColor  {
  
        public void SetColor (Bitmap objBitMap, Int x, Int y, Int nColor)
        {
           // Need To flip the colors because the .Net structure
           // representation is In abgr order which is how the bitmap
           // actually stores color information.
           Int a =  (nColor>>24) & 0x000000ff;
           Int b = (nColor>>16) & 0x000000ff;
           Int g = (nColor>>8) & 0x000000ff;
           Int r = nColor & 0x000000ff;
           objBitMap.SetPixel(x, y, Color.FromArgb(a, r, g, b));
        }
     }
  }
  ;$"
  
     objResult = objCSharp.CompileAssemblyFromSource(objParams,cSharpSource)
  
     ; Shouldn't see any of this if the C# code is written correctly.
     strOutput = ''
     bError = 0
     If objResult.Output.Count > 0
        strOuput - 'Compiler Output: ':@lf
        For x = 0 To objResult.Output.Count-1
           If strOutput == "" Then strOutput = objResult.Output.Item(x)
           Else strOutput = strOutput:@lf:objResult.Output.Item(x)
        Next
     EndIf
     ; Compiler Errors
     If objResult.Errors.Count > 0
        strErrors = ''
        ForEach ce In objResult.Errors
           If strErrors == "" Then strErrors = ce.ToString()
           Else strErrors = strErrors:@lf:ce.ToString()
         Next
        strOuput := @lf:@lf:'Compiler Errors: ':lf:strErrors
        bError = 1
     EndIf
     If strOutput != ''
        Pause('Compile Report', strOutput)
        If bError Then Exit ; Abort on compiler error.
     EndIf
  
     ; Releasing objects is not necessary because all valiables
     ; are automaticaly release because the UDFs variable table
     ; is cleared when the variables go out of scope.
     Return 1
  #EndFunction
  
  
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; EmbedText
  ;;
  ;;  Embeds text in a bigmap file using the LSB techneque.  A serries of 8 zero bits indicastes
  ;;  the end of the embedded text.  It is possible for 8 zero LSBs to occure naturally in
  ;;  the bitmap but not within the range of pixels with embed text.
  ;;
  ;; _strBitIn  - array returned by GdiplusStartup()
  ;; _strBitOut - image handle returned by gpLoadImageFromFile()
  ;; _strText  - text to hide.
  ;;
  ;; returns 1 on succes; otherwise 0 if Image is to small to hold the text.
  ;;
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  #DefineFunction EmbedText(_strBitIn, _strBitOut, _strText)
  
     objBitmap  = ObjectClrNew('System.Drawing.Bitmap', _strBitIn)
     objWbColor = ObjectClrNew('WinBatch.WbColor') ; Helper class.
  
     xMax = objBitmap.Width - 1
     yMax = objBitmap.Height - 1
  
     nTotalPix = objBitmap.Width * objBitmap.Height
     nTextLen  = StrLen(_strText)
     nPixNeeded = (nTextLen+1)/3 ; +1 for stop byte.
     If nTextLen mod 3 Then nPixNeeded += 1
  
     ; Check for enough room
     If nPixNeeded > nTotalPix Then Return 0  ; Not enough room.
  
     aText = ArrayFromStr(_strText)
     iMax = nTextLen
  
     ; RGB target bits
     LsbR = 1<<16
     lsbG = 1<<8
     lsbB = 1
  
     ; Encode each bit of each characeter in a pixel color's LSB.
     x = 0
     y = 0
     nMask = LsbR  ; LSB Red
     nColor = objBitmap.GetPixel(x, y)
     For i = 0 To iMax
        If i == iMax Then nChar = 0 ; Encode a stop byte
        Else nchar = Char2Num(aText[i])
  
        For j = 0 To 7
           bBit = nchar & (1<<j)
           bColorBit = nColor&nMask
  
           ; Flip the bit as needed.
           If bColorBit && bBit == 0
              nColor &= (~nMask) ; Clear bit.
           ElseIf bColorBit == 0 && bBit
              nColor |= nMask   ; Set bit.
           EndIf
  
           ;; Set the next mask.
           If nMask == LsbR
              nMask = lsbG ; LSB green
           ElseIf nMask == lsbG
              nMask = lsbB ; LSB Blue
           ElseIf nMask == lsbB
  
              ;; Save then load a pixel.
              objWbColor.SetColor(objBitmap, x, y, i4:nColor)
              If x == xMax
                 y += 1
                 x = 0
              Else
                 x += 1
              EndIf
              nColor = objBitmap.GetPixel(x, y)
              nMask = LsbR  ; LSB Red
           EndIf
        Next
     Next
  
     ; Make sure the last pixel is saved.
     objWbColor.SetColor(objBitmap, x, y, i4:nColor)
  
     ; Save the new Bitmap.
     objBitmap.Save(_strBitOut)
  
     objBitmap.Dispose()
     Return 1
  #EndFunction
  
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; ExtractText
  ;;
  ;; Decodes text imbedded in a bitmap image. A serries of 8 zero bits indicastes
  ;; the end of the embedded text.  It is possible for 8 zero LSBs to occure naturally in
  ;; the bitmap but not within the range of pixels with embed text.
  ;;
  ;; _strFile - Full name+path  of bitmap file.
  ;;
  ;; returns extrated text on succes; otherwise an empty string.
  ;;
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  #DefineFunction ExtractText(_strFile)
  
     strReturn = ''
     objBitmap  = ObjectClrNew('System.Drawing.Bitmap', _strFile)
  
     xMax = objBitmap.Width - 1
     yMax = objBitmap.Height - 1
  
     nCharCnt = 0
     x = 0
     y = 0
  
     ; RGB target bits
     LsbR = 1<<16
     lsbG = 1<<8
     lsbB = 1
  
     nMask = LsbR
     nColor = objBitmap.GetPixel(x, y)
  
     nZeroCnt = 0
     While nZeroCnt < 8  ; Until we encounter a stop byte.
  
        nChar = 0
        nZeroCnt = 0
        For j = 0 To 7
  
           ; Decode
           If nColor&nMask Then nChar |= 1<<j
           Else nZerocnt += 1
           If nMask == LsbR
              nMask = lsbG
           ElseIf nMask == lsbG
              nMask = lsbB
           ElseIf nMask == lsbB
  
              ; Load a pixel.
              If x == xMax
                 x = 0
                 If y == yMax Then Return '' ; Stop byte not found.
                 y += 1
              Else
                 x += 1
              EndIf
              nColor = objBitmap.GetPixel(x, y)
              nMask = LsbR
           EndIf
        Next
        strReturn := Num2Char(nChar)
     EndWhile
  
     objBitmap.Dispose()
     Return strReturn
  
  #EndFunction
  
  Return ; from UDP definitions.
  

Article ID:   W18535
Filename:   Use System.Drawing for Steganograhpy.txt
File Created: 2020:07:29:09:50:26
Last Updated: 2020:07:29:09:50:26