• openssl3.2 - exp - calc PE file checksum and SHA3-512


    openssl3.2 - exp - calc PE file checksum and SHA3-512

    概述

    想在程序中, 对自身的PE内容算校验和和HASH, 然后送给服务端判断PE文件是否被修改了.

    前几天, 看了一个资料, 里面有算PE校验和的实现. 迁移到自己工程.
    但是没有算HASH, 正好已经将openssl官方demo过了一遍, 有个官方demo正好是对buffer算hash(openssl3.2 - 官方demo学习 - encode - rsa_encode.c), 也迁移到自己工程.

    程序中释放openssl资源时, 开始判断条件写错了. 如下:

        if (NULL == _ossl_lib_ctx)
        {
            OSSL_LIB_CTX_free(_ossl_lib_ctx);
            _ossl_lib_ctx = NULL;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    导致有内存泄漏.
    但是我前几天做了openssl3.2检测内存泄漏的实验(openssl3.2 - crypto-mdebug被弃用后, 内存泄漏检查的替代方法), 非常好使.

    现在我的工程模板中都加入了内存检测的实现, 程序跑完, 退出时, 如果有内存泄漏, 直接断言, 然后用代码块注释法, 可以很快的定位修复内存泄漏问题.

    void* my_CRYPTO_malloc(size_t num, const char* file, int line)
    {
    	void* p = NULL;
    	It_mem_hook it;
    	CMemHookRec* rec = NULL;
    
    	p = malloc(num);
    	if (NULL != p)
    	{
    		it = g_mem_hook_map.find((uint64_t)p);
    		if (it != g_mem_hook_map.end()) {
    			// printf("find key\n");
    			assert(false);
    		}
    		else {
    			// printf("not find key\n");
    			rec = new CMemHookRec();
    			if (NULL != rec)
    			{
    				rec->rec_sn = ++g_u64_malloc_cnt_all;
    				// 观察UI上显示的内存分配记录的序号, 然后在具体序号上下断点, 然后跟进库里面, 再跟出到自己的应用代码处, 就基本知道是啥没释放:) 
    				if (2232 == rec->rec_sn)
    				{
    					rec->rec_sn = rec->rec_sn; // 如果哪里泄漏了, 可以单步到openssl库代码中
    					// 如果是自己没调用释放函数, 用代码块的注释排除法, 很快能确定问题.
    				}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    俺居然预判了可能会发生内存泄漏时如何检测的场景, 提前将检测措施搞定了. 真机智啊:P

    笔记

    main.cpp

    /*!
    * \file main.cpp
    * \note openssl3.2 - exp - calc PE file checksum and SHA3-512
    */
    
    #include "my_openSSL_lib.h"
    #include 
    #include 
    
    #include 
    #include 
    #include 
    
    #include "CMemHookRec.h"
    
    #include 
    #pragma comment(lib, "imagehlp.lib")
    
    #include "CPeFileCheck.h"
    
    void my_openssl_app();
    
    const char* psz_argv0 = NULL;
    
    int main(int argc, char** argv)
    {
    	psz_argv0 = argv[0];
    
    	setvbuf(stdout, NULL, _IONBF, 0); // 清掉stdout缓存, 防止调用printf时阻塞
    	mem_hook();
    
    	my_openssl_app();
    
    	mem_unhook();
    
    	return 0;
    
    	/*! run result
    	PE calc ok
    	PE checksum old  = 0x0
    	PE checksum calc = 0x23776
    	SHA3 512 len = 64
    	SHA3 512 data below:
    	0C F4 16 D4 4E 2A 9B 20
    	6A 9C B4 22 4F A8 3D 19
    	25 D8 6E 7F 7C 45 20 6B
    	70 78 77 4B FF A6 94 B5
    	D1 EE 16 EB 6D 0A B3 97
    	19 0B 1D 7D EE 63 0A D6
    	1D 01 F9 02 1D 93 2C 91
    	F5 00 39 CC 82 9D 65 92
    
    	END
    	free map, g_mem_hook_map.size() = 0
    	*/
    }
    
    void my_openssl_app()
    {
    	CPeFileCheck* pe = NULL;
    	DWORD dwPeCheckSum = 0;
    	bool b_rc = false;
    
    	DWORD dwPeCheckSumOrg = 0;
    	DWORD dwPeCheckSumCalc = 0;
    
    	uint8_t* pHash = NULL;
    	int HashLen = 0;
    
    	int i = 0;
    	int col_cnt = 0;
    
    	do {
    		pe = new CPeFileCheck();
    		if (NULL == pe)
    		{
    			break;
    		}
    
    		// 必须是全路径名称
    		b_rc = pe->PE_calc(psz_argv0);
    		if (!b_rc)
    		{
    			printf("error\n");
    		}
    		else {
    			printf("PE calc ok\n");
    
    			if (pe->get_PE_checkSum(dwPeCheckSumOrg, dwPeCheckSumCalc))
    			{
    				printf("PE checksum old  = 0x%X\n", dwPeCheckSumOrg);
    				printf("PE checksum calc = 0x%X\n", dwPeCheckSumCalc);
    			}
    
    			if (pe->get_PE_Hash_SHA3_512(&pHash, HashLen))
    			{
    				printf("SHA3 512 len = %d\n", HashLen);
    
    				printf("SHA3 512 data below:\n");
    				for (i = 0; i < HashLen; i++)
    				{
    					printf("%2.2X", pHash[i]);
    					if (8 == ++col_cnt)
    					{
    						col_cnt = 0;
    						printf("\n");
    					}
    					else {
    						printf(" ");
    					}
    				}
    			}
    		}
    	} while (false);
    		
    	if (NULL != pe)
    	{
    		delete pe;
    		pe = NULL;
    	}
    
    	printf("\nEND\n");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124

    CPeFileCheck.h

    /*!
    \file CPeFileCheck.h
    */
    
    #ifndef __CPEFILECHECK_H__
    #define __CPEFILECHECK_H__
    
    #include "my_openSSL_lib.h"
    #include 
    
    #ifndef BYTE_ORDER
    #define LITTLE_ENDIAN    1234
    #define BIG_ENDIAN       4321
    #define BYTE_ORDER       LITTLE_ENDIAN
    #endif /* BYTE_ORDER */
    
    #if BYTE_ORDER == BIG_ENDIAN
    #define LE_UINT16(x) ((((x) >> 8) & 0x00FF) | \
                         (((x) << 8) & 0xFF00))
    #define LE_UINT32(x) (((x) >> 24) | \
                         (((x) & 0x00FF0000) >> 8) | \
                         (((x) & 0x0000FF00) << 8) | \
                         ((x) << 24))
    #else
    #define LE_UINT16(x) (x)
    #define LE_UINT32(x) (x)
    #endif /* BYTE_ORDER == BIG_ENDIAN */
    
    #define SIZE_64K 65536       /* 2^16 */
    #define SIZE_16M 16777216    /* 2^24 */
    
    #define GET_UINT8_LE(p) ((const u_char *)(p))[0]
    
    #define GET_UINT16_LE(p) (uint16_t)(((const u_char *)(p))[0] | \
                                       (((const u_char *)(p))[1] << 8))
    
    #define GET_UINT32_LE(p) (uint32_t)(((const u_char *)(p))[0] | \
                                       (((const u_char *)(p))[1] << 8) | \
                                       (((const u_char *)(p))[2] << 16) | \
                                       (((const u_char *)(p))[3] << 24))
    
    #define PUT_UINT8_LE(i, p) ((u_char *)(p))[0] = (u_char)((i) & 0xff);
    
    #define PUT_UINT16_LE(i,p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); \
                               ((u_char *)(p))[1] = (u_char)(((i) >> 8) & 0xff)
    
    #define PUT_UINT32_LE(i,p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); \
                               ((u_char *)(p))[1] = (u_char)(((i) >> 8) & 0xff); \
                               ((u_char *)(p))[2] = (u_char)(((i) >> 16) & 0xff); \
                               ((u_char *)(p))[3] = (u_char)(((i) >> 24) & 0xff)
    
    class CPeFileCheck
    {
    public:
    	CPeFileCheck();
    	virtual ~CPeFileCheck();
    
    public:
    	bool PE_calc(const char* pszFilePathName);
    
    	bool get_PE_checkSum(DWORD& dwPECheckSumOrg, DWORD& dwPECheckSumCalc);
    	bool get_PE_Hash_SHA3_512(uint8_t** ppdata, int& len);
    
    private:
    	uint32_t get_file_size(const char* infile);
    	uint8_t* map_file(const char* infile, const size_t size);
    	void unmap_file(uint8_t* indata);
    
    	bool is_PE_format_ok();
    	bool calc_PE_checksum(DWORD& dwPeCheckSumCalc);
    	bool calc_hash_SHA3_512();
    
    private:
    	uint32_t m_u32_file_size;
    	uint8_t* m_pu8_map_file;
    	DWORD m_dwPeCheckSumOrg;
    	DWORD m_dwPeCheckSumCalc;
    
    	uint32_t m_header_size;
    	uint32_t m_pe32plus;
    	uint32_t m_magic;
    
    	uint32_t m_nrvas;
    	uint32_t m_sigpos;
    	uint32_t m_siglen;
    
    	unsigned int m_digest_length;
    	uint8_t m_ary_digest_value[1024];
    
    	bool m_b_calc_ok;
    };
    
    #endif // #ifndef __CPEFILECHECK_H__
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93

    CPeFileCheck.cpp

    //! \file CPeFileCheck.cpp
    
    #include "CPeFileCheck.h"
    #include 
    
    #include "my_openSSL_lib.h"
    #include 
    #include 
    
    #include 
    #include 
    #include 
    
    CPeFileCheck::CPeFileCheck()
    {
        m_u32_file_size = 0;
        m_pu8_map_file = NULL;
    
        m_dwPeCheckSumOrg = 0;
        m_dwPeCheckSumCalc = 0;
    
        m_header_size = 0;
        m_pe32plus = 0;
        m_magic = 0;
    
        m_nrvas = 0;
        m_sigpos = 0;
        m_siglen = 0;
    
        m_digest_length = 0;
        memset(m_ary_digest_value, 0, sizeof(m_ary_digest_value));
    
        m_b_calc_ok = false;
    }
    
    CPeFileCheck::~CPeFileCheck()
    {
        unmap_file(this->m_pu8_map_file);
    }
    
    bool CPeFileCheck::get_PE_checkSum(DWORD& dwPECheckSumOrg, DWORD& dwPECheckSumCalc)
    {
        dwPECheckSumOrg = this->m_dwPeCheckSumOrg;
        dwPECheckSumCalc = this->m_dwPeCheckSumCalc;
        return m_b_calc_ok;
    }
    
    bool CPeFileCheck::get_PE_Hash_SHA3_512(uint8_t** ppdata, int& len)
    {
        bool b_rc = false;
        do {
            if (NULL == ppdata)
            {
                break;
            }
    
            *ppdata = this->m_ary_digest_value;
            len = this->m_digest_length;
    
            b_rc = m_b_calc_ok;
        } while (false);
        return b_rc;
    }
    
    bool CPeFileCheck::PE_calc(const char* pszFilePathName)
    {
    	bool b_rc = false;
    
    	do {
    		if (NULL == pszFilePathName)
    		{
    			break;
    		}
    
            m_b_calc_ok = false;
    
            if (NULL != m_pu8_map_file)
            {
                unmap_file(m_pu8_map_file);
            }
    
            m_u32_file_size = get_file_size(pszFilePathName);
            m_pu8_map_file = map_file(pszFilePathName, m_u32_file_size);
            if (NULL == m_pu8_map_file)
            {
                break;
            }
    
            if (!is_PE_format_ok())
            {
                break;
            }
    
            if (!calc_PE_checksum(m_dwPeCheckSumCalc))
            {
                break;
            }
    
            if (!calc_hash_SHA3_512())
            {
                break;
            }
    
            m_b_calc_ok = true;
            b_rc = true;
    	} while (false);
    
    	return b_rc;
    }
    
    bool CPeFileCheck::calc_hash_SHA3_512()
    {
        //! \ref https://blog.csdn.net/LostSpeed/article/details/135581192
        
        bool b_rc = false;
    
        OSSL_LIB_CTX* _ossl_lib_ctx;
        int ret = 0;
        const char* _psz_option_properties = NULL;
        EVP_MD* _evp_md = NULL;
        EVP_MD_CTX* _evp_md_ctx = NULL;
        unsigned int digest_length;
        uint8_t* _p_digest_value = NULL;
    
        do {
            _ossl_lib_ctx = OSSL_LIB_CTX_new();
            if (NULL == _ossl_lib_ctx) {
                // fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
                break;
            }
    
            /*
             * Fetch a message digest by name
             * The algorithm name is case insensitive.
             * See providers(7) for details about algorithm fetching
             */
            _evp_md = EVP_MD_fetch(_ossl_lib_ctx,"SHA3-512", _psz_option_properties);
            if (NULL == _evp_md) {
                // fprintf(stderr, "EVP_MD_fetch could not find SHA3-512.");
                break;
            }
    
            /* Determine the length of the fetched digest type */
            digest_length = EVP_MD_get_size(_evp_md);
            if (digest_length <= 0) {
                // fprintf(stderr, "EVP_MD_get_size returned invalid size.\n");
                break;
            }
    
            _p_digest_value = (uint8_t*)OPENSSL_malloc(digest_length);
            if (_p_digest_value == NULL) {
                // fprintf(stderr, "No memory.\n");
                break;
            }
    
            /*
             * Make a message digest context to hold temporary state
             * during digest creation
             */
            _evp_md_ctx = EVP_MD_CTX_new();
            if (NULL == _evp_md_ctx) {
                // fprintf(stderr, "EVP_MD_CTX_new failed.\n");
                break;
            }
    
            /*
             * Initialize the message digest context to use the fetched
             * digest provider
             */
            if (EVP_DigestInit(_evp_md_ctx, _evp_md) != 1) {
                // fprintf(stderr, "EVP_DigestInit failed.\n");
                break;
            }
    
            /* Digest parts one and two of the soliloqy */
            if (EVP_DigestUpdate(_evp_md_ctx, this->m_pu8_map_file, this->m_u32_file_size) != 1) {
                // fprintf(stderr, "EVP_DigestUpdate(hamlet_1) failed.\n");
                break;
            }
    
            if (EVP_DigestFinal(_evp_md_ctx, _p_digest_value, &digest_length) != 1) {
                // fprintf(stderr, "EVP_DigestFinal() failed.\n");
                break;
            }
    
            // hash in _p_digest_value[], len = digest_length
            if (digest_length > sizeof(m_ary_digest_value))
            {
                assert(false);
                break;
            }
    
            m_digest_length = digest_length;
            memcpy(m_ary_digest_value, _p_digest_value, digest_length);
    
            b_rc = true;
        } while (false);
    
        // 咱这次做的openssl内存泄漏检查的措施挺NB的, 如果下面的指针判断写错了(e.g. if (NULL == _evp_md_ctx) { ... }), 导致内存泄漏, 程序结束时, 就能有断言:P
    
        /* OpenSSL free functions will ignore NULL arguments */
        if (NULL != _evp_md_ctx)
        {
            EVP_MD_CTX_free(_evp_md_ctx);
            _evp_md_ctx = NULL;
        }
        
        if (NULL != _p_digest_value)
        {
            OPENSSL_free(_p_digest_value);
            _p_digest_value = NULL;
        }
        
        if (NULL != _evp_md)
        {
            EVP_MD_free(_evp_md);
            _evp_md = NULL;
        }
        
        if (NULL != _ossl_lib_ctx)
        {
            OSSL_LIB_CTX_free(_ossl_lib_ctx);
            _ossl_lib_ctx = NULL;
        }
    
        return b_rc;
    }
    
    bool CPeFileCheck::is_PE_format_ok()
    {
        bool b_rc = false;
    
        do {
            if (0 != memcmp(m_pu8_map_file, "MZ", 2)) {
                break;
            }
    
            if (this->m_u32_file_size < 64) {
                // printf("Corrupt DOS file - too short\n");
                break;
            }
    
    		/* SizeOfHeaders field specifies the combined size of an MS-DOS stub, PE header,
             * and section headers rounded up to a multiple of FileAlignment.
             * SizeOfHeaders must be < filesize and cannot be < 0x0000002C (44) in Windows 7
             * because of a bug when checking section names for compatibility purposes */
    		m_header_size = GET_UINT32_LE(this->m_pu8_map_file + 60);
    		if (m_header_size < 44 || m_header_size > this->m_u32_file_size) {
    			// printf("Unexpected SizeOfHeaders field: 0x%08X\n", header_size);
                break;
    		}
    
            if (this->m_u32_file_size < m_header_size + 176) {
                // printf("Corrupt PE file - too short\n");
                break;
            }
    
            if (0 != memcmp(this->m_pu8_map_file + m_header_size, "PE\0\0", 4)) {
                // printf("Unrecognized DOS file type\n");
                break;
            }
    
            /* Magic field identifies the state of the image file. The most common number is
            * 0x10B, which identifies it as a normal executable file,
            * 0x20B identifies it as a PE32+ executable,
            * 0x107 identifies it as a ROM image (not supported) */
            m_magic = GET_UINT16_LE(this->m_pu8_map_file + m_header_size + 24);
            if (m_magic == 0x20b) {
                m_pe32plus = 1;
            }
            else if (m_magic == 0x10b) {
                m_pe32plus = 0;
            }
            else {
                // printf("Corrupt PE file - found unknown magic %04X\n", magic);
                break;
            }
    
            /* The image file checksum */
            this->m_dwPeCheckSumOrg = GET_UINT32_LE(this->m_pu8_map_file + m_header_size + 88);
    
            /* NumberOfRvaAndSizes field specifies the number of data-directory entries
             * in the remainder of the optional header. Each describes a location and size. */
            m_nrvas = GET_UINT32_LE(this->m_pu8_map_file + m_header_size + 116 + m_pe32plus * 16);
            if (m_nrvas < 5) {
                // printf("Can not handle PE files without certificate table resource\n");
                break;
            }
    
            /* Certificate Table field specifies the attribute certificate table address (4 bytes) and size (4 bytes) */
            m_sigpos = GET_UINT32_LE(this->m_pu8_map_file + m_header_size + 152 + m_pe32plus * 16);
            m_siglen = GET_UINT32_LE(this->m_pu8_map_file + m_header_size + 152 + m_pe32plus * 16 + 4);
    
            /* Since fix for MS Bulletin MS12-024 we can really assume
               that signature should be last part of file */
            if (((m_sigpos != 0) || (m_siglen != 0)) &&
                ((m_sigpos == 0) || (m_siglen == 0) || (m_sigpos >= this->m_u32_file_size) || ((m_sigpos + m_siglen) != this->m_u32_file_size))) {
                // printf("Ignoring PE signature not at the end of the file\n");
                m_sigpos = 0;
                m_siglen = 0;
            }
    
            b_rc = true;
        } while (false);
    
        return b_rc;
    }
    
    bool CPeFileCheck::calc_PE_checksum(DWORD& dwPeCheckSumCalc)
    {
        bool b_rc = false;
        uint32_t n = 0, checkSum = 0, offset = 0;
        BIO* bio = BIO_new(BIO_s_mem());
        uint8_t* buf = (uint8_t*)OPENSSL_malloc(SIZE_64K);
    
        do {
            dwPeCheckSumCalc = 0;
    
            /* calculate the checkSum */
            while (n < this->m_u32_file_size) {
                size_t i, written, nread;
                size_t left = m_u32_file_size - n;
                unsigned short val = 0;
    
                if (left > SIZE_64K)
                    left = SIZE_64K;
                if (!BIO_write_ex(bio, this->m_pu8_map_file + n, left, &written))
                {
                    break;
                }
    
                // 如果只想移动指针, 就用BIO_seek
                (void)BIO_seek(bio, 0);
                // BIO_reset(bio); // BIO_reset对于不是只读的BIO, 会清掉内容
    
                n += (uint32_t)written;
                if (!BIO_read_ex(bio, buf, written, &nread))
                {
                    break;
                }
    
                for (i = 0; i < nread / 2; i++) {
                    val = LE_UINT16(buf[i]);
                    if (offset == m_header_size + 88
                        || offset == m_header_size + 90) {
                        /* The image file checksum */
                        val = 0;
                    }
                    checkSum += val;
                    checkSum = LOWORD(LOWORD(checkSum) + HIWORD(checkSum));
                    offset += 2;
                }
            }
    
            checkSum = LOWORD(LOWORD(checkSum) + HIWORD(checkSum));
            checkSum += offset;
    
            dwPeCheckSumCalc = checkSum;
            b_rc = true;
        } while (false);
    
        if (NULL != buf)
        {
            OPENSSL_free(buf);
            buf = NULL;
        }
        
        if (NULL != bio)
        {
            BIO_free(bio);
            bio = NULL;
        }
        
        return b_rc;
    }
    
    uint32_t CPeFileCheck::get_file_size(const char* infile)
    {
        int ret = 0;
    
        struct _stat64 st;
        ret = _stat64(infile, &st); // 必须是全路径名称, 否则返回-1
    
        if (ret) {
            // printf("Failed to open file: %s\n", infile);
            return 0;
        }
    
        if (st.st_size < 4) {
            // printf("Unrecognized file type - file is too short: %s\n", infile);
            return 0;
        }
        if (st.st_size > UINT32_MAX) {
            // printf("Unsupported file - too large: %s\n", infile);
            return 0;
        }
    
        return (uint32_t)st.st_size;
    }
    
    uint8_t* CPeFileCheck::map_file(const char* infile, const size_t size)
    {
        uint8_t* indata = NULL;
    
        HANDLE fhandle, fmap;
        (void)size;
        fhandle = CreateFileA(infile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
        if (fhandle == INVALID_HANDLE_VALUE) {
            return NULL;
        }
        fmap = CreateFileMapping(fhandle, NULL, PAGE_READONLY, 0, 0, NULL);
        CloseHandle(fhandle);
        if (fmap == NULL) {
            return NULL;
        }
        indata = (uint8_t*)MapViewOfFile(fmap, FILE_MAP_READ, 0, 0, 0);
        CloseHandle(fmap);
    
        return indata;
    }
    
    void CPeFileCheck::unmap_file(uint8_t* indata)
    {
        if (!indata)
            return;
    
        UnmapViewOfFile(indata);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428

    END

  • 相关阅读:
    分库分表三:ShardingJDBC进阶实战案例下
    华为云云耀云服务器L实例评测 | 实例评测使用之硬件参数评测:华为云云耀云服务器下的监控 glances
    java最优建树算法
    java spring cloud 企业工程管理系统源码+二次开发+定制化服务
    SQL语句实现模糊查询
    博纳影业明日上市:于冬陷入与江疏影绯闻 被曝斥资千万买珠宝
    轻量封装WebGPU渲染系统示例<1>-彩色三角形(源码)
    ubuntu 18.04 OAK-D系列相机运行VINS-Fusion 双目+IMU
    字符串常用方法 --- 字符串对象的属性 与 字符串对象的方法(上)
    1688开放平台API接口获取商品详情信息
  • 原文地址:https://blog.csdn.net/LostSpeed/article/details/136352735