
هدف کلی
این کد یک شلکد (Shellcode) است که:
آدرس GetProcAddress را از حافظه پیدا میکند
کتابخانه user32.dll را لود میکند
تابع MessageBoxA را پیدا میکند
یک پیام "hello" نمایش میدهد
سپس برنامه را با ExitProcess خاتمه میدهد
بخش اول: پیدا کردن بیس آدرس kernel32.dll
.386 ; هدف: پردازنده 386 (32 بیتی) .model flat, stdcall ; مدل حافظه flat و قرارداد فراخوانی stdcall .code start:
xor ecx, ecx
رجیستر ECX را صفر میکند (معادل mov ecx, 0 اما سریعتر)
ASSUME fs:NOTHING mov eax, dword ptr fs:[ecx+30h] ASSUME fs:ERROR
از سگمنت FS آدرس PEB (Process Environment Block) را میخواند
آفست 0x30 در TEB (Thread Environment Block) اشاره به PEB دارد
چون ECX=0 است، fs:[ecx+30h] == fs:[30h]
TEB └─ [0x30] ──► PEB
mov eax, dword ptr ds:[eax+0Ch]
از PEB آفست 0x0C را میخواند که به PEB_LDR_DATA اشاره دارد
PEB └─ [0x0C] ──► PEB_LDR_DATA
mov esi, dword ptr ds:[eax+14h]
از PEB_LDR_DATA آفست 0x14 را میخواند که InMemoryOrderModuleList است
این لیست شامل ماژولهای لود شده در حافظه است
PEB_LDR_DATA └─ [0x14] ──► InMemoryOrderModuleList ├─ [0] ntdll.dll ├─ [1] kernel32.dll ◄── هدف ما └─ ...
بخش دوم: پیمایش لیست ماژولها
lodsd ; eax = dword ptr ds:[esi] ; ESI به طور خودکار +4 میشود
اولین عنصر لیست را میخواند (ntdll.dll را رد میکند) LODSD = Load String Double word
xchg eax, esi
مقدار EAX و ESI را جابجا میکند حالا ESI به اولین ورودی واقعی اشاره دارد.
lodsd ; eax = dword ptr ds:[esi]
دومین عنصر لیست را میخواند (kernel32.dll)
mov ebx, dword ptr ds:[eax+10h]
آفست 0x10 از ورودی ماژول = بیس آدرس kernel32.dll
حالا EBX = بیس آدرس kernel32.dll
بخش سوم: پیدا کردن Export Table
mov edx, dword ptr ds:[ebx+3Ch]
از بیس آدرس، آفست 0x3C را میخواند
این آفست به PE Header (امضای NT) اشاره دارد
add edx, ebx
آدرس واقعی PE Header = بیس + آفست
mov edx, dword ptr ds:[edx+78h]
آفست 0x78 در PE Header = آفست Export Table
add edx, ebx
آدرس واقعی Export Table = بیس + آفست
PE Header └─ [0x78] ──► Export Table ├─ [0x20] ──► AddressOfNames ├─ [0x24] ──► AddressOfNameOrdinals └─ [0x1C] ──► AddressOfFunctions
mov esi, dword ptr ds:[edx+20h] add esi, ebx
آدرس AddressOfNames را میخواند (جدول نام توابع)
xor ecx, ecx
شمارنده حلقه را صفر میکند.
بخش چهارم: جستجوی GetProcAddress
jne_01: inc ecx
شمارنده را یک واحد افزایش میدهد (برای پیدا کردن اوردینال)
lodsd ; eax = dword ptr ds:[esi]
آفست نام تابع بعدی را میخواند
add eax, ebx
آدرس واقعی نام تابع = بیس + آفست
cmp dword ptr ds:[eax], 50746547h
بررسی میکند آیا ۴ بایت اول = "GetP" است؟
50746547h به صورت Little Endian = "GetP"
jne jne_01
اگر برابر نبود به اول حلقه برمیگردد
cmp dword ptr ds:[eax+04h], 41636F72h
بررسی میکند آیا بایتهای بعدی = "rocA" است؟
jne jne_01
cmp dword ptr ds:[eax+08h], 65726464h
بررسی میکند آیا بایتهای بعدی = "ddre" است؟
"GetP" + "rocA" + "ddre" = "GetProcAddre..." یعنی تابع GetProcAddress پیدا شد!
jne jne_01
بخش پنجم: گرفتن آدرس واقعی تابع
mov esi, dword ptr ds:[edx+24h] add esi, ebx
آدرس AddressOfNameOrdinals (جدول اوردینالها)
mov cx, word ptr ds:[esi+ecx*2h]
اوردینال تابع GetProcAddress را از جدول میخواند
dec ecx
اوردینال را یک واحد کم میکند (به دلیل اینکه inc در ابتدای حلقه اضافه شده بود)
mov esi, dword ptr ds:[edx+1Ch] add esi, ebx
آدرس AddressOfFunctions (جدول آدرس توابع)
mov edx, dword ptr ds:[esi+ecx*4h] add edx, ebx
آدرس واقعی تابع GetProcAddress را محاسبه میکند
حالا EDX = آدرس GetProcAddress
بخش ششم: فراخوانی LoadLibraryA
xor ecx, ecx push ebx ; بیس آدرس kernel32.dll push edx ; آدرس GetProcAddress push ecx ; صفر (null terminator) push 41797261h ; "Ayra" ◄─┐ push 7262694Ch ; "rbiL" ◄─┤ روی هم = "LoadLibraryA\0" push 64616F4Ch ; "daoL" ◄─┘ push esp ; اشارهگر به رشته "LoadLibraryA" push ebx ; هندل kernel32.dll call edx ; GetProcAddress(kernel32, "LoadLibraryA")
بعد از فراخوانی، EAX = آدرس LoadLibraryA
add esp, 0Ch
پاکسازی پارامترها از stack (رشته "LoadLibraryA")
pop ecx
مقدار null را از stack برمیدارد
بخش هفتم: لود کردن user32.dll
push eax ; آدرس LoadLibraryA را ذخیره میکند xor eax, eax mov ax, 6C6Ch ; "ll" push eax ; "ll\0\0" push 642E3233h ; "d.23" push 72657375h ; "resu" push esp ; اشارهگر به "user32.dll\0" call dword ptr ss:[esp+10h] ; LoadLibraryA("user32.dll")
رشته روی stack: "user" + "32.d" + "ll\0" = "user32.dll"
بعد از فراخوانی، EAX = هندل user32.dll
add esp, 0Ch
پاکسازی رشته از stack
بخش هشتم: پیدا کردن MessageBoxA
push eax ; هندل user32.dll xor eax, eax mov eax, 2341786Fh ; "23Axo" (با null جعلی) push eax sub dword ptr ss:[esp+3h], 23h ; تبدیل '23' به null push 42656761h ; "Bega" -> "egaB" push 7373654Dh ; "sseM" push esp ; اشارهگر به "MessageBox" push dword ptr ss:[esp+10h] ; هندل user32.dll call dword ptr ss:[esp+1Ch] ; GetProcAddress(user32, "MessageBoxA")
رشته ساخته شده: "MesS" + "ageB" + "ox\0" = "MessageBoxA"
add esp, 0Ch
پاکسازی رشته از stack
push eax ; آدرس MessageBoxA xor eax, eax mov eax, 23737365h ; با null جعلی push eax sub dword ptr ss:[esp+03h], 23h ; اصلاح null push 636F7250h ; "corP" push 74697845h ; "tixE" push esp ; اشارهگر به "ExitProcess" push dword ptr ss:[esp+20h] ; هندل kernel32.dll call dword ptr ss:[esp+20h] ; GetProcAddress(kernel32, "ExitProcess")
بخش دهم: نمایش MessageBox
push eax ; آدرس ExitProcess xor eax, eax mov eax, 236E6977h ; "win" با null جعلی push eax sub dword ptr ss:[esp+03h], 23h ; اصلاح null push esp ; اشارهگر به "win\0" (caption) xor eax, eax mov al, 6Fh ; 'o' push eax ; "o\0" push 6C6C6568h ; "lleh" push esp ; اشارهگر به "hello\0" (متن پیام) xor eax, eax push eax ; NULL (هندل پنجره) push dword ptr ss:[esp+04h] ; "hello" push dword ptr ss:[esp+14h] ; "win" (caption) xor eax, eax push eax ; MB_OK = 0 call dword ptr ss:[esp+28h] ; MessageBoxA(NULL, "hello", "win", 0)
بخش یازدهم: خاتمه برنامه
add esp, 14h
پاکسازی stack
.386 .model flat, stdcall .code start: xor ecx,ecx ASSUME fs:NOTHING mov eax,dword ptr fs:[ecx+30h] ASSUME fs:ERROR mov eax,dword ptr ds:[eax+0Ch] mov esi,dword ptr ds:[eax+14h] lodsd; eax,dword ptr ds:[esi] xchg eax,esi lodsd; eax,dword ptr ds:[esi] mov ebx,dword ptr ds:[eax+10h] mov edx,dword ptr ds:[ebx+3Ch] add edx,ebx mov edx,dword ptr ds:[edx+78h] add edx,ebx mov esi,dword ptr ds:[edx+20h] add esi,ebx xor ecx,ecx jne_01: inc ecx lodsd; eax,dword ptr ds:[esi] add eax,ebx cmp dword ptr ds:[eax],50746547h jne jne_01 cmp dword ptr ds:[eax+04h],41636F72h jne jne_01 cmp dword ptr ds:[eax+08h],65726464h jne jne_01 mov esi,dword ptr ds:[edx+24h] add esi,ebx mov cx,word ptr ds:[esi+ecx*2h] dec ecx mov esi,dword ptr ds:[edx+1Ch] add esi,ebx mov edx,dword ptr ds:[esi+ecx*4h] add edx,ebx xor ecx,ecx push ebx push edx push ecx push 41797261h push 7262694Ch push 64616F4Ch push esp push ebx call edx add esp,0Ch pop ecx push eax xor eax,eax mov ax,6C6Ch push eax push 642E3233h push 72657375h push esp call dword ptr ss:[esp+10h] add esp,0Ch push eax xor eax,eax mov eax,2341786Fh push eax sub dword ptr ss:[esp+3h],23h push 42656761h push 7373654Dh push esp push dword ptr ss:[esp+10h] call dword ptr ss:[esp+1Ch] add esp,0Ch push eax xor eax,eax mov eax,23737365h push eax sub dword ptr ss:[esp+03h],23h push 636F7250h push 74697845h push esp push dword ptr ss:[esp+20h] call dword ptr ss:[esp+20h] add esp,0Ch push eax xor eax,eax mov eax,236E6977h push eax sub dword ptr ss:[esp+03h],23h push esp xor eax,eax mov al,6Fh push eax push 6C6C6568h push esp xor eax,eax push eax push dword ptr ss:[esp+04h] push dword ptr ss:[esp+14h] xor eax,eax push eax call dword ptr ss:[esp+28h] add esp,14h END start


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