ReverseEngineering
1.33K subscribers
50 photos
11 videos
112 files
916 links
Download Telegram
Then, if the variable type and base address are known, you can assign the structure type to the relevant variable so that accesses are more readable instead of raw offsets.

For example, instead of just seeing that the program reads from [rcx+4], you can recognize that it is reading the second field of the structure.

This also simplifies the analysis of subsequent functions because you do not have to calculate from the beginning which memory section each offset refers to each time.

Exercise:

Suppose you find these instructions in a binary file.

Asm

mov eax, dword ptr [rbx]

cmp eax, 0

mov ecx, dword ptr [rbx+8]

mov byte ptr [rbx+12], 1

Based on these instructions, determine

what memory offsets are used and what is the size of each access.

What types of fields are possible in this Offsets exist

Why can't we still say with certainty what fields the original structure has?

The main point of this section is that in reverse engineering you don't need to know the original structure from the start. By gathering evidence from offsets, access sizes, and how data is used, you can build a plausible model of the memory structure step by step

@reverseengine
قسمت سی و پنجم بافر اورفلو


Concolic Execution

ترکیب اجرای واقعی و نمادین برای کشف مسیرهای جدید



Concolic Execution
ترکیبی از دو روشه:

Concrete Execution:
اجرای برنامه با ورودی واقعی

Symbolic Execution:
بررسی نمادین داده‌ ها و شرط‌ های مسیر اجرا

هدف اینه که از یک اجرای واقعی شروع کنیم شرط‌ هایی رو که برنامه طی کرده استخراج کنیم و ورودی‌ های جدیدی بسازیم تا مسیر های دیگه هم بررسی بشن

یک مثال ساده

فرض کنید برنامه اینه:

int check(int x)
{
if (x > 10)
{
if (x < 20)
return 1;
}

return 0;
}

برنامه رو با این ورودی اجرا میکنیم:

x = 5

چون شرط "x > 10" برقرار نیست برنامه مستقیما به "return 0" میرسه

مسیر اجرا:

x = 5
|
x > 10 ?
|
False
|
return 0

تا اینجا فقط یک مسیر رو بررسی کردیم

اما Concolic Execution میتونه از همین اجرا برای پیدا کردن ورودی جدید استفاده کنه

استخراج شرط مسیر

در اجرای بالا شرط زیر بررسی شده:

if (x > 10)

مقدار واقعی "x" برابر 5 بوده پس شرط غلط شده

محدودیت نمادین مسیر طی‌ شده اینه:

x <= 10

حالا برای بررسی شاخه‌ی مخالف این شرط رو در نظر میگیریم:

x > 10

حل‌کننده‌ی محدودیت‌ها مثل SMT Solver میتونه یک مقدار مناسب پیشنهاد بده:

x = 15

با اجرای مجدد برنامه:

x = 15
|
x > 10 ?
|
True
|
x < 20 ?

این بار به شرط دوم رسیدیم مسیری که اجرای قبلی بهش نرسیده بودیم

ساخت ورودی جدید برای مسیر بعدی

شرط دوم اینه:

if (x < 20)

برای ورودی 15 این شرط هم برقرار میشه و برنامه به این بخش میرسه:

return 1;

محدودیت‌های مسیر موفق این برنامه عبارت‌اند از:

x > 10
AND
x < 20

یعنی:

10 < x < 20

پس "x = 15" یک ورودی معتبر برای رسیدن به این مسیر محسوب میشه

نکته‌ی مهم اینه که ورودی جدید صرفا تصادفی انتخاب نشده بلکه با استفاده از شرط‌ های مسیر ساخته شده

در عمل ابزار میتونه مسیرهای اجراشده رو ثبت کنه و با تغییر یکی از شرط‌ها ورودی جدیدی برای رسیدن به شاخه‌ ی متفاوت بسازه

الگوریتم کلی Concolic Execution

اجرای برنامه

برنامه با یک ورودی واقعی اجرا میشه

ثبت شرط‌های مسیر

ابزار شرط‌ های شاخه‌ هایی رو که برنامه ازشون عبور کرده ثبت میکنه به این شرط‌ ها "Path Constraints" گفته میشه.
تغییر یک شرط مسیر

یکی از شرط‌ ها رو برای بررسی شاخه‌ی مخالف تغییر میده در حالی که شرط‌ های قبلی مسیر رو هم در نظر میگیره

حل محدودیت‌ها

یک "SMT Solver" تلاش میکنه ورودی‌ ای پیدا کنه که شرط‌ های جدید رو برآورده کنه

اجرای مجدد با ورودی جدید

برنامه با ورودی به‌دست‌ اومده دوباره اجرا میشه تا مسیر متفاوتی بررسی بشه

این چرخه میتونه بارها تکرار بشه تا مسیرهای بیشتری پوشش داده بشن

ارتباط Concolic Execution با Fuzzing

در Fuzzing معمولی ورودی‌ ها اغلب با جهش یا تغییر ورودی‌ های قبلی ساخته میشن

مثلا:

Input A
↓
Mutation
↓
Input B
↓
New Execution

اما بعضی وقتا برنامه شرطی داره که رسیدن به شاخه‌ی موردنظر رو دشوار میکنه

مثلا:

if (input[0] == 'R' &&
input[1] == 'E' &&
input[2] == 'V')
{
process_special_case();
}

Fuzzer
باید ورودی‌ ای پیدا کنه که هر سه شرط رو برقرار کنه

Concolic Execution
میتونه شرط‌ های بررسی‌ شده رو تحلیل کنه و برای عبور از شاخه‌ ها ورودی مناسب پیشنهاد بده

Input
↓
Execution
↓
Path Constraints
↓
Solver
↓
New Input
↓
New Path

این ایده در Concolic Testing و بعضی روش‌های هدایت هوشمند ورودی در تست نرم‌افزار کاربرد داره

البته Fuzzer های مدرن هم میتونن از تکنیک‌هایی مثل "Coverage-Guided Fuzzing" استفاده کنن و بدون حل نمادین شرط‌ ها با جهش‌ های هدفمند به مسیرهای جدید برسن

محدودیت‌ های این روش

Concolic Execution
جادو نیست هرچند اسمش طوریه که انگار قراره برنامه خودش رو برای ما توضیح بده

چند مشکل مهم داره:

Path Explosion:
تعداد مسیرهای ممکن میتونه به‌سرعت زیاد بشه

محدودیت حل‌ کننده:
بعضی شرط‌ ها مخصوصا محاسبات پیچیده یا عملیات پشتیبانی‌ نشده ممکنه سخت حل بشن

وابستگی به اجرا:
تحلیل معمولا از مسیر هایی شروع میشه که با ورودی‌ های اولیه اجرا شدن برای رسیدن به مسیرهای دیگه باید ورودی‌های مناسبی تولید بشن

محیط اجرا:
تعامل با فایل شبکه سیستم‌ عامل یا کد خارجی میتونه تحلیل رو پیچیده‌تر کنه

به همین دلیل این روش معمولا در کنار Fuzzing و Static Analysis استفاده میشه نه به‌عنوان جایگزین کامل اون‌ها

تفاوت سه روش
روش ایده‌ی اصلی
Symbolic Execution
تحلیل مسیرها با مقادیر نمادین و محدودیت‌ها

Concrete Execution
اجرای برنامه با مقادیر واقعی

Concolic Execution
اجرای واقعی همراه با تحلیل نمادین مسیر


در Concolic Execution اجرای واقعی برنامه نقطه‌ی شروعه شرط‌ های مسیر ثبت میشن یکی از شرط‌ ها برای بررسی مسیر جدید تغییر میکنه و حل‌ کننده تلاش میکنه ورودی مناسبی پیدا کنه

این روش در تحلیل باینری تست خودکار کشف مسیر های کمتر بررسی‌ شده و کمک به Fuzzing کاربرد داره

@reverseengine
ReverseEngineering
قسمت سی و پنجم بافر اورفلو Concolic Execution ترکیب اجرای واقعی و نمادین برای کشف مسیرهای جدید Concolic Execution ترکیبی از دو روشه: Concrete Execution: اجرای برنامه با ورودی واقعی Symbolic Execution: بررسی نمادین داده‌ ها و شرط‌ های مسیر اجرا هدف…
Part 35 Buffer Overflow


Concolic Execution

Combining Real and Symbolic Execution to Discover New Paths

Concolic Execution
is a combination of two methods:

Concrete Execution:
Executing the program with real input

Symbolic Execution:
Symbolically examining the data and conditions of the execution path

The goal is to start from a real execution, extract the conditions that the program has passed and create new inputs so that other paths can be examined

A simple example

Suppose the program is:

int check(int x)
{
if (x > 10)
{
if (x < 20)
return 1;
}

return 0;
}

We execute the program with this input:

x = 5

Since the condition "x > 10" is not true, the program goes directly to "return 0"

Execution path:

x = 5
|
x > 10 ?
|
False
|
return 0

So far we have only examined one path

But Concolic Execution can use the same execution to find new inputs

Extracting Path Condition

In the above execution, the following condition is examined:

if (x > 10)

The actual value of "x" is 5, so the condition is false

The symbolic constraint of the path taken is:

x <= 10

Now, to examine the opposite branch, we consider this condition:

x > 10

A constraint solver such as SMT Solver can suggest a suitable value:

x = 15

By re-executing the program:

x = 15
|
x > 10 ?
|
True
|
x < 20 ?

This time we reached the second condition, a path that we had not reached in the previous execution

Create a new input for the next path

The second condition is:

if (x < 20)

For input 15, this condition is also met and the program reaches this section:

return 1;

The constraints of the successful path of this program are:

x > 10
AND
x < 20

That is:

10 < x < 20

So "x = 15" is a valid input to reach this path

The important point is that the new input is not chosen randomly but is created using path constraints

In practice, the tool can record the executed paths and create a new input to reach a different branch by changing one of the conditions

General Algorithm of Concolic Execution

Program Execution

The program is executed with a real input

Recording Path Constraints

The tool records the conditions of the branches that the program has crossed. These conditions are called "Path Constraints".
Changing a Path Condition

Changes one of the conditions to check the opposite branch while still considering the previous path conditions

Resolving Constraints

An "SMT Solver" tries to find an input that satisfies the new conditions

Rerun with new input

The program is re-executed with the given input to check a different path

This cycle can be repeated many times to cover more paths

Relationship of Concolic Execution to Fuzzing

In typical Fuzzing, inputs are often created by mutating or changing previous inputs

For example:

Input A
↓
Mutation
↓
Input B
↓
New Execution

But sometimes the program has a condition that makes it difficult to reach the desired branch

For example:

if (input[0] == 'R' &&
input[1] == 'E' &&
input[2] == 'V')
{
process_special_case();

}

Fuzzer
must find an input that satisfies all three conditions

Concolic Execution
can analyze the conditions examined and suggest suitable inputs to traverse the branches

Input
↓
Execution
↓
Path Constraints
↓
Solver
↓
New Input
↓
New Path

This idea is used in Concolic Testing and some intelligent input guidance methods in software testing

Of course, modern fuzzers can also use techniques such as "Coverage-Guided Fuzzing" and reach new paths with targeted jumps without solving the conditions symbolically

Limitations of this method

Concolic Execution
is not magic, although its name seems to be explaining its program to us

It has several important problems:

Path Explosion:
The number of possible paths can increase rapidly

Solver Limitations:
Some conditions, especially complex calculations or operations Unsupported may be difficult to solve

Execution Dependency:
Analysis usually starts with paths that require proper inputs to be generated with the initial execution to reach other paths
ReverseEngineering
قسمت سی و پنجم بافر اورفلو Concolic Execution ترکیب اجرای واقعی و نمادین برای کشف مسیرهای جدید Concolic Execution ترکیبی از دو روشه: Concrete Execution: اجرای برنامه با ورودی واقعی Symbolic Execution: بررسی نمادین داده‌ ها و شرط‌ های مسیر اجرا هدف…
Execution Environment:
Interaction with network files, operating system, or external code can complicate the analysis

For this reason, this method is usually used alongside Fuzzing and Static Analysis, not as a complete replacement for them

Differences between the three methods

Methods Main Idea
Symbolic Execution
Path analysis with symbolic values ​​and constraints

Concrete Execution
Execution of the program with real values

Concolic Execution
Real execution with symbolic path analysis

In Concolic Execution, the actual execution of the program is the starting point. Path conditions are recorded. One of the conditions is changed to check the new path, and the solver tries to find a suitable input

This method is used in binary analysis, automatic testing, discovery of less-examined paths, and assistance in Fuzzing

@reverseengine
Image Loading
در برابر Manual Mapping

Windows Loader
چه کاری انجام میده و چرا تفاوت روش‌ های بارگذاری برای تحلیل Memory مهمه؟

تا اینجا با ساختار PE مفهوم ImageBase جدول IAT و تفاوت Raw Offset با RVA آشنا شدیم

حالا میرسیم به یکی از موضوعات مهم در مهندسی معکوس ویندوز:

تفاوت بین بارگذاری معمول یک فایل اجرایی و قرار گرفتن یک Image در حافظه به روشی متفاوت از مسیر عادی Loader

بارگذاری معمولی PE چطوری انجام میشه؟

وقتی Windows یک فایل اجرایی رو اجرا میکنه یا یک DLL رو به‌صورت معمول بارگذاری میکنه بخش‌ های مختلف سیستم‌ عامل در مدیریت این فرایند نقش دارن

نمای ساده‌ شده:

PE File
|
v
Windows Loader
|
├── بررسی ساختار PE
├── آماده‌سازی Image
├── مدیریت وابستگی‌ها
├── پردازش Relocation در صورت نیاز
├── آماده‌سازی Importها
└── تکمیل مراحل لازم برای بارگذاری
|
v
Image in Memory

این نمودار ساده‌ شده است
جزئیات واقعی به نوع Image وضعیت Process و مسیر بارگذاری بستگی دارن
نکته مهم اینه که بارگذاری PE فقط کپی کردن چند Byte از فایل به RAM نیست ساختار فایل باید برای استفاده در فضای آدرس مجازی آماده بشه و مراحل لازم برای وابستگی‌ها دسترسی حافظه و مقداردهی اولیه انجام بشن

Windows Loader
چه چیزهایی رو مدیریت میکنه؟

چند مورد مهم:

سکشن ها:
بخش‌های مختلف Image در فضای آدرس مجازی نگاشت میشن

Relocation:
در صورت نیاز آدرس‌های وابسته به محل بارگذاری اصلاح میشن

Import
ها:

وابستگی‌ های مورد نیاز برنامه مدیریت و آدرس توابع موردنیاز مشخص میشن

Memory Protection:
محدوده‌ های مختلف حافظه Permission های متناسب با کاربردشون میگیرن

Initialization:
مراحل لازم برای آماده شدن Module برای استفاده انجام میشن
البته تمام مسئولیت‌ ها در یک تابع واحد جمع نشده Windows Loadr Memory Manager و اجزای دیگه‌ی سیستم‌ عامل در این فرایند نقش دارن

Manual Mapping

اصطلاح Manual Mapping به روشی اشاره میکنه که در اون یک PE به‌جای اینکه تمام مسیر معمول بارگذاری Module رو طی کنه با منطق سفارشی در حافظه آماده میشه

به‌صورت مفهومی:
PE File
|
v
Custom Loading Logic
|
├── آماده‌سازی بخش‌های Image
├── مدیریت آدرس‌ها
├── رسیدگی به وابستگی‌ها
└── آماده‌سازی ساختار حافظه
|
v
Memory Region

این نمودار مفهوم کلی رو نشون میده نه یک پیاده‌سازی کامل جزئیات به نوع PE و روش مورد استفاده وابسته‌ان

Manual Mapping
به‌خودی‌خود مترادف بدافزار نیست بعضی ابزارهای تخصصی Runtime ها و محیط‌ های آزمایشی ممکنه از روش‌های بارگذاری غیرمعمول استفاده کنن با این حال این مفهوم در تحلیل بعضی تکنیک‌های مخرب هم اهمیت داره

نکته مهم اینه که آماده کردن یک PE در حافظه به‌ تنهایی به معنی کامل شدن تمام مراحل بارگذاری معمول ویندوز نیست مدیریت وابستگی‌ها Relocation ، Initialization و سایر جزئیات ممکنه به شکل متفاوتی انجام بشن یا نیازمند پیاده‌سازی جداگانه باشن

تفاوت اصلی از دید تحلیل‌گر چیه؟

فرض کنید دو Process داریم
در اولی یک DLL به شکل معمول بارگذاری شده:

Process A
|
└── Loaded Module
|
├── Module Information
├── Image Layout
└── Memory Permissions

در دومی یک ناحیه از حافظه وجود داره که محتوای اون شبیه یک Image اجراییه اما ارتباط واضحی با یک Module معمولی و قابل شناسایی نداره:

Process B
|
└── Memory Region
|
├── PE-like Structure
├── Memory Permissions
└── Unusual Module Relationship

این تفاوت میتونه برای بررسی بیشتر مهم باشه اما به‌تنهایی چیزی رو ثابت نمیکنه
برای مثال ممکنه یک ابزار تخصصی از روش بارگذاری متفاوتی استفاده کرده باشه یا اطلاعات Memory Dump برای شناسایی دقیق Module کافی نباشه
چرا فهرست Module ها همیشه کل داستان نیست؟

در ویندوز ابزارهای مختلفی وجود دارن که Module های یک Process رو نمایش میدن با این حال فهرست Module ها و تمام Memory های یک Process دو مفهوم متفاوت هستن

به این مدل توجه کنید:

Process Virtual Address Space
│
├── Executable Image
├── Loaded DLLs
├── Heap Allocations
├── Thread Stacks
├── Memory-Mapped Files
└── Other Memory Regions

هرکدوم از این بخش ها کاربرد متفاوتی دارن
بنابراین:

اگر یک Region در فهرست Module ها دیده نشد نمیتونیم نتیجه بگیریم که حتما مخربه یا هیچ ارتباطی با یک فایل اجرایی نداره.

برای رسیدن به نتیجه باید ساختار حافظه منشا Region و رفتار Process رو کنار هم بررسی کنیم

تحلیلگر چه شواهدی رو بررسی میکنه؟

در بررسی یک Region غیرمعمول این دسته اطلاعات میتونن مفید باشن:

هیچکدوم از این موارد به‌تنهایی حکم قطعی نیستن ارزش اصلی زمانی ایجاد میشه که چند شاهد مستقل با هم تطبیق داده بشن

ارتباطش با EDR و Memory Forensics

از دید دفاعی یک سؤال مهم اینه:

آیا میشه با بررسی صرفا فهرست Module ها تمام رفتارهای مرتبط با اجرای کد رو شناخت؟ نه

فهرست Module ها فقط یک نمای محدود از وضعیت Process ارائه میده برای بررسی دقیق‌تر ممکنه به اطلاعاتی از این جنس نیاز باشه:

Process
|
├── Module Inventory
├── Virtual Memory Map
├── Memory Protection
├── Thread Information
├── Call Stack
└── Event Timeline
|
v
Behavior Analysis

این رویکرد کمک میکنه تفاوت بین رفتار طبیعی برنامه و فعالیت غیرمعمول بهتر بررسی بشه

یک نکته هم مهمه:
همه‌ی EDR ها به یک اندازه به این اطلاعات دسترسی ندارن یا همه‌ی اون‌ها رو به یک شکل تحلیل نمیکنن نتیجه به قابلیت محصول تنظیمات و Telemetry موجود بستگی داره

تمرین مفهومی:

دو وضعیت زیر رو مقایسه کنید

وضعیت اول:

Region Type: Image
Module: Known DLL
Protection: RX

وضعیت دوم:

Region Type: Private
Module: No obvious association
Protection: RX

صرفا از روی این اطلاعات نمیشه گفت وضعیت دوم مخربه اما در وضعیت دوم ممکنه لازم باشه اطلاعات بیشتری جمع کنید

برای هر دو وضعیت این سؤال‌ها رو مطرح کنید:

آیا ساختار حافظه با نوع Region سازگاره؟

Thread ها و Call Stack اطلاعات مرتبطی ارائه میکنن؟
رویداد های قبل و بعد از ایجاد Region توضیح قابل قبولی دارن؟


سه مفهوم رو از هم جدا نگه دارید:

Normal Image Loading:
اپلود از مسیر معمول ویندوز و مدیریت مراحل مرتبط با آن

Manual Mapping:
آماده‌سازی یک Image در حافظه با منطق بارگذاری متفاوت از مسیر معمول

Memory Forensics:
بررسی ساختار و وضعیت حافظه برای فهمیدن اتفاقاتی که داخل Process افتادن

این سه مفهوم به هم مرتبطن اما یکی نیستن

@reverseengine
ReverseEngineering
Image Loading در برابر Manual Mapping Windows Loader چه کاری انجام میده و چرا تفاوت روش‌ های بارگذاری برای تحلیل Memory مهمه؟ تا اینجا با ساختار PE مفهوم ImageBase جدول IAT و تفاوت Raw Offset با RVA آشنا شدیم حالا میرسیم به یکی از موضوعات مهم در مهندسی…
Image Loading
vs. Manual Mapping

What does Windows Loader do and why are the differences in loading methods important for memory analysis?

So far, we have learned about the PE structure, the concept of the ImageBase table, and the difference between Raw Offset and RVA

Now we come to one of the important topics in Windows reverse engineering:

The difference between normal loading of an executable file and placing an Image in memory in a different way from the normal Loader path

How is normal PE loading done?

When Windows runs an executable file or loads a DLL normally, various parts of the operating system play a role in managing this process

Simplified view:

PE File
|
v
Windows Loader
|
├── Examine the PE structure
├── Prepare the Image
├── Manage dependencies
├── Process relocation if necessary
├── Prepare imports
└── Complete the steps required for loading
|
v
Image in Memory

This diagram is simplified

The actual details depend on the Image type, Process state, and loading path

The important thing is that PE loading is not just copying a few bytes from the file to RAM. The file structure must be prepared for use in the virtual address space, and the necessary steps for dependencies, memory access, and initialization must be performed

What does the Windows Loader handle?

Some important things:

Sections: Different parts of the image are mapped to the virtual address space

Relocation:
If necessary, the addresses dependent on the loading location are modified

Imports:
The dependencies required by the management program and the addresses of the required functions are specified

Memory Protection:
Different memory areas receive permissions appropriate to their use

Initialization:
The steps necessary to prepare the module for use are performed
Of course, not all responsibilities are collected in a single function. The Windows Loader Memory Manager and other operating system components play a role in this process

Manual Mapping

The term Manual Mapping refers to a method in which a PE is prepared in memory with custom logic instead of going through the entire usual module loading path

Conceptually:
PE File
|
v
Custom Loading Logic
|
├── Preparing Image Sections
├── Address Management
├── Handling Dependencies
└── Preparing the Memory Structure
|
v
Memory Region

This diagram shows the general concept, not a complete implementation, details the type of PE and the method used by the dependencies

Manual Mapping

It is not synonymous with malware in itself. Some specialized tools, runtimes and test environments may use unusual loading methods. However, this concept is also important in analyzing some malicious techniques

The important point is that preparing a PE in memory alone does not mean that all the usual Windows loading steps have been completed. Dependency management, relocation, initialization and other details may be done differently or require separate implementations

What is the main difference from the analyst's point of view?

Suppose we have two processes

In the first, a DLL is loaded in the usual way:

Process A
|
└── Loaded Module
|
├── Module Information
├── Image Layout
└── Memory Permissions

In the second, there is a region of memory whose content resembles an executable image but has no clear relationship to a regular and identifiable module:

Process B
|
└── Memory Region
|
├── PE-like Structure
├── Memory Permissions
└── Unusual Module Relationship

This difference can be important for further investigation, but it does not prove anything by itself

For example, a specialized tool may have used a different loading method, or the Memory Dump information may not be enough to accurately identify the Module

Why is the Module List not always the whole story?

In Windows, there are various tools that display the Modules of a Process, however, the Module List and the Total Memory of a Process are two different concepts

Pay attention to this model:
Consider this:

If a memory region does not appear in the list of loaded modules, should we conclude that it is necessarily malicious or unrelated to any executable file?
To reach a conclusion, we must examine the memory structure, the origin of the region, and the process's behavior in conjunction with one another.

What evidence does an analyst examine?

When investigating an unusual memory region, the following types of information can be useful:

None of these factors, taken in isolation, constitute definitive proof; the real value lies in how they are correlated with one another.

Relevance to EDR and Memory Forensics

From a defensive perspective, a key question arises:

Is it possible to identify all behaviors associated with code execution solely by examining the list of loaded modules? No.

The module list provides only a limited view of the process's state. A more thorough investigation may require data such as:

Process
|
├── Module Inventory
├── Virtual Memory Map
├── Memory Protection
├── Thread Information
├── Call Stack
└── Event Timeline
|
v
Behavioral Analysis

This facilitates a better distinction between the application's normal behavior and anomalous activity.

An important caveat:
Not all EDR (Endpoint Detection and Response) solutions have equal access to this information, nor do they all analyze it in the same way; the outcome depends on the quality of the product and the available telemetry.

Conceptual Exercise:

Compare the following two scenarios:

Scenario 1:

Region Type: Image
Module: Known DLL
Protection: RX (Read/Execute)

Scenario 2:

Region Type: Private
Module: No clear association
Protection: RX (Read/Execute)

Based solely on this information, one cannot definitively label the second scenario as malicious; however, it may warrant further data collection.

For both scenarios, ask the following question:

Is the memory structure consistent with the region type? Do the threads and the call stack provide relevant information?

Are there events occurring before and after the creation of a memory region?

Keep these three concepts distinct:

Standard Image Loading:
Loading via the conventional Windows path and managing the associated steps.

Manual Mapping:
Preparing an image in memory using loading logic that differs from the standard path.

Memory Forensics:
Examining the structure and state of memory to understand the events that took place within a process.

While related, these three concepts are not the same.

@reverseengine
QuarkslaB Dynamic binary Instrumentation

https://qbdi.quarkslab.com/introduction

@reverseengine