استگانوگرافی LSB

روزی روزگاری من نوشتم اولین پست در هاب. و آن پست به یک مشکل بسیار جالب اختصاص داشت، یعنی استگانوگرافی. البته راه حل ارائه شده در آن مبحث قدیمی را نمی توان به معنای واقعی کلمه استگانوگرافی نامید. این فقط یک بازی با فرمت های فایل است، اما با این وجود یک بازی بسیار جالب است.

امروز سعی خواهیم کرد کمی عمیق‌تر کاوش کنیم و الگوریتم LSB را بررسی کنیم. اگر علاقه مند هستید، زیر گربه خوش آمدید. (زیر برش ترافیک است: حدود یک مگابایت.)

قبل از هر چیز لازم است یک مقدمه کوتاه بیان شود. همه می دانند که هدف از رمزنگاری غیرممکن کردن خواندن اطلاعات مخفی است. البته رمزنگاری کاربردهای خود را دارد، اما رویکرد دیگری برای حفاظت از داده ها وجود دارد. ما مجبور نیستیم اطلاعات را رمزگذاری کنیم، اما وانمود کنیم که آنها را نداریم. دقیقاً به همین دلیل است که استگانوگرافی اختراع شد. ویکی‌پدیا به ما اطمینان می‌دهد که "استگانوگرافی (از یونانی στεγανοσ - پنهان و یونانی γραφω - من می نویسم، به معنای واقعی کلمه "نوشتن مخفی") علم انتقال پنهان اطلاعات با مخفی نگه داشتن حقیقت انتقال است.

البته هیچ کس ترکیب روش های رمزنگاری و استگانوگرافی را منع نمی کند. علاوه بر این، در عمل آنها این کار را انجام می دهند، اما وظیفه ما درک اصول اولیه است. اگر مقاله ویکی‌پدیا را به دقت مطالعه کنید، متوجه خواهید شد که الگوریتم‌های استگانوگرافی شامل به اصطلاح هستند. ظرف و پیام ظرف هر اطلاعاتی است که به مخفی کردن پیام مخفی ما کمک می کند.

در مورد ما، ظرف یک تصویر با فرمت BMP خواهد بود. ابتدا به ساختار این فایل نگاه می کنیم. فایل را می توان به 4 قسمت تقسیم کرد: هدر فایل، هدر تصویر، پالت و خود تصویر. برای اهداف ما فقط باید بدانیم که در سربرگ چه نوشته شده است.

دو بایت اول هدر، امضای BM است، سپس حجم فایل بر حسب بایت به صورت دو کلمه ای نوشته می شود، 4 بایت بعدی رزرو شده و باید حاوی صفر باشد و در نهایت، یک کلمه دوتایی دیگر شامل افست از ابتدای فایل به بایت های واقعی تصویر. در یک فایل bmp 24 بیتی، هر پیکسل با سه بایت BGR کدگذاری می شود.

اکنون می دانیم که چگونه به تصویر برسیم، تنها چیزی که باقی می ماند این است که بفهمیم چگونه می توانیم اطلاعات مورد نیاز خود را در آنجا بنویسیم. برای این کار به روش LSB نیاز داریم. ماهیت روش به شرح زیر است: ما کمترین بیت های مهم را در بایت های مسئول رمزگذاری رنگ جایگزین می کنیم. فرض کنید اگر بایت بعدی پیام مخفی ما 11001011 باشد و بایت های موجود در تصویر...11101100 01001110 01111100 0101100111... باشد، پس کدگذاری به این صورت خواهد بود. ما بایت پیام مخفی را به 4 قسمت دو بیتی تقسیم می کنیم: 11، 00، 10، 11، و بیت های مرتبه پایین تصویر را با قطعات به دست آمده جایگزین می کنیم: ...11101111 01001100 01111110 0101100111…. چنین جایگزینی معمولاً برای چشم انسان قابل توجه نیست. علاوه بر این، بسیاری از دستگاه های خروجی قدیمی حتی قادر به نمایش چنین تغییرات جزئی نیستند.

واضح است که شما می توانید نه تنها 2 بیت کم اهمیت، بلکه هر تعداد از آنها را تغییر دهید. الگوی زیر وجود دارد: هر چه بیت های بیشتری را تغییر دهیم، اطلاعات بیشتری را می توانیم مخفی کنیم، و تداخل بیشتری در تصویر اصلی ایجاد می کند. به عنوان مثال، در اینجا دو تصویر وجود دارد:

استگانوگرافی LSB
استگانوگرافی LSB

با وجود تمام تلاشم نتوانستم تفاوت بین آنها را ببینم، اما با این وجود، در تصویر دوم با استفاده از روش توصیف شده، شعر "شکار اسنارک" لوئیس کارول پنهان شده است. اگر تا اینجا خوانده اید، احتمالاً علاقه مند به یادگیری در مورد پیاده سازی هستید. بسیار ساده است، اما من فوراً به شما هشدار می دهم که همه چیز در دلفی انجام می شود. دو دلیل برای این وجود دارد: 1. به نظر من دلفی زبان خوبی است. 2. این برنامه در مراحل آماده سازی دوره مبانی بینایی کامپیوتر متولد شد و بچه هایی که من این دوره را به آنها آموزش می دهم هنوز چیزی جز دلفی نمی دانند. برای کسانی که با نحو آشنایی ندارند، یک چیز باید توضیح داده شود: shl x یک شیفت بیتی به چپ با x، shr x یک شیفت بیتی به سمت راست توسط x است.

ما فرض می کنیم که متن ذخیره شده در یک رشته را در ظرف می نویسیم و دو بایت پایین را جایگزین می کنیم:
کد ضبط:

برای i:=1 به طول(str) انجام دهید
    شروع
      l1:=byte(str[i]) shr 6;
      l2:=byte(str[i]) shl 2; l2:=l2 shr 6;
      l3:=byte(str[i]) shl 4; l3:=l3 shr 6;
      l4:=byte(str[i]) shl 6; l4:=l4 shr 6;
 
      f.ReadBuffer(tmp,1);
      f.Position:=f.Position-1;
      tmp:=((tmp shr 2) shl 2)+l1;
      f.WriteBuffer(tmp,1);
 
      f.ReadBuffer(tmp,1);
      f.Position:=f.Position-1;
      tmp:=((tmp shr 2) shl 2)+l2;
      f.WriteBuffer(tmp,1);
 
      f.ReadBuffer(tmp,1);
      f.Position:=f.Position-1;
      tmp:=((tmp shr 2) shl 2)+l3;
      f.WriteBuffer(tmp,1);
 
      f.ReadBuffer(tmp,1);
      f.Position:=f.Position-1;
      tmp:=((tmp shr 2) shl 2)+l4;
      f.WriteBuffer(tmp,1);
 
    پایان.

کد برای خواندن:

برای i:=1 به MsgSize انجام دهید
    شروع
      f.ReadBuffer(tmp,1);
      l1:=tmp shl 6;
      f.ReadBuffer(tmp,1);
      l2:=tmp shl 6; l2:=l2 shr 2;
      f.ReadBuffer(tmp,1);
      l3:=tmp shl 6; l3:=l3 shr 4;
      f.ReadBuffer(tmp,1);
      l4:=tmp shl 6; l4:=l4 shr 6;
      str:=str+char(l1+l2+l3+l4);
    پایان.

خوب، برای آنهایی که واقعا تنبل هستند - پیوند به برنامه و کد منبع آن.

متشکرم.

منبع: www.habr.com

اضافه کردن نظر