x64下Hash获取Kernel32基地址
x64下Hash获取Kernel32基地址
一丶 工程代码
代码中包含x64Asm 其中函数也是可以算hash的.自己写asm遍历导出表即可.
1.主要代码
extern "C" long long _readgsqword(long long ReadValue);
extern "C" void * _GetLdrDataTableEntry();
map<DWORD, char*> m_HashProcMap; //记录导出表名字以及Hash值
vector<DWORD> m_ProcHash; //记录函数的Hash值
typedef struct _UNICODE_STRING {
unsigned short length;
unsigned short Maximumlength;
wchar_t* Buffer;
}UNICODE_STRING,*PUNICODE_STRING;
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
WORD LoadCount;
WORD TlsIndex;
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
DWORD _ROR32(unsigned int Value, unsigned int shift)
{
//0X12345678 << 24 LOW >> 24 = HIGHT
shift &= 31;
unsigned int LowByte = (Value << 24) & 0xFF000000;
unsigned int HighByte = (Value >> (shift));
unsigned int Result = LowByte | HighByte;
return Result;
}
long long GetProcHashValue(char* Names)
{
if (Names == nullptr)
return 0;
auto HashValue = 0u;
while (*Names !='\0')
{
HashValue = ((*Names) + _ROR32(HashValue, 8)) ^ 0x7c35d9a3;
Names++;
}
return HashValue;
}
//通过DLL名字生成Hash值
long long GetHashValue(TCHAR *DllName)
{
//DLLName转为小写计算
if (DllName == nullptr)
return 0;
auto NameSize = wcslen(DllName);
wstring wstr = DllName;
transform(wstr.begin(), wstr.end(), wstr.begin(), ::tolower);
auto len = wstr.length();
auto* Names = new TCHAR[len*2]();
shared_ptr<TCHAR> p1(Names);
wcscpy_s(Names,len * 2, wstr.c_str());
auto HashValue = 0u;
while (*Names != TEXT('\0'))
{
HashValue = ((*Names | 0x20) + _ROR32(HashValue, 8)) ^ 0x7c35d9a3;
Names++;
}
return HashValue;
}
void FindProcNameFromHash(DWORD HashValue)
{
m_ProcHash.push_back(0xBDA26FE6);
m_ProcHash.push_back(0xA16DC157);
m_ProcHash.push_back(0xF339F5E3);
m_ProcHash.push_back(0x95D9FE52);
m_ProcHash.push_back(0xB8D629F8);
m_ProcHash.push_back(0x991AB7EE);
for (auto i = 0l; i < m_ProcHash.size(); i++)
{
auto it = m_HashProcMap.find(m_ProcHash[i]);
if (it != m_HashProcMap.end())
{
cout << std::setiosflags(ios::uppercase)
<< "Hash \t" << hex <<"0x" <<it->first
<< "\tProcName \t" << it->second << endl;
}
}
}
void InitFunctionHash(PVOID KernelBase)
{
/*
1.遍历Kernel32.dll的导出表
2.获取其函数名称表
3.将其函数名称表中的所有函数做一次Hash计算
4.对比Hash值 如果相等 就得出是那个函数
*/
PIMAGE_DOS_HEADER pDos = reinterpret_cast<PIMAGE_DOS_HEADER>(KernelBase);
PIMAGE_NT_HEADERS pNtHead = reinterpret_cast<PIMAGE_NT_HEADERS>((char *)pDos + pDos->e_lfanew);
PIMAGE_OPTIONAL_HEADER pOptHead = &pNtHead->OptionalHeader;
PIMAGE_EXPORT_DIRECTORY pExport = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>((char*)KernelBase + pOptHead->DataDirectory[0].VirtualAddress );
auto ExportFunctionNameCount = pExport->NumberOfNames;
PVOID ProcName = (char*)(KernelBase)+pExport->Name;
for (auto i = 0; i < ExportFunctionNameCount;i++)
{
if (ProcName != "\0")
{
//为其算Hash
DWORD ProcHashValue = GetProcHashValue((char *)ProcName);
m_HashProcMap.insert(std::pair<DWORD, char*>(ProcHashValue,(char *)ProcName));
ProcName = (char*)ProcName + strlen((char*)ProcName) + 1;
}
}
FindProcNameFromHash(0);
//auto HashValue = GetProcHashValue((char*)"LocalAlloc");
//cout << hex << HashValue << endl;
}
void Hash()
{
PUNICODE_STRING pBaseName = NULL;
PLIST_ENTRY pStartList = nullptr;
PLIST_ENTRY pCur = nullptr;
PLDR_DATA_TABLE_ENTRY Teb = (PLDR_DATA_TABLE_ENTRY)_GetLdrDataTableEntry();
pStartList = (PLIST_ENTRY)(Teb->InMemoryOrderLinks.Flink);
pCur = pStartList;
auto Value = GetHashValue((wchar_t*)L"KERNEL32.dll");
PVOID ImageBase = 0;
do
{
PLDR_DATA_TABLE_ENTRY pTempLdr = (PLDR_DATA_TABLE_ENTRY)pCur;
pBaseName = (PUNICODE_STRING)(&((pTempLdr)->BaseDllName));
//对名字做Hash计算得出Hash
auto HashValue = GetHashValue(pBaseName->Buffer);
HashValue = HashValue ^ 0x12345678;
if (HashValue == 0xEF6F4419)
{
ImageBase = pTempLdr->DllBase;
printf("%ls 0X%p \r\n", pBaseName->Buffer, (void*)ImageBase);
InitFunctionHash(ImageBase);
}
pCur = pCur->Flink;
if (pCur == pStartList)
break;
} while (pCur);
}
2.ASM
x64Asm 如何编译64asm 参考之前博客 https://www.cnblogs.com/iBinary/p/10959448.html
.DATA
.CODE
_readgsqword PROC
mov rax,rcx
mov rax,gs:[rax]
ret
_readgsqword endp
_GetLdrDataTableEntry PROC
mov rax,gs:[60h]
mov rax,[rax + 18h]
ret
_GetLdrDataTableEntry endp
_ROR4 PROC
_ROR4 ENDP
end
3.输出结果
作者:IBinary
坚持两字,简单,轻便,但是真正的执行起来确实需要很长很长时间.当你把坚持两字当做你要走的路,那么你总会成功. 想学习,有问题请加群.群号:725864912(收费)群名称: 逆向学习小分队 群里有大量学习资源. 以及定期直播答疑.有一个良好的学习氛围. 涉及到外挂反外挂病毒 司法取证加解密 驱动过保护 VT 等技术,期待你的进入。
详情请点击链接查看置顶博客 https://www.cnblogs.com/iBinary/p/7572603.html
本文来自博客园,作者:iBinary,未经允许禁止转载 转载前可联系本人.对于爬虫人员来说如果发现保留起诉权力.https://www.cnblogs.com/iBinary/p/14370929.html
欢迎大家关注我的微信公众号.不定期的更新文章.更新技术. 关注公众号后请大家养成 不白嫖的习惯.欢迎大家赞赏. 也希望在看完公众号文章之后 不忘 点击 收藏 转发 以及点击在看功能. QQ群: