吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 12640|回复: 51
收起左侧

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

  [复制链接]
R-R, 发表于 2020-12-21 19:22
//借用了  <无源码给程序加VMProtect授权>https://www.52pojie.cn/thread-417452-1-1.html 的汇编代码
//支持多语言编译的exe  不支持dll 和随机基址的exe

[Asm] 纯文本查看 复制代码

#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[dwFileSize];
	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[pPEHeader->NumberOfSections - 1];


	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[pPEHeader->NumberOfSections].Name;

	PDWORD pSecMisc = &pSectionHeader[pPEHeader->NumberOfSections].Misc.VirtualSize;
	PDWORD pSecVirtualAddress = &pSectionHeader[pPEHeader->NumberOfSections].VirtualAddress;
	PDWORD pSecSizeofRawData = &pSectionHeader[pPEHeader->NumberOfSections].SizeOfRawData;
	PDWORD pSecPointerToRawData = &pSectionHeader[pPEHeader->NumberOfSections].PointerToRawData;
	PDWORD pSecCharacteristic = &pSectionHeader[pPEHeader->NumberOfSections].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[1].VirtualAddress);

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

	PCHAR DllName = "VMProtectSDK32.dll";
	PCHAR  FunctionName = "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[2] = {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[1].Size = pOptionalHeader->DataDirectory[1].Size + 8;
	pOptionalHeader->DataDirectory[1].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;
}

步骤2

步骤2

步骤1

步骤1

VMPro编译好的.zip

5.03 KB, 下载次数: 501, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 9吾爱币 +15 热心值 +7 收起 理由
wuaiwu77 + 1 鼓励转贴优秀软件安全工具和文档!
maxism + 1 热心回复!
xiangzz + 1 + 1 自己建的key.ini不行呢,输入注册码后还是提示。生成的时候没有异常
yingfeng + 1 + 1 我很赞同!
antiol + 3 + 1 我很赞同!
twog + 1 + 1 谢谢@Thanks!
朱朱你堕落了 + 3 + 1 看不懂也不妨碍评分!
wmsuper + 3 + 1 用心讨论,共获提升!
hszt + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

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
虽然不懂,但是肯定狠厉害。
hackysh 发表于 2020-12-22 00:03
虽然不懂,但是肯定狠厉害。
张哥哥 发表于 2020-12-22 00:03
很不错,收藏了。。。
拉玛西亚 发表于 2020-12-22 00:35
都能给什么文件添加授权
键盘 发表于 2020-12-22 07:56
厉害是厉害,但为啥你要一行一行的复制粘贴。看着好别扭。哈哈哈哈哈哈哈
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文件不支持换行符

批量替换换行符了解下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-21 18:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表