1 265
Підписники
Немає даних24 години
-37 днів
+730 днів
Архів дописів
1 265
Find where dispatcher is executed
hexdump/strings/entropy to find bytecode data
Write a simple Python script for pattern matching in binary
Build a simple VM Sample C code
This code creates a very simple program that checks a string, but instead of cmp directly, it first creates a simple bytecode and then an interpreter to execute it. This is a low-level simulation of a virtualizer and is very good for practice
Copy the sample code and compile it on your development machine/VM
vm.c
#include <stdio.h> #include <string.h> #include <stdint.h> uint8_t prog[] = { 0x01, /* LOAD_INPUT */ 0x10, /* expect length (16) or unused */ 0x02, /* CMP_CONST */ '1','2','3','4',0, /* const "1234" + null */ 0x03 /* HALT/END */ }; int run_vm(const char *input) { int ip = 0; while (ip < sizeof(prog)) { uint8_t op = prog[ip++]; switch (op) { case 0x01: // LOAD_INPUT -- store pointer (no-op for this demo) // nothing to do; in real vm you'd load bytes to vm memory break case 0x02: { // CMP_CONST const char *c = (const char*)&prog[ip]; ip += 5; // length of constant in this toy example if (strcmp(input, c) == 0) return 1; break } case 0x03: return 0; default: return 0; } } return 0; } int main(int argc, char **argv) { if (argc < 2) { printf("usage: %s <pass>\n", argv[0]); return 0; } if (run_vm(argv[1])) printf("Access granted\n"); else printf("Access denied\n"); return 0; }Compile:
gcc simple_vm.c -o simple_vmStatic analysis: Run strings simple_vm and see where the strings are Open the file in IDA/Ghidra and look for the function run_vm. In the disassembler you will see a loop with switch/case and data prog[] this is the dispatcher/binary bytecode Dynamic analysis: Open the file with x64dbg and set a breakpoint on run_vm or on the address of the array prog Run the program with different inputs and see how the dispatcher path changes The goal is to understand where the bytecodes are, how the dispatcher works for them and where the comparison logic is VM detection: dispatcher loop bytecode table in data repeated calls to the interpreter How do we use static and dynamic together: static finds the bytecode dynamic shows the runtime what is happening It turns out devirtualization: The first goal is to identify the dispatcher and data bytecodes and document the execution logic. Then the bytecodes can be extracted and their meaning reconstructed.
1 265
Virtualization-based protection
بعضی محافظ ها کد اصلی رو تبدیل میکنن به یه بایت کد و یه مفسر/VM داخل برنامه میذارن که این بایت کد رو اجرا کنه این باعث میشه دیساسمبل مستقیم بی معنی یا سخت باشه
چطوری تشخیص بدیم یه باینری virtualized هست؟
وجود یه لوپ dispatcher بزرگ یک حلقه طولانی که بسته به مقدارِ یه متغیر شاخه رو انتخاب میکنه
خیلی از توابع یا بلاک ها به جای ASM معمولی فراخوانی هایی به یه مفسر/تابع dispatcher دارن
حجم زیادی از جدول بایت کد یا داده های عجیب داخل بخش .rdata/.data.
کنترل جریان عجیب و شاخه های نامعمول که توی دیساسمبل قابل فهم نیستن
سرعت اجرای توابع نسبت به کد نِیِتیو خیلی پایینتر چون مفسره
ابزارای مفید برای تشخیص و آنالیز:
IDA / Ghidra برای دیدن الگوها و dispatcher
x64dbg runtime
پیدا کردن جایی که dispatcher اجرا میشه
hexdump/strings/entropy برای پیدا کردن دادههای بایت کد
نوشتن اسکریپت ساده Python برای pattern matching توی باینری
ساخت یک VM ساده کد نمونه C
این کد یه برنامه خیلی ساده میسازه که یه رشته رو چک میکنه اما به جای اینکه مستقیم cmp کنه اول یه بایت کد ساده درست میکنه و بعد یه مفسر که اونو اجرا کنه این کار شبیهسازی یه virtualizer سطح پایینه و برای تمرین خیلی خوبه
نمونه کد کپی کنید و روی ماشین توسعه/VM خودتون کامپایل کنید
vm.c
#include <stdio.h> #include <string.h> #include <stdint.h> uint8_t prog[] = { 0x01, /* LOAD_INPUT */ 0x10, /* expect length (16) or unused */ 0x02, /* CMP_CONST */ '1','2','3','4',0, /* const "1234" + null */ 0x03 /* HALT/END */ }; int run_vm(const char *input) { int ip = 0; while (ip < sizeof(prog)) { uint8_t op = prog[ip++]; switch (op) { case 0x01: // LOAD_INPUT -- store pointer (no-op for this demo) // nothing to do; in real vm you'd load bytes to vm memory break; case 0x02: { // CMP_CONST const char *c = (const char*)&prog[ip]; ip += 5; // length of constant in this toy example if (strcmp(input, c) == 0) return 1; break; } case 0x03: return 0; default: return 0; } } return 0; } int main(int argc, char **argv) { if (argc < 2) { printf("usage: %s <pass>\n", argv[0]); return 0; } if (run_vm(argv[1])) printf("Access granted\n"); else printf("Access denied\n"); return 0; }کامپایل:
gcc simple_vm.c -o simple_vmآنالیز استاتیک: strings simple_vm رو اجرا کنید و ببینید رشته ها کجا هستن فایل رو توی IDA/Ghidra باز کنید دنبال تابع run_vm بگردید توی دیس اسمبل میبینید یه حلقه با switch/case و داده prog[] این همون dispatcher/binary bytecode هست آنالیز داینامیک: فایل رو با x64dbg باز کنید یک breakpoint بذارید روی run_vm یا روی آدرس آرایه prog برنامه رو با ورودیهای مختلف اجرا کنید و ببینید چطور مسیر dispatcher تغییر میکنه هدف اینه که بفهمید کجا بایتکدها هستن dispatcher چطوری براشون کار میکنه و منطق مقایسه کجاست تشخیص VM: dispatcher loop جدول بایت کد در دادهها فراخوانی مکرر مفسر چجوری از استاتیک و داینامیک با هم استفاده میکنیم: استاتیک بایت کد رو پیدا میکنه داینامیک نشون میده runtime چه اتفاقی میوفته devirtualization: هدف اولی شناسایی dispatcher و داده بایت کد و مستند سازی منطق اجراست بعد میشه بایت کدها رو استخراج و معنی شون رو بازسازی کرد Virtualization-based protection Some protectors convert the source code into bytecode and embed an interpreter/VM inside the program to execute this bytecode, making direct disassembly pointless or difficult How do we tell if a binary is virtualized? A large dispatcher loop, a long loop that selects a branch depending on the value of a variable Many functions or blocks have calls to an interpreter/dispatcher function instead of regular ASM A large bytecode table or strange data in the .rdata/.data section. Strange flow control and unusual branches that are not understandable in disassembly Execution speed of functions is much lower than native code because it is interpreted Useful tools for diagnostics and analysis: IDA / Ghidra to see patterns and dispatcher x64dbg runtime
1 265
Reverse Engineering Dotnet Applications
https://starkeblog.com/reverse-engineering/dotnet/2024/04/18/reverse-engineering-dotnet-applications.html?s=35
@reverseengine
1 265
Executing Code From Non-Executable Memory
https://redops.at/en/blog/the-emulators-gambit-executing-code-from-non-executable-memory
@reverseengine
@reverseengine
1 265
Ransomware Attack Update for the 15th of October 2025
https://darkwebinformer.com/ransomware-attack-update-for-the-15th-of-october-2025/
@reverseengine
1 265
تصمیم گرفتم بافراورفلو رو صفر تا صد تو چند تا قسمت توضیح بدم. اگه حمایتا خوب بود و راضی بودم، بقیه قسمت هاشم مینویسم.
I decided to explain Buffer Overflow from start to finish in a few parts. If the support is good and I'm satisfied, I'll write the rest of the parts.
1 265
چطور استک کار میکنه؟ (فریم تابع و آدرس بازگشت)
ساختار فریم تابع در استک
نمایش saved return address و saved base pointer یادگرفتن اینکه چجوری ببینیم فریم ها داخل دیباگر و تشخیص نقاطی ان که overflow میتونه تاثیر بزاره روشون
میخایم بفهمیم وقتی یک تابع فراخوانی میشه چه چیزی روی استک قرار میگیره و چرا این برای بافر اورفلو مهمه
فریم تابع و آدرس بازگشت رو بررسی میکنیم و یاد میگیریم چطور در gdb فریم ها رو ببینیم
وقتی تابعی فراخوانی میشه یک فریم روی استک ساخته میشه فریم شامل پارامترها و local variables و saved base pointer و saved return address است
در معماری x86 64 معمولا که رجیستر rbp برای لینک فریم استفاده میشه و آدرس بازگشت بالای فریم قرار میگیره اگر یک بافر محلی روی استک قرار داشته باشه و داده بیش از حد نوشته بشه میتونه تا saved rbp و saved return address میتونه پیش بره و اونها رو بازنویسی کنه بازنویسی saved return address یعنی وقتی تابع برمیگرده برنامه ممکنه به جای آدرس درست به آدرس دیگه ای بره یا کرش کنه
نمایش فریم در دیباگر
در gdb با دستور backtrace میتونیم زنجیره فراخوانی ها رو ببینیم
با دستور info frame یا display memory میتونیم محتوای فریم جاری رو مشاهده کنیم
ما میگیم saved return address کجاست و چجوری میتونیم offset بین ابتدای بافر و آدرس بازگشت رو محاسبه کنیم
کد فایل demo2c
#include <stdio.h> #include <string.h> void vulnerable(char *input) { char buffer[24]; printf("in vulnerable function\n"); strcpy(buffer, input); printf("after strcpy\n"); } int main(int argc, char **argv) { if (argc < 2) { printf("usage demo2 input\n"); return 1; } vulnerable(argv[1]); printf("returned normally\n"); return 0; }راهنمای اجرا gcc -g demo2.c -o demo2 در VM امن و با snapshot اجرا کنید gdb --args ./demo2 $(python3 -c "print('A'*80)") داخل gdb از دستورات زیر استفاده کنید break vulnerable run info frame x/40gx $rbp disassemble continue بعد از کرش از backtrace استفاده کنید How does stack work? (Function Frame and Return Address) Function Frame Structure on the Stack Showing Saved Return Address and Saved Base Pointer Learn how to view frames in the debugger and identify where they can be affected by overflow We want to understand what goes on the stack when a function is called and why this is important for buffer overflow We will examine the function frame and return address and learn how to view frames in gdb When a function is called, a frame is created on the stack. The frame contains parameters and local variables, the saved base pointer, and the saved return address In the x86 64 architecture, the rbp register is usually used for frame linking and the return address is placed above the frame. If a local buffer is on the stack and too much data is written, it can go up to the saved rbp and saved return address and overwrite them. Overwriting the saved return address means that when the function returns, the program may go to another address instead of the correct address or Crash Displaying frames in the debugger In gdb, with the backtrace command, we can see the chain of calls With the info frame or display memory command, we can see the contents of the current frame We say where the saved return address is and how we can calculate the offset between the beginning of the buffer and the return address Demo2c file code
#include <stdio.h> #include <string.h> void vulnerable(char *input) { char buffer[24]; printf("in vulnerable function\n"); strcpy(buffer, input); printf("after strcpy\n"); } int main(int argc, char **argv) { if (argc < 2) { printf("usage demo2 input\n"); return 1; } vulnerable(argv[1]); printf("returned normally\n"); return 0; }Run Guide gcc -g demo2.c -o demo2 Run in a secure VM with snapshot gdb --args ./demo2 $(python3 -c "print('A'*80)") Inside gdb use the following commands break vulnerable run info frame x/40gx $rbp disassemble continue Use backtrace after crash
1 265
System Programming Roadmap
https://github.com/ujjwal-kr/system-programming-roadmap
@reverseengine
1 265
Reverse engineering focusing on x64 Windows
https://github.com/FaxHack/Reverse-Engineering-Course
@reverseengine
1 265
Repost from Fuzzing ZONE
Talking with Ransomware Devman
https://analyst1.com/devmans-raas-launch-the-affiliate-who-aims-to-become-the-boss/
@FUZZ0x
1 265
Aiding reverse engineering with Rust and a local LLM
https://security.humanativaspa.it/aiding-reverse-engineering-with-rust-and-a-local-llm/
@reverseengine
1 265
ghidraMCP: Now AI Can Reverse Malware
https://www.youtube.com/watch?v=u2vQapLAW88
@reverseengine
1 265
DiffRays
ابزاری پژوهش محور برای تغییر پچهای دودوییه که برای کمک به تحقیقات در زمینه توسعه اکسپلویتهای آسیبپذیری و مهندسی معکوس طراحی شده
DiffRays is a research-oriented tool for binary patch diffing designed to aid in vulnerability research exploit development and reverse engineering
https://github.com/pwnfuzz/diffrays
@reverseengine
