吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6624|回复: 63
上一主题 下一主题
收起左侧

[Packers] 一个比较完整稳定的VMP授权添加工具,有码。

  [复制链接]
跳转到指定楼层
楼主
R-R, 发表于 2024-1-12 19:34 回帖奖励
<0>这是一个还算完整的VMP添加授权工具,比之前开源的版本修复了稳定性和不便性。和支持DLL。
<1>首先打开VMP_LIC工具如下图,然后选择要加密的文件。

<2>选择可执行文件后,目录下会多出一个new.exe或者dll的修改文件,目录下的VMSDK是在vmp目录下的 因为不加密的话打不开加密后的文件,
需要放置dll进去,加密后可以不需要这个vmpsdk的dll了,VMProtectSDK32.dll可以在论坛里面的3.x里面获取
可以看到下图,我构建了一段汇编,在里面添加了
VMProtectSetSerialNumber函数,并用PEB+0x500的地址作为参数用来传递key,这样做的好处是我可以写一个dll,dll用来获取机器码和key,
然后把key的地址放到PEB+0X500传进去,这样就达到了一键授权。

<3>再得到new.exe后用vmp加密,加密时锁定原来的oep,也可以自己添加任意地址锁定序列号。如下图

<4>这样加密后序列号锁定了,但由于没有获取到机器码和置入序列号,以下代码是一个获取机器码和置入序列号简版,你们可以用来修改。
[C++] 纯文本查看 复制代码
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include "VMProtectSDK.h"
#pragma comment(lib, "VMProtectSDK32.lib")

char ** LicAddr = NULL;

void __stdcall GetFs()
{
	__asm
	{
		mov eax, dword ptr fs : [0x30]
		lea eax, dword ptr ds : [eax + 0x500]
		mov LicAddr, eax;
	}

}

void ReadLicense()
{
	HANDLE hLicFile = CreateFileA("License.Lic", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
	if (INVALID_HANDLE_VALUE == hLicFile)
	{
		MessageBoxA(NULL, "Lic文件出错!", "Error", MB_OK);
	}
	DWORD LicSize;
	LicSize = GetFileSize(hLicFile, NULL);
	if (0 == LicSize)
	{
		MessageBoxA(NULL, "Lic文件内容为空!", "Error", MB_OK);
	}
	char* LicBuf = new char[LicSize + 1];
	DWORD ReadSize;
	ReadFile(hLicFile, LicBuf, LicSize, &ReadSize, NULL);
	CloseHandle(hLicFile);
	GetFs();
	*LicAddr = LicBuf;
}


void GetHwid_()
{
	DWORD HwidSize = VMProtectGetCurrentHWID(NULL, 0);
	char * HwidStr = new char[HwidSize + 1];
	VMProtectGetCurrentHWID(HwidStr, HwidSize);
	MessageBoxA(NULL, HwidStr, "机器码", MB_OK);
	ReadLicense();
}

BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
	)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		GetHwid_();
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}




<5>代码里面的VMProtectSDK.h和VMProtectSDK32.lib 都可以再论坛的VMP3.X里面获取得到,dll编译出来后需要加密以下,因为调用了vmp的sdk,需要加密来获取机器码,
再加密的时候,保护选项全部选否,这个可以只加密一次,因为这个只是获取机器码和置入key的工具,如下图,

<6>在dll弄好之后,可以用vmp的dllbox来封装他,如果你不喜欢有外置dll来获取机器码那些,这样就达到了对exe或dll加密后仍然是一个单文件的形式,
在放置dll进去的时候选择启动时载入,如下图

<7>加密出来后就是一个单文件的new.vmp.exe了,当你运行时会弹出机器码,没有key时会写出License.Lic文件,
你在vmp里面算号后把key放入License.Lic里即可(KEY不要有换行符)
如下图

<8>主程序代码如下,是控制台代码,我编译了一份MFC的程序。
[C++] 纯文本查看 复制代码
// Lic.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "windows.h"
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")

#define AddSize 0x20000


unsigned char OepData[0x0042] =
{
	0xeb, 0x10, 0x56, 0x4d, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x20, 0x62, 0x65, 0x67, 0x69,
	0x6e, 0x00, 0x60, 0x9c, 0x64, 0xa1, 0x30, 0x00, 0x00, 0x00, 0x8b, 0x80, 0x00, 0x05, 0x00, 0x00,
	0x83, 0xf8, 0x00, 0x74, 0x07, 0x50, 0xff, 0x15, 0x33, 0x71, 0x4b, 0x00, 0x9d, 0x61, 0xe9, 0xda,
	0x55, 0xfa, 0xff, 0xeb, 0x0e, 0x56, 0x4d, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x20, 0x65,
	0x6e, 0x64
};

DWORD rva2offset(LPVOID base, DWORD rva)
{
	IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)base;
	IMAGE_NT_HEADERS32* ntHeader = (IMAGE_NT_HEADERS32*)(dosHeader->e_lfanew + (DWORD)base);
	IMAGE_SECTION_HEADER* sectionHeader = (IMAGE_SECTION_HEADER*)((DWORD)ntHeader + sizeof(IMAGE_NT_HEADERS32));
	if (rva<ntHeader->OptionalHeader.SizeOfHeaders)
	{
		return rva;
	}
	for (DWORD i = 1; i <= ntHeader->FileHeader.NumberOfSections; i++)
	{
		
		if (i == ntHeader->FileHeader.NumberOfSections)
		{
			return rva - sectionHeader->VirtualAddress + sectionHeader->PointerToRawData;
		}
		else if (rva >= sectionHeader->VirtualAddress && rva < (sectionHeader + 1)->VirtualAddress)
		{
			return rva - sectionHeader->VirtualAddress + sectionHeader->PointerToRawData;
		}
		sectionHeader++;
	}
	return 0;
}

DWORD AddImprot(char *ModulePath)
{


	HANDLE hFile = CreateFileA(ModulePath, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == 0 || hFile == INVALID_HANDLE_VALUE)
	{
		return 0;
	}
	DWORD fileSize = GetFileSize(hFile, 0);
	char* buf = new char[fileSize];
	DWORD ReadSize;
	ReadFile(hFile, buf, fileSize, &ReadSize, NULL);
	CloseHandle(hFile);

	DWORD New_File_Size = fileSize + AddSize;
	PVOID pNewTempBuffer = (PVOID)malloc(New_File_Size);
	memset(pNewTempBuffer, 0, New_File_Size);
	memcpy(pNewTempBuffer, buf, fileSize);

	PIMAGE_NT_HEADERS32 ntHeader = (PIMAGE_NT_HEADERS32)((DWORD)pNewTempBuffer + ((PIMAGE_DOS_HEADER)(pNewTempBuffer))->e_lfanew);
	if ((ntHeader->FileHeader.NumberOfSections + 1)*sizeof(IMAGE_SECTION_HEADER)>ntHeader->OptionalHeader.SizeOfHeaders)
	{
		printf("剩余空间不足.");
		return 0;
	}

	
	PIMAGE_SECTION_HEADER newSection = (PIMAGE_SECTION_HEADER)(ntHeader + 1) + ntHeader->FileHeader.NumberOfSections;
	memcpy(newSection->Name, "VMPLic", 8); 
	newSection->Characteristics = 0xE0000020;
	newSection->Misc.VirtualSize = AddSize;
	newSection->NumberOfLinenumbers = 0;
	newSection->NumberOfRelocations = 0;
	newSection->PointerToLinenumbers = 0;
	newSection->PointerToRelocations = 0;
	newSection->SizeOfRawData = AddSize;

	DWORD NewAddSize = (newSection - 1)->Misc.VirtualSize > (newSection - 1)->SizeOfRawData ?
		(newSection - 1)->Misc.VirtualSize : (newSection - 1)->SizeOfRawData;

	newSection->VirtualAddress = (newSection - 1)->VirtualAddress + NewAddSize;
	if (newSection->VirtualAddress % ntHeader->OptionalHeader.SectionAlignment)
	{
		newSection->VirtualAddress = newSection->VirtualAddress / ntHeader->OptionalHeader.SectionAlignment *
			ntHeader->OptionalHeader.SectionAlignment + ntHeader->OptionalHeader.SectionAlignment;
	}
	newSection->PointerToRawData = (newSection - 1)->PointerToRawData + (newSection - 1)->SizeOfRawData;
	if (newSection->PointerToRawData  % ntHeader->OptionalHeader.FileAlignment)
	{
		newSection->PointerToRawData = newSection->PointerToRawData / ntHeader->OptionalHeader.FileAlignment *
			ntHeader->OptionalHeader.FileAlignment + ntHeader->OptionalHeader.FileAlignment;
	}


	DWORD ImprotAddress = rva2offset(pNewTempBuffer, ntHeader->OptionalHeader.DataDirectory[1].VirtualAddress);
	DWORD ImprotSize = ntHeader->OptionalHeader.DataDirectory[1].Size;


	char* DLLname = "VMProtectSDK32.dll";
	char* FunctionName = "VMProtectSetSerialNumber";


	memcpy(PVOID((DWORD)pNewTempBuffer + fileSize), PVOID((DWORD)pNewTempBuffer + ImprotAddress), ImprotSize);


	PIMAGE_IMPORT_DESCRIPTOR AddIMpoetAddr = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pNewTempBuffer + fileSize + ImprotSize - sizeof(IMAGE_IMPORT_DESCRIPTOR));


	AddIMpoetAddr->OriginalFirstThunk = newSection->VirtualAddress + ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR) + strlen(DLLname) + 1;
	AddIMpoetAddr->FirstThunk = AddIMpoetAddr->OriginalFirstThunk + sizeof(IMAGE_THUNK_DATA32) * 2;
	AddIMpoetAddr->ForwarderChain = 0;
	AddIMpoetAddr->Name = newSection->VirtualAddress + ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR);
	AddIMpoetAddr->TimeDateStamp = 0;



	memcpy((PVOID)((DWORD)pNewTempBuffer + fileSize + ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR)), DLLname, strlen(DLLname) + 1);
	memcpy((PVOID)((DWORD)pNewTempBuffer + fileSize + ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR) + strlen(DLLname) + 1 + 101 + 2), FunctionName, strlen(FunctionName) + 1);
	DWORD ByName = newSection->VirtualAddress + ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR) + strlen(DLLname) + 1 + 101;

	DWORD* OFT = PDWORD((DWORD)pNewTempBuffer + fileSize + ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR) + strlen(DLLname) + 1);
	DWORD* IAT = PDWORD((DWORD)pNewTempBuffer + fileSize + ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR) + strlen(DLLname) + 1 + sizeof(IMAGE_THUNK_DATA32) * 2);

	*OFT = ByName;
	*IAT = ByName;


	ntHeader->FileHeader.NumberOfSections++;
	ntHeader->OptionalHeader.SizeOfImage += AddSize;



	DWORD NewOep = newSection->VirtualAddress + ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR) + strlen(DLLname) + 1 + 101 + 200;
	memcpy(PVOID((DWORD)pNewTempBuffer + fileSize + ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR) + strlen(DLLname) + 1 + 101 + 200), OepData, 0x42);


	PDWORD CallIat = PDWORD((DWORD)pNewTempBuffer + fileSize + ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR) + strlen(DLLname) + 1 + 101 + 200 + 0x28);
	DWORD C_value = AddIMpoetAddr->FirstThunk + ntHeader->OptionalHeader.ImageBase;
	*CallIat = C_value;


	PDWORD JmpOep = PDWORD((DWORD)pNewTempBuffer + fileSize + ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR) + strlen(DLLname) + 1 + 101 + 200 + 0x2F);
	DWORD J_value = ntHeader->OptionalHeader.AddressOfEntryPoint -
		(newSection->VirtualAddress + ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR) + strlen(DLLname) + 1 + 101 + 200 + 0x2F) - 4;
	*JmpOep = J_value;


	ntHeader->OptionalHeader.AddressOfEntryPoint = NewOep;


	ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
	ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;

	ntHeader->OptionalHeader.DataDirectory[1].VirtualAddress = newSection->VirtualAddress;
	ntHeader->OptionalHeader.DataDirectory[1].Size = ImprotSize + sizeof(IMAGE_IMPORT_DESCRIPTOR);;

	if (0 != ntHeader->OptionalHeader.DataDirectory[1].VirtualAddress)
	{

		DWORD RelocAddr = rva2offset(pNewTempBuffer, ntHeader->OptionalHeader.DataDirectory[5].VirtualAddress);
		DWORD RelocSize = ntHeader->OptionalHeader.DataDirectory[5].Size;

		memcpy(PVOID((DWORD)pNewTempBuffer + fileSize + ImprotSize + 1000), PVOID((DWORD)pNewTempBuffer + RelocAddr), RelocSize);

		ntHeader->OptionalHeader.DataDirectory[5].VirtualAddress = newSection->VirtualAddress + +ImprotSize + 1000;
		ntHeader->OptionalHeader.DataDirectory[5].Size = ntHeader->OptionalHeader.DataDirectory[5].Size;

		DWORD* RelocBase = PDWORD((DWORD)pNewTempBuffer + fileSize + ImprotSize + 1000 + ntHeader->OptionalHeader.DataDirectory[5].Size);
		*RelocBase = newSection->VirtualAddress;
		*(RelocBase + 1) = 0xC;
		*(PWORD(RelocBase + 2)) = NewOep + 0x28 - newSection->VirtualAddress + 0x3000;
		ntHeader->OptionalHeader.DataDirectory[5].Size += 0xC;

	}


	char* newFileName = (ntHeader->FileHeader.Characteristics & IMAGE_FILE_DLL) ? "New.dll" : "New.exe";
	CHAR parentPath[MAX_PATH];
	CHAR newPath[MAX_PATH];
	PathRemoveFileSpecA(ModulePath);
	lstrcpyA(parentPath, ModulePath);
	PathCombineA(newPath, parentPath, newFileName);

	HANDLE hFile2 = CreateFileA(
		newPath, GENERIC_WRITE | GENERIC_READ,
		0,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	DWORD WriteSize = 0;
	WriteFile(hFile2, pNewTempBuffer, New_File_Size, &WriteSize, NULL);
	CloseHandle(hFile2);

}

int main(int argc, char *argv[])
{
	char * filepath = argv[1];
	AddImprot(filepath);
	return 0;
}


<9>大致总结,虽然我说了这么多,但使用起来应该很简单,
第一步:用VMP_LIC选择要加密的文件,然后写出new.exe的新文件后,放到vmp里加密,加密时要初始化授权,然后锁定源程序oep。
第二步:把dll编译好如我上加密后可以一只使用这个dll,你可以任意修改这个dll,甚至加上sdk等。
第三步:dll导入进去选择启动时载入,很简单的三步,其实很方便,在源代码的基础上也可以任意修改。
当然,也可以根据这个思路写一份x64的版本。
以下是我用MFC编译的主程序,其他的没什么了。

VMP_LIC.rar

1.32 MB, 下载次数: 340, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 15吾爱币 +27 热心值 +14 收起 理由
xiaoweng + 1 + 1 真的太牛了!
北城。 + 1 桥桥你挑粪去了啊
david891024 + 1 + 1 我很赞同!
cxn1ce + 1 + 1 谢谢@Thanks!
Hmily + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
zhczf + 1 + 1 我很赞同!
hunfeifei + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
fangchang819 + 1 + 1 谢谢@Thanks!
doublet + 1 + 1 我很赞同!
Hou + 1 + 1 谢谢@Thanks!
秋名山 + 1 + 1 谢谢@Thanks!
杨辣子 + 1 + 1 谢谢@Thanks!
Monitor + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
凉游浅笔深画眉 + 3 + 1 又学到一招
朱朱你堕落了 + 3 + 1 高清无码!错了,有高清有码!

查看全部评分

本帖被以下淘专辑推荐:

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

推荐
zhaode 发表于 2024-1-15 21:22
不错的教程     谢谢                                                
推荐
ianlcc 发表于 2024-1-15 12:34
很感谢楼主的分享!
这样子让没有源码的人可以试着用这个方式达到一机一码的方式…
希望有人可以分享一下创建的vmp.dll for x86&x64
沙发
95877133 发表于 2024-1-12 19:39
3#
HUHU666 发表于 2024-1-12 20:00
这个软件非常好!
4#
ssw12500 发表于 2024-1-12 20:04
感谢大佬分享
5#
Hou 发表于 2024-1-12 20:36
请教一下安全性如何?
6#
yuangao 发表于 2024-1-12 20:39
这样干, 就是文件很大..
7#
CQGaxm 发表于 2024-1-12 20:40
感谢分享,不错的教程
8#
lies2014 发表于 2024-1-12 20:44
谢谢分享!
9#
95877133 发表于 2024-1-12 21:00
有脱vmp的教程吗
10#
yaoguen 发表于 2024-1-12 21:00
多谢分享,希望支持x64
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

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

GMT+8, 2024-4-28 21:55

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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