Virtualization-based Obfuscation Devirtualization و Kernel RE
(فقط نرمافزار)
Virtualization-based Obfuscation VMProtect / Themida
یه لایه مجازی ساز داخل باینری میذارن: کد اصلی تبدیل میشه به دستورالعمل های مخصوص VM و یه انجین در زمان اجرا اونا رو اجرا میکنه سخت میشه بفهمید اصل منطق چیه
مثال:
نمونه open-source که با ابزار obfuscator ساده بسته بندی شده رو باز کنید و ببینید بخش dispatcher چطور بین بلاک ها سوئیچ میکنه فقط ببینید و ساختار جدول پرش رو تحلیل کنید نه حذف حفاظ
دیتکشن (چی باید نگاه کنید)
وجود یک حلقه dispatcher که با جدول ایندکس ها بلاک ها رو اجرا میکنه
الگو های ثابت decode/dispatch در چند تا تابع
کاهش شدید خوانایی pseudocode اما افزایش پیچیدگی CFG
میتیگیشن (مدافع/توسعهدهنده)
برای توسعهدهندگان: از Obfuscation فقط وقتی لازم باشه استفاده کنید و مستندات داخلی رو نگه دارید
آنالیزور/مدافع: ترکیب آنالیز ایستا و دینامیک لاگ گیری runtime و trace گرفتن از dispatcher کمک میکنه تا بفهمید VM چه دستورات منطقی ای اجرا میکنه
Virtualization-based Obfuscation Devirtualization and Kernel RE
(software only)
Virtualization-based Obfuscation VMProtect / Themida
Puts a virtualization layer inside the binary: the original code is converted to VM-specific instructions and an engine executes them at runtime. It is difficult to understand the logic behind it.
Example:
Open the open-source example packaged with a simple obfuscator tool and see how the dispatcher section switches between blocks. Just look and analyze the jump table structure, not remove the protection.
Detection (what to look for)
Presence of a dispatcher loop that executes blocks with index tables.
Constant decode/dispatch patterns in several functions.
Severely reduces pseudocode readability but increases CFG complexity.
Mitigation (Defender/Developer)
For developers: Use Obfuscation only when necessary and keep internal documentation.
Analyzer/Defender: Analysis combination Static and dynamic runtime logging and dispatcher tracing help you understand what logical commands the VM is executing.
@reverseengine
(فقط نرمافزار)
Virtualization-based Obfuscation VMProtect / Themida
یه لایه مجازی ساز داخل باینری میذارن: کد اصلی تبدیل میشه به دستورالعمل های مخصوص VM و یه انجین در زمان اجرا اونا رو اجرا میکنه سخت میشه بفهمید اصل منطق چیه
مثال:
نمونه open-source که با ابزار obfuscator ساده بسته بندی شده رو باز کنید و ببینید بخش dispatcher چطور بین بلاک ها سوئیچ میکنه فقط ببینید و ساختار جدول پرش رو تحلیل کنید نه حذف حفاظ
دیتکشن (چی باید نگاه کنید)
وجود یک حلقه dispatcher که با جدول ایندکس ها بلاک ها رو اجرا میکنه
الگو های ثابت decode/dispatch در چند تا تابع
کاهش شدید خوانایی pseudocode اما افزایش پیچیدگی CFG
میتیگیشن (مدافع/توسعهدهنده)
برای توسعهدهندگان: از Obfuscation فقط وقتی لازم باشه استفاده کنید و مستندات داخلی رو نگه دارید
آنالیزور/مدافع: ترکیب آنالیز ایستا و دینامیک لاگ گیری runtime و trace گرفتن از dispatcher کمک میکنه تا بفهمید VM چه دستورات منطقی ای اجرا میکنه
Virtualization-based Obfuscation Devirtualization and Kernel RE
(software only)
Virtualization-based Obfuscation VMProtect / Themida
Puts a virtualization layer inside the binary: the original code is converted to VM-specific instructions and an engine executes them at runtime. It is difficult to understand the logic behind it.
Example:
Open the open-source example packaged with a simple obfuscator tool and see how the dispatcher section switches between blocks. Just look and analyze the jump table structure, not remove the protection.
Detection (what to look for)
Presence of a dispatcher loop that executes blocks with index tables.
Constant decode/dispatch patterns in several functions.
Severely reduces pseudocode readability but increases CFG complexity.
Mitigation (Defender/Developer)
For developers: Use Obfuscation only when necessary and keep internal documentation.
Analyzer/Defender: Analysis combination Static and dynamic runtime logging and dispatcher tracing help you understand what logical commands the VM is executing.
@reverseengine
❤5
IDA Generating signatures for Nim and other non-C programming languages
https://hex-rays.com/blog/plugin-focus-generating-signatures-for-nim-and-other-non-c-programming-languages
@reverseengine
https://hex-rays.com/blog/plugin-focus-generating-signatures-for-nim-and-other-non-c-programming-languages
@reverseengine
Hex-Rays
Plugin focus: Generating signatures for Nim and other non-C programming languages – Hex Rays
This is a guest entry written by Holger Unterbrink from Cisco Talos. His views and opinions are his own and not those of Hex-Rays. Any technical or mainten
❤4
این پروژه یک وایت بورد در IDA در اختیارتون میزاره که میتونید داخلش هر چیزی که خواستید رو طراحی کنید
This project provides you with a whiteboard in IDA where you can design anything you want
https://github.com/idkhidden/DrawIDA
@reverseengine
This project provides you with a whiteboard in IDA where you can design anything you want
https://github.com/idkhidden/DrawIDA
@reverseengine
GitHub
GitHub - idkhidden/DrawIDA: Lightweight whiteboard plugin for IDA that allows reverse engineers to sketch and brainstorm directly…
Lightweight whiteboard plugin for IDA that allows reverse engineers to sketch and brainstorm directly inside IDA. - idkhidden/DrawIDA
❤6
Levering Generative AI to Reverse Engineering XLoader
https://research.checkpoint.com/2025/generative-ai-for-reverse-engineering
@reverseengine
https://research.checkpoint.com/2025/generative-ai-for-reverse-engineering
@reverseengine
Check Point Research
Leveraging Generative AI to Reverse Engineer XLoader
Check Point Research succeeded in understanding the infamous malware family, Xloader, by leveraging Generative AI
❤1
ReverseEngineering
Levering Generative AI to Reverse Engineering XLoader https://research.checkpoint.com/2025/generative-ai-for-reverse-engineering @reverseengine
GitHub
GitHub - AgentSmithers/x64DbgMCPServer: x64DbgMCPServer made from c# with Claude, Windsurf and Cursor support
x64DbgMCPServer made from c# with Claude, Windsurf and Cursor support - AgentSmithers/x64DbgMCPServer
❤1
Devirtualization
روشهای دفاع/تحلیلی
وقتی با VM-based obfuscation روبهرو میشید باید بفهمید چه الگویی برای برگردوندن pseudocode استفاده میکنن راه حل ها معمولا ترکیبی از آنالیز ایستا برای شناسایی و آنالیز دینامیک برای تقلید اجرای VM هستن
مثال:
trace
گرفتن از اجرای برنامه و استخراج sequence ای از دستورات dispatche
مثل opcode های VM و دسته بندی شون بدون اینکه بخواید قفل ها رو بشکنید فقط ساختار دستورها رو ببینید
دیتکشن
الگوهای تکراری در dispatcher که به opcodeهای مشخص اشاره میکنن
مقادیر ثابت جدولهای ترجمه که در runtime خونده و استفاده میشن
میتیگیشن
محقق: مستندسازی دقیق از رفتار runtime و نگهداری traces برای تحلیلهای بعدی
توسعهدهنده: اگر از VM استفاده میکنی لاگهای داخلی برای تیم خودت نگه دار تا در troubleshooting بهت کمک کنه
Devirtualization
Defense/Analysis Methods
When faced with VM-based obfuscation, you need to understand what pattern they are using to return pseudocode. Solutions are usually a combination of static analysis to identify and dynamic analysis to mimic VM execution
Example:
Trace
Taking a program execution and extracting a sequence of dispatcher instructions
Like VM opcodes and their categories without trying to break the locks, just see the instruction structure
Detection
Repeated patterns in dispatcher that point to specific opcodes
Constant values of translation tables that are read and used at runtime
Mitigation
Researcher: Accurately document runtime behavior and maintain traces for later analysis
Developer: If you use VM, keep internal logs for your team to help you troubleshoot
@reverseengine
روشهای دفاع/تحلیلی
وقتی با VM-based obfuscation روبهرو میشید باید بفهمید چه الگویی برای برگردوندن pseudocode استفاده میکنن راه حل ها معمولا ترکیبی از آنالیز ایستا برای شناسایی و آنالیز دینامیک برای تقلید اجرای VM هستن
مثال:
trace
گرفتن از اجرای برنامه و استخراج sequence ای از دستورات dispatche
مثل opcode های VM و دسته بندی شون بدون اینکه بخواید قفل ها رو بشکنید فقط ساختار دستورها رو ببینید
دیتکشن
الگوهای تکراری در dispatcher که به opcodeهای مشخص اشاره میکنن
مقادیر ثابت جدولهای ترجمه که در runtime خونده و استفاده میشن
میتیگیشن
محقق: مستندسازی دقیق از رفتار runtime و نگهداری traces برای تحلیلهای بعدی
توسعهدهنده: اگر از VM استفاده میکنی لاگهای داخلی برای تیم خودت نگه دار تا در troubleshooting بهت کمک کنه
Devirtualization
Defense/Analysis Methods
When faced with VM-based obfuscation, you need to understand what pattern they are using to return pseudocode. Solutions are usually a combination of static analysis to identify and dynamic analysis to mimic VM execution
Example:
Trace
Taking a program execution and extracting a sequence of dispatcher instructions
Like VM opcodes and their categories without trying to break the locks, just see the instruction structure
Detection
Repeated patterns in dispatcher that point to specific opcodes
Constant values of translation tables that are read and used at runtime
Mitigation
Researcher: Accurately document runtime behavior and maintain traces for later analysis
Developer: If you use VM, keep internal logs for your team to help you troubleshoot
@reverseengine
❤1
بخش هفتم بافر اورفلو
یافتن آفست دقیق بین ابتدای بافر و saved return address و دیدن قبل و بعد strcpy با الگوی غیر تکراری
فایل تولید الگو توضیح
این فایل یک الگوی غیر تکراری تولید میکنه تا با مقدار برگشتی که روی استک میبینیم بتونیم آفست رو حساب کنیم
فایل file4_pattern.py
#!/usr/bin/env python3
# simple cyclic pattern generator
import sys
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
nums = "abcdefghijklmnopqrstuvwxyz"
digits = "0123456789"
def pattern(n):
out = []
for a in alpha:
for b in nums:
for c in digits:
out.append(a+b+c)
if len("".join(out)) >= n:
return "".join(out)[:n]
return "".join(out)[:n]
if name == "main":
n = int(sys.argv[1]) if len(sys.argv)>1 else 200
print(pattern(n))
دستورات اجرا برای یافتن آفست و دیدن قبل و بعد strcpy
تولید الگو و اجرای فایل با الگو به عنوان ورودی
python3 file4_pattern.py 200 > pat.tx
t
gcc -g file4.c -o fil
e4
gdb --args ./file4 $(cat pat.txt)
# در gdb
break crash
run
x/32x $rbp-32 # strcpy قبل از
next # strcpy اجرای کامل
x/32x $rbp-32 # strcpy بعد از
continue # تا کرش اگر لازمه
پیدا کردن مقدار overwrite شده توضیح
بعد از کرش یا بعد از دیدن در gdb مقدار 8 بایتی که در محل return address افتاده رو بردارید و به صورت رشته hex بخونید
مثال دستور داخل gdb برای دیدن 8 بایت در محل return address
x/gx $rbp+8
توضیح فایل محاسبه آفست
این فایل یک تابع ساده برای پیدا کردن موقعیت یک رشته کوچیک داخل الگوی تولید شده میسازه
فایل file4_find_offset.py
#!/usr/bin/env python3
import sys
from file4_pattern import pattern
def find(sub, total=200):
p = pattern(total)
idx = p.find(sub)
return idx
if name == "main":
# ورودی sub به صورت بایت hex یا رشته باید به درستی فرمت شود
sub = sys.argv[1]
# اگر hex داده شد تبدیل کن
if sub.startswith("0x"):
raw = bytes.fromhex(sub[2:])
sub = raw.decode('latin-1')
print(find(sub, int(sys.argv[2]) if len(sys.argv)>2 else 200))
Part 7 Buffer Overflow
Finding the exact offset between the beginning of the buffer and the saved return address and seeing before and after strcpy with a non-repeating pattern
Pattern generation file Explanation
This file generates a non-repeating pattern so that we can calculate the offset with the return value we see on the stack
File file4_patte run.py
#!/usr/bin/env python3
# simple cyclic pattern generator
import sys
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
nums = "abcdefghijklmnopqrstuvwxyz"
digits = "0123456789"
def pattern(n):
out = []
for a in alpha:
for b in nums:
for c in digits:
out.append(a+b+c)
if len("".join(out)) >= n:
return "".join(out)[:n]
return "".join(out)[:n]
if name == "main":
n = int(sys.argv[1]) if len(sys.argv)>1 else 200
print(pattern(n))
Execution commands to find offset and see before and after strcpy
Generate pattern and execute file with pattern as input
python3 file4_pattern.py 200 >pat.txt
gcc -g file4.
c -o file4
gdb --args ./file4 $(cat pat.txt)
# in gdb
break crash
run
x/32x $rbp-32 # strcpy before
next # strcpy complete execution
x/32x $rbp-32 # strcpy after
continue # until crash if necessary
Finding overwritten value Explanation
After crash or after seeing in gdb, take the 8 bytes that are in the return address and write them as Read hex string
Example of gdb command to see 8 bytes at
return address
x/gx $rbp+8
File denoscription Calculate offset
This file creates a simple function to find the position of a small string within the generated pattern
File file4_find_offset.py
#!/usr/bin/env python3@reverseengine
import sys
from file4_pattern import pattern
def find(sub, total=200):
p = pattern(total)
idx = p.find(sub)
return idx
if name == "main":
# Sub input as hex bytes or string must be formatted properly
sub = sys.argv[1]
# Convert if given hex
if sub.startswith("0x"):
raw = bytes.fromhex(sub[2:])
sub = raw.decode('latin-1')
print(find(sub, int(sys.argv[2]) if len(sys.argv)>2 else 200))
❤1
Kernel Reverse Engineering Syscalls Drivers Kernel Debugging
تحلیل کد سطح کرنل یعنی کار با درایورها و syscall ها ابزار ها روش ها متفاوت و خطرناکن بنابر این باید فقط برای درک و دفاع انجام بشه نه سو استفاده
مثال:
با یک درایور نمونه open-source کار کن: build کن داخل VM نصب کنید و با WinDbg یا kgdb دیباگ کنید تا ببینید syscall چطور پارامترها رو میگذرونه تمرکز روی فهم API و کنترل فلو نه ایجاد exploit
دیتکشن
درایور های unsigned یا درایور هایی که اقدام به رجیستر کردن syscall های جدید میکنن
رفتار های غیر عادی مثل تغییر مستقیم ساختار های کرنل یا نصب hook های غیر معمول
میتیگیشن
محدود کردن نصب درایورهای ناشناس (signature enforcement) استفاده از HVCI/Kernel Patch Protection
مانیتورینگ تغییرات کرنل و هشدار به موقع مشاهده ماژول/درایور جدید یا نوشتن در مناطق حساس
Kernel Reverse Engineering Syscalls Drivers Kernel Debugging
Kernel-level code analysis means working with drivers and syscalls. Tools and methods are different and dangerous, so it should only be done for understanding and defense, not for exploitation.
Example:
Work with an open-source sample driver: build it, install it inside a VM, and debug it with WinDbg or kgdb to see how the syscall passes parameters. Focus on understanding the API and control flow, not creating exploits.
Detection
Unsigned drivers or drivers that attempt to register new syscalls.
Anomalies such as directly modifying kernel structures or installing unusual hooks.
Mitigation
Restricting installation of unknown drivers (signature enforcement). Use HVCI/Kernel Patch Protection.
Monitoring kernel changes and alerting when new modules/drivers are detected or written to sensitive areas
@reverseengine
تحلیل کد سطح کرنل یعنی کار با درایورها و syscall ها ابزار ها روش ها متفاوت و خطرناکن بنابر این باید فقط برای درک و دفاع انجام بشه نه سو استفاده
مثال:
با یک درایور نمونه open-source کار کن: build کن داخل VM نصب کنید و با WinDbg یا kgdb دیباگ کنید تا ببینید syscall چطور پارامترها رو میگذرونه تمرکز روی فهم API و کنترل فلو نه ایجاد exploit
دیتکشن
درایور های unsigned یا درایور هایی که اقدام به رجیستر کردن syscall های جدید میکنن
رفتار های غیر عادی مثل تغییر مستقیم ساختار های کرنل یا نصب hook های غیر معمول
میتیگیشن
محدود کردن نصب درایورهای ناشناس (signature enforcement) استفاده از HVCI/Kernel Patch Protection
مانیتورینگ تغییرات کرنل و هشدار به موقع مشاهده ماژول/درایور جدید یا نوشتن در مناطق حساس
Kernel Reverse Engineering Syscalls Drivers Kernel Debugging
Kernel-level code analysis means working with drivers and syscalls. Tools and methods are different and dangerous, so it should only be done for understanding and defense, not for exploitation.
Example:
Work with an open-source sample driver: build it, install it inside a VM, and debug it with WinDbg or kgdb to see how the syscall passes parameters. Focus on understanding the API and control flow, not creating exploits.
Detection
Unsigned drivers or drivers that attempt to register new syscalls.
Anomalies such as directly modifying kernel structures or installing unusual hooks.
Mitigation
Restricting installation of unknown drivers (signature enforcement). Use HVCI/Kernel Patch Protection.
Monitoring kernel changes and alerting when new modules/drivers are detected or written to sensitive areas
@reverseengine
❤1
ARM64 Reversing and Exploitation Part 2 Use After Free | 8kSec Blogs
https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free
@reverseengine
https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free
@reverseengine
❤1
ساخت یک باینری نیتیو (Win32) شبیه سازی شده که مکانیزم های واقعی حفاظت آنتی دیباگ ساده چک یکپارچگی تولید سریال بر اساس اسم داخل داشته باشه تا بدون ریسک قانونی بتونید تمرین RE و عملیات کرک سازی رو انجام بدید
ویژگیها:
GUI
ساده با فیلدهای Name و Serial و دکمه Activate & Play
Anti-Debug: فراخوانی
IsDebuggerPresent() قبل از فعالسازی
Integrity (شبیهسازی):
بررسی ساده مسیر exe قابل ارتقا به checksum واقعی
الگوریتم سریال: تابع gen_expected_serial که روی نام کاربر s = s*31 + ch انجام میده و بعد سه گروه 16بیتی با XOR/شیفت میسازه خروجی در قالب AAAA-BBBB-CCCC
پیام موفق/ناموفق با MessageBoxA.
هشدار اخلاقی/قانونی: این کد فقط برای تمرین روی باینری ایه که خودتون ساختید کرک و انتشار کرک نرم افزارهای تجاری غیرقانونیه
کد کامل فایل hotspot_sim.c
کد رو دقیقا در یک فایل به اسم hotspot_sim.c ذخیره کنید
// hotspot_sim.c
یک برنامه شبیه سازی شده برای تمرین RE
ویژگیها:
GUI
ساده با فیلدهای Name و Serial و دکمه Activate & Play
Anti-Debug: فراخوانی
IsDebuggerPresent() قبل از فعالسازی
Integrity (شبیهسازی):
بررسی ساده مسیر exe قابل ارتقا به checksum واقعی
الگوریتم سریال: تابع gen_expected_serial که روی نام کاربر s = s*31 + ch انجام میده و بعد سه گروه 16بیتی با XOR/شیفت میسازه خروجی در قالب AAAA-BBBB-CCCC
پیام موفق/ناموفق با MessageBoxA.
هشدار اخلاقی/قانونی: این کد فقط برای تمرین روی باینری ایه که خودتون ساختید کرک و انتشار کرک نرم افزارهای تجاری غیرقانونیه
کد کامل فایل hotspot_sim.c
کد رو دقیقا در یک فایل به اسم hotspot_sim.c ذخیره کنید
// hotspot_sim.c
یک برنامه شبیه سازی شده برای تمرین RE
#include <windows.h>
#include <stdio.h>
#include <string.h>
// شناساگر کنترلها
#define IDC_NAME 1001
#define IDC_SERIAL 1002
#define IDC_BUTTON 1003
// یه تابع ساده برای ساختن سریال مورد انتظار بر اساس اسم کاربر
// فرمت خروجی: AAAA-BBBB-CCCC (اعداد هگز چهار رقمی)
void gen_expected_serial(const char *name, char *out, size_t outlen)
{
unsigned long s = 0;
// جمع مقادیر کاراکترها رو میگیریم
for (size_t i = 0; i < strlen(name); ++i) {
s = s * 31 + (unsigned char)name[i]; // یه ضرب و جمع ساده
}
// میایم سه گروه 16 بیتی میسازیم
unsigned g1 = (unsigned)((s ^ 0xA5A5A5A5) & 0xFFFF);
unsigned g2 = (unsigned)(((s >> 3) ^ 0x5A5A5A5A) & 0xFFFF);
unsigned g3 = (unsigned)(((s << 7) ^ 0x3C3C3C3C) & 0xFFFF);
// قالببندی نهایی
_snprintf_s(out, outlen, _TRUNCATE, "%04X-%04X-%04X", g1, g2, g3);
}
// تابعی که سریال ورودی رو با سریال تولیدشده مقایسه میکنه
int verify_serial(const char *name, const char *serial)
{
char expected[64];
gen_expected_serial(name, expected, sizeof(expected));
// اینجا مقایسهٔ ساده میکنیم (حساس به حروف)
if (_stricmp(expected, serial) == 0) return 1;
return 0;
}
// تابعی که integrity ساده رو شبیهسازی میکنه
// اینجا فقط چک میکنیم که exe path طول مشخصی داشته باشه (نمونهست)
int integrity_ok()
{
char path[MAX_PATH];
if (GetModuleFileNameA(NULL, path, MAX_PATH) == 0) return 0;
size_t L = strlen(path);
// شبیهسازی: اگه طول مسیر خیلی کوتاه باشه یا خیلی بلند باشه خطا بدیم
if (L < 5) return 0;
return 1;
}
// پنجره اصلی و پردازش پیامها
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
// یک لیبل و یک فیلد برای نام
CreateWindowA("static", "Name:", WS_VISIBLE | WS_CHILD, 10, 10, 50, 20, hWnd, NULL, NULL, NULL);
CreateWindowA("edit", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
70, 10, 240, 22, hWnd, (HMENU)IDC_NAME, NULL, NULL);
// لیبل و فیلد سریال
CreateWindowA("static", "Serial:", WS_VISIBLE | WS_CHILD, 10, 40, 50, 20, hWnd, NULL, NULL, NULL);
CreateWindowA("edit", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
70, 40, 240, 22, hWnd, (HMENU)IDC_SERIAL, NULL, NULL);
// دکمه Activate
CreateWindowA("button", "Activate & Play", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
110, 80, 120, 30, hWnd, (HMENU)IDC_BUTTON, NULL, NULL);
break;
}
case WM_COMMAND:
{
if (LOWORD(wParam) == IDC_BUTTON)
{
// اگه دیباگر باشه لغو میکنیم
if (IsDebuggerPresent()) {
MessageBoxA(hWnd, "Activation failed: debugger detected.", "Error", MB_OK | MB_ICONERROR);
break;
}
// integrity ساده
if (!integrity_ok()) {
MessageBoxA(hWnd, "Activation failed: integrity check failed.", "Error", MB_OK | MB_ICONERROR);
❤1
break;
}
// گرفتن متن از کنترل ها
char name[128] = {0};
char serial[128] = {0};
HWND hName = GetDlgItem(hWnd, IDC_NAME);
HWND hSerial = GetDlgItem(hWnd, IDC_SERIAL);
GetWindowTextA(hName, name, sizeof(name));
GetWindowTextA(hSerial, serial, sizeof(serial));
// پاک کردن فضای خالی ابتدای/انتهای رشته
if (strlen(name) == 0) {
MessageBoxA(hWnd, "Please enter your name first.", "Info", MB_OK | MB_ICONINFORMATION);
break;
}
if (strlen(serial) == 0) {
MessageBoxA(hWnd, "Please enter serial.", "Info", MB_OK | MB_ICONINFORMATION);
break;
}
// بررسی سریال
if (verify_serial(name, serial)) {
MessageBoxA(hWnd, "Activation successful! Playing...", "OK", MB_OK | MB_ICONINFORMATION);
} else {
MessageBoxA(hWnd, "Invalid serial!", "Error", MB_OK | MB_ICONERROR);
}
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcA(hWnd, msg, wParam, lParam);
}
return 0;
}
// نقطهٔ ورود برنامه ویندوزی
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// ساخت کلاس پنجره
WNDCLASSA wc = {0};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = "HotspotSimClass";
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClassA(&wc)) return -1;
// ساخت پنجره
HWND hWnd = CreateWindowA("HotspotSimClass", "Hotspot Player (Simulated - Native)",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, 340, 160, NULL, NULL, hInstance, NULL);
if (!hWnd) return -1;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// لوپ پیام ساده
MSG msg;
while (GetMessageA(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
return (int)msg.wParam;
}
Build a simulated native (Win32) binary that has real anti-debug protection mechanisms, simple integrity check, serial generation based on the name inside, so you can practice RE and cracking operations without legal risk
Features:
Simple GUI
with Name and Serial fields and Activate & Play button
Anti-Debug: Call
IsDebuggerPresent() before activation
Integrity (simulation):
Simple check of exe path, upgradeable to real checksum
Serial algorithm: gen_expected_serial function that does s = s*31 + ch on the username and then creates three 16-bit groups with XOR/shift. Output in the format AAAA-BBBB-CCCC
Success/Failure message with MessageBoxA.
Ethical/Legal Warning: This code is for practice only on a binary that you have created yourself. Cracking and distributing commercial software is illegal
Full code of the hotspot_sim.c file
Save the code exactly in a file named hotspot_sim.c
// hotspot_sim.c
A simulated program for practicing RE
Simple and vernacular explanations and comments
#include <windows.h>
#include <stdio.h>
#include <string.h>
// Control identifiers
#define IDC_NAME 1001
#define IDC_SERIAL 1002
#define IDC_BUTTON 1003
// A simple function to generate the expected serial based on the user name
// Output format: AAAA-BBBB-CCCC (four-digit hex numbers)
void gen_expected_serial(const char *name, char *out, size_t outlen)
{
unsigned long s = 0;
// We take the sum of the character values
for (size_t i = 0; i < strlen(name); ++i) {
s = s * 31 + (unsigned char)name[i]; // A simple multiplication and addition
}
// Let's create three 16-bit groups
unsigned g1 = (unsigned)((s ^ 0xA5A5A5A5) & 0xFFFF);
unsigned g2 = (unsigned)(((s >> 3) ^ 0x5A5A5A5A) & 0xFFFF);
unsigned g3 = (unsigned)(((s << 7) ^ 0x3C3C3C3C) & 0xFFFF);
// Final formatting
_snprintf_s(out, outlen, _TRUNCATE, "%04X-%04X-%04X", g1, g2, g3);
}
❤1
// A function that compares the input serial with the generated serial
int verify_serial(const char *name, const char *serial)
{
char expected[64];
gen_expected_serial(name, expected, sizeof(expected));
// Here we do a simple comparison (case sensitive)
if (_stricmp(expected, serial) == 0) return 1;
return 0;
}
// A function that simulates simple integrity
// Here we just check that the exe path has a certain length (example)
int integrity_ok()
{
char path[MAX_PATH];
if (GetModuleFileNameA(NULL, path, MAX_PATH) == 0) return 0;
size_t L = strlen(path);
// Simulation: throw an error if the path length is too short or too long
if (L < 5) return 0;
return 1;
}
// Main window and message processing
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
// A label and a field for the name
CreateWindowA("static", "Name:", WS_VISIBLE | WS_CHILD, 10, 10, 50, 20, hWnd, NULL, NULL, NULL);
CreateWindowA("edit", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
70, 10, 240, 22, hWnd, (HMENU)IDC_NAME, NULL, NULL);
// Label and serial field
CreateWindowA("static", "Serial:", WS_VISIBLE | WS_CHILD, 10, 40, 50, 20, hWnd, NULL, NULL, NULL);
CreateWindowA("edit", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
70, 40, 240, 22, hWnd, (HMENU)IDC_SERIAL, NULL, NULL);
// Activate button
CreateWindowA("button", "Activate & Play", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
110, 80, 120, 30, hWnd, (HMENU)IDC_BUTTON, NULL, NULL);
break;
}
case WM_COMMAND:
{
if (LOWORD(wParam) == IDC_BUTTON)
{
// Cancel if debugger
if (IsDebuggerPresent()) {
MessageBoxA(hWnd, "Activation failed: debugger detected.", "Error", MB_OK | MB_ICONERROR);
break;
}
// Simple integrity
if (!integrity_ok()) {
MessageBoxA(hWnd, "Activation failed: integrity check failed.", "Error", MB_OK | MB_ICONERROR);
break;
}
// Get text from controls
char name[128] = {0};
char serial[128] = {0};
HWND hName = GetDlgItem(hWnd, IDC_NAME);
HWND hSerial = GetDlgItem(hWnd, IDC_SERIAL);
GetWindowTextA(hName, name, sizeof(name));
GetWindowTextA(hSerial, serial, sizeof(serial));
// Remove leading/trailing whitespace
if (strlen(name) == 0) {
MessageBoxA(hWnd, "Please enter your name first.", "Info", MB_OK | MB_ICONINFORMATION);
break;
}
if (strlen(serial) == 0) {
MessageBoxA(hWnd, "Please enter serial.", "Info", MB_OK | MB_ICONINFORMATION);
break;
}
// Verify serial
if (verify_serial(name, serial)) {
MessageBoxA(hWnd, "Activation successful! Playing...", "OK", MB_OK | MB_ICONINFORMATION);
} else {
MessageBoxA(hWnd, "Invalid serial!", "Error", MB_OK | MB_ICONERROR);
}
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcA(hWnd, msg, wParam, lParam);
}
return 0;
}
// Windows application entry point
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Create window class
WNDCLASSA wc = {0};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = "HotspotSimClass";
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClassA(&wc)) return -1;
// Create the window
HWND hWnd = CreateWindowA("HotspotSimClass", "Hotspot Player (Simulated - Native)",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, 340, 160, NULL, NULL, hInstance, NULL);
if (!hWnd) return -1;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Simple message loop
msg msg;
while (GetMessageA(&msg, NULL, 0, 0)) {
translateMessage(&msg);
DispatchMessageA(&msg);
}
return (int)msg.wParam;
}
@reverseengine
❤1
برنامه کمکی: تولید سریال فایل: gen_serial.c
برای راحتی کار و تمرین یک برنامه C ساده که همون الگوریتم رو اجرا میکنه و سریال برای یک اسم میسازه
// gen_serial.c
// برنامه ساده برای تولید سریال بر اساس اسم
نحوه ساخت Build
با MinGW (در ویندوز):
برای hotspot_sim.c:
mwindows برای حذف پنجره کنسول و ساخت GUI
برای gen_serial.c:
با MSVC (Developer Command Prompt):
hotspot_sim.c:
cl /EHsc hotspot_sim.c user32.lib gdi32.lib
gen_serial.c:
cl /EHsc gen_serial.c
چجوری تست و استفاده کنید
داخل VM ویندوزی حتما VM و snapshot برای فایل hotspot_sim.exe رو اجرا کنید
اسم دلخواه بزنید مثلا Ali حالا یا سریال رو با gen_serial.exe Ali بسازید و در فیلد Serial پیست کنید یا داخل دیباگر تابع تولید رو اجرا و مقدار expected را بخونید
اگر سریال درست باشه MessageBox موفقیت نمایش میده
راهنمای کوتاه آنالیز در x64dbg / IDA
جستجوی رشتهها
: "Name:", "Serial:", "%04X-%04X-%04X", "Activate & Play" → رفرنسها معمولا توابع مهم رو نشون میدن
IsDebuggerPresent: breakpoint
روی IsDebuggerPresent یا آدرسی که اون رو صدا میزنه اگر 1 برگرده برنامه مسیر خطا رو میزنه
GetWindowTextA: breakpoint
بذارید تا مقدار name و serial رو داخل حافظه ببینید
ثابتها: جستجوی ثابتهای XOR (0xA5A5A5A5, 0x5A5A5A5A, 0x3C3C3C3C) یا قالب %04X-%04X-%04X شما رو به تابع تولید سریال میرسونه
مقایسه: breakpoint روی stricmp تا قبل از مقایسه دو بافر رو ببینید
MessageBoxA:
گذاشتن breakpoint اینجا سریع میگه کدوم شاخه اجرا شده موفق یا خطا
Auxiliary program: Serial generation File: gen_serial.c)
For convenience and practice, a simple C program that implements the same algorithm and creates a serial for a name
// gen_serial.c
// Simple program to generate serial based on name
برای راحتی کار و تمرین یک برنامه C ساده که همون الگوریتم رو اجرا میکنه و سریال برای یک اسم میسازه
// gen_serial.c
// برنامه ساده برای تولید سریال بر اساس اسم
#include <stdio.h>
#include <stdint.h>
#include <string.h>
// تولید سریال مثل gen_expected_serial در باینری
void gen_expected_serial(const char *name, char *out, size_t outlen)
{
uint64_t s = 0;
// s = s*31 + ch
for (size_t i = 0; i < strlen(name); ++i) {
unsigned char ch = (unsigned char)name[i];
s = s * 31 + ch;
}
unsigned g1 = (unsigned)((s ^ 0xA5A5A5A5ULL) & 0xFFFF);
unsigned g2 = (unsigned)(((s >> 3) ^ 0x5A5A5A5AULL) & 0xFFFF);
unsigned g3 = (unsigned)(((s << 7) ^ 0x3C3C3C3CULL) & 0xFFFF);
// فرمت AAAA-BBBB-CCCC (حروف بزرگ هگز)
snprintf(out, outlen, "%04X-%04X-%04X", g1, g2, g3);
}
int main(int argc, char **argv)
{
char name[256] = {0};
char serial[64] = {0};
if (argc >= 2) {
strncpy(name, argv[1], sizeof(name)-1);
} else {
printf("Enter name: ");
if (!fgets(name, sizeof(name), stdin)) return 1;
name[strcspn(name, "\r\n")] = 0;
}
if (strlen(name) == 0) {
fprintf(stderr, "Name is empty\n");
return 1;
}
gen_expected_serial(name, serial, sizeof(serial));
printf("Name: %s\nSerial: %s\n", name, serial);
return 0;
}
نحوه ساخت Build
با MinGW (در ویندوز):
برای hotspot_sim.c:
gcc hotspot_sim.c -o hotspot_sim.exe -mwindows
mwindows برای حذف پنجره کنسول و ساخت GUI
برای gen_serial.c:
gcc gen_serial.c -o gen_serial.exe
با MSVC (Developer Command Prompt):
hotspot_sim.c:
cl /EHsc hotspot_sim.c user32.lib gdi32.lib
gen_serial.c:
cl /EHsc gen_serial.c
چجوری تست و استفاده کنید
داخل VM ویندوزی حتما VM و snapshot برای فایل hotspot_sim.exe رو اجرا کنید
اسم دلخواه بزنید مثلا Ali حالا یا سریال رو با gen_serial.exe Ali بسازید و در فیلد Serial پیست کنید یا داخل دیباگر تابع تولید رو اجرا و مقدار expected را بخونید
اگر سریال درست باشه MessageBox موفقیت نمایش میده
راهنمای کوتاه آنالیز در x64dbg / IDA
جستجوی رشتهها
: "Name:", "Serial:", "%04X-%04X-%04X", "Activate & Play" → رفرنسها معمولا توابع مهم رو نشون میدن
IsDebuggerPresent: breakpoint
روی IsDebuggerPresent یا آدرسی که اون رو صدا میزنه اگر 1 برگرده برنامه مسیر خطا رو میزنه
GetWindowTextA: breakpoint
بذارید تا مقدار name و serial رو داخل حافظه ببینید
ثابتها: جستجوی ثابتهای XOR (0xA5A5A5A5, 0x5A5A5A5A, 0x3C3C3C3C) یا قالب %04X-%04X-%04X شما رو به تابع تولید سریال میرسونه
مقایسه: breakpoint روی stricmp تا قبل از مقایسه دو بافر رو ببینید
MessageBoxA:
گذاشتن breakpoint اینجا سریع میگه کدوم شاخه اجرا شده موفق یا خطا
Auxiliary program: Serial generation File: gen_serial.c)
For convenience and practice, a simple C program that implements the same algorithm and creates a serial for a name
// gen_serial.c
// Simple program to generate serial based on name
#include <stdio.h>
#include <stdint.h>
#include <string.h>
// Generate serial like gen_expected_serial in binary
void gen_expected_serial(const char *name, char *out, size_t outlen)
{
uint64_t s = 0;
// s = s*31 + ch
for (size_t i = 0; i < strlen(name); ++i) {
unsigned char ch = (unsigned char)name[i];
s = s * 31 + ch;
}
unsigned g1 = (unsigned)((s ^ 0xA5A5A5A5ULL) & 0xFFFF);
unsigned g2 = (unsigned)(((s >> 3) ^ 0x5A5A5A5AULL) & 0xFFFF);
unsigned g3 = (unsigned)(((s << 7) ^ 0x3C3C3C3CULL) & 0xFFFF);
// format AAAA-BBBB-CCCC (hex uppercase letters)
snprintf(out, outlen, "%04X-%04X-%04X", g1, g2, g3);
}
int main(int argc, char **argv)
{
char name[256] = {0};
char serial[64] = {0};
if (argc >= 2) {
strncpy(name, argv[1], sizeof(name)-1);
} else {
printf("Enter name: ");
if (!fgets(name, sizeof(name), stdin)) return 1;
name[strcspn(name, "\r\n")] = 0;
}
if (strlen(name) == 0) {
fprintf(stderr, "Name is empty\n");
return 1;
}
gen_expected_serial(name, serial, sizeof(serial));
printf("Name: %s\nSerial: %s\n", name, serial);
return 0;
}
❤1
How to Build
With MinGW (on Windows):
For hotspot_sim.c:
mwindows to remove the console window and build the GUI
For gen_serial.c:
With MSVC (Developer Command Prompt):
hotspot_sim.c:
cl /EHsc hotspot_sim.c user32.lib gdi32.lib
gen_serial.c:
cl /EHsc gen_serial.c
How to test and use
Inside a Windows VM, be sure to run the VM and snapshot for the hotspot_sim.exe file
Give it a name of your choice, for example Ali. Now either create the serial with gen_serial.exe Ali and paste it in the Serial field, or run the generation function inside the debugger and read the expected value
If the serial is correct, the MessageBox will display success
A short guide to analyzing in x64dbg / IDA
Search Strings
: "Name:", "Serial:", "%04X-%04X-%04X", "Activate & Play" → References usually indicate important functions
IsDebuggerPresent: breakpoint
On IsDebuggerPresent or the address that calls it, if it returns 1, the program will hit the error path
GetWindowTextA: breakpoint
Put it to see the value of name and serial in memory
Constants: Search for XOR constants (0xA5A5A5A5, 0x5A5A5A5A, 0x3C3C3C3C) or the pattern %04X-%04X-%04X will take you to the serial generation function
Comparison: breakpoint on stricmp to see the two buffers before comparing
MessageBoxA:
Putting a breakpoint here will quickly tell you which branch was executed successfully or failed
@reverseengine
With MinGW (on Windows):
For hotspot_sim.c:
gcc hotspot_sim.c -o hotspot_sim.exe -mwindows
mwindows to remove the console window and build the GUI
For gen_serial.c:
gcc gen_serial.c -o gen_serial.exe
With MSVC (Developer Command Prompt):
hotspot_sim.c:
cl /EHsc hotspot_sim.c user32.lib gdi32.lib
gen_serial.c:
cl /EHsc gen_serial.c
How to test and use
Inside a Windows VM, be sure to run the VM and snapshot for the hotspot_sim.exe file
Give it a name of your choice, for example Ali. Now either create the serial with gen_serial.exe Ali and paste it in the Serial field, or run the generation function inside the debugger and read the expected value
If the serial is correct, the MessageBox will display success
A short guide to analyzing in x64dbg / IDA
Search Strings
: "Name:", "Serial:", "%04X-%04X-%04X", "Activate & Play" → References usually indicate important functions
IsDebuggerPresent: breakpoint
On IsDebuggerPresent or the address that calls it, if it returns 1, the program will hit the error path
GetWindowTextA: breakpoint
Put it to see the value of name and serial in memory
Constants: Search for XOR constants (0xA5A5A5A5, 0x5A5A5A5A, 0x3C3C3C3C) or the pattern %04X-%04X-%04X will take you to the serial generation function
Comparison: breakpoint on stricmp to see the two buffers before comparing
MessageBoxA:
Putting a breakpoint here will quickly tell you which branch was executed successfully or failed
@reverseengine
❤1
تحلیل استفاده از ابزارهای RMM برا بایپس EDR در حملات گروه های باج افزاری Medusa و DragonForce
Analysis of the use of RMM tools to bypass EDR in Medusa and DragonForce ransomware attacks
https://zensec.co.uk/blog/how-rmm-abuse-fuelled-medusa-dragonforce-attacks
@FUZZ0x
Analysis of the use of RMM tools to bypass EDR in Medusa and DragonForce ransomware attacks
https://zensec.co.uk/blog/how-rmm-abuse-fuelled-medusa-dragonforce-attacks
@FUZZ0x
Zensec
How RMM abuse fuelled Medusa & DragonForce attacks - Zensec
If you are reading this because you have experienced a ransomware incident and are unsure how to deal with it, contact Zensec immediately.
❤1
Bootloader to Iris: A Security Teardown of a Hardware Wallet
https://hhj4ck.github.io/en/iris-wallet-security-teardown.html
@reverseengine
https://hhj4ck.github.io/en/iris-wallet-security-teardown.html
@reverseengine
Guanxing’s Blog
Bootloader to Iris: A Security Teardown of a Hardware Wallet
Recently, I got my hands on a hardware wallet that features iris recognition as a selling point. The novelty of the iris component sparked my curiosity, so I decided to take a deep dive into its implementation. Since the wallet’s hardware and software design…
❤1