UltraDebug

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: A C D R G Y M Z X S P
公益项目,接受捐赠
查看: 1087|回复: 0
收起左侧

[加壳脱壳] 完整稳定的VMP授权添加工具

[复制链接]
0632955255184

主题

0

回帖

UD

新手上路

UID
360
积分
16
注册时间
2024-3-15
最后登录
1970-1-1
2025-1-10 20:45:51 | 显示全部楼层 |阅读模式
<0>这是一个还算完整的VMP添加授权工具,比之前开源的版本修复了稳定性和不便性。和支持DLL。
<1>首先打开VMP_LIC工具如下图,然后选择要加密的文件。
完整稳定的VMP授权添加工具 - 0632955255184_UltraDebug

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

<3>再得到new.exe后用vmp加密,加密时锁定原来的oep,也可以自己添加任意地址锁定序列号。如下图
完整稳定的VMP授权添加工具 - 0632955255184_UltraDebug

<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;
}
SyntaxHighlighter Copyright 2004-2013 Alex Gorbatchev.
<5>代码里面的VMProtectSDK.h和VMProtectSDK32.lib 都可以再论坛的VMP3.X里面获取得到,dll编译出来后需要加密以下,因为调用了vmp的sdk,需要加密来获取机器码,
再加密的时候,保护选项全部选否,这个可以只加密一次,因为这个只是获取机器码和置入key的工具,如下图,
完整稳定的VMP授权添加工具 - 0632955255184_UltraDebug

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

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

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

VMP_LIC.rar

1.32 MB, 下载次数: 1, 下载积分: UD -2

UltraDebug免责声明
✅以上内容均来自网友转发或原创,如存在侵权请发送到站方邮件9003554@qq.com处理。
✅The above content is forwarded or original by netizens. If there is infringement, please send the email to the destination 9003554@qq.com handle.
回复 打印

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|站点地图|UltraDebug ( 滇ICP备2022002049号-2 滇公网安备 53032102000034号)

GMT+8, 2025-6-18 07:19 , Processed in 0.036838 second(s), 10 queries , Redis On.

Powered by Discuz X3.4

© 2001-2023 Discuz! Team.

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