首页 > 开发 > 综合 > 正文

该C#程序可将文本文件藏于位图中,也可导出之!

2024-07-21 02:19:05
字体:
来源:转载
供稿:网友
//使用方法:
// bmpsafe.exe /file2bmp (input bmp) (input file to hide) [output file]
//bmpsafe.exe /bmp2file (data bmp) [output file]

using system;
using system.io;
using system.drawing;

public class bitmap24writer
{
protected bitmap bmp;
protected int curx, cury, irgb;
protected uint bitsleft, bitstotal;
protected byte r, g, b;

public bitmap24writer(bitmap bmp)
{
if (bmp.pixelformat != system.drawing.imaging.pixelformat.format24bpprgb)
throw new argumentexception();
// assign vars
curx = cury = irgb = 0;
this.bmp = bmp;
bitsleft = bitstotal = (uint)bmp.height * (uint)bmp.width * 3;
}

public uint getunusedbitcount()
{
return bitsleft;
}

public uint getmaxbitstoragecount()
{
return bitstotal;
}

public bitmap getbitmap()
{
return bmp;
}

public bool writebyte(byte by)
{
if (bitsleft < 8)
return false;

uint bits2do = 8;

for (; curx < bmp.width; curx++)
{
if (cury >= bmp.height)
cury = 0;

for (; cury < bmp.height; cury++)
{
if (bits2do == 0)
return true;

color col = bmp.getpixel(curx, cury);
r = col.r;
g = col.g;
b = col.b;

for ( ; ; )
{
byte curbit = (byte)(by & 1);

switch( irgb )
{
case 0:
r = (byte)(r & 0xfe);
r |= curbit;
break;

case 1:
g = (byte)(g & 0xfe);
g |= curbit;
break;

case 2:
b = (byte)(b & 0xfe);
b |= curbit;
break;
}
--bits2do;
--bitsleft;
by >>= 1;
bmp.setpixel(curx, cury, color.fromargb(r, g, b));
if (irgb == 2)
{
irgb = 0;
break;
}
irgb++;
if (bits2do == 0)
return true;
}
}
}
return true;
}
}

public class bitmap24reader
{
protected bitmap bmp;
protected int curx, cury, irgb;
protected uint bitsleft, bitstotal;

public bitmap24reader(bitmap bmp)
{
if (bmp.pixelformat != system.drawing.imaging.pixelformat.format24bpprgb)
throw new argumentexception();
curx = cury = irgb = 0;
this.bmp = bmp;
bitsleft = bitstotal = (uint)bmp.height * (uint)bmp.width * 3;
}

public uint getunusedbitcount()
{
return bitsleft;
}

public uint getmaxbitstoragecount()
{
return bitstotal;
}

public bitmap getbitmap()
{
return bmp;
}

public bool readbyte(out byte by)
{
by = 0;

if (bitsleft < 8)
return false;

byte bit = 0;
uint bits2do = 8;
for (; curx < bmp.width; curx++)
{
if (cury >= bmp.height)
cury = 0;

for (; cury < bmp.height; cury++)
{
if (bits2do == 0)
return true;

color col = bmp.getpixel(curx, cury);
for ( ; ; )
{
switch( irgb )
{
case 0:
bit = (byte)(col.r & 1);
break;

case 1:
bit = (byte)(col.g & 1);
break;

case 2:
bit = (byte)(col.b & 1);
break;
}
--bits2do;
--bitsleft;
by |= (byte)(bit << 7);
if (bits2do != 0)
by >>= 1;
if (irgb == 2)
{
irgb = 0;
break;
}
irgb++;
if (bits2do == 0)
return true;
}
}
}
return true;
}
}

public class bitmapworks
{
public static bool data2bmp(filestream datastream, filestream bmpstream, string outfname, out string error)
{
error = "";

bitmap bmp;
try
{
bmp = new bitmap(bmpstream);
}
catch
{
error = "are you sure the specified bitmap is a valid bitmap ?";
return false;
}
if (bmp.pixelformat != system.drawing.imaging.pixelformat.format24bpprgb)
{
error = "please drop only 24bit bitmaps,thanks !";
return false;
}

error += "-> bitmap info: height=" + bmp.height + " width=" + bmp.width + ".../n";

if (datastream.length == 0)
{
error = "input data has a not supported size of 0 !";
return false;
}
uint maxbytestorage = ((uint)bmp.height * (uint)bmp.width * 3) / 8;
error += "-> up to " + (maxbytestorage-4) + " bytes could be stored in this bitmap.../n";
if (maxbytestorage < datastream.length + 4)
{
error = "not enough pixel in target bitmap to hide the input data block !";
return false;
}

bitmap24writer bmpwriter = new bitmap24writer(bmp);
uint datasize = (uint)datastream.length;
try
{
for (uint u = 0; u < 4; u++)
{
bmpwriter.writebyte( (byte)datasize );
datasize >>= 8;
}
for (uint u = 0; u < datastream.length; u++)
bmpwriter.writebyte( (byte)datastream.readbyte() );
}
catch
{
error = "error while modifing the bitmap's pixels !";
return false;
}

double maxbitstorage = bmpwriter.getmaxbitstoragecount();
double spaceused = (100 * (maxbitstorage - bmpwriter.getunusedbitcount())) / maxbitstorage;
error += "-> space used: " + convert.touint32(spaceused) + "%.../n";

try
{
if ( file.exists( outfname ) )
file.delete( outfname );
bmpwriter.getbitmap().save(outfname);
}
catch
{
error = "couldn't save output to " + outfname + " !";
return false;
}

error += "-> output saved to: " + outfname + ".../n";

return true;
}

public static bool bmp2data(filestream bmpstream, string outfname, out string error)
{
error = "";

bitmap bmp;
try
{
bmp = new bitmap(bmpstream);
}
catch
{
error = "are you sure the specified bitmap is a valid bitmap ?";
return false;
}

bitmap24reader bmpreader;
try
{
bmpreader = new bitmap24reader(bmp);
}
catch (argumentexception)
{
error = "this isn't a 24bit bitmap !";
return false;
}

filestream outstream;
try
{
outstream = file.create( outfname );
}
catch
{
error = "couldn't create output file: " + outfname + " !";
return false;
}
uint datasize = 0;
byte outbyte;
try
{
for (uint u = 0; u < 4; u++)
{
if ( !bmpreader.readbyte( out outbyte ) )
throw new exception();
datasize |= (uint)( outbyte << 8*3 );
if (u != 3)
datasize >>= 8;
}
error += "-> size of hidden data: " + datasize + " bytes.../n";
for (uint u = 0; u < datasize; u++)
{
if ( !bmpreader.readbyte( out outbyte ) )
throw new exception();
outstream.writebyte( outbyte );
}
}
catch
{
error = "exception caught while reading the hidden data !";
return false;
}
finally
{
outstream.close();
}

error += "-> output saved to: " + outfname + ".../n";

return true;
}

}

class bmpsafe
{
public static string cmdline =
"command line:/n" +
" bmpsafe.exe /file2bmp (input bmp) (input file to hide) [output file]/n" +
" bmpsafe.exe /bmp2file (data bmp) [output file]";

private static string serviceone = "/file2bmp";
private static string servicetwo = "/bmp2file";

[stathread]
static void main(string[] args)
{
console.writeline(
"bmpsafe - hide files in 24bit bitmaps/n" +
" a little steganografie implementation/n" +
" by yoda/n" +
"-------------------------------------------------------------------------------/n");

string infile = "", inbmp, outfile;
bool bfile2bmp;
if (args.length < 2)
{
console.writeline("!! invalid number of arguments :(");
console.writeline(cmdline);
return; // err
}
if ( string.compare(args[0], serviceone, true) == 0 )
bfile2bmp = true;
else if ( string.compare(args[0], servicetwo, true) == 0)
bfile2bmp = false;
else
{
console.writeline("!! first parameters must be either /"/file2bmp/" or /"/bmp2file/" !");
return;
}

inbmp = args[1];
if (bfile2bmp)
{
if (args.length < 3)
{
console.writeline("!! invalid number of arguments :(");
console.writeline(cmdline);
return;
}
infile = args[2];
if (args.length > 3)
outfile = args[3];
else
outfile = "secret.bmp";
}
else
{
if (args.length > 2)
outfile = args[2];
else
outfile = "secret.bin";
}

console.writeline("-> processing input...");
try
{
string err;
bool ret;

if (bfile2bmp)
ret = bitmapworks.data2bmp(
file.openread(infile),
file.openread(inbmp),
outfile,
out err );
else
ret = bitmapworks.bmp2data(
file.openread(inbmp),
outfile,
out err);
if (!ret)
{
console.writeline("!! " + err);
return;
}
else
console.write( err );
}
catch(filenotfoundexception)
{
console.writeline("!! at least one file could not be found :(");
return;
}
catch
{
console.writeline("!! an exception occurred :(");
return;
}

console.writeline("-> job done...");

return;
}
}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表