[2021]微软ApiSetMap的MEME huoji windows,ApiSetMap,meme 2021-06-07 850 次浏览 0 次点赞 windows ApiSetMap机制是win7以后最奇怪的机制之一,老外在博客上评论是"but no one really know why its useful.".特征就是在你编译你的dll后你的一些导入表的api的dll本来是kernel32.dll的会变成api-min-xxxxx.dll 这会导致很多问题,**比如沙箱解析、和内存注入失败** ## 为什么会存在这个机制 微软目标是将“API”功能(堆分配、字符串操作等)与子系统实现(枚举进程、注册服务等)分离,因此使用ApiSetMap机制,准备分离这些api. 但是写到一半估计是不想继续写了,于是烂尾了.然后导致各种api-ms-xxxxx丢失 ## 解析 详细解析可以在先知社区查看: https://xz.aliyun.com/t/7019 对于沙箱,我用如下代码解析这个东西: ```cpp /* 解决掉api-ms-xxxxx */ typedef enum _WinVer { WINVER_7 = 0x0610, WINVER_7_SP1 = 0x0611, WINVER_8 = 0x0620, WINVER_81 = 0x0630, WINVER_10 = 0x0A00, WINVER_10_RS1 = 0x0A01, // Anniversary update WINVER_10_RS2 = 0x0A02, // Creators update WINVER_10_RS3 = 0x0A03, // Fall creators update WINVER_10_RS4 = 0x0A04, // Spring creators update WINVER_10_RS5 = 0x0A05, // October 2018 update WINVER_10_19H1 = 0x0A06, // May 2019 update 19H1 WINVER_10_19H2 = 0x0A07, // November 2019 update 19H2 WINVER_10_20H1 = 0x0A08, // April 2020 update 20H1 } WinVer; std::string get_dll_name_from_api_set_map(const std::string& api_set) { std::wstring wapi_set(api_set.begin(), api_set.end()); typedef LONG(__stdcall* fnRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation); fnRtlGetVersion pRtlGetVersion = (fnRtlGetVersion)GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlGetVersion"); RTL_OSVERSIONINFOEXW verInfo = { 0 }; verInfo.dwOSVersionInfoSize = sizeof(verInfo); pRtlGetVersion((PRTL_OSVERSIONINFOW)&verInfo); ULONG ver_short = (verInfo.dwMajorVersion << 8) | (verInfo.dwMinorVersion << 4) | verInfo.wServicePackMajor; if (ver_short >= WINVER_10) { auto apiSetMap = (API_SET_NAMESPACE_ARRAY_10*)((X64PEB*)__readgsqword(0x60))->ApiSetMap; auto apiSetMapAsNumber = reinterpret_cast(apiSetMap); auto nsEntry = reinterpret_cast((apiSetMap->Start + apiSetMapAsNumber)); for (ULONG i = 0; i < apiSetMap->Count; i++) { UNICODE_STRING nameString, valueString; nameString.MaximumLength = static_cast(nsEntry->NameLength); nameString.Length = static_cast(nsEntry->NameLength); nameString.Buffer = reinterpret_cast(apiSetMapAsNumber + nsEntry->NameOffset); std::wstring name = std::wstring(nameString.Buffer, nameString.Length / sizeof(WCHAR)) + L".dll"; if (_wcsicmp(wapi_set.c_str(), name.c_str()) == 0) { auto valueEntry = reinterpret_cast(apiSetMapAsNumber + nsEntry->ValueOffset); if (nsEntry->ValueCount == 0) return ""; valueString.Buffer = reinterpret_cast(apiSetMapAsNumber + valueEntry->ValueOffset); valueString.MaximumLength = static_cast(valueEntry->ValueLength); valueString.Length = static_cast(valueEntry->ValueLength); auto value = std::wstring(valueString.Buffer, valueString.Length / sizeof(WCHAR)); //note: there might be more than one value, but we will just return the first one.. return std::string(value.begin(), value.end()); } nsEntry++; } } else { __debugbreak(); } return ""; } ``` 本文由 huoji 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。 点赞 0
还不快抢沙发