Ukrywaliśmy już pliki, wiadomość i obrazki w różnych miejscach. Siłą rzeczy następnym miejscem, w którym ukryjemy nasze elementy, będą pliki dźwiękowe, do najprostszych, jeśli chodzi o strukturę, należy format WAVE. Jest on bardzo podobny do struktury formatu pliku BMP, do zapisu i odczytania danych używana jest konwersja bezstratna, dlatego możemy bez przeszkód, manipulować tymi danymi nie martwiąc się, że po ich zmianie dane ulegną uszkodzeniu lub będą błędnie odczytane. Plik WAVE składa się z trzech głównych elementów:
Nagłówek RIFF:
Podkategoria „fmt” opisuje format danych dźwiękowych:
Podkategoria „danych” zawiera rozmiar danych i rzeczywisty dźwięk:
Czasem występuje również podkategoria JUNK, która nadaje się do ukrycia tekstu w bardzo prosty sposób. W dalszej części pokaże algorytm, który będzie dodawał takie pola. Kategoria ta może występować zarówno po RIFF, jak i po „fmt „:


Można ją wygenerować sztucznie i wpisać w niej cokolwiek tylko chcemy, z zachowaniem pewnych zasad. Przykładowy program pozwalający na ukrycie pliku w bajtach nagłówka JUNK:
Imports System.Windows.Forms
Module Module1
Sub Main()
'Otwiera dialog z użytkownikiem
Console.WriteLine("Co chesz zrobić? Wpisz cyfrę zadania." + vbNewLine + "1.Wydobądź ukryty plik." _
+ vbNewLine + "2.Ukryj plik.")
Dim zad As String
Do
zad = Console.ReadLine()
If zad = "1" Or zad = "2" Then
Exit Do
Else
Console.WriteLine("możesz wybrać tylko cyfrę 1 lub 2.")
End If
Loop
Dim open_dialog As New OpenFileDialog()
open_dialog.InitialDirectory = "c:\"
open_dialog.Filter = "Image Files (*.wav)| *.wav"
If open_dialog.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
If zad = 2 Then
''Ukrywanie pliku
Dim File_bytes As Byte() = IO.File.ReadAllBytes(open_dialog.FileName)
Dim plikDoUkrycia As New OpenFileDialog()
plikDoUkrycia.InitialDirectory = "c:\"
plikDoUkrycia.Filter = "All Files|*.*"
If plikDoUkrycia.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
Dim File_DoUkrycia As Byte() = IO.File.ReadAllBytes(plikDoUkrycia.FileName)
'tworzymy nagłówek Junk wraz z wielkością pliku ukrywanego
Dim naglowekJunk() As Byte = System.Text.Encoding.ASCII.GetBytes("JUNK")
Dim wielkoscJunk() As Byte = System.BitConverter.GetBytes(File_DoUkrycia.Count)
'kopiujemy poczatek bajtów pliku oryginalnego (12 bajtów nagłówka RIFF
Dim poczatek(12) As Byte
Array.Copy(File_bytes, poczatek, 12)
'Tworzy nową tablicę o wielkośći połączonych ilości bajtów pliku kontenera,
' pliku ukrywanego i 8 bajtów dla slowa JUNK i wielkości dla pliku ukrywanego
Dim nowyplik(File_bytes.Count + File_DoUkrycia.Count + 7) As Byte
'kopiuje RIFF
Array.Copy(poczatek, nowyplik, poczatek.Count)
'kopiuje JUNK i wielkość pliku ukrywanego
Array.Copy(naglowekJunk, 0, nowyplik, 12, naglowekJunk.Count)
Array.Copy(wielkoscJunk, 0, nowyplik, 16, wielkoscJunk.Count)
'kopiuje bajty pliku ukrywanego
Array.Copy(File_DoUkrycia, 0, nowyplik, 20, File_DoUkrycia.Count)
'kopiuje reszte bajtów kontenera
Array.Copy(File_bytes, 12, nowyplik, 20 + File_DoUkrycia.Length, File_bytes.Count - 12)
Console.Write("Podaj nazwę pliku pod którym chcesz zapisać plik wav: ")
Dim nazwapliku As String = Console.ReadLine()
IO.File.WriteAllBytes("C:\Users\piotr\Desktop\" + nazwapliku + ".wav", nowyplik)
Console.WriteLine("Bajty zostały ukryte. Zapisano plik: " + "C:\Users\piotr\Desktop\" +
nazwapliku + ".wav")
End If
Console.ReadLine()
Else
'przygotowanie pliku
Dim listaBajtowPlikuUkrytego As New List(Of Byte)
Dim wielkoscPliku As Integer = 0
'otwórz wskazany plik
Dim wavefile() As Byte = IO.File.ReadAllBytes(open_dialog.FileName)
Dim memstream As New IO.MemoryStream(wavefile)
'czytaj wszystkie bajty pliku
Using binreader As New IO.BinaryReader(memstream)
Do
'czytaj do czasu aż natrafisz na 'JUNK' lub 'junk'
Dim Junk As String = BitConverter.ToString(binreader.ReadBytes(4), 0)
If (Junk = "6A-75-6E-6B" Or Junk = "4A-55-4E-4B") Then
'pobierz wielkość pliku ukrytego
wielkoscPliku = BitConverter.ToInt32(binreader.ReadBytes(4), 0)
Exit Do
End If
Loop
'zapisz bajty pliku ukrytego do listy
For i As Integer = 0 To wielkoscPliku - 1
listaBajtowPlikuUkrytego.Add(binreader.ReadByte)
Next
End Using
'stwórz nową tablicę
Dim nowyplik() As Byte = listaBajtowPlikuUkrytego.ToArray()
'Podaj nazwę pliku
Console.WriteLine()
Console.Write("Podaj nazwę pliku pod którycm chcesz zapisać plik: ")
Dim nazwapliku As String = Console.ReadLine()
'zapisz plik
IO.File.WriteAllBytes("C:\Users\piotr\Desktop\" + nazwapliku, nowyplik)
Console.WriteLine("Bajty zostały odzyskane. Zapisano plik: " + "C:\Users\piotr\Desktop\" + nazwapliku)
Console.ReadLine()
End If
End If
End Sub
End Module
Taki program pobiera bajty pliku kontenera, oddziela dwanaście pierwszych bajtów i dodaje cztery bajty JUNK, wielkość bajtów pliku ukrytego, a następnie bajty ukrytego pliku i resztę bajtów kontenera. Pierwsza opcja pozwala na pobranie i zapis tych bajtów. Jeśli plik ukrywany nie jest duży, może zdezorientować analityka, który potraktuje te sekcje jako śmieci. Kolejną metodą dodania dodatkowych bajtów do kontenera jest przekształcenie nagłówka „fmt” przekształcając Subchunk1size, ExtraParamSize i ExtraParams:
Imports System.Windows.Forms
Module Module1
Sub Main()
'Otwiera dialog z użytkownikiem
Console.WriteLine("Co chesz zrobić? Wpisz cyfrę zadania." + vbNewLine + "1.Wydobądź ukryty plik." _
+ vbNewLine + "2.Ukryj plik.")
Dim zad As String
Do
zad = Console.ReadLine()
If zad = "1" Or zad = "2" Then
Exit Do
Else
Console.WriteLine("możesz wybrać tylko cyfrę 1 lub 2.")
End If
Loop
Dim open_dialog As New OpenFileDialog()
open_dialog.InitialDirectory = "c:\"
open_dialog.Filter = "Image Files (*.wav)| *.wav"
If open_dialog.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
If zad = 2 Then
''Ukrywanie pliku
Dim File_bytes As Byte() = IO.File.ReadAllBytes(open_dialog.FileName)
Dim plikDoUkrycia As New OpenFileDialog()
plikDoUkrycia.InitialDirectory = "c:\"
plikDoUkrycia.Filter = "All Files|*.*"
If plikDoUkrycia.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
Dim File_DoUkrycia As Byte() = IO.File.ReadAllBytes(plikDoUkrycia.FileName)
Dim poczatek(16) As Byte
Array.Copy(File_bytes, poczatek, 16)
Dim wielkoscPoczatkowa() As Byte = {File_bytes(16), File_bytes(17), File_bytes(18), File_bytes(19)}
'Jeśli plik nie zawiera dodatkowych danych (Subchunk1Size = 16)
If BitConverter.ToString(wielkoscPoczatkowa, 0) = "10-00-00-00" Then
'pobiera początkowe 18 bajtów
Dim wielkoscFMT() As Byte = System.BitConverter.GetBytes(File_DoUkrycia.Count + 18)
wielkoscPoczatkowa = wielkoscFMT
'Tworzymy nową tablicę o wielkośc pliku i pliku ukrywanego + 2 bajty dla ExtraParamSize
Dim nowyplik(File_bytes.Count + File_DoUkrycia.Count + 2) As Byte
' kopiujemy początek do noewgo pliku
Array.Copy(poczatek, nowyplik, poczatek.Count)
'nadajemy nową wartość dla Subchunk1Size
Array.Copy(wielkoscPoczatkowa, 0, nowyplik, 16, wielkoscPoczatkowa.Count)
'dodajemy 16 bajtów nagłówka fmt
Array.Copy(File_bytes, 20, nowyplik, 20, 16)
'tworzymy wielkość dla ExtraParamSize
Dim wielkoscPliku As Short
Try 'wielkość ta jes dwu bajtowa więc nasz pli nie może mieć więcej niż (FF FF) bajtów czyli 65535
wielkoscPliku = File_DoUkrycia.Length
Catch ex As Exception
Console.WriteLine("Twój plik jest za duży. Można ukryć tylko pliki nie większe niż: " + Short.MaxValue.ToString + " bajtów" + vbNewLine +
" twój plik zawiera: " + File_DoUkrycia.Length.ToString + " bajtów")
Exit Sub
End Try
'dodajemy ExtraParamSize
Array.Copy(System.BitConverter.GetBytes(wielkoscPliku), 0, nowyplik, 36, 2)
'dodajemy bajty pliku do ukrycia
Array.Copy(File_DoUkrycia, 0, nowyplik, 38, File_DoUkrycia.Count)
'dodajemy resztę bajtów pliku kontenera
Array.Copy(File_bytes, 36, nowyplik, 38 + File_DoUkrycia.Length, File_bytes.Count - 36)
'zapisujemy plik
Console.Write("Podaj nazwę pliku pod którym chcesz zapisać plik wav: ")
Dim nazwapliku As String = Console.ReadLine()
IO.File.WriteAllBytes("C:\Users\piotr\Desktop\" + nazwapliku + ".wav", nowyplik)
Console.WriteLine("Bajty zostały ukryte. Zapisano plik: " + "C:\Users\piotr\Desktop\" +
nazwapliku + ".wav")
Else
Console.WriteLine("Twój plik już zawieje dodatkowe parametry.")
End If
End If
Console.ReadLine()
Else
'przygotowanie pliku
Dim listaBajtowPlikuUkrytego As New List(Of Byte)
Dim wavefile() As Byte = IO.File.ReadAllBytes(open_dialog.FileName)
Dim wielkoscPoczatkowa() As Byte = {wavefile(16), wavefile(17), wavefile(18), wavefile(19)}
'sprawdzamy czy Subchunk1Size = 16 jesli nie to
If Not BitConverter.ToString(wielkoscPoczatkowa, 0) = "10-00-00-00" Then
'pobieramy wielkość ukrytego pliku
Dim wielkoscPlikuUkrytego As Short = BitConverter.ToInt16({wavefile(36), wavefile(37)}, 0)
'dodajemy bajty ukrytego pliku do listy
For i As Integer = 38 To 38 + wielkoscPlikuUkrytego - 1
listaBajtowPlikuUkrytego.Add(wavefile(i))
Next
End If
'tworzymy nową tablicę
Dim nowyplik() As Byte = listaBajtowPlikuUkrytego.ToArray()
'Podaj nazwę pliku
Console.WriteLine()
Console.Write("Podaj nazwę pliku pod którycm chcesz zapisać plik: ")
Dim nazwapliku As String = Console.ReadLine()
'zapisz plik
IO.File.WriteAllBytes("C:\Users\piotr\Desktop\" + nazwapliku, nowyplik)
Console.WriteLine("Bajty zostały odzyskane. Zapisano plik: " + "C:\Users\piotr\Desktop\" + nazwapliku)
Console.ReadLine()
End If
End If
End Sub
End Module
Zasada działania jest taka sama jak przy dodawaniu nagłówka JUNK, w tym wypadku pobieramy bajty pliku i modyfikujemy obszary, aby następnie dodać dwa bajty wielkości tekstu/pliku i jego bajty. Wiemy już gdzie ukryć dane w strukturze pliku. Zajmijmy się samym dźwiękiem. Jak już wcześniej wspomniałem pliki w formacie WAVE, zawierają dane 8, 16, 24, lub 32 bitowe. Gdzie 8 bitowych plików WAVE już się nie używa. Zmiana dźwięku poprzez zerowanie LSB będzie najbardziej efektywna, gdy będziemy mieli do czynienia z plikami 32 bitowymi, ponieważ ich modyfikacje nie zmienią znacząco dźwięku, gdyż jego długość jest dosyć duża:
16 bit = 00 00 do FF FF (0 do 65535)
24 bit = 00 00 00 do FF FF FF (0 do 16777215)
32 bity = 00 00 00 00 do FF FF FF FF (0 do 4294967295)
Zapożyczenie, nawet 2 bajtów w przypadku pliku 32 bitowego, nie pogorszy znacząco jego jakości. Przygotowałem aplikację, która prezentuje zmianę dźwięk po wyzerowaniu wskazanej ilości bajtów: program zerujący bity w pliku WAV
Uwaga, program może mieć problem z rysowaniem histogramu dla 32 bitowych plików WAV. Spowodowane jest to dużą skalą, która może w takim pliku występować. Histogram rysowany przez program jest tylko pomocniczy, aby w pełni zaobserwować zmiany dokonane na pliku, zapisz jego zmodyfikowaną wersje przy użyciu przycisku „Zapisz”.
Imports System.Windows.forms
Imports System.Drawing
Module Module1
Dim pictureboxKontener As New PictureBox
Dim buttonKontenera As New Button
Dim label1 As New Label
Dim trackbar1 As New TrackBar
Dim pictureboxGenerowany As New PictureBox
Dim buttonGeneratora As New Button
Dim buttonZapisz As New Button
Dim panel1 As New Panel
Dim panel2 As New Panel
Dim bajtyNaglowka As New List(Of Byte)
Dim DaneOryginalne As New List(Of UInteger)
Dim DaneLSB As New List(Of UInteger)
Dim najwyzszaWartoscDzwieku As Integer = 0
Dim iloscBitow As Short
Private Sub WygenerujForme()
Dim form1 As New Form
form1.StartPosition = FormStartPosition.CenterScreen
form1.Size = New System.Drawing.Size(371, 698)
panel1.Size = New System.Drawing.Size(355, 240)
panel1.Location = New System.Drawing.Point(0, 0)
panel1.AutoScroll = True
panel1.Anchor = AnchorStyles.Left Or AnchorStyles.Top Or AnchorStyles.Right
form1.Controls.Add(panel1)
buttonKontenera.Location = New System.Drawing.Point(5, 246)
buttonKontenera.Name = "buttonKontenera"
buttonKontenera.Size = New System.Drawing.Size(75, 23)
buttonKontenera.TabIndex = 1
buttonKontenera.Text = "Play"
AddHandler buttonKontenera.Click, AddressOf GrajOryginal
form1.Controls.Add(buttonKontenera)
label1.Location = New System.Drawing.Point(12, 287)
label1.Name = "label1"
label1.AutoSize = False
label1.Size = New System.Drawing.Size(331, 23)
label1.TabIndex = 2
label1.Text = "Wyzerowano 0 ostatnich bitów , to daje: 0 wojnych Bajtów."
form1.Controls.Add(label1)
trackbar1.Location = New System.Drawing.Point(0, 316)
trackbar1.Name = "trackbar1"
trackbar1.RightToLeft = RightToLeft.Yes
trackbar1.Size = New System.Drawing.Size(355, 45)
If iloscBitow = 16 Then
trackbar1.Maximum = 14
ElseIf iloscBitow = 24 Then
trackbar1.Maximum = 22
ElseIf iloscBitow = 32 Then
trackbar1.Maximum = 30
End If
trackbar1.TabIndex = 3
AddHandler trackbar1.ValueChanged, AddressOf TrackBar1_ZmianaWartosci
form1.Controls.Add(trackbar1)
panel2.Size = New System.Drawing.Size(355, 240)
panel2.Location = New System.Drawing.Point(0, 367)
panel2.AutoScroll = True
panel2.Anchor = AnchorStyles.Left Or AnchorStyles.Top Or AnchorStyles.Right
form1.Controls.Add(panel2)
buttonGeneratora.Location = New System.Drawing.Point(5, 626)
buttonGeneratora.Name = "buttonGeneratora"
buttonGeneratora.Size = New System.Drawing.Size(75, 23)
buttonGeneratora.TabIndex = 5
buttonGeneratora.Text = "Play"
AddHandler buttonGeneratora.Click, AddressOf GrajWygenerownyDzwiek
form1.Controls.Add(buttonGeneratora)
buttonZapisz.Location = New System.Drawing.Point(85, 626)
buttonZapisz.Name = "buttonZapisz"
buttonZapisz.Size = New System.Drawing.Size(75, 23)
buttonZapisz.TabIndex = 6
buttonZapisz.Text = "Zapisz"
AddHandler buttonZapisz.Click, AddressOf ZapiszKlik
form1.Controls.Add(buttonZapisz)
form1.ShowDialog()
End Sub
Sub Main()
Dim open_dialog As New OpenFileDialog()
open_dialog.InitialDirectory = "c:\"
open_dialog.Filter = "Image Files (*.wav)|*.wav"
open_dialog.Title = "Wskaż plik dźwiękowy"
If open_dialog.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
PobierzBajty(open_dialog.FileName)
WygenerujForme()
End If
End Sub
Private Sub PobierzBajty(ByVal FileName As String)
Dim wavefile() As Byte = IO.File.ReadAllBytes(FileName)
Dim memstream As New IO.MemoryStream(wavefile)
Using binreader As New IO.BinaryReader(memstream)
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' ChunkID
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' filesize
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' rifftype
' fmtID (czasem w plikach Wave znajduje się dodatkowy nagłówek zwany JUNK, jeśli istnieje, należy jego dane dodać lub usunąć)
'dodawanie
Do Until BitConverter.ToString({bajtyNaglowka(bajtyNaglowka.Count - 4), bajtyNaglowka(bajtyNaglowka.Count - 3),
bajtyNaglowka(bajtyNaglowka.Count - 2), bajtyNaglowka(bajtyNaglowka.Count - 1)}, 0) = "66-6D-74-20"
bajtyNaglowka.Add(binreader.ReadByte)
Loop
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' fmtsize
Dim fmtsize As Byte() = {bajtyNaglowka(bajtyNaglowka.Count - 4), bajtyNaglowka(bajtyNaglowka.Count - 3),
bajtyNaglowka(bajtyNaglowka.Count - 2), bajtyNaglowka(bajtyNaglowka.Count - 1)}
bajtyNaglowka.AddRange(binreader.ReadBytes(2)) ' fmtcode
bajtyNaglowka.AddRange(binreader.ReadBytes(2)) ' fmtcode
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' samplerate
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' fmtAvgBPS
bajtyNaglowka.AddRange(binreader.ReadBytes(2)) ' fmtblockalign
bajtyNaglowka.AddRange(binreader.ReadBytes(2)) ' bitdepth
iloscBitow = BitConverter.ToInt16({bajtyNaglowka(bajtyNaglowka.Count - 2), bajtyNaglowka(bajtyNaglowka.Count - 1)}, 0)
If BitConverter.ToUInt32(fmtsize, 0) = 18 Then
bajtyNaglowka.AddRange(binreader.ReadBytes(2))
End If
' DataID'
Do Until BitConverter.ToString({bajtyNaglowka(bajtyNaglowka.Count - 4), bajtyNaglowka(bajtyNaglowka.Count - 3),
bajtyNaglowka(bajtyNaglowka.Count - 2), bajtyNaglowka(bajtyNaglowka.Count - 1)}, 0) = "64-61-74-61"
bajtyNaglowka.Add(binreader.ReadByte)
Loop
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' DataSize
Dim DataSize As Byte() = {bajtyNaglowka(bajtyNaglowka.Count - 4), bajtyNaglowka(bajtyNaglowka.Count - 3) _
, bajtyNaglowka(bajtyNaglowka.Count - 2), bajtyNaglowka(bajtyNaglowka.Count - 1)}
'ładuje odpowiednio duże dane do listy
If iloscBitow = 16 Then
For i = 0 To (BitConverter.ToUInt32(DataSize, 0) / 2) - 1
DaneOryginalne.Add(binreader.ReadUInt16())
Next
ElseIf iloscBitow = 32 Then
For i = 0 To (BitConverter.ToUInt32(DataSize, 0) / 4) - 1
DaneOryginalne.Add(binreader.ReadUInt32())
Next
ElseIf iloscBitow = 24 Then
For i = 0 To (BitConverter.ToUInt32(DataSize, 0) / 3) - 1
Dim DataSize2(3) As Byte
DataSize2(3) = 0
DataSize2(0) = binreader.ReadByte
DataSize2(1) = binreader.ReadByte
DataSize2(2) = binreader.ReadByte
DaneOryginalne.Add(BitConverter.ToUInt32(DataSize2, 0))
Next
End If
End Using
OryginalHistogram()
End Sub
Private Sub OryginalHistogram()
Dim przeskok As Integer
pictureboxKontener.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
pictureboxKontener.Location = New System.Drawing.Point(0, 0)
pictureboxKontener.Name = "Kontener"
If Not iloscBitow = 32 Then
pictureboxKontener.Size = New System.Drawing.Size((DaneOryginalne.Count - 1) / 2, 220)
przeskok = 1
Else
pictureboxKontener.Size = New System.Drawing.Size((DaneOryginalne.Count - 1) / 2000, 220)
przeskok = (DaneOryginalne.Count - 1) / 2000
End If
pictureboxKontener.TabIndex = 0
pictureboxKontener.TabStop = False
panel1.Controls.Add(pictureboxKontener)
Dim obraz As New Bitmap(pictureboxKontener.Width, 240)
Dim gfx As Graphics = Graphics.FromImage(obraz)
'Stwórz grafikę kwadratu ktory posłuży za tło
gfx.FillRectangle(Brushes.White, 0, 0, obraz.Width, obraz.Height)
'ustawiamy przeskok tak aby zmieściły nam się dane (2*szerokość obrazka)
Dim polowa As Integer = (obraz.Height / 2) 'ustalamy połowe wysokości obrazka
If Not iloscBitow = 32 Then
For i = 1 To obraz.Width - 10
If DaneOryginalne(i * przeskok) > najwyzszaWartoscDzwieku Then 'wymagane do stworzenia histogramu
najwyzszaWartoscDzwieku = DaneOryginalne(i * przeskok)
End If
Next
Else
For i = 1 To obraz.Width - 10
If DaneOryginalne(i * przeskok) > najwyzszaWartoscDzwieku Then 'wymagane do stworzenia histogramu
If DaneOryginalne(i * przeskok) > Integer.MaxValue Then
najwyzszaWartoscDzwieku = Integer.MaxValue / 4
Exit For
Else
najwyzszaWartoscDzwieku = DaneOryginalne(i * przeskok)
End If
End If
Next
End If
For i As UInteger = 1 To obraz.Width - 10 Step 2 'ponieważ w jednym ruchu rysujemy dwie linie
Dim leftdata As UInteger = Math.Abs(DaneOryginalne(i * przeskok)) 'podejmujemy (i* przeskok) element
'procent jaki osiąga dzwięk w stosunku do najdłuższego znalezionego dźwięku
Dim leftpercent As Double = leftdata / (najwyzszaWartoscDzwieku * 2)
'otrzymujemy procent połowy wysokości obrazka odpowiadającej długości dźwięku
Dim leftpicheight As Integer = leftpercent * obraz.Height
gfx.DrawLine(Pens.Green, i, polowa, i, leftpicheight + polowa) 'generuje grafikę słupka w górę
'podejmujemy ((i+1)* przeskok) element (i+1 ponieważ mamy "step 2" w pętli
Dim rightdata As UInteger = Math.Abs(DaneOryginalne((i + 1) * przeskok))
Dim rightpercent As Double = -rightdata / (najwyzszaWartoscDzwieku * 2) 'rysuje słupek w dół
Dim rightpicheight As Integer = rightpercent * obraz.Height
gfx.DrawLine(Pens.Black, i, polowa, i, rightpicheight + polowa) 'generuje grafikę słupka w dół
Next
pictureboxKontener.Image = obraz
End Sub
Private Sub GrajOryginal()
My.Computer.Audio.Stop()
Dim oryginal As Byte()
Dim listaPolaczona As New List(Of Byte)
listaPolaczona.AddRange(bajtyNaglowka)
If iloscBitow = 16 Then
For i As Integer = 0 To DaneOryginalne.Count - 1
Dim test As Byte() = BitConverter.GetBytes(DaneOryginalne(i))
listaPolaczona.Add(test(0))
listaPolaczona.Add(test(1))
Next
ElseIf iloscBitow = 32 Then
For i As Integer = 0 To DaneOryginalne.Count - 1
Dim test As Byte() = BitConverter.GetBytes(DaneOryginalne(i))
listaPolaczona.Add(test(0))
listaPolaczona.Add(test(1))
listaPolaczona.Add(test(2))
listaPolaczona.Add(test(3))
Next
ElseIf iloscBitow = 24 Then
For i As Integer = 0 To DaneOryginalne.Count - 1
Dim test As Byte() = BitConverter.GetBytes(DaneOryginalne(i))
listaPolaczona.Add(test(0))
listaPolaczona.Add(test(1))
listaPolaczona.Add(test(2))
Next
End If
oryginal = listaPolaczona.ToArray()
My.Computer.Audio.Play(oryginal, AudioPlayMode.Background)
End Sub
Dim LISTA As New List(Of String)
Private Sub TrackBar1_ZmianaWartosci()
DaneLSB.Clear()
LISTA.Clear()
For i As UInteger = 0 To DaneOryginalne.Count - 1
Dim wartosc As UInteger = DaneOryginalne(i) - (DaneOryginalne(i) Mod (2 ^ trackbar1.Value))
Dim test As Byte() = BitConverter.GetBytes(DaneOryginalne(i))
Dim test2 As Byte() = BitConverter.GetBytes(wartosc)
Dim string1 As String = BitConverter.ToString(test).ToString
Dim testOdwrocony As String() = string1.Split("-")
Dim dolisty1 As String = testOdwrocony(3) + "-" + testOdwrocony(2) + "-" + testOdwrocony(1) + "-" + testOdwrocony(0)
Dim string2 As String = BitConverter.ToString(test2).ToString
Dim testOdwrocony2 As String() = string2.Split("-")
Dim dolisty2 As String = testOdwrocony2(3) + "-" + testOdwrocony2(2) + "-" + testOdwrocony2(1) + "-" + testOdwrocony2(0)
Dim test3 As UInteger = DaneOryginalne(i) Mod (2 ^ trackbar1.Value)
LISTA.Add(DaneOryginalne(i).ToString + " (" + dolisty1 + ") -" + test3.ToString +
" =" + (DaneOryginalne(i) - test3).ToString + " (" + dolisty2 + ")" + " (" +
Convert.ToString(test2(3), 2).PadLeft(8, "0") + "-" + Convert.ToString(test2(2), 2).PadLeft(8, "0") _
+ "-" + Convert.ToString(test2(1), 2).PadLeft(8, "0") + "-" + Convert.ToString(test2(0), 2).PadLeft(8, "0") + ")")
DaneLSB.Add(DaneOryginalne(i) - (DaneOryginalne(i) Mod (2 ^ trackbar1.Value)))
Next
label1.Text = "Wyzerowano " + trackbar1.Value.ToString + " ostatnich bitów, to daje: " +
(Math.Floor((DaneOryginalne.Count / 8) * trackbar1.Value).ToString + " wojnych Bajtów.")
GenerowanyHistogram()
End Sub
Private Sub GenerowanyHistogram()
panel2.Controls.Clear()
Dim przeskok As Integer
pictureboxGenerowany.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
pictureboxGenerowany.Location = New System.Drawing.Point(0, 0)
pictureboxGenerowany.Name = "pictureboxGenerowany"
If Not iloscBitow = 32 Then
pictureboxGenerowany.Size = New System.Drawing.Size((DaneOryginalne.Count - 1) / 2, 220)
przeskok = 1
Else
pictureboxGenerowany.Size = New System.Drawing.Size((DaneOryginalne.Count - 1) / 2000, 220)
przeskok = (DaneOryginalne.Count - 1) / 2000
End If
pictureboxGenerowany.TabIndex = 4
pictureboxGenerowany.TabStop = False
panel2.Controls.Add(pictureboxGenerowany)
Dim obraz As New Bitmap(pictureboxGenerowany.Width, 240)
Dim gfx As Graphics = Graphics.FromImage(obraz)
'Stwórz grafikę kwadratu ktory posłuży za tło
gfx.FillRectangle(Brushes.White, 0, 0, obraz.Width, obraz.Height)
Dim polowa As Integer = (obraz.Height / 2)
For i As UInteger = 1 To obraz.Width - 10 Step 2 'ponieważ w jednym ruchu rysujemy dwie linie
Dim leftdata As UInteger = Math.Abs(DaneLSB(i * przeskok))
Dim leftpercent As Single = leftdata / (najwyzszaWartoscDzwieku * 2)
Dim leftpicheight As Integer = leftpercent * obraz.Height
gfx.DrawLine(Pens.Green, i, polowa, i, leftpicheight + polowa)
Dim rightdata As UInteger = Math.Abs(DaneLSB((i + 1) * przeskok))
Dim rightpercent As Single = -rightdata / (najwyzszaWartoscDzwieku * 2)
Dim rightpicheight As Integer = rightpercent * obraz.Height
gfx.DrawLine(Pens.Black, i, polowa, i, rightpicheight + polowa)
Next
pictureboxGenerowany.Image = obraz
End Sub
Private Sub GrajWygenerownyDzwiek()
My.Computer.Audio.Stop()
Dim Wygenerowany As Byte()
Dim listaPolaczona As New List(Of Byte)
listaPolaczona.AddRange(bajtyNaglowka)
If iloscBitow = 16 Then
For i As Integer = 0 To DaneLSB.Count - 1
Dim test As Byte() = BitConverter.GetBytes(DaneLSB(i))
listaPolaczona.Add(test(0))
listaPolaczona.Add(test(1))
Next
ElseIf iloscBitow = 32 Then
For i As Integer = 0 To DaneLSB.Count - 1
Dim test As Byte() = BitConverter.GetBytes(DaneLSB(i))
listaPolaczona.Add(test(0))
listaPolaczona.Add(test(1))
listaPolaczona.Add(test(2))
listaPolaczona.Add(test(3))
Next
ElseIf iloscBitow = 24 Then
For i As Integer = 0 To DaneLSB.Count - 1
Dim test As Byte() = BitConverter.GetBytes(DaneLSB(i))
listaPolaczona.Add(test(0))
listaPolaczona.Add(test(1))
listaPolaczona.Add(test(2))
Next
End If
Wygenerowany = listaPolaczona.ToArray()
My.Computer.Audio.Play(Wygenerowany, AudioPlayMode.Background)
End Sub
Private Sub ZapiszKlik()
Dim Wygenerowany As Byte()
Dim listaPolaczona As List(Of Byte) = bajtyNaglowka
If iloscBitow = 16 Then
For i As Integer = 0 To DaneLSB.Count - 1
Dim test As Byte() = BitConverter.GetBytes(DaneLSB(i))
listaPolaczona.Add(test(0))
listaPolaczona.Add(test(1))
Next
ElseIf iloscBitow = 32 Then
For i As Integer = 0 To DaneLSB.Count - 1
Dim test As Byte() = BitConverter.GetBytes(DaneLSB(i))
listaPolaczona.Add(test(0))
listaPolaczona.Add(test(1))
listaPolaczona.Add(test(2))
listaPolaczona.Add(test(3))
Next
ElseIf iloscBitow = 24 Then
For i As Integer = 0 To DaneLSB.Count - 1
Dim test As Byte() = BitConverter.GetBytes(DaneLSB(i))
listaPolaczona.Add(test(0))
listaPolaczona.Add(test(1))
listaPolaczona.Add(test(2))
Next
End If
Wygenerowany = listaPolaczona.ToArray()
Dim saveFileDialog1 As New SaveFileDialog()
saveFileDialog1.Title = "Save an wav File"
saveFileDialog1.Filter = "Wav Files | *.wav"
saveFileDialog1.DefaultExt = "wav"
saveFileDialog1.ShowDialog()
If saveFileDialog1.FileName <> "" Then
IO.File.WriteAllBytes(saveFileDialog1.FileName, Wygenerowany)
Dim sciezka As String = IO.Path.GetDirectoryName(saveFileDialog1.FileName) _
+ "\" + IO.Path.GetFileNameWithoutExtension(saveFileDialog1.FileName)
IO.File.WriteAllLines(sciezka + "_listabitow.txt", LISTA)
End If
End Sub
End Module
Aplikacja jest dosyć rozbudowana, ale jej działanie jest bardzo proste. Pobiera bajty pliku i segreguje je, umieszczając w odpowiednich listach, aby po modyfikacji można było połączyć je w całość i odtworzyć (wyświetlić histogram). Pliki, na których ja testowałem algorytmy::
Jeśli wyzerujemy ostatnie 8 bitów w 16 bitowym pliku WAVE, zmiana będzie niezauważalna (w dźwięku). Dopiero wyzerowanie więcej niż 10 bitów zmienia zauważalnie jakość dźwięku:

Procedura zerowania 8 bitów dla 16-bitowego pliku WAVe wygląda następująco:
DaneOryginalne(i) - (DaneOryginalne(i) Mod (2 ^ trackbar1.Value)) 'w naszym wypadku trackbar1.Value =8

Odpowiednio, dla pliku 16, 24, 32 bitowego( do pobrania na początku artykułu) zerowanie przebiega następująco:
ZerowanieOstatniegoBajtaW16bitowejPróbce –> plik audio po zerowaniu ostatniego bajta: ZerowanieOstatniegoBajtaW16bitowejPróbce
ZerowanieOstatniegoBajtaW24bitowejPróbce –> plik audio po zerowaniu ostatniego bajta: ZerowanieOstatniegoBajtaW24bitowejPróbce
ZerowanieOstatniegoBajtaW32bitowejPróbce –> plik audio po zerowaniu ostatniego bajta: ZerowanieOstatniegoBajtaW32bitowejPróbce
Zachęcam was do przeprowadzenia takiego eksperymentu, przy użyciu algorytmu i sprawdzenia ich na własnych uszach. Ukrycie pliku w takim nośniku nie powinno sprawić wam problemu. Tak jak w przypadku plików graficznych w formacie bmp, zerujemy bity pliku dźwiękowego (kontener) i ukrywamy tam bity naszego pliku. Aby, nie zerować wszystkich bitów danych pliku WAV użyjemy czterech pierwszych bajtów danych do zapisania w nich wielkości pliku, warto również użyć formatu danych Uinteger(dlaczego, dowiesz się, rozwijając zakładkę projektu). Będzie to wyglądało następująco:


Plik WAVE 16-bitowy z ukrytym tekstem (ukryty plik) :
Jeśli już rozbieraliście na części plik WAV, na pewno zauważyliście, że danych dźwiękowych jest bardzo dużo, więc z plik ukrywany może być znacząco mniejszy niż ilość danych dźwiękowych. Toteż ukrywanie wszystkich bajtów pliku tajnego na początku danych kontenera może spowodować słyszalny szum, dużo lepszą metodą jest podzielenie ilości dostępnych bajtów przez ilość bajtów pliku tajnego i zapisanie jego bajtów, w co piątym, szóstym czy siódmym elemencie:

Znając ilość ukrytych danych (pierwsze cztery bajty danych kontenera) bajty można rozłożyć w kontenerze tak jak na obrazku powyrzej.
plik ukryty w kontenerze: ukryty plik2
do odsłuchania, plik z ukrytymi danymi (16-bit wave z ukrytym plikiem „ukryty plik2”):
Przykładowy algorytm ukrywający bajty pliku w kontenerze WAV:
Już na wstępie chciałbym zaznaczyć, że utworzenie programu do szyfrowania bajtów pliku dźwiękowego będzie trochę trudniejsze niż w przypadku plików graficznych. Problem może sprawić to, że operujemy na więcej niż jednym bajcie. Program pobiera dwa, trzy lub cztery bajty i zamienia je na Uint (zakres integer jest od -2147483648 do 2147483647 (7F-FF-FF-FF) a Uint od 0 do 4294967295 (FF-FF-FF-FF)), jak łatwo się domyślić cztery bajty przyjmują zakres od 00-00-00-00 do FF-FF-FF-FF, a więc wszelkiego rodzaju zamiana czterech czy dwóch bajtów na liczbę naturalną będzie wygodniejsza dla Uint. Jeśli wartość bajtów przekroczy maksymalną wartość integer, wtedy liczna naturalna przyjmuje wartość ujemną, a dodawanie czy odejmowanie ich wartości nie będzie miało sensu. Program poniżej przeprowadza edycje bajtów pliku WAV, wyodrębnia z niego poszczególne elementy i je modyfikuje:
Z uwagi na to, że nie ma w vb.net czegoś takiego jak Uint24, pobieramy trzy bajty i dodajemy zerowy bajt z przodu i zamieniamy cztery bajty na Uint32
Imports System.Windows.Forms
Module Module1
Sub Main()
Dim open_dialog As New OpenFileDialog()
Dim open_dialog_ukrywany As New OpenFileDialog()
open_dialog.InitialDirectory = "c:\"
open_dialog.Filter = "Image Files (*.wav)| *.wav"
open_dialog.Title = "Wskarz kontener w formacie WAV w którym ukryjesz plik"
If open_dialog.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
open_dialog_ukrywany.InitialDirectory = "c:\"
open_dialog_ukrywany.Filter = "All Files|*.*"
open_dialog_ukrywany.Title = "Wybierz plik który chcesz ukryć"
If open_dialog_ukrywany.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
Dim adresKontenera As String = open_dialog.FileName
Dim adreskUkrywany As String = open_dialog_ukrywany.FileName
Dim DaneOryginalne As New List(Of UInteger)
Dim iloscBitow As Integer = 0
Dim bajtyNaglowka As New List(Of Byte)
Dim plikUkrywany() As Byte = IO.File.ReadAllBytes(adreskUkrywany)
Dim wavefile() As Byte = IO.File.ReadAllBytes(adresKontenera)
Dim memstream As New IO.MemoryStream(wavefile)
'''''obszar oddziela nagłówek od danych
Using binreader As New IO.BinaryReader(memstream)
' DataID'
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' ChunkID
Do Until BitConverter.ToString({bajtyNaglowka(bajtyNaglowka.Count - 4),
bajtyNaglowka(bajtyNaglowka.Count - 3), bajtyNaglowka(bajtyNaglowka.Count - 2),
bajtyNaglowka(bajtyNaglowka.Count - 1)}, 0) = "66-6D-74-20"
bajtyNaglowka.Add(binreader.ReadByte)
Loop
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' fmtsize
Dim fmtsize As Byte() = {bajtyNaglowka(bajtyNaglowka.Count - 4),
bajtyNaglowka(bajtyNaglowka.Count - 3), bajtyNaglowka(bajtyNaglowka.Count - 2),
bajtyNaglowka(bajtyNaglowka.Count - 1)}
bajtyNaglowka.AddRange(binreader.ReadBytes(14)) ' fmtcode
bajtyNaglowka.AddRange(binreader.ReadBytes(2)) ' bitdepth
iloscBitow = BitConverter.ToInt16({bajtyNaglowka(bajtyNaglowka.Count - 2),
bajtyNaglowka(bajtyNaglowka.Count - 1)}, 0)
If BitConverter.ToInt32(fmtsize, 0) = 18 Then
bajtyNaglowka.AddRange(binreader.ReadBytes(2))
End If
' DataID'
Do Until BitConverter.ToString({bajtyNaglowka(bajtyNaglowka.Count - 4),
bajtyNaglowka(bajtyNaglowka.Count - 3), bajtyNaglowka(bajtyNaglowka.Count - 2),
bajtyNaglowka(bajtyNaglowka.Count - 1)}, 0) = "64-61-74-61"
bajtyNaglowka.Add(binreader.ReadByte)
Loop
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' DataSize
Dim DataSize As Byte() = {bajtyNaglowka(bajtyNaglowka.Count - 4),
bajtyNaglowka(bajtyNaglowka.Count - 3), bajtyNaglowka(bajtyNaglowka.Count - 2),
bajtyNaglowka(bajtyNaglowka.Count - 1)}
'ładuje odpowiednio duże dane do listy
If iloscBitow = 16 Then
For i = 0 To (BitConverter.ToUInt32(DataSize, 0) / 2) - 1
DaneOryginalne.Add(binreader.ReadUInt16())
Next
ElseIf iloscBitow = 32 Then
For i = 0 To (BitConverter.ToUInt32(DataSize, 0) / 4) - 1
DaneOryginalne.Add(binreader.ReadUInt32())
Next
ElseIf iloscBitow = 24 Then
For i = 0 To (BitConverter.ToUInt32(DataSize, 0) / 3) - 1
Dim DataSize2(3) As Byte
DataSize2(3) = 0
DataSize2(0) = binreader.ReadByte
DataSize2(1) = binreader.ReadByte
DataSize2(2) = binreader.ReadByte
DaneOryginalne.Add(BitConverter.ToUInt32(DataSize2, 0))
Next
End If
End Using
'''''
'sparwdza czy plik ukrywany ma mniej danych niż kontener
If Not plikUkrywany.Length + 2 > DaneOryginalne.Count Then
Dim przeskok As UInteger = 1
Dim listaPolaczona As List(Of Byte) = bajtyNaglowka
Dim wielkoscpliku As UInteger = plikUkrywany.Length
If iloscBitow = 16 Then
'dodaje bajty wielkości pliku
listaPolaczona.Add(BitConverter.GetBytes(wielkoscpliku)(0))
listaPolaczona.Add(BitConverter.GetBytes(wielkoscpliku)(1))
listaPolaczona.Add(BitConverter.GetBytes(wielkoscpliku)(2))
listaPolaczona.Add(BitConverter.GetBytes(wielkoscpliku)(3))
DaneOryginalne.RemoveAt(0) 'usuwa pierwszy wiersz (ułatwia to pracę algorytmu)
przeskok = Math.Floor(((DaneOryginalne.Count - 1) / plikUkrywany.Length))
'algorytm ukrywający bajty
For i As UInteger = 0 To plikUkrywany.Length - 1
DaneOryginalne((i + 1) * przeskok) = (DaneOryginalne((i + 1) * przeskok) -
(DaneOryginalne((i + 1) * przeskok) Mod (2 ^ 8))) + Convert.ToInt32(plikUkrywany(i))
Next
Else
przeskok = Math.Floor(((DaneOryginalne.Count - 1) / plikUkrywany.Length))
'algorytm ukrywający bajty
For i As UInteger = 0 To plikUkrywany.Length - 1
DaneOryginalne((i + 1) * przeskok) = (DaneOryginalne((i + 1) * przeskok) -
(DaneOryginalne((i + 1) * przeskok) Mod (2 ^ 8))) + Convert.ToInt32(plikUkrywany(i))
Next
End If
Dim Wygenerowany As Byte()
'zespalanie pliku
If iloscBitow = 16 Then
For i As UInteger = 1 To DaneOryginalne.Count - 1
Dim test As Byte() = BitConverter.GetBytes(DaneOryginalne(i))
listaPolaczona.Add(test(0))
listaPolaczona.Add(test(1))
Next
ElseIf iloscBitow = 32 Then
'dodaje bajty wielkości pliku
listaPolaczona.Add(BitConverter.GetBytes(wielkoscpliku)(0))
listaPolaczona.Add(BitConverter.GetBytes(wielkoscpliku)(1))
listaPolaczona.Add(BitConverter.GetBytes(wielkoscpliku)(2))
listaPolaczona.Add(BitConverter.GetBytes(wielkoscpliku)(3))
For i As UInteger = 1 To DaneOryginalne.Count - 1
Dim test As Byte() = BitConverter.GetBytes(DaneOryginalne(i))
listaPolaczona.AddRange(test.ToList)
Next
ElseIf iloscBitow = 24 Then
'dodaje bajty wielkości pliku
listaPolaczona.Add(BitConverter.GetBytes(wielkoscpliku)(0))
listaPolaczona.Add(BitConverter.GetBytes(wielkoscpliku)(1))
listaPolaczona.Add(BitConverter.GetBytes(wielkoscpliku)(2))
For i As UInteger = 1 To DaneOryginalne.Count - 1
Dim test As Byte() = BitConverter.GetBytes(DaneOryginalne(i))
listaPolaczona.Add(test(0))
listaPolaczona.Add(test(1))
listaPolaczona.Add(test(2))
Next
End If
Wygenerowany = listaPolaczona.ToArray()
Console.WriteLine()
Console.Write("Podaj nazwę nowego pliku: ")
Dim nazwapliku As String = Console.ReadLine()
'zapisz plik
IO.File.WriteAllBytes("C:\Users\piotr\Desktop\" + nazwapliku + ".wav", Wygenerowany)
Console.WriteLine("Bajty zostały ukryte. Zapisano plik: " +
"C:\Users\piotr\Desktop\" + nazwapliku)
Console.ReadLine()
Else
Console.WriteLine("Twój kontener jest zbyt mały.")
Console.WriteLine("Bajty kontenera: " + DaneOryginalne.Count.ToString)
Console.WriteLine("Bajty pliku ukrywanego: " + plikUkrywany.Length.ToString)
Console.WriteLine("Wybierz większy plik kontenera.")
Console.ReadLine()
End If
End If
End If
End Sub
End Module
Jeśli wiemy jak dodawać bajty, ich wyciągnięcie nie stanowi problemu, z bajtów danych pobieramy informację na temat wielkości pliku i na tej podstawie wyodrębniamy bajty..
Imports System.Windows.Forms
Module Module1
Sub Main()
Dim open_dialog As New OpenFileDialog()
open_dialog.InitialDirectory = "c:\"
open_dialog.Filter = "Image Files (*.wav)| *.wav"
open_dialog.Title = "Wskarz kontener w formacie WAV w którym ukryjesz plik"
If open_dialog.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
Dim adresKontenera As String = open_dialog.FileName
Dim DaneOryginalne As New List(Of Integer)
Dim iloscBitow As Integer = 0
Dim bajtyNaglowka As New List(Of Byte)
Dim wavefile() As Byte = IO.File.ReadAllBytes(adresKontenera)
Dim memstream As New IO.MemoryStream(wavefile)
Dim wielkoscpliku As Integer = 0
'Oddziela nagłówek od danych
Using binreader As New IO.BinaryReader(memstream)
' DataID'
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' ChunkID
Do Until BitConverter.ToString({bajtyNaglowka(bajtyNaglowka.Count - 4),
bajtyNaglowka(bajtyNaglowka.Count - 3), bajtyNaglowka(bajtyNaglowka.Count - 2),
bajtyNaglowka(bajtyNaglowka.Count - 1)}, 0) = "66-6D-74-20"
bajtyNaglowka.Add(binreader.ReadByte)
Loop
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' fmtsize
Dim fmtsize As Byte() = {bajtyNaglowka(bajtyNaglowka.Count - 4),
bajtyNaglowka(bajtyNaglowka.Count - 3), bajtyNaglowka(bajtyNaglowka.Count - 2),
bajtyNaglowka(bajtyNaglowka.Count - 1)}
bajtyNaglowka.AddRange(binreader.ReadBytes(14)) ' fmtcode
bajtyNaglowka.AddRange(binreader.ReadBytes(2)) ' bitdepth
iloscBitow = BitConverter.ToInt16({bajtyNaglowka(bajtyNaglowka.Count - 2),
bajtyNaglowka(bajtyNaglowka.Count - 1)}, 0)
If BitConverter.ToInt32(fmtsize, 0) = 18 Then
bajtyNaglowka.AddRange(binreader.ReadBytes(2))
End If
' DataID'
Do Until BitConverter.ToString({bajtyNaglowka(bajtyNaglowka.Count - 4),
bajtyNaglowka(bajtyNaglowka.Count - 3), bajtyNaglowka(bajtyNaglowka.Count - 2),
bajtyNaglowka(bajtyNaglowka.Count - 1)}, 0) = "64-61-74-61"
bajtyNaglowka.Add(binreader.ReadByte)
Loop
bajtyNaglowka.AddRange(binreader.ReadBytes(4)) ' DataSize
Dim DataSize As Byte() = {bajtyNaglowka(bajtyNaglowka.Count - 4),
bajtyNaglowka(bajtyNaglowka.Count - 3), bajtyNaglowka(bajtyNaglowka.Count - 2),
bajtyNaglowka(bajtyNaglowka.Count - 1)}
'ładuje odpowiednio duże dane do listy
If iloscBitow = 16 Then
DaneOryginalne.Add(binreader.ReadInt32())
For i = 2 To (BitConverter.ToInt32(DataSize, 0) / 2) - 1
DaneOryginalne.Add(binreader.ReadInt16())
Next
ElseIf iloscBitow = 32 Then
For i = 1 To (BitConverter.ToInt32(DataSize, 0) / 4) - 1
DaneOryginalne.Add(binreader.ReadInt32())
Next
ElseIf iloscBitow = 24 Then
For i = 1 To (BitConverter.ToInt32(DataSize, 0) / 3) - 1
Dim DataSize2(3) As Byte
DataSize2(3) = 0
DataSize2(0) = binreader.ReadByte
DataSize2(1) = binreader.ReadByte
DataSize2(2) = binreader.ReadByte
DaneOryginalne.Add(BitConverter.ToInt32(DataSize2, 0))
Next
End If
End Using
Dim przeskok As Integer = 1
Dim test2 As Byte() = BitConverter.GetBytes(DaneOryginalne(0))
wielkoscpliku = BitConverter.ToInt32(test2, 0)
If iloscBitow = 16 Then
przeskok = Math.Floor(((DaneOryginalne.Count - 1) / wielkoscpliku))
Else
przeskok = Math.Floor(((DaneOryginalne.Count - 1) / wielkoscpliku))
End If
'tworzymy nowy plik
Dim Wygenerowany As Byte()
Dim listaPolaczona As New List(Of Byte)
If iloscBitow = 16 Then
For i As Integer = 1 To wielkoscpliku
Dim test As Byte() = BitConverter.GetBytes(DaneOryginalne(i * przeskok))
listaPolaczona.Add(test(0))
Next
ElseIf iloscBitow = 32 Then
For i As Integer = 1 To wielkoscpliku
Dim test As Byte() = BitConverter.GetBytes(DaneOryginalne(i * przeskok))
listaPolaczona.Add(test(0))
Next
ElseIf iloscBitow = 24 Then
For i As Integer = 1 To wielkoscpliku
Dim test As Byte() = BitConverter.GetBytes(DaneOryginalne(i * przeskok))
listaPolaczona.Add(test(0))
Next
End If
Wygenerowany = listaPolaczona.ToArray()
Console.WriteLine()
Console.Write("Podaj nazwę pliku pod którycm chcesz go zapisać: ")
Dim nazwapliku As String = Console.ReadLine()
'zapisz plik
IO.File.WriteAllBytes("C:\Users\piotr\Desktop\" + nazwapliku, Wygenerowany)
Console.WriteLine("Bajty zostały odzyskane. Zapisano plik: " + "C:\Users\piotr\Desktop\" + nazwapliku)
Console.ReadLine()
End If
End Sub
End Module
Plik wygenerowany, nie będzie miał rozszerzenia. Spowodowane jest to brakiem informacji (którą jeśli chcemy, możemy umieścić w kontenerze) o rodzaju pliku. Warto również połączyć możliwości JUNK i LSB.
Do przetestowania: Program_ukrywający_bajty_w_pliku_wav , Odzyskiwanie_ostatniego_bajta_z_pliku_WAV
(artykuł będzie rozwijany)




