日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

用ASM编写一个简单的Windows Shellcode思路总结

發布時間:2025/3/21 windows 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用ASM编写一个简单的Windows Shellcode思路总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

shellcode 是什么?

“代碼也好數據也好只要是與位置無關的二進制就都是shellcode。”
為了寫出位置無關的代碼,需要注意以下幾點:

  • 不能對字符串使用直接偏移,必須將字符串存儲在堆棧中
  • dll中的函數尋址,由于 ASLR 不會每次都在同一個地址中加載,可以通過 PEB.PEB_LDR_DATA
    找到加載模塊調用其導出的函數,或加載新 dll。
  • 避免空字節

NULL 字節的值為 0x00,在 C/C++ 代碼中,NULL 字節被視為字符串的終止符。因此,shellcode 中這些字節的存在可能會干擾目標應用程序的功能,并且我們的 shellcode 可能無法正確復制到內存中。

mov ebx, 0x00xor ebx, ebx

用下面的語句代替上面的語句,結果是一樣的。

此外,在某些特定情況下,shellcode 必須避免使用字符,例如 \r 或 \n,甚至只使用字母數字字符。

windows下dll加載的機制

在 Windows 中,應用程序不能直接訪問系統調用,使用來自 Windows API ( WinAPI ) 的函數,Windows API函數都存儲在 kernel32.dll、advapi32.dll、gdi32.dll 等中。ntdll.dll 和 kernel32.dll 非常重要,以至于每個進程都會導入它們:

這是我編寫 nothing_to_do 程序,用 listdlls列出導入的 dll:

dll尋址

TEB(線程環境塊)該結構包含用戶模式中的線程信息,32位系統中我們可以使用 FS 寄存器在偏移0x30處找到進程環境塊(PEB) 的地址。

PEB.ldr 指向PEB_LDR_DATA提供有關加載模塊的信息的結構的指針,包含kernel32 和 ntdll 的基地址

typedef struct _PEB_LDR_DATA {BYTE Reserved1[8];PVOID Reserved2[3];LIST_ENTRY InMemoryOrderModuleList; } PEB_LDR_DATA, *PPEB_LDR_DATA;

PEB_LDR_DATA.InMemoryOrderModuleList 包含進程加載模塊的雙向鏈表的頭部。列表中的每一項都是指向 LDR_DATA_TABLE_ENTRY 結構的指針

typedef struct _LIST_ENTRY {PLIST_ENTRY Flink;PLIST_ENTRY Blink; } LIST_ENTRY, *PLIST_ENTRY;

LDR_DATA_TABLE_ENTRY 加載的 DLL 信息:

typedef struct _LDR_DATA_TABLE_ENTRY {PVOID Reserved1[2];LIST_ENTRY InMemoryOrderLinks;PVOID Reserved2[2];PVOID DllBase;PVOID EntryPoint;PVOID Reserved3;UNICODE_STRING FullDllName;BYTE Reserved4[8];PVOID Reserved5[3];union {ULONG CheckSum;PVOID Reserved6;};ULONG TimeDateStamp; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

tips

在 Vista 之前的 Windows 版本中,InInitializationOrderModuleList 中的前兩個DLL是 ntdll.dll和kernel32.dll,但對于 Vista 及以后的版本,第二個DLL更改為kernelbase.dll。

InMemoryOrderModuleList 中的第一個 calc.exe(可執行文件),第二個是ntdll.dll,第三個是kernel32.dll,目前這適用于所有 Windows 版本是首選方法。

kernel32.dll尋址流程:

轉化為匯編代碼:

xor ecx, ecx mov ebx, fs:[ecx + 0x30] ; 避免 00 空值 ebx = PEB基地址 mov ebx, [ebx+0x0c] ; ebx = PEB.Ldr mov esi, [ebx+0x14] ; ebx = PEB.Ldr.InMemoryOrderModuleList lodsd ; eax = Second module xchg eax, esi ; eax = esi, esi = eax lodsd ; eax = Third(kernel32) mov ebx, [eax + 0x10] ; ebx = dll Base address

dll導出表中函數尋址

之前學習pe結構相關資料在這。

ImageOptionalHeader32.DataDirectory[0].VirtualAddress 指向導出表RVA,
導出表的結構如下:

typedef struct _IMAGE_EXPORT_DIRECTORY {DWORD Characteristics; //未使用DWORD TimeDateStamp; //時間戳WORD MajorVersion; //未使用WORD MinorVersion; //未使用DWORD Name; //指向改導出表文件名字符串DWORD Base; //導出表的起始序號DWORD NumberOfFunctions; //導出函數的個數(更準確來說是AddressOfFunctions的元素數,而不是函數個數)DWORD NumberOfNames; //以函數名字導出的函數個數DWORD AddressOfFunctions; //導出函數地址表RVA:存儲所有導出函數地址(表元素寬度為4,總大小NumberOfFunctions * 4)DWORD AddressOfNames; //導出函數名稱表RVA:存儲函數名字符串所在的地址(表元素寬度為4,總大小為NumberOfNames * 4)DWORD AddressOfNameOrdinals; //導出函數序號表RVA:存儲函數序號(表元素寬度為2,總大小為NumberOfNames * 2) } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

函數尋址流程:

導出表尋址匯編:

mov edx, [ebx + 0x3c] ; 找到 dos header e_lfanew 偏移量 add edx, ebx ; edx = pe header mov edx, [edx + 0x78] ; edx = offset export table add edx, ebx ; edx = export table mov esi, [edx + 0x20] ; esi = offset names table add esi, ebx ; esi = names table

查找 Winexec 函數名:

xor ecx, ecx Get_Function:inc ecx ; ecx++lodsd ; eax = 下一個函數名字符串rvaadd eax, ebx ; eax = 函數名字符串指針cmp dword ptr[eax], 0x456E6957 ; eax[0:4] == EniWjnz Get_Function dec ecx;

查找 Winexec 函數指針:

mov esi, [edx + 0x24] ; esi = ordianl table rva add esi, ebx ; esi = ordianl table mov cx, [esi + ecx * 2] ; ecx = func ordianl mov esi, [edx + 0x1c] ; esi = address table rva add esi, ebx ; esi = address table mov edx, [esi + ecx * 4] ; edx = func address rva add edx, ebx ; edx = func address

調用 Winexec 函數:

xor eax, eax push edx push eax ; 0x00 push 0x6578652e push 0x636c6163 push 0x5c32336d push 0x65747379 push 0x535c7377 push 0x6f646e69 push 0x575c3a43 mov esi, esp ; esi = "C:\Windows\System32\calc.exe" push 10 ; window state SW_SHOWDEFAULT push esi ; "C:\Windows\System32\calc.exe" call edx ; WinExec(esi, 10)

最終的shellcode:

int main() {__asm {; Find where kernel32.dll is loaded into memoryxor ecx, ecxmov ebx, fs:[ecx + 0x30] ; 避免 00 空值 ebx = PEB基地址mov ebx, [ebx+0x0c] ; ebx = PEB.Ldrmov esi, [ebx+0x14] ; ebx = PEB.Ldr.InMemoryOrderModuleListlodsd ; eax = Second modulexchg eax, esi ; eax = esi, esi = eaxlodsd ; eax = Third(kernel32)mov ebx, [eax + 0x10] ; ebx = dll Base address; Find PE export tablemov edx, [ebx + 0x3c] ; 找到 dos header e_lfanew 偏移量add edx, ebx ; edx = pe headermov edx, [edx + 0x78] ; edx = offset export tableadd edx, ebx ; edx = export tablemov esi, [edx + 0x20] ; esi = offset names tableadd esi, ebx ; esi = names table; 查找 WinExec 函數名; EniW 456E6957xor ecx, ecxGet_Function:inc ecx ; ecx++lodsd ; eax = 下一個函數名字符串rvaadd eax, ebx ; eax = 函數名字符串指針cmp dword ptr[eax], 0x456E6957 ; eax[0:4] == EniWjnz Get_Functiondec ecx;; 查找 Winexec 函數指針mov esi, [edx + 0x24] ; esi = ordianl table rvaadd esi, ebx ; esi = ordianl tablemov cx, [esi + ecx * 2] ; ecx = func ordianlmov esi, [edx + 0x1c] ; esi = address table rvaadd esi, ebx ; esi = address tablemov edx, [esi + ecx * 4] ; edx = func address rvaadd edx, ebx ; edx = func address; 調用 Winexec 函數xor eax, eaxpush edxpush eax ; 0x00push 0x6578652epush 0x636c6163push 0x5c32336dpush 0x65747379push 0x535c7377push 0x6f646e69push 0x575c3a43mov esi, esp ; esi = "C:\Windows\System32\calc.exe"push 10 ; window state SW_SHOWDEFAULTpush esi ; "C:\Windows\System32\calc.exe"call edx ; WinExec(esi, 10); exitadd esp, 0x1cpop eaxpop edx}return 0; }

dump shellcode

vs 生成 shellcode 體積膨脹了好多,用 masm 重新寫一下,體積小了很多:shellcode.asm

編譯:

F:\> ml -c -coff .\shellcode.asm F:\> link -subsystem:windows .\shellcode.obj

兩種方法:

dumpbin.exe
$ dumpbin.exe /ALL .\shellcode.obj


從 PE .text 區塊中讀取
從 PointerToRawData 開始,取 VirtualSize 大小的數據

用 golang 寫個 loader

loader.go,直接用Makefile編譯:$ make

成功!!!

最后

關注私我獲取【網絡安全學習攻略

總結

以上是生活随笔為你收集整理的用ASM编写一个简单的Windows Shellcode思路总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。