محافظت در برابر سرریز بافر
مثال از canary

تخصیص بافر معمولی برای معماری‌های x86 و سایر معماری‌های مشابه در سرریز بافر نشان داده شده است. در اینجا ما فرایند تغییر یافته را به صورتی که به StackGuard مربوط می‌شود را نشان خواهیم داد.
زمانی که یک تابع فراخوانی می‌شود، یک فریم شته ایجاد می‌شود. یک فریم پشته از انتهای حافظه تا ابتدا آن ساخته شده است. هر فریم پشته در بالای پشته قرار داده می‌شود که نزدیکترین به ابتدا حافظه است. بنابراین، اجرای قطعه آخر از داده‌ها در یک فریم پشته، داده‌های قبلی که قبلاً وارد فریم پشته شدند را تغییر می‌دهد و اجرای انتها یک فریم پشته داده‌ها در فریم پشته قبلی قرار می‌دهد. یک فریم پشته معمولی ممکن است به شکل زیر باشد:
آدرس بازگشت (RETA) در ابتدا
دستورات (CTLI) در ادامه
(CTLI)(RETA)
در C، یک تابع ممکن است شامل ساختارهای مختلف داده به ازای هر فراخوانی باشد. هر قطعه از داده‌ها که در فراخوانی ایجاد می‌شود به ترتیب در پشته قرار می‌گیرد، بنابراین از انتها تا ابتدا حافظه مرتب می‌شوند. در زیر یک تابع فرضی و فریم پشته آن وجود دارد.
int foo() {
  int a;             /* integer */
  int *b;            /* pointer to integer */
  char c[10];        /* character arrays */
  char d[3];

  b = &a;            /* initialize b to point to location of a */
  strcpy(c,get_c()); /* get c from somewhere, write it to c */
  *b = 5;            /* the data at the point in memory b indicates is set to 5 */
  strcpy(d,get_d());
  return *b;         /* read from b and pass it to the caller */
}
(d..)(c.........)(b...)(a...)(CTLI)(RETA)
در این وضعیت فرضی، اگر بیش از ده بایت در آرایه c، یا بیش از 13 بایت در آرایه کاراکتری d نوشته شود، مازاد آن در اشاره‌گر عدد صحیح b، سپس در عدد صحیح a، پس از آن در دستورات کنترلی و در نهایت در آدرس بازگشت سرریز می‌شود. با بازنویسی b، اشاره‌گر می‌تواند به مکانی از حافظه اشاره کند و در نتیجه هر آدرس دلخواهی از حافظه را بخواند. با بازنویسی RETA، تابع می‌تواند کد دیگری را اجرا کند (در زمانی که قصد بازگشت دارد). این کد می‌تواند از بین توابع موجود، یا کدهای نوشته شده در پشته در زمان سرریز باشد.
به طور خلاصه، مدیریت ضعیف متغیرهای d و c، مانند فراخوانی strcpy در بدون تعیین مرز بالا، می‌تواند به مهاجمین اجازه دهد برنامه را با مقادیر منتسب شده در c و d بطور مستقیم کنترل کند. هدف از محافظت در برابر سرریز بافر، شناسایی این مشکلات با کمترین هزینه می‌باشد. این کار با حذف مقادیر مضر غیر ضروری یا افزودن canary بعد از بافر انجام می‌شود.
محافظت در برابر سرریز بافر در کامپایلر پیاده سازی می‌شود. به این ترتیب، برای محافظت می‌توان ساختار داده را در فریم پشته تغییر داد. این کار دقیقاً همان چیزی است که در سیستم‌هایی مانند ProPolice انجام می‌شود. برای امن کردن تابع بالا، ترتیب زیر بصورت خودکار تنظیم می‌شود: آرایه c و d در ابتدا فریم پشته قرار می‌گیرند که در نتیجه اعداد صحیح a و b قبل از آن‌ها در حافظه قرار می‌گیرند. بنابراین فریم پشته به شکل زیر می‌شود.
حفاظت از سرریز بافر به عنوان تغییری در کامپایلر اجرا می‌شود. به این ترتیب ، برای محافظت می‌توان ساختار داده را در قاب پشته تغییر داد. این دقیقاً در سیستم‌هایی مانند ProPolice رخ می‌دهد . متغیرهای خودکار تابع بالا را بخواهند صفحاتی دوباره مرتب با خیال راحت تر است: آرایه‌ها c و d برای اولین بار در قاب پشته اختصاص داده، که مکان صحیح و اشاره گر عدد صحیح a b قبل از آنها در حافظه است. بنابراین قاب پشته می‌شود
(b...)(a...)(d..)(c.........)(CTLI)(RETA)
از آنجا که انتقال CTLI یا RETA بدون تغییر سورس کد غیرممکن است، روش دیگری قابل استفاده می‌باشد. یک قطعه اطلاعات اضافی به نام canary (CNRY) پس از بافر در فریم پشته قرار می‌گیرد. زمانی که بافر سرریز می‌شود، مقدار canary تغییر می‌کند. بنابراین، برای یک حمله موثر به برنامه، مهاجم باید مقدار canary را دست نخورده باقی بگذارد. فریم پشته بصورت زیر است.
(b...)(a...)(d..)(c.........)(CNRY)(CTLI)(RETA)
در انتهای هر تابع یک دستوالعمل وجود دارد که اجرای برنامه را از آدرس مشخص شده در RETA ادامه می‌دهد. قبل از اجرای این دستورالعمل، مطمئن می‌شویم که مقدار CNRY تغییر نکرده باشد. در صورتی که این تست با خطا روبرو شود، اجرای برنامه سریعاً متوقف می‌شود. در اصل، هر دو حمله عمدی و اشکالات برنامه نویسی سهوی منجر به قطع برنامه می‌شوند.
روش canary قبل از هر اختصاص پویای بافر و بعد از هر جداسازی پویای بافر یکسری دستورالعمل سربار اضافه می‌کند. سربار تولید شده در این روش قابل توجه نیست. تا زمانی که این مقدار تغییر نکند برنامه کار می‌کند. اگر مهاجم بداند canary وجود دارد، مقدار آن چیست و موقعیت آن کجاست، می‌تواند مقدار آن را بدون تغییر نگه دارد. معمولاً این کار دشوار است.
موقعیت قرارگیری مقدار canary در پیاده‌سازی مشخص می‌شود، اما همیشه بین بافر و داده‌های محافظت‌شده قرار دارد. موقعیت و طول‌های متفاوت دارای مزایایی نیز هستند.