通用shellcode
所有 win_32 程序都会加载 ntdll.dll 和 kernel32.dll 这两个最基础的动态链接库。如果想要
fs是什么?TEB是什么?
TEB结构如下: // // Thread Environment Block (TEB) // typedef struct _TEB { NT_TIB Tib; /* 00h */ PVOID EnvironmentPointer; /* 1Ch */ CLIENT_ID Cid; /* 20h */ PVOID ActiveRpcHandle; /* 28h */ PVOID ThreadLocalStoragePointer; /* 2Ch */ struct _PEB *ProcessEnvironmentBlock; /* 30h */ ULONG LastErrorValue; /* 34h */ ULONG CountOfOwnedCriticalSections; /* 38h */ PVOID CsrClientThread; /* 3Ch */ struct _W32THREAD* Win32ThreadInfo; /* 40h */ ULONG User32Reserved[0x1A]; /* 44h */ ULONG UserReserved[5]; /* ACh */ PVOID WOW32Reserved; /* C0h */ LCID CurrentLocale; /* C4h */ ULONG FpSoftwareStatusRegister; /* C8h */ PVOID SystemReserved1[0x36]; /* CCh */ LONG ExceptionCode; /* 1A4h */ struct _ACTIVATION_CONTEXT_STACK *ActivationContextStackPointer; /* 1A8h */ UCHAR SpareBytes1[0x28]; /* 1ACh */ GDI_TEB_BATCH GdiTebBatch; /* 1D4h */ CLIENT_ID RealClientId; /* 6B4h */ PVOID GdiCachedProcessHandle; /* 6BCh */ ULONG GdiClientPID; /* 6C0h */ ULONG GdiClientTID; /* 6C4h */ PVOID GdiThreadLocalInfo; /* 6C8h */ ULONG Win32ClientInfo[62]; /* 6CCh */ PVOID glDispatchTable[0xE9]; /* 7C4h */ ULONG glReserved1[0x1D]; /* B68h */ PVOID glReserved2; /* BDCh */ PVOID glSectionInfo; /* BE0h */ PVOID glSection; /* BE4h */ PVOID glTable; /* BE8h */ PVOID glCurrentRC; /* BECh */ PVOID glContext; /* BF0h */ NTSTATUS LastStatusValue; /* BF4h */ UNICODE_STRING StaticUnicodeString; /* BF8h */ WCHAR StaticUnicodeBuffer[0x105]; /* C00h */ PVOID DeallocationStack; /* E0Ch */ PVOID TlsSlots[0x40]; /* E10h */ LIST_ENTRY TlsLinks; /* F10h */ PVOID Vdm; /* F18h */ PVOID ReservedForNtRpc; /* F1Ch */ PVOID DbgSsReserved[0x2]; /* F20h */ ULONG HardErrorDisabled; /* F28h */ PVOID Instrumentation[14]; /* F2Ch */ PVOID SubProcessTag; /* F64h */ PVOID EtwTraceData; /* F68h */ PVOID WinSockData; /* F6Ch */ ULONG GdiBatchCount; /* F70h */ BOOLEAN InDbgPrint; /* F74h */ BOOLEAN FreeStackOnTermination; /* F75h */ BOOLEAN HasFiberData; /* F76h */ UCHAR IdealProcessor; /* F77h */ ULONG GuaranteedStackBytes; /* F78h */ PVOID ReservedForPerf; /* F7Ch */ PVOID ReservedForOle; /* F80h */ ULONG WaitingOnLoaderLock; /* F84h */ ULONG SparePointer1; /* F88h */ ULONG SoftPatchPtr1; /* F8Ch */ ULONG SoftPatchPtr2; /* F90h */ PVOID *TlsExpansionSlots; /* F94h */ ULONG ImpersionationLocale; /* F98h */ ULONG IsImpersonating; /* F9Ch */ PVOID NlsCache; /* FA0h */ PVOID pShimData; /* FA4h */ ULONG HeapVirualAffinity; /* FA8h */ PVOID CurrentTransactionHandle; /* FACh */ PTEB_ACTIVE_FRAME ActiveFrame; /* FB0h */ PVOID FlsData; /* FB4h */ UCHAR SafeThunkCall; /* FB8h */ UCHAR BooleanSpare[3]; /* FB9h */ } TEB,*PTEB; PEB结构 typedef struct _PEB { UCHAR InheritedAddressSpace; // 00h UCHAR ReadImageFileExecOptions; // 01h UCHAR BeingDebugged; // 02h UCHAR Spare; // 03h PVOID Mutant; // 04h PVOID ImageBaseAddress; // 08h PPEB_LDR_DATA Ldr; // 0Ch PRTL_USER_PROCESS_PARAMETERS ProcessParameters; // 10h PVOID SubSystemData; // 14h PVOID ProcessHeap; // 18h PVOID FastPebLock; // 1Ch PPEBLOCKROUTINE FastPebLockRoutine; // 20h PPEBLOCKROUTINE FastPebUnlockRoutine; // 24h ULONG EnvironmentUpdateCount; // 28h PVOID* KernelCallbackTable; // 2Ch PVOID EventLogSection; // 30h PVOID EventLog; // 34h PPEB_FREE_BLOCK FreeList; // 38h ULONG TlsExpansionCounter; // 3Ch PVOID TlsBitmap; // 40h ULONG TlsBitmapBits[0x2]; // 44h PVOID ReadOnlySharedMemoryBase; // 4Ch PVOID ReadOnlySharedMemoryHeap; // 50h PVOID* ReadOnlyStaticServerData; // 54h PVOID AnsiCodePageData; // 58h PVOID OemCodePageData; // 5Ch PVOID UnicodeCaseTableData; // 60h ULONG NumberOfProcessors; // 64h ULONG NtGlobalFlag; // 68h UCHAR Spare2[0x4]; // 6Ch LARGE_INTEGER CriticalSectionTimeout; // 70h ULONG HeapSegmentReserve; // 78h ULONG HeapSegmentCommit; // 7Ch ULONG HeapDeCommitTotalFreeThreshold; // 80h ULONG HeapDeCommitFreeBlockThreshold; // 84h ULONG NumberOfHeaps; // 88h ULONG MaximumNumberOfHeaps; // 8Ch PVOID** ProcessHeaps; // 90h PVOID GdiSharedHandleTable; // 94h PVOID ProcessStarterHelper; // 98h PVOID GdiDCAttributeList; // 9Ch PVOID LoaderLock; // A0h ULONG OSMajorVersion; // A4h ULONG OSMinorVersion; // A8h ULONG OSBuildNumber; // ACh ULONG OSPlatformId; // B0h ULONG ImageSubSystem; // B4h ULONG ImageSubSystemMajorVersion; // B8h ULONG ImageSubSystemMinorVersion; // C0h ULONG GdiHandleBuffer[0x22]; // C4h PVOID ProcessWindowStation; // ??? } PEB,*PPEB; PEB_LDR_DATA结构 typedef struct _PEB_LDR_DATA { ULONG Length; // +0x00 BOOLEAN Initialized; // +0x04 PVOID SsHandle; // +0x08 LIST_ENTRY InLoadOrderModuleList; // +0x0c LIST_ENTRY InMemoryOrderModuleList; // +0x14 LIST_ENTRY InInitializationOrderModuleList;// +0x1c } PEB_LDR_DATA,*PPEB_LDR_DATA; // +0x24 LIST_ENTRY结构 typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } LIST_ENTRY,*PLIST_ENTRY,*RESTRICTED_POINTER PRLIST_ENTRY;
按照上面的方法,我们已经可以获得 kernel32.dll 中的任意函数。类似地,我们已经具备了 其实,在摸透了 kernel32.dll 中的所有导出函数之后,结合使用其中的两个函数 LoadLibrary() int main() { _asm { mov eax,fs:[0x30] ;PEB的地址 mov eax,[eax + 0x0c] ;Ldr的地址 mov esi,[eax + 0x1c] ;Flink地址 lodsd mov eax,[eax + 0x08] ;eax就是kernel32.dll的地址 } return 0; } 一个弹出对话框,然后退出程序的shellcode
本次使用的hash算法 #include <stdio.h> DWORD GetHash(char *fun_name) { DWORD digest=0; while(*fun_name) { digest=((digest<<25)|(digest>>7)); //循环右移7位 /* movsx eax,byte ptr[esi] cmp al,ah jz compare_hash --> ror edx,7 ;这一行我看了俩小时,最后才意识到是((循环))右移,不是单纯的 >>7 add edx,eax inc esi jmp hash_loop 这是我第一次知道汇编也有比C语言方便的时候 */ digest+= *fun_name ; //累加 fun_name++; } return digest; } main() { DWORD hash; hash= GetHash("AddAtomA"); printf("%#xn",hash); }
CLD ;清空标志位DF push 0x1E380A6A ;压入MessageBoxA的hash-->user32.dll push 0x4FD18963 ;压入ExitProcess的hash-->kernel32.dll push 0x0C917432 ;压入LoadLibraryA的hash-->kernel32.dll mov esi,esp ;esi=esp,指向堆栈中存放LoadLibraryA的地址 lea edi,[esi-0xc] ;函数地址的开始 抬高栈顶,保护 shellcode 不被入栈数据破坏。 xor ebx,ebx mov bh,0x04 sub esp,ebx 定位kernel32.dll的基地址 mov ebx,fs:[edx+0x30] ;PEB mov ecx,[ebx+0xC] ;PEB_LDR_DATA mov ecx,[ecx+0x1C] ;InInitializationOrderModuleList mov ecx,[ecx] ;进入链表第一个就是ntdll.dll mov ebp,[ecx+0x8] ;ebp= kernel32.dll的基地址 下面找函数表的地址 mov eax,[ebp+0x3C] //dll的PE头 ebp是pe文件的开头位置(MZ) mov ecx,[ebp+eax+0x78] //导出表的指针 add ecx,ebp //ecx=0x78C00000+0x262c mov ebx,[ecx+0x20] //导出函数名列表指针 add ebx,ebp //导出函数名列表指基地址 导出表的结构 typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; //PE文件的模块名 DWORD Base; //模块基地址 DWORD NumberOfFunctions; //总的导出函数的个数 DWORD NumberOfNames; //有名称的函数的个数(这一行我真不想写,没用,还可能会误导初学者),有的导出函数没有名字的只有序号 DWORD AddressOfFunctions; //导出地址表 DWORD AddressOfNames; //函数名表 DWORD AddressOfNameOrdinals; //函数序号,并不一定是连续的,但一般和导出地址表是一一对应的 } IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY; 在导出表中搜索AIP的逻辑可以设计如图 具体代码如下 #include <stdio.h> #include <windows.h> int main() { __asm { CLD //清空标志位DF push 0x1E380A6A //压入MessageBoxA的hash-->user32.dll push 0x4FD18963 //压入ExitProcess的hash-->kernel32.dll push 0x0C917432 //压入LoadLibraryA的hash-->kernel32.dll mov esi,esp //esi=esp,指向堆栈中存放LoadLibraryA的地址 lea edi,[esi-0xc] //空出8字节应该是为了兼容性 //======开辟一些栈空间 xor ebx,ebx mov bh,0x04 sub esp,ebx //esp-=0x400 //======压入"user32.dll" mov bx,0x3233 push ebx //" 32" push 0x72657375 //"user" push esp xor edx,edx //edx=0 //======找kernel32.dll的基地址 mov ebx,fs:[edx+0x30] //[TEB+0x30]-->PEB mov ecx,[ebx+0xC] //[PEB+0xC]--->PEB_LDR_DATA mov ecx,[ecx+0x1C] //[PEB_LDR_DATA+0x1C]--->InInitializationOrderModuleList mov ecx,[ecx] //进入链表第一个就是ntdll.dll mov ebp,[ecx+0x8] //ebp= kernel32.dll的基地址 //======是否找到了自己所需全部的函数 find_lib_functions: lodsd //eax=[esi],esi+=4 cmp eax,0x1E380A6A //与MessageBoxA的hash比较 jne find_functions xchg eax,ebp //-------------------------------------------------> | call [edi-0x8] //LoadLibraryA("user32") | xchg eax,ebp //ebp=userl32.dll的基地址,eax=MessageBoxA的hash <-- | //======导出函数名列表指针 find_functions: pushad //保护寄存器 mov eax,[ebp+0x3C] //dll的PE头 mov ecx,[ebp+eax+0x78] //导出表的指针 add ecx,ebp //ecx=导出表的基地址 mov ebx,[ecx+0x20] //导出函数名列表指针 add ebx,ebp //ebx=导出函数名列表指针的基地址 xor edi,edi //======找下一个函数名 next_function_loop: inc edi mov esi,[ebx+edi*4] //从列表数组中读取 add esi,ebp //esi = 函数名称所在地址 cdq //edx = 0 //======函数名的hash运算 hash_loop: movsx eax,byte ptr[esi] cmp al,ah //字符串结尾就跳出当前函数 jz compare_hash ror edx,7 add edx,eax inc esi jmp hash_loop //======比较找到的当前函数的hash是否是自己想找的 compare_hash: cmp edx,[esp+0x1C] //lods pushad后,栈+1c为LoadLibraryA的hash jnz next_function_loop mov ebx,[ecx+0x24] //ebx = 顺序表的相对偏移量 add ebx,ebp //顺序表的基地址 mov di,[ebx+2*edi] //匹配函数的序号 mov ebx,[ecx+0x1C] //地址表的相对偏移量 add ebx,ebp //地址表的基地址 add ebp,[ebx+4*edi] //函数的基地址 xchg eax,ebp //eax<==>ebp 交换 pop edi stosd //把找到的函数保存到edi的位置 push edi popad cmp eax,0x1e380a6a //messagebox的hash jne find_lib_functions //======让他做些自己想做的事 function_call: xor ebx,ebx push ebx push 0x74736577 push 0x6c696166 //push "failwest" mov eax,esp push ebx push eax push eax push ebx call [edi-0x04] //MessageBoxA(NULL,"failwest",NULL) push ebx call [edi-0x08] //ExitProcess(0); nop nop nop nop } return 0; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |