R-R, 发表于 2020-12-21 19:22

用C++写的无源码给VMP添加授权工具【开源】

//借用了<无源码给程序加VMProtect授权>https://www.52pojie.cn/thread-417452-1-1.html 的汇编代码
//支持多语言编译的exe不支持dll 和随机基址的exe



#include "stdafx.h"
#include "windows.h"


int GetPe(TCHAR* PeFileName, PVOID* FileBuffer){

        TCHAR* FileName = PeFileName;
        char* buf = nullptr;
        HANDLE hFile;
        DWORD dwFileSize;
        DWORD ReadSize = 0;

        hFile = CreateFile(
                FileName, GENERIC_READ,
                0,
                NULL,
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                NULL);

        dwFileSize = GetFileSize(hFile, NULL);
        buf = new char;
        ReadFile(hFile, buf, dwFileSize, &
                ReadSize, NULL);

        //by _ R-R,
        PIMAGE_DOS_HEADER pDosH = (PIMAGE_DOS_HEADER)buf;
        PIMAGE_NT_HEADERS32 pNtH = (PIMAGE_NT_HEADERS32)(buf + pDosH->e_lfanew);
        PIMAGE_FILE_HEADER pFh = (PIMAGE_FILE_HEADER)((DWORD)pNtH+ 4);
        PIMAGE_OPTIONAL_HEADER32 pOptH = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFh + IMAGE_SIZEOF_FILE_HEADER);

        if (pDosH->e_magic != IMAGE_DOS_SIGNATURE)
        {
                MessageBoxW(NULL, L"DOS头错误!", L"Error", MB_OK);
                CloseHandle(hFile);
                return 0;
        }
        if (pNtH->Signature != IMAGE_NT_SIGNATURE)
        {
                MessageBoxW(NULL, L"NT头错误!", L"Error", MB_OK);
                CloseHandle(hFile);
                return 0;
        }
        *FileBuffer = buf;
        buf = NULL;
        CloseHandle(hFile);
        return dwFileSize;


}



PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pPEHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_SECTION_HEADER pLastSection = NULL;


DWORD RVA_To_FOA(DWORD rva)
{

        int offset = 0;
        int i = 0;   
        if (rva<pOptionalHeader->SizeOfHeaders)
                return rva;
        PIMAGE_SECTION_HEADER ptempSection = pSectionHeader;
        for (i = 0; i <= pPEHeader->NumberOfSections; i++, ptempSection++)
        {
                if (rva >= ptempSection->VirtualAddress &&
                        rva <= (ptempSection->VirtualAddress + ptempSection->SizeOfRawData))
                        break;
        }

        if (i > pPEHeader->NumberOfSections)
        {
                return 0;
        }


        offset = rva - ptempSection->VirtualAddress;
        return ptempSection->PointerToRawData + offset;

}


int AddNec(PVOID OldBuf, DWORD OldSize, PVOID* NewBuf)
{

        //by _ R-R,
       
        const unsigned char CheckVmp[] =
        {
                0x33, 0xC9, 0x64, 0xA1, 0x30, 0x00, 0x00, 0x00,
                0x8B, 0x40, 0x0C, 0x8B, 0x70, 0x1C, 0x8B, 0x46,
                0x08, 0x8B, 0x7E, 0x20, 0x8B, 0x36, 0x66, 0x39,
                0x4F, 0x18, 0x75, 0xF2, 0x8B, 0xD0, 0x8B, 0x42,
                0x3C, 0x8B, 0x44, 0x10, 0x78, 0x03, 0xC2, 0x8B,
                0x70, 0x20, 0x03, 0xF2, 0x68, 0x73, 0x73, 0x00,
                0x00, 0x68, 0x64, 0x64, 0x72, 0x65, 0x68, 0x72,
                0x6F, 0x63, 0x41, 0x68, 0x47, 0x65, 0x74, 0x50,
                0x54, 0x33, 0xC9, 0x8B, 0x3E, 0x03, 0xFA, 0x56,
                0x8B, 0x74, 0x24, 0x04, 0x51, 0xB9, 0x0F, 0x00,
                0x00, 0x00, 0xF3, 0xA6, 0x74, 0x0B, 0x59, 0x5E,
                0x83, 0xC6, 0x04, 0x41, 0x3B, 0x48, 0x18, 0x72,
                0xE2, 0x59, 0x8B, 0x70, 0x24, 0x03, 0xF2, 0x0F,
                0xB7, 0x0C, 0x4E, 0x8B, 0x70, 0x1C, 0x03, 0xF2,
                0x8B, 0x34, 0x8E, 0x03, 0xF2, 0x8B, 0xFA, 0x6A,
                0x00, 0x68, 0x61, 0x72, 0x79, 0x41, 0x68, 0x4C,
                0x69, 0x62, 0x72, 0x68, 0x4C, 0x6F, 0x61, 0x64,
                0x54, 0x52, 0xFF, 0xD6, 0xE8, 0x0D, 0x00, 0x00,
                0x00, 0x6B, 0x65, 0x72, 0x6E, 0x65, 0x6C, 0x33,
                0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x5B, 0x53,
                0xFF, 0xD0, 0xE8, 0x19, 0x00, 0x00, 0x00, 0x47,
                0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74,
                0x65, 0x50, 0x72, 0x6F, 0x66, 0x69, 0x6C, 0x65,
                0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x41, 0x00,
                0x5B, 0x53, 0x50, 0xFF, 0xD6, 0xE8, 0x0A, 0x00,
                0x00, 0x00, 0x2E, 0x5C, 0x4B, 0x65, 0x79, 0x2E,
                0x69, 0x6E, 0x69, 0x00, 0x5B, 0x53, 0x68, 0x56,
                0x02, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00,
                0x5B, 0x83, 0xC3, 0x50, 0x53, 0x6A, 0x00, 0xE8,
                0x04, 0x00, 0x00, 0x00, 0x4C, 0x69, 0x63, 0x00,
                0x5B, 0x53, 0xE8, 0x09, 0x00, 0x00, 0x00, 0xCA,
                0xDA, 0xC8, 0xA8, 0xCE, 0xC4, 0xBC, 0xFE, 0x00,
                0x5B, 0x53, 0xFF, 0xD0, 0x8B, 0x44, 0x24, 0xF4,
                0xE8, 0x07, 0x00, 0x00, 0x00, 0x90, 0xFF, 0x25,
                0x11, 0x22, 0x33, 0x44, 0x90, 0x5B, 0x50, 0xFF,
                0xD3, 0x90, 0x68, 0x00, 0x10, 0x40, 0x00, 0xC3,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

        };

        //by _ R-R,
        PVOID buf = NULL;
        DWORD dwFileSize = OldSize;
        buf = OldBuf;

        DWORD New_file_size = dwFileSize + 0x1000;
        PVOID pNewTempBuffer = (PVOID)malloc(New_file_size);

        if (!pNewTempBuffer)
        {
                printf("pNewTempBuffer开辟空间失败!\n");
                return 0;
        }

        memset(pNewTempBuffer, 0, New_file_size);

        memcpy(pNewTempBuffer, buf, dwFileSize);


        pDosHeader = (PIMAGE_DOS_HEADER)(pNewTempBuffer);
        pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pNewTempBuffer + pDosHeader->e_lfanew);
        pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
        pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
        pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pPEHeader->SizeOfOptionalHeader);
       
        pLastSection = &pSectionHeader;


        DWORD Remained_size = (DWORD)(pOptionalHeader->SizeOfHeaders -
                pDosHeader->e_lfanew - 4 -
                sizeof(PIMAGE_FILE_HEADER) -
                pPEHeader->SizeOfOptionalHeader -
                sizeof(PIMAGE_SECTION_HEADER)*pPEHeader->NumberOfSections);

        if (Remained_size < 2 * sizeof(PIMAGE_SECTION_HEADER))
        {
                printf("exe文件头部剩余空间不足!\n");
                free(pNewTempBuffer);
                return 0;
        }


        PWORD pNumberOfSection = &pPEHeader->NumberOfSections;
        PDWORD pSizeOfImage = &pOptionalHeader->SizeOfImage;
       
        PVOID pSecName = &pSectionHeader.Name;

        PDWORD pSecMisc = &pSectionHeader.Misc.VirtualSize;
        PDWORD pSecVirtualAddress = &pSectionHeader.VirtualAddress;
        PDWORD pSecSizeofRawData = &pSectionHeader.SizeOfRawData;
        PDWORD pSecPointerToRawData = &pSectionHeader.PointerToRawData;
        PDWORD pSecCharacteristic = &pSectionHeader.Characteristics;

        *pNumberOfSection = pPEHeader->NumberOfSections + 1;


        *pSizeOfImage = pOptionalHeader->SizeOfImage + 0x1000;
        //by _ R-R,
        memcpy(pSecName, ".VMP", 8);
        *pSecMisc = 0x1000;
       

        DWORD add_size = pLastSection->Misc.VirtualSize > pLastSection->SizeOfRawData ?
                pLastSection->Misc.VirtualSize : pLastSection->SizeOfRawData;


        *pSecVirtualAddress = pLastSection->VirtualAddress + add_size;

        if (*pSecVirtualAddress % pOptionalHeader->SectionAlignment)
        {
                *pSecVirtualAddress = *pSecVirtualAddress / pOptionalHeader->SectionAlignment * pOptionalHeader->SectionAlignment + pOptionalHeader->SectionAlignment;
        }
        *pSecSizeofRawData = 0x1000;
        *pSecPointerToRawData = pLastSection->PointerToRawData + pLastSection->SizeOfRawData;

        if (*pSecPointerToRawData % pOptionalHeader->FileAlignment)
        {
                *pSecPointerToRawData = (*pSecPointerToRawData) / pOptionalHeader->FileAlignment * pOptionalHeader->FileAlignment + pOptionalHeader->FileAlignment;
        }
        *pSecCharacteristic = 0xE0000020;

        DWORD ImprotAddress = RVA_To_FOA(pOptionalHeader->DataDirectory.VirtualAddress);

        DWORD ImprotSize = pOptionalHeader->DataDirectory.Size;
        DWORD NewImportAddress = *pSecVirtualAddress;
       
        //by _ R-R,

        PCHAR DllName = "VMProtectSDK32.dll";
        PCHARFunctionName = "VMProtectSetSerialNumber";
        DWORD Newsize = sizeof(IMAGE_IMPORT_DESCRIPTOR) +
                sizeof(IMAGE_THUNK_DATA) +
                (sizeof(DllName) + 1) +
                (sizeof(FunctionName) + 1 + 2) +
                ImprotSize;

        PIMAGE_IMPORT_DESCRIPTOR pIMPORT = (PIMAGE_IMPORT_DESCRIPTOR)(((DWORD)pNewTempBuffer) + ImprotAddress);
        PBYTE Newsection = PBYTE((DWORD)pNewTempBuffer + *pSecPointerToRawData);

        memset(Newsection, 0, 0x1000);


               
        int i = 0;
        while (pIMPORT->FirstThunk != 0)
        {
                memcpy(Newsection, pIMPORT, sizeof(IMAGE_IMPORT_DESCRIPTOR));
                pIMPORT++;
                Newsection += sizeof(IMAGE_IMPORT_DESCRIPTOR);
                i++;
        }
       
        memcpy(Newsection, (Newsection - sizeof(IMAGE_IMPORT_DESCRIPTOR)), sizeof(IMAGE_IMPORT_DESCRIPTOR));
        DWORD NecRaw = *pSecPointerToRawData;
        DWORD NecRva = *pSecVirtualAddress;

        char hit = {0x00,0x01};

        memcpy(Newsection + (sizeof(IMAGE_IMPORT_DESCRIPTOR) * 2), DllName, strlen(DllName));
        memcpy(Newsection + (sizeof(IMAGE_IMPORT_DESCRIPTOR) * 2) + strlen(DllName) , hit, 2);
        memcpy(Newsection + (sizeof(IMAGE_IMPORT_DESCRIPTOR) * 2) + strlen(DllName) + 3, FunctionName, strlen(FunctionName));

        DWORD ThunkData = (((DWORD)(Newsection + (sizeof(IMAGE_IMPORT_DESCRIPTOR) * 2) + strlen(DllName) + 1)) -
                (DWORD)pNewTempBuffer) - NecRaw + NecRva;

        memcpy(Newsection + (sizeof(IMAGE_IMPORT_DESCRIPTOR) * 2) + strlen(DllName) + 3 + 8 + strlen(FunctionName), &ThunkData, 4);

        DWORD Ofts = (((DWORD)(Newsection + (sizeof(IMAGE_IMPORT_DESCRIPTOR) * 2) + strlen(DllName) + 3 + 8 + strlen(FunctionName))) -
                (DWORD)pNewTempBuffer) - NecRaw + NecRva;

        DWORD name = (((DWORD)(Newsection + (sizeof(IMAGE_IMPORT_DESCRIPTOR) * 2))) -
                (DWORD)pNewTempBuffer) - NecRaw + NecRva;

        memcpy(Newsection, &Ofts, 4);
        memcpy(Newsection + 16, &Ofts, 4);
        memcpy(Newsection + 12, &name, 4);

        PBYTE ShellAddress = Newsection + (sizeof(IMAGE_IMPORT_DESCRIPTOR) * 2) + strlen(DllName) + 3 + 8 + strlen(FunctionName) + 100;
        memcpy(ShellAddress, CheckVmp, sizeof(CheckVmp));
               
       
        DWORD NewOep = (DWORD)ShellAddress - (DWORD)pNewTempBuffer - NecRaw + NecRva;
       
        DWORD OldOep = pOptionalHeader->AddressOfEntryPoint + pOptionalHeader->ImageBase;
        printf("%s\n%x", "原始OEP地址,可作为保护代码", OldOep);
        DWORD VMPset = Ofts + pOptionalHeader->ImageBase;
       
        memcpy(ShellAddress + 272, &VMPset,4);
        memcpy(ShellAddress + 283, &OldOep, 4);
        pOptionalHeader->AddressOfEntryPoint = NewOep;
        pOptionalHeader->DataDirectory.Size = pOptionalHeader->DataDirectory.Size + 8;
        pOptionalHeader->DataDirectory.VirtualAddress = NewImportAddress;
       
        //by _ R-R,


        *NewBuf = pNewTempBuffer;
        pNewTempBuffer = NULL;
        return New_file_size;

}





void Write(PVOID wBuf,DWORD wSize){

        PVOID Wbuffer = NULL;
        DWORD wbSize = 0;
        Wbuffer = wBuf;
        wbSize = wSize;

        //by _ R-R,
        HANDLE hFile2 = CreateFile(
                _T(".\\2.exe"), GENERIC_WRITE | GENERIC_READ,
                0,
                NULL,
                CREATE_ALWAYS,
                FILE_ATTRIBUTE_NORMAL,
                NULL);

        DWORD WriteSize = 0;
        WriteFile(hFile2, Wbuffer, wbSize, &WriteSize, NULL);
        CloseHandle(hFile2);
}


int _tmain(int argc, _TCHAR* argv[])
{
       
       
        TCHAR *PePatch = _T(".\\1.exe");
        DWORD OldFileSize = 0;
        PVOID OldFileBuf = NULL;
        //by _ R-R,
        OldFileSize = GetPe(PePatch, &OldFileBuf);
    PVOID NewBuffer = NULL;
        DWORD NewSize = 0;
        NewSize =AddNec(OldFileBuf, OldFileSize, &NewBuffer);
        Write(NewBuffer, NewSize);

        getchar();
        return 0;
}

ianlcc 发表于 2023-9-6 11:04

测试了好几天…自己的exe一直无法授权
就连运行vmpro所得到的oep码,输入vmprotect,找不到这个进程oep
觉得很奇怪
后来随便弄了一个exe档後,就可以正常使用了
我的电脑是windowns 10、vmprotect测试版本是3.6
不过,我发现有一个问题
如果我在“添加授权”这个步骤,若是勾选使用次数5次的话
运行2.vmp.exe超过5次,还可以正常使用

submariner 发表于 2022-6-23 17:17

测试了一下,VMP3.5版本,可以使用,但最高只能使用RSA3072算法;超过3072后,会始终认为无序列号或者序列号不正确(也许是序列号长度超过楼主的预期?希望楼主能修复这个问题)

hszt 发表于 2020-12-21 19:38

不错,感谢分享

GhostTest 发表于 2020-12-21 20:04

虽然不懂,但是肯定狠厉害。:lol

hackysh 发表于 2020-12-22 00:03

虽然不懂,但是肯定狠厉害。

张哥哥 发表于 2020-12-22 00:03

很不错,收藏了。。。

拉玛西亚 发表于 2020-12-22 00:35

都能给什么文件添加授权

键盘 发表于 2020-12-22 07:56

厉害是厉害,但为啥你要一行一行的复制粘贴:Dweeqw。看着好别扭。哈哈哈哈哈哈哈

jy04468108 发表于 2020-12-22 08:41

支持哪些版本的VMP啊?

R-R, 发表于 2020-12-22 09:39

键盘 发表于 2020-12-22 07:56
厉害是厉害,但为啥你要一行一行的复制粘贴。看着好别扭。哈哈哈哈哈哈哈

因为读取key文件不支持换行符

错的是世界 发表于 2020-12-22 10:17

R-R, 发表于 2020-12-22 09:39
因为读取key文件不支持换行符

批量替换换行符了解下{:1_918:}
页: [1] 2 3 4 5 6
查看完整版本: 用C++写的无源码给VMP添加授权工具【开源】