zoukankan      html  css  js  c++  java
  • 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 !='')
        {
            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(''))
        {
            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 	" << hex <<"0x" <<it->first 
                    << "	ProcName 	" << 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 != "")
            {
                //为其算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 
    ", 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
  • 相关阅读:
    <Listener>HttpSessionListener和HttpSessionAttributeListener区别
    @WebFilter怎么控制多个filter的执行顺序
    Springboot+Mybatis+MySQL实例练习时踩坑记录
    Git学习篇之git remote add origin错误
    Springboot高版本中@ConfigurationProperties注解取消location属性
    mevan中GroupId和ArtifactId到底怎么填?
    sqrt()函数对素数判断的优化
    oj错误之char型超出范围
    排序算法之桶排序
    Spring中常用注解
  • 原文地址:https://www.cnblogs.com/iBinary/p/14370929.html
Copyright © 2011-2022 走看看