es
Feedback

¡No caigas en manos de tramposos! Telemetrio encuentra y marca estos canales 👉 Si quieres ver la etiqueta, suscríbete

ReverseEngineering

ReverseEngineering

Ir al canal en Telegram
1 443
Suscriptores
+224 horas
+1087 días
+11030 días
Archivo de publicaciones
This is a collection of tools you may like if you are interested in reverse engineering and/or malware analysis on x86 and x64 Windows systems. https://github.com/mentebinaria/retoolkit @reverseengine

Analysis of Virtualization-based Obfuscation (r2con2021workshop) https://youtu.be/b6udPT79itk @reverseengine

Reverse Engineering/Game Patching Tutorial: Full Res Roller Coaster Tycoon with Ghidra+x64dbg+Python https://www.youtube.com/watch?v=cwBoUuy4nGc&t=13s&ab_channel=jeFF0Falltrades

Awesome HyperDbg: A list of awesome resources about HyperDbg. https://github.com/HyperDbg/awesome @reverseengine

Two Windows bugs found with a frontier model, the first in just over an hour, and the human direction it took to get there. Then the same hunt replayed on open-weight local models to measure how much frontier capability survives. https://youtu.be/8C5v4bgK1H0

+1
Introduction to C & GUI Programming [2019] Simon Long.pdf8.99 MB

Programming_Rust,_2nd_Edition_Early_Release_2021_Jim_Blandy,_Jason.rar3.61 MB

Operating System Concepts, 10th edition

+1
imagination_gpu_offensivecon_2026.pdf12.92 MB

New Update — Evil Agent 📡 Introducing Evil Agent, a new payload generator for Discord and Telegram agents, supporting EXE, D
New Update — Evil Agent 📡 Introducing Evil Agent, a new payload generator for Discord and Telegram agents, supporting EXE, DLL, BIN, and HEX formats, with configurable message sizes and an alternative communication channel without requiring a dedicated listener or exposed port. The update also includes fixes to the existing Listener Payload Generator, Makefile improvements for smoother compilation, and GUI enhancements. Repository: https://github.com/S3N4T0R-0X0/BEAR-C2

Cross-Platform Micro-VM Sandbox for Agentic Workloads https://github.com/microsoft/nvx @reverseengine

Recreating uncensored Epstein PDFs from raw encoded attachments https://neosmart.net/blog/recreating-epstein-pdfs-from-raw-encoded-attachments @reverseengine

This example demonstrates that the selection of the next path to explore depends on the specific goals of the analysis; there is no single "best" criterion that applies to all programs. The Relationship Between Path Explosion and Reverse Engineering When analyzing an unknown binary, we generally do not want to examine every possible execution path. Our objective is to identify paths that yield the most information regarding the program's behavior. A practical workflow might look like this: Binary ↓ Find Interesting Functions ↓ Identify Important Branches ↓ Choose Target Paths ↓ Symbolic / Concolic Execution ↓ Generate Inputs ↓ Analyze New Behavior For instance, if a function processes network input, examining conditions related to data length or memory access is likely more valuable than exploring unrelated paths. Naturally, the significance of a function should be determined based on evidence found within the binary and the program's actual behavior—not merely by the function's name. Path Explosion This is a primary limitation of both Symbolic and Concolic execution. Several techniques can be employed to manage this issue: Limiting search depth and the number of loop iterations. Prioritizing significant paths. Utilizing code coverage to discover new paths. Avoiding the re-exploration of redundant states. Focusing on functions and behaviors relevant to the analysis objectives. The key takeaway is that we are not intended to explore every single path; rather, we should concentrate our analytical resources on paths most likely to reveal new insights about the program or uncover potential bugs. @reverseengine

Path A ──┐ ├──> Similar Program State Path B ──┘ However, this is not always straightforward. If two paths involve different memory values ​​or different constraints, an incorrect merge could compromise the analysis results. Therefore, the tool must carefully determine which states are truly mergeable. Determining the Next Path ...to choose Suppose we have 3 different paths to explore in a program: We can use various criteria to select the next path: Prioritizing paths that execute new code; prioritizing paths that reach sensitive memory operations; Prioritizing shallower paths. For instance, Path B might be a better choice because it executes newer code and helps increase coverage.

Buffer Overflow – Part 36 Path Explosion and Path Management In the previous part, we learned how Concolic Execution generates new inputs and explores additional execution paths by running the program and solving conditional constraints. However, there is a major issue: As the number of conditional statements in a program increases, the number of potential execution paths can grow exponentially. We call this problem "Path Explosion." Why does the number of paths increase? Suppose a program contains three independent conditional statements: if (a) do_a(); if (b) do_b(); if (c) do_c(); Each condition has two possible states: The condition is true. The condition is false. Therefore, in this simple scenario, the total number of possible combinations is: 2 ^ 3 = 8 Now, consider a case with 20 independent and reachable conditions: 2^20 = 1,048,576 That is over one million possible combinations. Of course, this figure represents the theoretical number of combinations; it does not necessarily mean the program actually possesses that many reachable paths. Now, imagine dealing with a program that contains thousands of conditional statements. Exploring every single path with limited resources is practically impossible. Loops exacerbate this problem further. Consider this code: C++ int sum(int n) { int result = 0; for (int i = 0; i < n; i++) { result += i; } return result; } If symbolic analysis treats the value of $n$ as indeterminate, the number of loop iterations may also be indeterminate. For instance, the execution paths through a loop could include scenarios such as: 0 iterations 1 iteration 2 iterations 3 iterations ... If the loop also contains internal conditional statements, the situation becomes even more complex. Consequently, some tools impose a limit on the number of times a loop can be traversed. This constraint is typically referred to as a "Loop Unrolling Bound." Limiting Search Depth One straightforward approach is to prevent the analysis from proceeding too far along lengthy execution paths. For example: Maximum Depth = 50 This means the analysis only proceeds to a specific depth along any given path. The advantage of this method is that it keeps resource consumption under control. However, it has a drawback: A bug might exist at a depth of 70, which the analysis would never reach. Therefore, the limit must be chosen carefully, in accordance with the specific goals of the analysis. Prioritizing Paths Not all paths are of equal value. Suppose we are analyzing a parser: Input | v Parser | +---- Invalid Input | +---- Valid Input | v Length Check | Memory Operations If our goal is to find memory bugs, paths that lead to memory operations might be given higher priority. We can rank paths based on criteria such as: Reaching code that has not yet been executed. Reaching functions that are critical in terms of memory management. Reaching conditional statements influenced by external inputs. Getting closer to a point where a crash has previously occurred. Note that while prioritization increases the likelihood of reaching significant areas, it does not guarantee that all bugs will be discovered. Using Code Coverage Code coverage is a common metric used for path selection. Suppose we have two inputs: Input A → 20 basic blocks Input B → 25 basic blocks If Input B executes five new basic blocks, it might be more valuable for further investigation. However, the raw number of blocks is not the only factor. We must determine whether these blocks are truly new and if they provide useful information regarding the program's behavior. In fuzzing, tools like AFL++ also utilize execution coverage to guide the generation of inputs. Merging Similar States Sometimes, different paths lead to program states that are effectively equivalent from an analysis perspective. In such cases, some symbolic execution engines can merge these states or prevent the storage of redundant ones. For example:

این مثال نشون میده انتخاب مسیر بعدی به هدف تحلیل بستگی داره و هیچ معیار واحدی برای همه برنامه‌ها بهترین نیست ارتباط Path Explosion با Reverse Engineering وقتی یک Binary ناشناخته رو تحلیل میکنیم معمولا نمیخوایم همه مسیرهای ممکن رو بررسی کنیم هدفمون اینه مسیرهایی رو پیدا کنیم که بیشترین اطلاعات رو درباره رفتار برنامه بهمون میدن یک فرایند عملی میتونه به این شکل باشه: Binary ↓ Find Interesting Functions ↓ Identify Important Branches ↓ Choose Target Paths ↓ Symbolic / Concolic Execution ↓ Generate Inputs ↓ Analyze New Behavior مثلا اگه یک تابع ورودی شبکه رو پردازش میکنه بررسی شرط‌های مربوط به طول داده و دسترسی‌های حافظه میتونه از بررسی مسیرهای نامرتبط مفیدتر باشه البته اهمیت تابع باید بر اساس شواهد موجود توی Binary و رفتار برنامه مشخص بشه نه صرفا اسم تابع Path Explosion یکی از محدودیت‌های اصلی Symbolic Execution و Concolic Execution هست برای کنترل این مشکل میتونیم از چند روش استفاده کنیم محدود کردن عمق جست‌ و جو و دفعات پیمایش حلقه اولویت‌ بندی مسیرهای مهم استفاده از Code Coverage برای پیدا کردن مسیرهای جدید جلوگیری از بررسی حالت‌های تکراری تمرکز روی توابع و رفتارهای مرتبط با هدف تحلیل نکته اصلی اینه که قرار نیست همه مسیرها رو بررسی کنیم باید منابع تحلیل رو روی مسیرهایی متمرکز کنیم که احتمال بیشتری داره اطلاعات جدیدی درباره برنامه یا باگ‌های احتمالی بهمون بدن @reverseengine

قسمت سی و پنجم بافر اورفلو
Path Explosion و مدیریت مسیرها توی قسمت قبل یاد گرفتیم Concolic Execution چطوری با اجرای برنامه و حل شرط‌ها ورودی‌های جدید میسازه و مسیرهای بیشتری رو بررسی میکنه اما یه مشکل بزرگ وجود داره هرچی تعداد شرط‌ های برنامه بیشتر بشه تعداد مسیرهای احتمالی هم میتونه به‌شدت افزایش پیدا کنه به این مشکل میگیم Path Explosion چرا تعداد مسیرها زیاد میشه فرض کنید برنامه 3 تا شرط مستقل داره: if (a) do_a(); if (b) do_b(); if (c) do_c(); هر شرط 2 حالت داره شرط برقرار باشه شرط برقرار نباشه پس توی حالت ساده تعداد ترکیب‌های ممکن میشه 2 ^ 3 = 8 حالا اگه 20 تا شرط داشته باشیم و هرکدوم مستقل و قابل‌ دسترس باشن 2^20 = 1,048,576 یعنی بیشتر از 1 میلیون ترکیب احتمالی البته این عدد تعداد ترکیب‌های نظریه و لزوما به این معنی نیست که برنامه همین تعداد مسیر قابل‌دسترسی داره حالا تصور کنید با برنامه‌ای روبه‌رو هستیم که هزاران شرط داره بررسی همه مسیرها با منابع محدود عملا امکان‌پذیر نیست حلقه‌ها مشکل رو شدیدتر میکنن این کد رو در نظر بگیرید: C++ int sum(int n) { int result = 0; for (int i = 0; i < n; i++) { result += i; } return result; } اگه تحلیل نمادین مقدار n رو نامشخص در نظر بگیره تعداد دفعات اجرای حلقه هم میتونه نامشخص باشه مثلا مسیرهای اجرای حلقه میتونن شامل این حالت‌ ها باشن: 0 iterations 1 iteration 2 iterations 3 iterations ... اگه حلقه شرط‌های داخلی هم داشته باشه وضعیت پیچیده‌ تر میشه برای همین بعضی ابزارها تعداد دفعات پیمایش حلقه رو محدود میکنن به این محدودیت معمولا Loop Unrolling Bound یا محدودیت بازکردن حلقه گفته میشه محدودکردن عمق جست‌ و جو یکی از راهکار های ساده اینه که اجازه ندیم تحلیل بیش از حد توی مسیرهای طولانی پیش بره مثلا: Maximum Depth = 50 یعنی تحلیل فقط تا عمق مشخصی از مسیر ادامه پیدا میکنه مزیت این روش اینه که مصرف منابع کنترل میشه اما یه مشکل هم داره ممکنه باگی در عمق 70 وجود داشته باشه و تحلیل هیچوقت بهش نرسه پس باید محدودیت رو متناسب با هدف تحلیل انتخاب کنیم اولویت‌ بندی مسیرها همه مسیرها ارزش یکسانی ندارن فرض کنید داریم یک Parser رو تحلیل میکنیم: Input | v Parser | +---- Invalid Input | +---- Valid Input | v Length Check | v Memory Operation اگه هدفمون پیدا کردن Memory Bug باشه مسیر هایی که به عملیات حافظه میرسن ممکنه اولویت بیشتری داشته باشن میتونیم مسیرها رو بر اساس معیارهایی مثل این مرتب کنیم رسیدن به کدهایی که هنوز اجرا نشدن رسیدن به توابع حساس از نظر مدیریت حافظه رسیدن به شرط‌ هایی که ورودی خارجی روی اون‌ها تاثیر میذاره نزدیک‌ شدن به نقطه‌ای که قبلا Crash رخ داده نکته اینه که اولویت‌ بندی کمک میکنه احتمال رسیدن به نقاط مهم بیشتر بشه اما تضمین نمیکنه همه باگ‌ها پیدا بشن استفاده از Code Coverage یکی از معیارهای رایج برای انتخاب مسیر Code Coverage هست فرض کنید 2 ورودی داریم: Input A → 20 basic blocks Input B → 25 basic blocks اگه ورودی B پنج Basic Block جدید رو اجرا کرده باشه ممکنه برای بررسی بیشتر ارزشمندتر باشه اما فقط تعداد بلوک‌ ها مهم نیست باید بررسی کنیم این بلوک‌ها واقعا جدید هستن یا اطلاعات مفیدی درباره رفتار برنامه بهمون میدن توی Fuzzing هم ابزارهایی مثل ++AFL از پوشش اجرا برای هدایت تولید ورودی‌ها استفاده میکنن قاطی کردن حالت‌ های مشابه گاهی چند مسیر به وضعیت‌هایی میرسن که از دید تحلیل تقریبا معادل هستن توی چنین شرایطی بعضی موتور های Symbolic Execution میتونن حالت‌ ها رو ادغام کنن یا جلوی نگهداری حالت‌های تکراری رو بگیرن مثلا: Path A ──┐ ├──> Similar Program State Path B ──┘ اما این کار همیشه ساده نیست اگه 2 مسیر مقادیر متفاوتی توی حافظه یا محدودیت‌ های متفاوتی داشته باشن ادغام اشتباه میتونه نتیجه تحلیل رو خراب کنه پس ابزار باید با دقت مشخص کنه کدوم حالت‌ها واقعا قابل ادغام هستن چطور مسیر بعدی رو انتخاب کنی م فرض کنید برای بررسی یک برنامه 3 مسیر مختلف داریم: برای انتخاب مسیر بعدی میتونیم از معیارهای مختلفی استفاده کنیم اولویت‌دادن به مسیرهایی که کد جدیدی اجرا میکنن اولویت‌ دادن به مسیرهایی که به عملیات حساس حافظه میرسن اولویت‌ دادن به مسیر های کم‌ عمق‌ تر مثلا ممکنه Path B انتخاب بهتری باشه چون کد جدیدتری رو اجرا میکنه و به افزایش پوشش کمک میکنه