1<pre>
2using System;
3using System.IO;
4using System.Drawing;
5
6public class Bitmap24Writer
7{
8protected Bitmap bmp;
9protected int curX, curY, iRGB;
10protected uint bitsLeft, bitsTotal;
11protected byte r, g, b;
12
13public Bitmap24Writer(Bitmap bmp)
14{
15if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb)
16throw new ArgumentException();
17// assign vars
18curX = curY = iRGB = 0;
19this.bmp = bmp;
20bitsLeft = bitsTotal = (uint)bmp.Height * (uint)bmp.Width * 3;
21}
22
23public uint GetUnusedBitCount()
24{
25return bitsLeft;
26}
27
28public uint GetMaxBitStorageCount()
29{
30return bitsTotal;
31}
32
33public Bitmap GetBitmap()
34{
35return bmp;
36}
37
38public bool WriteByte(byte by)
39{
40if (bitsLeft < 8)
41return false;
42
43uint bits2Do = 8;
44
45for (; curX < bmp.Width; curX++)
46{
47if (curY >= bmp.Height)
48curY = 0;
49
50for (; curY < bmp.Height; curY++)
51{
52if (bits2Do == 0)
53return true;
54
55Color col = bmp.GetPixel(curX, curY);
56r = col.R;
57g = col.G;
58b = col.B;
59
60for ( ; ; )
61{
62byte curBit = (byte)(by & 1);
63
64switch( iRGB )
65{
66case 0:
67r = (byte)(r & 0xFE);
68r |= curBit;
69break;
70
71case 1:
72g = (byte)(g & 0xFE);
73g |= curBit;
74break;
75
76case 2:
77b = (byte)(b & 0xFE);
78b |= curBit;
79break;
80}
81\--bits2Do;
82\--bitsLeft;
83by >>= 1;
84bmp.SetPixel(curX, curY, Color.FromArgb(r, g, b));
85if (iRGB == 2)
86{
87iRGB = 0;
88break;
89}
90iRGB++;
91if (bits2Do == 0)
92return true;
93}
94}
95}
96return true;
97}
98}
99
100public class Bitmap24Reader
101{
102protected Bitmap bmp;
103protected int curX, curY, iRGB;
104protected uint bitsLeft, bitsTotal;
105
106public Bitmap24Reader(Bitmap bmp)
107{
108if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb)
109throw new ArgumentException();
110curX = curY = iRGB = 0;
111this.bmp = bmp;
112bitsLeft = bitsTotal = (uint)bmp.Height * (uint)bmp.Width * 3;
113}
114
115public uint GetUnusedBitCount()
116{
117return bitsLeft;
118}
119
120public uint GetMaxBitStorageCount()
121{
122return bitsTotal;
123}
124
125public Bitmap GetBitmap()
126{
127return bmp;
128}
129
130public bool ReadByte(out byte by)
131{
132by = 0;
133
134if (bitsLeft < 8)
135return false;
136
137byte bit = 0;
138uint bits2Do = 8;
139for (; curX < bmp.Width; curX++)
140{
141if (curY >= bmp.Height)
142curY = 0;
143
144for (; curY < bmp.Height; curY++)
145{
146if (bits2Do == 0)
147return true;
148
149Color col = bmp.GetPixel(curX, curY);
150for ( ; ; )
151{
152switch( iRGB )
153{
154case 0:
155bit = (byte)(col.R & 1);
156break;
157
158case 1:
159bit = (byte)(col.G & 1);
160break;
161
162case 2:
163bit = (byte)(col.B & 1);
164break;
165}
166\--bits2Do;
167\--bitsLeft;
168by |= (byte)(bit << 7);
169if (bits2Do != 0)
170by >>= 1;
171if (iRGB == 2)
172{
173iRGB = 0;
174break;
175}
176iRGB++;
177if (bits2Do == 0)
178return true;
179}
180}
181}
182return true;
183}
184}
185
186public class BitmapWorks
187{
188public static bool Data2Bmp(FileStream dataStream, FileStream bmpStream, string outFName, out string error)
189{
190error = "";
191
192Bitmap bmp;
193try
194{
195bmp = new Bitmap(bmpStream);
196}
197catch
198{
199error = "Are you sure the specified bitmap is a valid bitmap ?";
200return false;
201}
202if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb)
203{
204error = "Please drop only 24bit bitmaps,thanks !";
205return false;
206}
207
208error += "-> Bitmap info: height=" + bmp.Height + " width=" + bmp.Width + "...\n";
209
210if (dataStream.Length == 0)
211{
212error = "Input data has a not supported size of 0 !";
213return false;
214}
215uint maxByteStorage = ((uint)bmp.Height * (uint)bmp.Width * 3) / 8;
216error += "-> Up to " + (maxByteStorage-4) + " bytes could be stored in this bitmap...\n";
217if (maxByteStorage < dataStream.Length + 4)
218{
219error = "Not enough pixel in target bitmap to hide the input data block !";
220return false;
221}
222
223Bitmap24Writer bmpWriter = new Bitmap24Writer(bmp);
224uint dataSize = (uint)dataStream.Length;
225try
226{
227for (uint u = 0; u < 4; u++)
228{
229bmpWriter.WriteByte( (byte)dataSize );
230dataSize >>= 8;
231}
232for (uint u = 0; u < dataStream.Length; u++)
233bmpWriter.WriteByte( (byte)dataStream.ReadByte() );
234}
235catch
236{
237error = "Error while modifing the bitmap's pixels !";
238return false;
239}
240
241double maxBitStorage = bmpWriter.GetMaxBitStorageCount();
242double spaceUsed = (100 * (maxBitStorage - bmpWriter.GetUnusedBitCount())) / maxBitStorage;
243error += "-> Space used: " + Convert.ToUInt32(spaceUsed) + "%...\n";
244
245try
246{
247if ( File.Exists( outFName ) )
248File.Delete( outFName );
249bmpWriter.GetBitmap().Save(outFName);
250}
251catch
252{
253error = "Couldn't save output to " + outFName + " !";
254return false;
255}
256
257error += "-> Output saved to: " + outFName + "...\n";
258
259return true;
260}
261
262public static bool Bmp2Data(FileStream bmpStream, string outFName, out string error)
263{
264error = "";
265
266Bitmap bmp;
267try
268{
269bmp = new Bitmap(bmpStream);
270}
271catch
272{
273error = "Are you sure the specified bitmap is a valid bitmap ?";
274return false;
275}
276
277Bitmap24Reader bmpReader;
278try
279{
280bmpReader = new Bitmap24Reader(bmp);
281}
282catch (ArgumentException)
283{
284error = "This isn't a 24bit bitmap !";
285return false;
286}
287
288FileStream outStream;
289try
290{
291outStream = File.Create( outFName );
292}
293catch
294{
295error = "Couldn't create output file: " + outFName + " !";
296return false;
297}
298uint dataSize = 0;
299byte outByte;
300try
301{
302for (uint u = 0; u < 4; u++)
303{
304if ( !bmpReader.ReadByte( out outByte ) )
305throw new Exception();
306dataSize |= (uint)( outByte << 8*3 );
307if (u != 3)
308dataSize >>= 8;
309}
310error += "-> Size of hidden data: " + dataSize + " bytes...\n";
311for (uint u = 0; u < dataSize; u++)
312{
313if ( !bmpReader.ReadByte( out outByte ) )
314throw new Exception();
315outStream.WriteByte( outByte );
316}
317}
318catch
319{
320error = "Exception caught while reading the hidden data !";
321return false;
322}
323finally
324{
325outStream.Close();
326}
327
328error += "-> Output saved to: " + outFName + "...\n";
329
330return true;
331}
332
333}
334
335class BmpSafe
336{
337public static string cmdLine =
338"Command line:\n" +
339" BmpSafe.exe /file2bmp (input BMP) (input file to hide) [output file]\n" +
340" BmpSafe.exe /bmp2file (data BMP) [output file]";
341
342private static string serviceOne = "/file2bmp";
343private static string serviceTwo = "/bmp2file";
344
345[STAThread]
346static void Main(string[] args)
347{
348Console.WriteLine(
349"BmpSafe - hide files in 24bit bitmaps\n" +
350" a little steganografie implementation\n" +
351" by yoda\n" +
352"-------------------------------------------------------------------------------\n");
353
354string inFile = "", inBmp, outFile;
355bool bFile2Bmp;
356if (args.Length < 2)
357{
358Console.WriteLine("!! Invalid number of arguments :(");
359Console.WriteLine(cmdLine);
360return; // ERR
361}
362if ( String.Compare(args[0], serviceOne, true) == 0 )
363bFile2Bmp = true;
364else if ( String.Compare(args[0], serviceTwo, true) == 0)
365bFile2Bmp = false;
366else
367{
368Console.WriteLine("!! First parameters must be either \"/file2bmp\" or \"/bmp2file\" !");
369return;
370}
371
372inBmp = args[1];
373if (bFile2Bmp)
374{
375if (args.Length < 3)
376{
377Console.WriteLine("!! Invalid number of arguments :(");
378Console.WriteLine(cmdLine);
379return;
380}
381inFile = args[2];
382if (args.Length > 3)
383outFile = args[3];
384else
385outFile = "Secret.BMP";
386}
387else
388{
389if (args.Length > 2)
390outFile = args[2];
391else
392outFile = "Secret.bin";
393}
394
395Console.WriteLine("-> Processing input...");
396try
397{
398string err;
399bool ret;
400
401if (bFile2Bmp)
402ret = BitmapWorks.Data2Bmp(
403File.OpenRead(inFile),
404File.OpenRead(inBmp),
405outFile,
406out err );
407else
408ret = BitmapWorks.Bmp2Data(
409File.OpenRead(inBmp),
410outFile,
411out err);
412if (!ret)
413{
414Console.WriteLine("!! " + err);
415return;
416}
417else
418Console.Write( err );
419}
420catch(FileNotFoundException)
421{
422Console.WriteLine("!! At least one file could not be found :(");
423return;
424}
425catch
426{
427Console.WriteLine("!! An exception occurred :(");
428return;
429}
430
431Console.WriteLine("-> Job done...");
432
433return;
434}
435}
436</pre>
该C#程序可将文本文件藏于位图中,也可导出之。
comments powered by Disqus