什么是shellcode
一段位置无关的代码(不依赖外部环境)
也就是遵循如下规则
-
不能使用全局变量 -
不能使用常量字符串 -
不能直接调用windowsAPI
如何实现一个通用的shellcode
我们先来看这么一段代码
#include<Windows.h>intmain(){MessageBox(0,0,0,0);}
转到反汇编 由于ALSR的存在 每次MessageBox的地址是不一样的 所以直接硬编码是不行的
那么动态获取函数地址呢? 是不是可以解决这个问题?
typedefint(WINAPI*pMessageBoxW)(_In_opt_HWNDhWnd,_In_opt_LPCWSTRlpText,_In_opt_LPCWSTRlpCaption,_In_UINTuType);intmain(){HMODULEhUser32Module=LoadLibrary(L"User32.dll");pMessageBoxWMsgBox=(pMessageBoxW)GetProcAddress(hUser32Module,"MessageBoxW");MsgBox(0,0,0,0);}
并不行 因为LoadLibrary
GetProcAddress
是Kernel32.dll中的导出函数 也不能直接使用
那么我们可以考虑获取Kernel32.dll
的基址 然后解析导出表来拿到对应函数的地址
获取Kernel32.dll基址
获取PEB后 遍历_PEB_LDR_DATA
中三个链表任意一个 链表是LDR_DATA_TABLE_ENTRY
结构 通过对比BaseDllName
确定当前获取的模块
先获取PEB
#ifdef _WIN64PPEBpeb=(PPEB)__readgsqword(0x60);#endif#ifdef _X86_PPEBpeb=(PPEB)__readfsdword(0x30);#endif
获取Kernel32.dll基址
PPEB_LDR_DATApLdr=peb->LoaderData;PLIST_ENTRYmoduleList=&pLdr->InLoadOrderModuleList;PLIST_ENTRYcurrent=moduleList->Flink;WCHARtarget[]={L'K',L'e',L'r',L'n',L'e',L'l',L'3',L'2',L'.',L'd',L'l',L'l',L'�'};PVOIDdllBase=NULL;while(current!=moduleList){PLDR_DATA_TABLE_ENTRYentry=(PLDR_DATA_TABLE_ENTRY)current;if(_wcsnicmp(entry->BaseDllName.Buffer,target,wcslen(target))==0){dllBase=entry->DllBase;break;}current=current->Flink;}
这样遍历是有问题的 不要用_wcsnicmp
不然到时候shellcode用不了 自己实现逻辑
字符串相关的这种函数都不要用
PPEB_LDR_DATApLdr=peb->LoaderData;PLIST_ENTRYmoduleList=&pLdr->InLoadOrderModuleList;PLIST_ENTRYcurrent=moduleList->Flink;WCHARtarget[]={L'K',L'e',L'r',L'n',L'e',L'l',L'3',L'2',L'.',L'd',L'l',L'l',L'�'};PVOIDdllBase=NULL;while(current!=moduleList){PLDR_DATA_TABLE_ENTRYentry=(PLDR_DATA_TABLE_ENTRY)current;WCHAR*buffer=entry->BaseDllName.Buffer;WCHAR*targetPtr=target;size_ti=0;while(targetPtr[i]!=L'�'){++i;}size_ttargetLength=i;i=0;while(i<targetLength){WCHARc1=buffer[i];WCHARc2=target[i];if(c1>=L'A'&&c1<=L'Z')c1+=32;if(c2>=L'A'&&c2<=L'Z')c2+=32;if(c1!=c2)break;if(c1==L'�')break;++i;}if(i==targetLength){dllBase=entry->DllBase;break;}current=current->Flink;}
解析导出表
通过解析pe结构
拿到Loadlibrary
和GetProcAddress
的地址
PIMAGE_DOS_HEADERpDosHeader=(PIMAGE_DOS_HEADER)dllBase;PIMAGE_NT_HEADERSpNtHeader=(PIMAGE_NT_HEADERS)((DWORD_PTR)dllBase+pDosHeader->e_lfanew);PIMAGE_DATA_DIRECTORYpDataDir=(PIMAGE_DATA_DIRECTORY)&pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];PIMAGE_EXPORT_DIRECTORYexportTable=(PIMAGE_EXPORT_DIRECTORY)(pDataDir->VirtualAddress+(DWORD_PTR)dllBase);charstr1[]={'L','o','a','d','L','i','b','r','a','r','y','W','�'};charstr2[]={'G','e','t','P','r','o','c','A','d','d','r','e','s','s','�'};FARPROCLoadLibraryfuncAddr=NULL;FARPROCGetProcAddrfuncAddr=NULL;PDWORDNameArray=(PDWORD)((DWORD64)dllBase+exportTable->AddressOfNames);PDWORDAddressArray=(PDWORD)((DWORD64)dllBase+exportTable->AddressOfFunctions);PWORDOrdinalArray=(PWORD)((DWORD64)dllBase+exportTable->AddressOfNameOrdinals);for(SIZE_Ti=0;i<exportTable->NumberOfNames;i++){LPCSTRcurrentName=(LPCSTR)((DWORD64)dllBase+NameArray[i]);if(strcmp(str1,currentName)==0){LoadLibraryfuncAddr=(FARPROC)((DWORD64)dllBase+AddressArray[OrdinalArray[i]]);continue;}elseif(strcmp(str2,currentName)==0){GetProcAddrfuncAddr=(FARPROC)((DWORD64)dllBase+AddressArray[OrdinalArray[i]]);continue;}if(GetProcAddrfuncAddr&&LoadLibraryfuncAddr){break;}}pLoadLibraryWmyLoadLib=(pLoadLibraryW)LoadLibraryfuncAddr;pGetProcAddressmyGetProc=(pGetProcAddress)GetProcAddrfuncAddr;WCHARUser32Str[]={L'U',L's',L'e',L'r',L'3',L'2',L'.',L'd',L'l',L'l','�'};charMsgBoxStr[]={'M','e','s','s','a','g','e','B','o','x','W','�'};pMessageBoxWMsgBox=(pMessageBoxW)myGetProc(myLoadLib(User32Str),MsgBoxStr);MsgBox(0,0,0,0);
同样的 自实现字符串比较部分
for(SIZE_Ti=0;i<exportTable->NumberOfNames;i++){LPCSTRcurrentName=(LPCSTR)((DWORD64)dllBase+NameArray[i]);size_tj=0;boolmatch1=true;while(str1[j]!='�'&¤tName[j]!='�'){charc1=str1[j];charc2=currentName[j];if(c1>='A'&&c1<='Z')c1+=32;if(c2>='A'&&c2<='Z')c2+=32;if(c1!=c2){match1=false;break;}j++;}if(str1[j]!='�'||currentName[j]!='�'){match1=false;}if(match1){LoadLibraryfuncAddr=(FARPROC)((DWORD64)dllBase+AddressArray[OrdinalArray[i]]);continue;}boolmatch2=true;j=0;while(str2[j]!='�'&¤tName[j]!='�'){charc1=str2[j];charc2=currentName[j];if(c1>='A'&&c1<='Z')c1+=32;if(c2>='A'&&c2<='Z')c2+=32;if(c1!=c2){match2=false;break;}j++;}if(str2[j]!='�'||currentName[j]!='�'){match2=false;}if(match2){GetProcAddrfuncAddr=(FARPROC)((DWORD64)dllBase+AddressArray[OrdinalArray[i]]);continue;}if(GetProcAddrfuncAddr&&LoadLibraryfuncAddr){break;}}
输出shellcode
现在将刚刚的代码封装成函数 并在下面添加一个空函数定位
将shellcode写入到shellcode.h
中
constuintptr_tstart_address=(uintptr_t)&shellcode_start;constuintptr_tend_address=(uintptr_t)&shellcode_end;constsize_tshellcode_size=end_address-start_address;FILE*output_file=fopen("shellcode.h","w");if(!output_file){perror("Failed to open file");return1;}fprintf(output_file,"unsigned char shellcode[] = {n");for(size_ti=0;i<shellcode_size;++i){unsignedcharsig_code=((unsignedchar*)start_address)[i];fprintf(output_file,"0x%02X%s",sig_code,(i+1<shellcode_size)?",":"");if((i+1)%16==0||i+1==shellcode_size){fprintf(output_file,"n");}}fprintf(output_file,"};n");fclose(output_file);return0;
将vs用于检查堆栈 等额外添加的功能全部关了 禁用优化
完整代码
#include<iostream>#include<Windows.h>#include"shellcode.h"typedefstruct_UNICODE_STRING{USHORTLength;USHORTMaximumLength;PWSTRBuffer;}UNICODE_STRING,*PUNICODE_STRING;typedefstruct_RTL_DRIVE_LETTER_CURDIR{USHORTFlags;USHORTLength;ULONGTimeStamp;UNICODE_STRINGDosPath;}RTL_DRIVE_LETTER_CURDIR,*PRTL_DRIVE_LETTER_CURDIR;typedefstruct_RTL_USER_PROCESS_PARAMETERS{ULONGMaximumLength;ULONGLength;ULONGFlags;ULONGDebugFlags;PVOIDConsoleHandle;ULONGConsoleFlags;HANDLEStdInputHandle;HANDLEStdOutputHandle;HANDLEStdErrorHandle;UNICODE_STRINGCurrentDirectoryPath;HANDLECurrentDirectoryHandle;UNICODE_STRINGDllPath;UNICODE_STRINGImagePathName;UNICODE_STRINGCommandLine;PVOIDEnvironment;ULONGStartingPositionLeft;ULONGStartingPositionTop;ULONGWidth;ULONGHeight;ULONGCharWidth;ULONGCharHeight;ULONGConsoleTextAttributes;ULONGWindowFlags;ULONGShowWindowFlags;UNICODE_STRINGWindowTitle;UNICODE_STRINGDesktopName;UNICODE_STRINGShellInfo;UNICODE_STRINGRuntimeData;RTL_DRIVE_LETTER_CURDIRDLCurrentDirectory[0x20];}RTL_USER_PROCESS_PARAMETERS,*PRTL_USER_PROCESS_PARAMETERS;typedefstruct_PEB_LDR_DATA{ULONGLength;BOOLEANInitialized;PVOIDSsHandle;LIST_ENTRYInLoadOrderModuleList;LIST_ENTRYInMemoryOrderModuleList;LIST_ENTRYInInitializationOrderModuleList;}PEB_LDR_DATA,*PPEB_LDR_DATA;typedefstruct_PEB{BOOLEANInheritedAddressSpace;BOOLEANReadImageFileExecOptions;BOOLEANBeingDebugged;BOOLEANSpare;HANDLEMutant;PVOIDImageBaseAddress;PPEB_LDR_DATALoaderData;PRTL_USER_PROCESS_PARAMETERSProcessParameters;PVOIDSubSystemData;PVOIDProcessHeap;PVOIDFastPebLock;PVOIDFastPebLockRoutine;PVOIDFastPebUnlockRoutine;ULONGEnvironmentUpdateCount;PVOIDKernelCallbackTable;PVOIDEventLogSection;PVOIDEventLog;PVOIDFreeList;ULONGTlsExpansionCounter;PVOIDTlsBitmap;ULONGTlsBitmapBits[0x2];PVOIDReadOnlySharedMemoryBase;PVOIDReadOnlySharedMemoryHeap;PVOIDReadOnlyStaticServerData;PVOIDAnsiCodePageData;PVOIDOemCodePageData;PVOIDUnicodeCaseTableData;ULONGNumberOfProcessors;ULONGNtGlobalFlag;BYTESpare2[0x4];LARGE_INTEGERCriticalSectionTimeout;ULONGHeapSegmentReserve;ULONGHeapSegmentCommit;ULONGHeapDeCommitTotalFreeThreshold;ULONGHeapDeCommitFreeBlockThreshold;ULONGNumberOfHeaps;ULONGMaximumNumberOfHeaps;PVOID*ProcessHeaps;PVOIDGdiSharedHandleTable;PVOIDProcessStarterHelper;PVOIDGdiDCAttributeList;PVOIDLoaderLock;ULONGOSMajorVersion;ULONGOSMinorVersion;ULONGOSBuildNumber;ULONGOSPlatformId;ULONGImageSubSystem;ULONGImageSubSystemMajorVersion;ULONGImageSubSystemMinorVersion;ULONGGdiHandleBuffer[0x22];ULONGPostProcessInitRoutine;ULONGTlsExpansionBitmap;BYTETlsExpansionBitmapBits[0x80];ULONGSessionId;}PEB,*PPEB;typedefBOOLEAN(NTAPI*PLDR_INIT_ROUTINE)(_In_PVOIDDllHandle,_In_ULONGReason,_In_opt_PVOIDContext);typedefstruct_ACTIVATION_CONTEXT*PACTIVATION_CONTEXT;typedefstruct_LDR_SERVICE_TAG_RECORD{struct_LDR_SERVICE_TAG_RECORD*Next;ULONGServiceTag;}LDR_SERVICE_TAG_RECORD,*PLDR_SERVICE_TAG_RECORD;typedefstruct_LDRP_CSLIST{PSINGLE_LIST_ENTRYTail;}LDRP_CSLIST,*PLDRP_CSLIST;typedefenum_LDR_DDAG_STATE{LdrModulesMerged=-5,LdrModulesInitError=-4,LdrModulesSnapError=-3,LdrModulesUnloaded=-2,LdrModulesUnloading=-1,LdrModulesPlaceHolder=0,LdrModulesMapping=1,LdrModulesMapped=2,LdrModulesWaitingForDependencies=3,LdrModulesSnapping=4,LdrModulesSnapped=5,LdrModulesCondensed=6,LdrModulesReadyToInit=7,LdrModulesInitializing=8,LdrModulesReadyToRun=9}LDR_DDAG_STATE;typedefstruct_LDR_DDAG_NODE{LIST_ENTRYModules;PLDR_SERVICE_TAG_RECORDServiceTagList;ULONGLoadCount;ULONGLoadWhileUnloadingCount;ULONGLowestLink;union{LDRP_CSLISTDependencies;SINGLE_LIST_ENTRYRemovalLink;};LDRP_CSLISTIncomingDependencies;LDR_DDAG_STATEState;SINGLE_LIST_ENTRYCondenseLink;ULONGPreorderNumber;}LDR_DDAG_NODE,*PLDR_DDAG_NODE;typedefenum_LDR_DLL_LOAD_REASON{LoadReasonStaticDependency,LoadReasonStaticForwarderDependency,LoadReasonDynamicForwarderDependency,LoadReasonDelayloadDependency,LoadReasonDynamicLoad,LoadReasonAsImageLoad,LoadReasonAsDataLoad,LoadReasonEnclavePrimary,// since REDSTONE3LoadReasonEnclaveDependency,LoadReasonPatchImage,// since WIN11LoadReasonUnknown=-1}LDR_DLL_LOAD_REASON,*PLDR_DLL_LOAD_REASON;typedefstruct_LDRP_LOAD_CONTEXT*PLDRP_LOAD_CONTEXT;typedefstruct_RTL_BALANCED_NODE{union{struct_RTL_BALANCED_NODE*Children[2];struct{struct_RTL_BALANCED_NODE*Left;struct_RTL_BALANCED_NODE*Right;};};union{UCHARRed:1;UCHARBalance:2;ULONG_PTRParentValue;};}RTL_BALANCED_NODE,*PRTL_BALANCED_NODE;typedefenum_LDR_HOT_PATCH_STATE{LdrHotPatchBaseImage,LdrHotPatchNotApplied,LdrHotPatchAppliedReverse,LdrHotPatchAppliedForward,LdrHotPatchFailedToPatch,LdrHotPatchStateMax,}LDR_HOT_PATCH_STATE,*PLDR_HOT_PATCH_STATE;typedefstruct_LDR_DATA_TABLE_ENTRY{LIST_ENTRYInLoadOrderLinks;LIST_ENTRYInMemoryOrderLinks;LIST_ENTRYInInitializationOrderLinks;PVOIDDllBase;PLDR_INIT_ROUTINEEntryPoint;ULONGSizeOfImage;UNICODE_STRINGFullDllName;UNICODE_STRINGBaseDllName;union{UCHARFlagGroup[4];ULONGFlags;struct{ULONGPackagedBinary:1;ULONGMarkedForRemoval:1;ULONGImageDll:1;ULONGLoadNotificationsSent:1;ULONGTelemetryEntryProcessed:1;ULONGProcessStaticImport:1;ULONGInLegacyLists:1;ULONGInIndexes:1;ULONGShimDll:1;ULONGInExceptionTable:1;ULONGReservedFlags1:2;ULONGLoadInProgress:1;ULONGLoadConfigProcessed:1;ULONGEntryProcessed:1;ULONGProtectDelayLoad:1;ULONGReservedFlags3:2;ULONGDontCallForThreads:1;ULONGProcessAttachCalled:1;ULONGProcessAttachFailed:1;ULONGCorDeferredValidate:1;ULONGCorImage:1;ULONGDontRelocate:1;ULONGCorILOnly:1;ULONGChpeImage:1;ULONGChpeEmulatorImage:1;ULONGReservedFlags5:1;ULONGRedirected:1;ULONGReservedFlags6:2;ULONGCompatDatabaseProcessed:1;};};USHORTObsoleteLoadCount;USHORTTlsIndex;LIST_ENTRYHashLinks;ULONGTimeDateStamp;PACTIVATION_CONTEXTEntryPointActivationContext;PVOIDLock;// RtlAcquireSRWLockExclusivePLDR_DDAG_NODEDdagNode;LIST_ENTRYNodeModuleLink;PLDRP_LOAD_CONTEXTLoadContext;PVOIDParentDllBase;PVOIDSwitchBackContext;RTL_BALANCED_NODEBaseAddressIndexNode;RTL_BALANCED_NODEMappingInfoIndexNode;ULONG_PTROriginalBase;LARGE_INTEGERLoadTime;ULONGBaseNameHashValue;LDR_DLL_LOAD_REASONLoadReason;// since WIN8ULONGImplicitPathOptions;ULONGReferenceCount;// since WIN10ULONGDependentLoadFlags;UCHARSigningLevel;// since REDSTONE2ULONGCheckSum;// since 22H1PVOIDActivePatchImageBase;LDR_HOT_PATCH_STATEHotPatchState;}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;typedefHMODULE(WINAPI*pLoadLibraryW)(_In_LPCWSTRlpLibFileName);typedefFARPROC(WINAPI*pGetProcAddress)(_In_HMODULEhModule,_In_LPCSTRlpProcName);typedefint(WINAPI*pMessageBoxW)(_In_opt_HWNDhWnd,_In_opt_LPCWSTRlpText,_In_opt_LPCWSTRlpCaption,_In_UINTuType);voidshellcode_start(){#ifdef _WIN64PPEBpeb=(PPEB)__readgsqword(0x60);#endif#ifdef _X86_PPEBpeb=(PPEB)__readfsdword(0x30);#endifPPEB_LDR_DATApLdr=peb->LoaderData;PLIST_ENTRYmoduleList=&pLdr->InLoadOrderModuleList;PLIST_ENTRYcurrent=moduleList->Flink;WCHARtarget[]={L'K',L'e',L'r',L'n',L'e',L'l',L'3',L'2',L'.',L'd',L'l',L'l',L'�'};PVOIDdllBase=NULL;while(current!=moduleList){PLDR_DATA_TABLE_ENTRYentry=(PLDR_DATA_TABLE_ENTRY)current;WCHAR*buffer=entry->BaseDllName.Buffer;WCHAR*targetPtr=target;size_ti=0;while(targetPtr[i]!=L'�'){++i;}size_ttargetLength=i;i=0;while(i<targetLength){WCHARc1=buffer[i];WCHARc2=target[i];if(c1>=L'A'&&c1<=L'Z')c1+=32;if(c2>=L'A'&&c2<=L'Z')c2+=32;if(c1!=c2)break;if(c1==L'�')break;++i;}if(i==targetLength){dllBase=entry->DllBase;break;}current=current->Flink;}PIMAGE_DOS_HEADERpDosHeader=(PIMAGE_DOS_HEADER)dllBase;PIMAGE_NT_HEADERSpNtHeader=(PIMAGE_NT_HEADERS)((DWORD_PTR)dllBase+pDosHeader->e_lfanew);PIMAGE_DATA_DIRECTORYpDataDir=(PIMAGE_DATA_DIRECTORY)&pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];PIMAGE_EXPORT_DIRECTORYexportTable=(PIMAGE_EXPORT_DIRECTORY)(pDataDir->VirtualAddress+(DWORD_PTR)dllBase);charstr1[]={'L','o','a','d','L','i','b','r','a','r','y','W','�'};charstr2[]={'G','e','t','P','r','o','c','A','d','d','r','e','s','s','�'};FARPROCLoadLibraryfuncAddr=NULL;FARPROCGetProcAddrfuncAddr=NULL;PDWORDNameArray=(PDWORD)((DWORD64)dllBase+exportTable->AddressOfNames);PDWORDAddressArray=(PDWORD)((DWORD64)dllBase+exportTable->AddressOfFunctions);PWORDOrdinalArray=(PWORD)((DWORD64)dllBase+exportTable->AddressOfNameOrdinals);for(SIZE_Ti=0;i<exportTable->NumberOfNames;i++){LPCSTRcurrentName=(LPCSTR)((DWORD64)dllBase+NameArray[i]);size_tj=0;boolmatch1=true;while(str1[j]!='�'&¤tName[j]!='�'){charc1=str1[j];charc2=currentName[j];if(c1>='A'&&c1<='Z')c1+=32;if(c2>='A'&&c2<='Z')c2+=32;if(c1!=c2){match1=false;break;}j++;}if(str1[j]!='�'||currentName[j]!='�'){match1=false;}if(match1){LoadLibraryfuncAddr=(FARPROC)((DWORD64)dllBase+AddressArray[OrdinalArray[i]]);continue;}boolmatch2=true;j=0;while(str2[j]!='�'&¤tName[j]!='�'){charc1=str2[j];charc2=currentName[j];if(c1>='A'&&c1<='Z')c1+=32;if(c2>='A'&&c2<='Z')c2+=32;if(c1!=c2){match2=false;break;}j++;}if(str2[j]!='�'||currentName[j]!='�'){match2=false;}if(match2){GetProcAddrfuncAddr=(FARPROC)((DWORD64)dllBase+AddressArray[OrdinalArray[i]]);continue;}if(GetProcAddrfuncAddr&&LoadLibraryfuncAddr){break;}}pLoadLibraryWmyLoadLib=(pLoadLibraryW)LoadLibraryfuncAddr;pGetProcAddressmyGetProc=(pGetProcAddress)GetProcAddrfuncAddr;WCHARUser32Str[]={L'U',L's',L'e',L'r',L'3',L'2',L'.',L'd',L'l',L'l','�'};charMsgBoxStr[]={'M','e','s','s','a','g','e','B','o','x','W','�'};pMessageBoxWMsgBox=(pMessageBoxW)myGetProc(myLoadLib(User32Str),MsgBoxStr);MsgBox(0,0,0,0);}voidshellcode_end(){}intmain(){uintptr_tstart_address=(uintptr_t)&shellcode_start;uintptr_tend_address=(uintptr_t)&shellcode_end;size_tshellcode_size=end_address-start_address;printf("0x%x",shellcode_size);FILE*output_file=fopen("shellcode.h","w");if(!output_file){perror("Failed to open file");return1;}fprintf(output_file,"unsigned char shellcode[] = {n");for(size_ti=0;i<shellcode_size;++i){unsignedcharsig_code=((unsignedchar*)start_address)[i];fprintf(output_file,"0x%02X%s",sig_code,(i+1<shellcode_size)?",":"");if((i+1)%16==0||i+1==shellcode_size){fprintf(output_file,"n");}}fprintf(output_file,"};n");fclose(output_file);return0;// LPVOID lpMem = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);// memcpy(lpMem, shellcode, sizeof(shellcode));// ((void(*)(void)) lpMem)();}
参考
https://mp.weixin.qq.com/s/QFA8Aiyl_Zh2MKANpCQjMw
https://bbs.kanxue.com/thread-276757.htm
【来源】:https://xz.aliyun.com/t/16579
原文始发于微信公众号(船山信安):免杀基础-shellcode开发
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论