吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 12645|回复: 53
收起左侧

[原创工具] 给破解的程序加一个验证

[复制链接]
我是人民币 发表于 2015-7-25 17:00
写在前面:破解程序没错,转卖就会牵扯到相关的法律问题,出了问题与本人无关。这篇帖子仅供爱好者参考和学习。
我看不少破解者需要就放出来了。

主要功能就是在目标程序内添加一段Shell,然后加载DLL。Shell通过DLL的某导出函数反馈的结果来决定当前程序是否继续执行来达到验证的效果。
先满足伸手党的胃口,后面说原理性的东西:
AddVerify.zip (4.7 KB, 下载次数: 176) 成品 AddVerify.exe。
上面这个程序就是关键了,运行 AddVerify.exe。选择已经破解的程序,选择后, AddVerify.exe会一闪而过然后退出, 这说明你破解的程序已经处理完毕了。
然后用任意编译型编程语言(易语言/C++等) 写一个DLL ,命名为 DataCore.dll。
DataCore.dll 有一个导出函数,名字为:verify,无参数。
AddVerify.exe处理后的程序会自动加载DataCore.dll,并调用verify函数。 如果verify返回1,被破解的程序就会继续跑,返回0就退出。 你可以在verify添加网络验证,本地验证什么的。
p1.jpg
看看DLL的关键部分吧:
p2.jpg


然后你可以给处理好的程序加一些壳,来保护你的劳动成果,嘻嘻!

好了,伸手党们可以把当前页面给关了。
下面我们来谈谈原理:
AddVerify.exe 的代码比较简单,主要是在PE文件中新建一个节表,然后把Shell写入。
[C++] 纯文本查看 复制代码
#include <windows.h>
#include "pe.h"
unsigned char data[428] = {
	0xE9, 0xA2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x65, 0x74, 0x4D, 0x6F, 0x64, 0x75, 
	0x6C, 0x65, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x41, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 
	0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x00, 0x4B, 0x65, 0x72, 0x6E, 0x65, 0x6C, 0x33, 0x32, 0x2E, 
	0x64, 0x6C, 0x6C, 0x00, 0x4C, 0x6F, 0x61, 0x64, 0x4C, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x41, 
	0x00, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6F, 0x72, 0x65, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x45, 0x78, 
	0x69, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x00, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 
	0x00, 0x55, 0x8B, 0xEC, 0x83, 0xC4, 0xF8, 0x60, 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x8B, 
	0x7D, 0x0C, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0x32, 0xC0, 0xFC, 0xF2, 0xAE, 0x8B, 0xCF, 0x2B, 0x4D, 
	0x0C, 0x89, 0x4D, 0xF8, 0x8B, 0x75, 0x08, 0x03, 0x76, 0x3C, 0x8B, 0x76, 0x78, 0x03, 0x75, 0x08, 
	0x8B, 0x5E, 0x20, 0x03, 0x5D, 0x08, 0x33, 0xD2, 0x56, 0x8B, 0x3B, 0x03, 0x7D, 0x08, 0x8B, 0x75, 
	0x0C, 0x8B, 0x4D, 0xF8, 0xF3, 0xA6, 0x75, 0x03, 0x5E, 0xEB, 0x0C, 0x5E, 0x83, 0xC3, 0x04, 0x42, 
	0x3B, 0x56, 0x18, 0x72, 0xE3, 0xEB, 0x22, 0x2B, 0x5E, 0x20, 0x2B, 0x5D, 0x08, 0xD1, 0xEB, 0x03, 
	0x5E, 0x24, 0x03, 0x5D, 0x08, 0x0F, 0xB7, 0x03, 0xC1, 0xE0, 0x02, 0x03, 0x46, 0x1C, 0x03, 0x45, 
	0x08, 0x8B, 0x00, 0x03, 0x45, 0x08, 0x89, 0x45, 0xFC, 0x61, 0x8B, 0x45, 0xFC, 0xC9, 0xC2, 0x08, 
	0x00, 0x64, 0xA1, 0x30, 0x00, 0x00, 0x00, 0x8B, 0x40, 0x0C, 0x8B, 0x70, 0x1C, 0xAD, 0x8B, 0x40, 
	0x08, 0xC3, 0x55, 0x8B, 0xEC, 0x83, 0xC4, 0xDC, 0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5B, 0x81, 
	0xEB, 0xFE, 0x10, 0x40, 0x00, 0x89, 0x5D, 0xF4, 0xE8, 0xD4, 0xFF, 0xFF, 0xFF, 0x89, 0x45, 0xFC, 
	0x8D, 0x83, 0x09, 0x10, 0x40, 0x00, 0x50, 0xFF, 0x75, 0xFC, 0xE8, 0x42, 0xFF, 0xFF, 0xFF, 0x89, 
	0x45, 0xF0, 0x8D, 0x83, 0x27, 0x10, 0x40, 0x00, 0x50, 0xFF, 0x55, 0xF0, 0x89, 0x45, 0xF8, 0x8D, 
	0x83, 0x1A, 0x10, 0x40, 0x00, 0x50, 0xFF, 0x75, 0xF8, 0xE8, 0x23, 0xFF, 0xFF, 0xFF, 0x89, 0x45, 
	0xEC, 0x8D, 0x83, 0x34, 0x10, 0x40, 0x00, 0x50, 0xFF, 0x75, 0xF8, 0xE8, 0x11, 0xFF, 0xFF, 0xFF, 
	0x89, 0x45, 0xE8, 0x8D, 0x83, 0x4E, 0x10, 0x40, 0x00, 0x50, 0xFF, 0x75, 0xF8, 0xE8, 0xFF, 0xFE, 
	0xFF, 0xFF, 0x89, 0x45, 0xE4, 0x8D, 0x83, 0x41, 0x10, 0x40, 0x00, 0x50, 0xFF, 0x55, 0xE8, 0x89, 
	0x45, 0xE0, 0x83, 0xF8, 0x00, 0x74, 0x2B, 0x8D, 0x83, 0x5A, 0x10, 0x40, 0x00, 0x50, 0xFF, 0x75, 
	0xE0, 0xE8, 0xDB, 0xFE, 0xFF, 0xFF, 0x83, 0xF8, 0x00, 0x74, 0x17, 0x89, 0x45, 0xDC, 0xFF, 0x55, 
	0xDC, 0x83, 0xF8, 0x01, 0x75, 0x0C, 0x8B, 0x83, 0x05, 0x10, 0x40, 0x00, 0x89, 0x45, 0x04, 0x61, 
	0xC9, 0xC3, 0x6A, 0xFF, 0xFF, 0x55, 0xE4, 0xE8, 0x46, 0xFF, 0xFF, 0xFF
};
int _tmain(int argc, char* argv[])
{
	CPeFile mype;
	char recvBuf[MAX_PATH];
	PIMAGE_SECTION_HEADER psec;
	DWORD * OEP;
	char *filter="PE 文件(*.exe)\0";
	OPENFILENAMEA of={0};
	of.lStructSize=sizeof(OPENFILENAMEA);
	of.lpstrFilter = filter;
	of.Flags = OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST;
	of.nMaxFile = MAX_PATH;
	of.lpstrFile=recvBuf;
	if (GetOpenFileNameA(&of)==IDOK)
	{
		if(!mype.LoadPe(recvBuf))
		{
			printf("打开文件:%s 失败\n",recvBuf);
			exit(-1);
		}
		psec=mype.AddSection(".Core",sizeof(data));
		if (!psec)
		{
			printf("创建节表失败!\n");
			exit(-1);
		}
		OEP = (DWORD *)&data[5];
		*OEP = mype.GetEntry()+mype.GetImageBase();
		mype.SetNewEntry(psec->VirtualAddress);
		mype.WriteDataByRaw(psec->PointerToRawData,(char *)&data,sizeof(data));
		mype.FlushBuffer();
		return 0;
	}
}

pe.h是我写的PE类,篇幅有限,这里就不贴代码了。

data数组是一段16进制数据,这是什么鬼?别慌,这就是在目标程序体中的Shell。
下面代码用masm32编译后有一个节表,用PEID把.text dump出来,然后用winhex把数据复制成C语言数组的形式。
[Asm] 纯文本查看 复制代码
.386
.model flat, stdcall  ;32 bit memory model
option casemap :none  ;case sensitive
include windows.inc

GetModuleHandleA typedef proto :dword
CreateThread_t	typedef proto :dword,:dword,:dword,:dword,:dword
LoadLibrary_t	typedef proto :dword
verify_t		typedef proto ;返回1放行,返回0退出
ExitProcess_t	typedef proto :dword
.code
jmp _start
;VA
OEP	dd 0
szGetModuleHandleA db 'GetModuleHandleA',0
szCreateThread	db 'CreateThread',0
szKernel32	db 'Kernel32.dll',0
szLoadLibraryA	db 'LoadLibraryA',0
szDll		db 'DataCore.dll',0
szExitProcess	db 'ExitProcess',0
szVerify	db 'verify',0

_getApi proc _hModule,_lpApi
   local @ret
   local @dwLen
   pushad
   mov @ret,0
   ;计算API字符串的长度,含最后的零
   mov edi,_lpApi
   mov ecx,-1
   xor al,al
   cld
   repnz scasb
   mov ecx,edi
   sub ecx,_lpApi
   mov @dwLen,ecx
   ;从pe文件头的数据目录获取导出表地址
   mov esi,_hModule
   add esi,dword ptr[esi+3ch]
   assume esi:ptr IMAGE_NT_HEADERS
   mov esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
   add esi,_hModule
   assume esi:ptr IMAGE_EXPORT_DIRECTORY
   ;查找符合名称的导出函数名
   mov ebx,[esi].AddressOfNames
   add ebx,_hModule
   xor edx,edx
   .repeat
     push esi
     mov edi,[ebx]
     add edi,_hModule
     mov esi,_lpApi
     mov ecx,@dwLen
     repz cmpsb
     .if ZERO?
       pop esi
       jmp @F
     .endif
     pop esi
     add ebx,4
     inc edx
   .until edx>=[esi].NumberOfNames
   jmp _ret
@@:
   ;通过API名称索引获取序号索引再获取地址索引
   sub ebx,[esi].AddressOfNames
   sub ebx,_hModule
   shr ebx,1
   add ebx,[esi].AddressOfNameOrdinals
   add ebx,_hModule
   movzx eax,word ptr [ebx]
   shl eax,2
   add eax,[esi].AddressOfFunctions
   add eax,_hModule
   ;从地址表得到导出函数的地址
   mov eax,[eax]
   add eax,_hModule
   mov @ret,eax
 
_ret:
   assume esi:nothing
   popad
   mov eax,@ret
   ret
_getApi endp
_getKernelBase  proc
assume fs:nothing
 	mov eax,fs:[30h] ;PEB的地址 
            mov eax, [eax + 0ch] ;Ldr的地址 
            mov esi, [eax + 01ch] ;Flink地址 
            lodsd  
            mov eax, [eax + 08h] ;eax就是kernel32.dll的地址
	ret
_getKernelBase  endp
main proc
	LOCAL kernelBa
	LOCAL kernel32
	LOCAL loc
	LOCAL getmodulehandlea:GetModuleHandleA
	LOCAL CreateThread_m:CreateThread_t
	LOCAL LoadLibraryA:LoadLibrary_t
	LOCAL ExitProcessA:ExitProcess_t
	LOCAL hInst:dword
	LOCAL verify:verify_t
	pushad
	call @f
	@@:
	pop ebx
	sub ebx,offset @b
	mov loc,ebx
	invoke _getKernelBase
	mov kernelBa,eax
	invoke _getApi,kernelBa,addr [ebx+szGetModuleHandleA] ;获取GetModuleHandleA 
	mov getmodulehandlea,eax
	invoke getmodulehandlea,addr[ebx+szKernel32] ;获取Kernel32基址
	mov kernel32,eax
	invoke _getApi,kernel32,addr[ebx+szCreateThread];获取CreateThread
	mov CreateThread_m,eax 
	invoke _getApi,kernel32,addr[ebx+szLoadLibraryA]
	mov LoadLibraryA,eax
	
	invoke _getApi,kernel32,addr[ebx+szExitProcess]
	mov ExitProcessA,eax
	
	invoke LoadLibraryA,addr[ebx+szDll]
	mov hInst,eax
	cmp eax,0
	je exit1
	invoke _getApi,hInst,addr[ebx+szVerify]
	cmp eax,0
	je	exit1
	mov verify,eax
	invoke verify
	cmp eax,1
	jne exit1
	mov eax,[ebx+OEP]
	mov [ebp+4],eax
	popad
	ret
exit1:
	invoke ExitProcessA,-1
main endp

_start:
invoke main
end _start



代码领取处:
AddDLL.zip (515.62 KB, 下载次数: 213)




点评

感谢分享,菜鸟拿走了  发表于 2015-7-26 11:05

免费评分

参与人数 9热心值 +9 收起 理由
liang2708 + 1 已答复!
吾爱∝混时哥 + 1 鼓励优秀软件安全工具和文档!
Fivean + 1 谢谢@Thanks!
流浪的猫眼石 + 1 好高深,看起来很高档的样子
et流氓 + 1 感谢分享
Syer + 1 已答复!
hupengpeng + 1 我很赞同!
帝天 + 1 谢谢@Thanks!
wb9353 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.

查看全部评分

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

smile1110 发表于 2015-7-25 18:31

指点谈不上,弊端就是 Verify 所有的craker看到都会心里一抖,断点少不了,然后加载这个datacore.dll 名字太生硬了,大部分craker看到这个dll都知道这个不是程序本身必须的,肯定反汇编跟,甚至直接删除掉,修复重定位,最后就是这个网络验证内存数据返回是1,就算是0或者11111 2222 这些常见的简单的可以进行域名劫持 host劫持等,复杂的可以直接对这个内存数值下手,反馈下面肯定要进行判断,这个网络验证只能防君子,不能放成天摸爬滚打的小人,特征太明显
panzer1313208 发表于 2015-7-29 04:11
我是人民币 发表于 2015-7-27 16:50
DLL呢?
DLL编写正确了吗?

你能不能做一个软件,和你这个差不多的,但是选择文件之后可以弹出一个窗口,然后让设置密码,设置好后按完成,之后打开那个软件就必须要填入之前设置的密码的这种软件啊
 楼主| 我是人民币 发表于 2015-7-25 17:10
头像被屏蔽
zzfafa 发表于 2015-7-25 17:10
提示: 作者被禁止或删除 内容自动屏蔽
smile1110 发表于 2015-7-25 17:16
这玩意还是有一定弊端的
 楼主| 我是人民币 发表于 2015-7-25 17:20
smile1110 发表于 2015-7-25 17:16
这玩意还是有一定弊端的

求大大指点一下。
陆地的星空 发表于 2015-7-25 18:10
路过=-=膜拜一下无名大神
Hmily 发表于 2015-7-25 18:39
我这运行不了。
这只猪 发表于 2015-7-25 21:30
我一把都是SE--EMG---WINLICENSE-TMD
弑剑丶霄河 发表于 2015-7-26 00:26
66666666666666666
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-25 06:19

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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